diff --git a/.github/VOUCHED.td b/.github/VOUCHED.td new file mode 100644 index 00000000000..3b7bb8914a9 --- /dev/null +++ b/.github/VOUCHED.td @@ -0,0 +1,20 @@ +# Vouched contributors for this project. +# +# See https://github.com/mitchellh/vouch for details. +# +# Syntax: +# - One handle per line (without @), sorted alphabetically. +# - Optional platform prefix: platform:username (e.g., github:user). +# - Denounce with minus prefix: -username or -platform:username. +# - Optional details after a space following the handle. +adamdotdevin +-florianleibert +fwang +iamdavidhill +jayair +kitlangton +kommander +r44vc0rp +rekram1-node +-spider-yamet clawdbot/llm psychosis, spam pinging the team +thdxr diff --git a/.github/workflows/compliance-close.yml b/.github/workflows/compliance-close.yml new file mode 100644 index 00000000000..5b424d0adfa --- /dev/null +++ b/.github/workflows/compliance-close.yml @@ -0,0 +1,86 @@ +name: compliance-close + +on: + schedule: + # Run every 30 minutes to check for expired compliance windows + - cron: "*/30 * * * *" + workflow_dispatch: + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + close-non-compliant: + runs-on: ubuntu-latest + steps: + - name: Close non-compliant issues and PRs after 2 hours + uses: actions/github-script@v7 + with: + script: | + const { data: items } = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + labels: 'needs:compliance', + state: 'open', + per_page: 100, + }); + + if (items.length === 0) { + core.info('No open issues/PRs with needs:compliance label'); + return; + } + + const now = Date.now(); + const twoHours = 2 * 60 * 60 * 1000; + + for (const item of items) { + const isPR = !!item.pull_request; + const kind = isPR ? 'PR' : 'issue'; + + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: item.number, + }); + + const complianceComment = comments.find(c => c.body.includes('')); + if (!complianceComment) continue; + + const commentAge = now - new Date(complianceComment.created_at).getTime(); + if (commentAge < twoHours) { + core.info(`${kind} #${item.number} still within 2-hour window (${Math.round(commentAge / 60000)}m elapsed)`); + continue; + } + + const closeMessage = isPR + ? 'This pull request has been automatically closed because it was not updated to meet our [contributing guidelines](../blob/dev/CONTRIBUTING.md) within the 2-hour window.\n\nFeel free to open a new pull request that follows our guidelines.' + : 'This issue has been automatically closed because it was not updated to meet our [contributing guidelines](../blob/dev/CONTRIBUTING.md) within the 2-hour window.\n\nFeel free to open a new issue that follows our issue templates.'; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: item.number, + body: closeMessage, + }); + + if (isPR) { + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: item.number, + state: 'closed', + }); + } else { + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: item.number, + state: 'closed', + state_reason: 'not_planned', + }); + } + + core.info(`Closed non-compliant ${kind} #${item.number} after 2-hour window`); + } diff --git a/.github/workflows/docs-locale-sync.yml b/.github/workflows/docs-locale-sync.yml new file mode 100644 index 00000000000..8cd0cc52e2a --- /dev/null +++ b/.github/workflows/docs-locale-sync.yml @@ -0,0 +1,85 @@ +name: docs-locale-sync + +on: + push: + branches: + - dev + paths: + - packages/web/src/content/docs/*.mdx + +jobs: + sync-locales: + if: github.actor != 'opencode-agent[bot]' + runs-on: blacksmith-4vcpu-ubuntu-2404 + permissions: + id-token: write + contents: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Bun + uses: ./.github/actions/setup-bun + + - 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: Compute changed English docs + id: changes + run: | + FILES=$(git diff --name-only "${{ github.event.before }}" "${{ github.sha }}" -- 'packages/web/src/content/docs/*.mdx' || true) + if [ -z "$FILES" ]; then + echo "has_changes=false" >> "$GITHUB_OUTPUT" + echo "No English docs changed in push range" + exit 0 + fi + echo "has_changes=true" >> "$GITHUB_OUTPUT" + { + echo "files<> "$GITHUB_OUTPUT" + + - name: Sync locale docs with OpenCode + if: steps.changes.outputs.has_changes == 'true' + uses: sst/opencode/github@latest + env: + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} + with: + model: opencode/gpt-5.2 + agent: docs + prompt: | + Update localized docs to match the latest English docs changes. + + Changed English doc files: + + ${{ steps.changes.outputs.files }} + + + Requirements: + 1. Update all relevant locale docs under packages/web/src/content/docs// so they reflect these English page changes. + 2. You MUST use the Task tool for translation work and launch subagents with subagent_type `translator` (defined in .opencode/agent/translator.md). + 3. Do not translate directly in the primary agent. Use translator subagent output as the source for locale text updates. + 4. Run translator subagent Task calls in parallel whenever file/locale translation work is independent. + 5. Preserve frontmatter keys, internal links, code blocks, and existing locale-specific metadata unless the English change requires an update. + 6. Keep locale docs structure aligned with their corresponding English pages. + 7. Do not modify English source docs in packages/web/src/content/docs/*.mdx. + 8. If no locale updates are needed, make no changes. + + - name: Commit and push locale docs updates + if: steps.changes.outputs.has_changes == 'true' + run: | + if [ -z "$(git status --porcelain)" ]; then + echo "No locale docs changes to commit" + exit 0 + fi + git add -A + git commit -m "docs(i18n): sync locale docs from english changes" + git pull --rebase --autostash origin "$GITHUB_REF_NAME" + git push origin HEAD:"$GITHUB_REF_NAME" diff --git a/.github/workflows/vouch-check-issue.yml b/.github/workflows/vouch-check-issue.yml new file mode 100644 index 00000000000..94569f47312 --- /dev/null +++ b/.github/workflows/vouch-check-issue.yml @@ -0,0 +1,96 @@ +name: vouch-check-issue + +on: + issues: + types: [opened] + +permissions: + contents: read + issues: write + +jobs: + check: + runs-on: ubuntu-latest + steps: + - name: Check if issue author is denounced + uses: actions/github-script@v7 + with: + script: | + const author = context.payload.issue.user.login; + const issueNumber = context.payload.issue.number; + + // Skip bots + if (author.endsWith('[bot]')) { + core.info(`Skipping bot: ${author}`); + return; + } + + // Read the VOUCHED.td file via API (no checkout needed) + let content; + try { + const response = await github.rest.repos.getContent({ + owner: context.repo.owner, + repo: context.repo.repo, + path: '.github/VOUCHED.td', + }); + content = Buffer.from(response.data.content, 'base64').toString('utf-8'); + } catch (error) { + if (error.status === 404) { + core.info('No .github/VOUCHED.td file found, skipping check.'); + return; + } + throw error; + } + + // Parse the .td file for denounced users + const denounced = new Map(); + for (const line of content.split('\n')) { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith('#')) continue; + if (!trimmed.startsWith('-')) continue; + + const rest = trimmed.slice(1).trim(); + if (!rest) continue; + const spaceIdx = rest.indexOf(' '); + const handle = spaceIdx === -1 ? rest : rest.slice(0, spaceIdx); + const reason = spaceIdx === -1 ? null : rest.slice(spaceIdx + 1).trim(); + + // Handle platform:username or bare username + // Only match bare usernames or github: prefix (skip other platforms) + const colonIdx = handle.indexOf(':'); + if (colonIdx !== -1) { + const platform = handle.slice(0, colonIdx).toLowerCase(); + if (platform !== 'github') continue; + } + const username = colonIdx === -1 ? handle : handle.slice(colonIdx + 1); + if (!username) continue; + + denounced.set(username.toLowerCase(), reason); + } + + // Check if the author is denounced + const reason = denounced.get(author.toLowerCase()); + if (reason === undefined) { + core.info(`User ${author} is not denounced. Allowing issue.`); + return; + } + + // Author is denounced — close the issue + const body = 'This issue has been automatically closed.'; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body, + }); + + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + state: 'closed', + state_reason: 'not_planned', + }); + + core.info(`Closed issue #${issueNumber} from denounced user ${author}`); diff --git a/.github/workflows/vouch-check-pr.yml b/.github/workflows/vouch-check-pr.yml new file mode 100644 index 00000000000..470b8e0a5ad --- /dev/null +++ b/.github/workflows/vouch-check-pr.yml @@ -0,0 +1,93 @@ +name: vouch-check-pr + +on: + pull_request_target: + types: [opened] + +permissions: + contents: read + pull-requests: write + +jobs: + check: + runs-on: ubuntu-latest + steps: + - name: Check if PR author is denounced + uses: actions/github-script@v7 + with: + script: | + const author = context.payload.pull_request.user.login; + const prNumber = context.payload.pull_request.number; + + // Skip bots + if (author.endsWith('[bot]')) { + core.info(`Skipping bot: ${author}`); + return; + } + + // Read the VOUCHED.td file via API (no checkout needed) + let content; + try { + const response = await github.rest.repos.getContent({ + owner: context.repo.owner, + repo: context.repo.repo, + path: '.github/VOUCHED.td', + }); + content = Buffer.from(response.data.content, 'base64').toString('utf-8'); + } catch (error) { + if (error.status === 404) { + core.info('No .github/VOUCHED.td file found, skipping check.'); + return; + } + throw error; + } + + // Parse the .td file for denounced users + const denounced = new Map(); + for (const line of content.split('\n')) { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith('#')) continue; + if (!trimmed.startsWith('-')) continue; + + const rest = trimmed.slice(1).trim(); + if (!rest) continue; + const spaceIdx = rest.indexOf(' '); + const handle = spaceIdx === -1 ? rest : rest.slice(0, spaceIdx); + const reason = spaceIdx === -1 ? null : rest.slice(spaceIdx + 1).trim(); + + // Handle platform:username or bare username + // Only match bare usernames or github: prefix (skip other platforms) + const colonIdx = handle.indexOf(':'); + if (colonIdx !== -1) { + const platform = handle.slice(0, colonIdx).toLowerCase(); + if (platform !== 'github') continue; + } + const username = colonIdx === -1 ? handle : handle.slice(colonIdx + 1); + if (!username) continue; + + denounced.set(username.toLowerCase(), reason); + } + + // Check if the author is denounced + const reason = denounced.get(author.toLowerCase()); + if (reason === undefined) { + core.info(`User ${author} is not denounced. Allowing PR.`); + return; + } + + // Author is denounced — close the PR + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: 'This pull request has been automatically closed.', + }); + + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + state: 'closed', + }); + + core.info(`Closed PR #${prNumber} from denounced user ${author}`); diff --git a/.github/workflows/vouch-manage-by-issue.yml b/.github/workflows/vouch-manage-by-issue.yml new file mode 100644 index 00000000000..cf0524c21a8 --- /dev/null +++ b/.github/workflows/vouch-manage-by-issue.yml @@ -0,0 +1,37 @@ +name: vouch-manage-by-issue + +on: + issue_comment: + types: [created] + +concurrency: + group: vouch-manage + cancel-in-progress: false + +permissions: + contents: write + issues: write + pull-requests: read + +jobs: + manage: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + fetch-depth: 0 + + - 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 }} + + - uses: mitchellh/vouch/action/manage-by-issue@main + with: + issue-id: ${{ github.event.issue.number }} + comment-id: ${{ github.event.comment.id }} + env: + GITHUB_TOKEN: ${{ steps.committer.outputs.token }} diff --git a/.opencode/agent/translator.md b/.opencode/agent/translator.md new file mode 100644 index 00000000000..dec6fa6c4fc --- /dev/null +++ b/.opencode/agent/translator.md @@ -0,0 +1,883 @@ +--- +description: Translate content for a specified locale while preserving technical terms +mode: subagent +model: opencode/gemini-3-pro +--- + +You are a professional translator and localization specialist. + +Translate the user's content into the requested target locale (language + region, e.g. fr-FR, de-DE). + +Requirements: + +- Preserve meaning, intent, tone, and formatting (including Markdown/MDX structure). +- Preserve all technical terms and artifacts exactly: product/company names, API names, identifiers, code, commands/flags, file paths, URLs, versions, error messages, config keys/values, and anything inside inline code or code blocks. +- Also preserve every term listed in the Do-Not-Translate glossary below. +- Do not modify fenced code blocks. +- Output ONLY the translation (no commentary). + +If the target locale is missing, ask the user to provide it. + +--- + +# Do-Not-Translate Terms (OpenCode Docs) + +Generated from: `packages/web/src/content/docs/*.mdx` (default English docs) +Generated on: 2026-02-10 + +Use this as a translation QA checklist / glossary. Preserve listed terms exactly (spelling, casing, punctuation). + +General rules (verbatim, even if not listed below): + +- Anything inside inline code (single backticks) or fenced code blocks (triple backticks) +- MDX/JS code in docs: `import ... from "..."`, component tags, identifiers +- CLI commands, flags, config keys/values, file paths, URLs/domains, and env vars + +## Proper nouns and product names + +Additional (not reliably captured via link text): + +```text +Astro +Bun +Chocolatey +Cursor +Docker +Git +GitHub Actions +GitLab CI +GNOME Terminal +Homebrew +Mise +Neovim +Node.js +npm +Obsidian +opencode +opencode-ai +Paru +pnpm +ripgrep +Scoop +SST +Starlight +Visual Studio Code +VS Code +VSCodium +Windsurf +Windows Terminal +Yarn +Zellij +Zed +anomalyco +``` + +Extracted from link labels in the English docs (review and prune as desired): + +```text +@openspoon/subtask2 +302.AI console +ACP progress report +Agent Client Protocol +Agent Skills +Agentic +AGENTS.md +AI SDK +Alacritty +Anthropic +Anthropic's Data Policies +Atom One +Avante.nvim +Ayu +Azure AI Foundry +Azure portal +Baseten +built-in GITHUB_TOKEN +Bun.$ +Catppuccin +Cerebras console +ChatGPT Plus or Pro +Cloudflare dashboard +CodeCompanion.nvim +CodeNomad +Configuring Adapters: Environment Variables +Context7 MCP server +Cortecs console +Deep Infra dashboard +DeepSeek console +Duo Agent Platform +Everforest +Fireworks AI console +Firmware dashboard +Ghostty +GitLab CLI agents docs +GitLab docs +GitLab User Settings > Access Tokens +Granular Rules (Object Syntax) +Grep by Vercel +Groq console +Gruvbox +Helicone +Helicone documentation +Helicone Header Directory +Helicone's Model Directory +Hugging Face Inference Providers +Hugging Face settings +install WSL +IO.NET console +JetBrains IDE +Kanagawa +Kitty +MiniMax API Console +Models.dev +Moonshot AI console +Nebius Token Factory console +Nord +OAuth +Ollama integration docs +OpenAI's Data Policies +OpenChamber +OpenCode +OpenCode config +OpenCode Config +OpenCode TUI with the opencode theme +OpenCode Web - Active Session +OpenCode Web - New Session +OpenCode Web - See Servers +OpenCode Zen +OpenCode-Obsidian +OpenRouter dashboard +OpenWork +OVHcloud panel +Pro+ subscription +SAP BTP Cockpit +Scaleway Console IAM settings +Scaleway Generative APIs +SDK documentation +Sentry MCP server +shell API +Together AI console +Tokyonight +Unified Billing +Venice AI console +Vercel dashboard +WezTerm +Windows Subsystem for Linux (WSL) +WSL +WSL (Windows Subsystem for Linux) +WSL extension +xAI console +Z.AI API console +Zed +ZenMux dashboard +Zod +``` + +## Acronyms and initialisms + +```text +ACP +AGENTS +AI +AI21 +ANSI +API +AST +AWS +BTP +CD +CDN +CI +CLI +CMD +CORS +DEBUG +EKS +ERROR +FAQ +GLM +GNOME +GPT +HTML +HTTP +HTTPS +IAM +ID +IDE +INFO +IO +IP +IRSA +JS +JSON +JSONC +K2 +LLM +LM +LSP +M2 +MCP +MR +NET +NPM +NTLM +OIDC +OS +PAT +PATH +PHP +PR +PTY +README +RFC +RPC +SAP +SDK +SKILL +SSE +SSO +TS +TTY +TUI +UI +URL +US +UX +VCS +VPC +VPN +VS +WARN +WSL +X11 +YAML +``` + +## Code identifiers used in prose (CamelCase, mixedCase) + +```text +apiKey +AppleScript +AssistantMessage +baseURL +BurntSushi +ChatGPT +ClangFormat +CodeCompanion +CodeNomad +DeepSeek +DefaultV2 +FileContent +FileDiff +FileNode +fineGrained +FormatterStatus +GitHub +GitLab +iTerm2 +JavaScript +JetBrains +macOS +mDNS +MiniMax +NeuralNomadsAI +NickvanDyke +NoeFabris +OpenAI +OpenAPI +OpenChamber +OpenCode +OpenRouter +OpenTUI +OpenWork +ownUserPermissions +PowerShell +ProviderAuthAuthorization +ProviderAuthMethod +ProviderInitError +SessionStatus +TabItem +tokenType +ToolIDs +ToolList +TypeScript +typesUrl +UserMessage +VcsInfo +WebView2 +WezTerm +xAI +ZenMux +``` + +## OpenCode CLI commands (as shown in docs) + +```text +opencode +opencode [project] +opencode /path/to/project +opencode acp +opencode agent [command] +opencode agent create +opencode agent list +opencode attach [url] +opencode attach http://10.20.30.40:4096 +opencode attach http://localhost:4096 +opencode auth [command] +opencode auth list +opencode auth login +opencode auth logout +opencode auth ls +opencode export [sessionID] +opencode github [command] +opencode github install +opencode github run +opencode import +opencode import https://opncd.ai/s/abc123 +opencode import session.json +opencode mcp [command] +opencode mcp add +opencode mcp auth [name] +opencode mcp auth list +opencode mcp auth ls +opencode mcp auth my-oauth-server +opencode mcp auth sentry +opencode mcp debug +opencode mcp debug my-oauth-server +opencode mcp list +opencode mcp logout [name] +opencode mcp logout my-oauth-server +opencode mcp ls +opencode models --refresh +opencode models [provider] +opencode models anthropic +opencode run [message..] +opencode run Explain the use of context in Go +opencode serve +opencode serve --cors http://localhost:5173 --cors https://app.example.com +opencode serve --hostname 0.0.0.0 --port 4096 +opencode serve [--port ] [--hostname ] [--cors ] +opencode session [command] +opencode session list +opencode stats +opencode uninstall +opencode upgrade +opencode upgrade [target] +opencode upgrade v0.1.48 +opencode web +opencode web --cors https://example.com +opencode web --hostname 0.0.0.0 +opencode web --mdns +opencode web --mdns --mdns-domain myproject.local +opencode web --port 4096 +opencode web --port 4096 --hostname 0.0.0.0 +opencode.server.close() +``` + +## Slash commands and routes + +```text +/agent +/auth/:id +/clear +/command +/config +/config/providers +/connect +/continue +/doc +/editor +/event +/experimental/tool?provider=

&model= +/experimental/tool/ids +/export +/file?path= +/file/content?path=

+/file/status +/find?pattern= +/find/file +/find/file?query= +/find/symbol?query= +/formatter +/global/event +/global/health +/help +/init +/instance/dispose +/log +/lsp +/mcp +/mnt/ +/mnt/c/ +/mnt/d/ +/models +/oc +/opencode +/path +/project +/project/current +/provider +/provider/{id}/oauth/authorize +/provider/{id}/oauth/callback +/provider/auth +/q +/quit +/redo +/resume +/session +/session/:id +/session/:id/abort +/session/:id/children +/session/:id/command +/session/:id/diff +/session/:id/fork +/session/:id/init +/session/:id/message +/session/:id/message/:messageID +/session/:id/permissions/:permissionID +/session/:id/prompt_async +/session/:id/revert +/session/:id/share +/session/:id/shell +/session/:id/summarize +/session/:id/todo +/session/:id/unrevert +/session/status +/share +/summarize +/theme +/tui +/tui/append-prompt +/tui/clear-prompt +/tui/control/next +/tui/control/response +/tui/execute-command +/tui/open-help +/tui/open-models +/tui/open-sessions +/tui/open-themes +/tui/show-toast +/tui/submit-prompt +/undo +/Users/username +/Users/username/projects/* +/vcs +``` + +## CLI flags and short options + +```text +--agent +--attach +--command +--continue +--cors +--cwd +--days +--dir +--dry-run +--event +--file +--force +--fork +--format +--help +--hostname +--hostname 0.0.0.0 +--keep-config +--keep-data +--log-level +--max-count +--mdns +--mdns-domain +--method +--model +--models +--port +--print-logs +--project +--prompt +--refresh +--session +--share +--title +--token +--tools +--verbose +--version +--wait + +-c +-d +-f +-h +-m +-n +-s +-v +``` + +## Environment variables + +```text +AI_API_URL +AI_FLOW_CONTEXT +AI_FLOW_EVENT +AI_FLOW_INPUT +AICORE_DEPLOYMENT_ID +AICORE_RESOURCE_GROUP +AICORE_SERVICE_KEY +ANTHROPIC_API_KEY +AWS_ACCESS_KEY_ID +AWS_BEARER_TOKEN_BEDROCK +AWS_PROFILE +AWS_REGION +AWS_ROLE_ARN +AWS_SECRET_ACCESS_KEY +AWS_WEB_IDENTITY_TOKEN_FILE +AZURE_COGNITIVE_SERVICES_RESOURCE_NAME +AZURE_RESOURCE_NAME +CI_PROJECT_DIR +CI_SERVER_FQDN +CI_WORKLOAD_REF +CLOUDFLARE_ACCOUNT_ID +CLOUDFLARE_API_TOKEN +CLOUDFLARE_GATEWAY_ID +CONTEXT7_API_KEY +GITHUB_TOKEN +GITLAB_AI_GATEWAY_URL +GITLAB_HOST +GITLAB_INSTANCE_URL +GITLAB_OAUTH_CLIENT_ID +GITLAB_TOKEN +GITLAB_TOKEN_OPENCODE +GOOGLE_APPLICATION_CREDENTIALS +GOOGLE_CLOUD_PROJECT +HTTP_PROXY +HTTPS_PROXY +K2_ +MY_API_KEY +MY_ENV_VAR +MY_MCP_CLIENT_ID +MY_MCP_CLIENT_SECRET +NO_PROXY +NODE_ENV +NODE_EXTRA_CA_CERTS +NPM_AUTH_TOKEN +OC_ALLOW_WAYLAND +OPENCODE_API_KEY +OPENCODE_AUTH_JSON +OPENCODE_AUTO_SHARE +OPENCODE_CLIENT +OPENCODE_CONFIG +OPENCODE_CONFIG_CONTENT +OPENCODE_CONFIG_DIR +OPENCODE_DISABLE_AUTOCOMPACT +OPENCODE_DISABLE_AUTOUPDATE +OPENCODE_DISABLE_CLAUDE_CODE +OPENCODE_DISABLE_CLAUDE_CODE_PROMPT +OPENCODE_DISABLE_CLAUDE_CODE_SKILLS +OPENCODE_DISABLE_DEFAULT_PLUGINS +OPENCODE_DISABLE_FILETIME_CHECK +OPENCODE_DISABLE_LSP_DOWNLOAD +OPENCODE_DISABLE_MODELS_FETCH +OPENCODE_DISABLE_PRUNE +OPENCODE_DISABLE_TERMINAL_TITLE +OPENCODE_ENABLE_EXA +OPENCODE_ENABLE_EXPERIMENTAL_MODELS +OPENCODE_EXPERIMENTAL +OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS +OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT +OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER +OPENCODE_EXPERIMENTAL_EXA +OPENCODE_EXPERIMENTAL_FILEWATCHER +OPENCODE_EXPERIMENTAL_ICON_DISCOVERY +OPENCODE_EXPERIMENTAL_LSP_TOOL +OPENCODE_EXPERIMENTAL_LSP_TY +OPENCODE_EXPERIMENTAL_MARKDOWN +OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX +OPENCODE_EXPERIMENTAL_OXFMT +OPENCODE_EXPERIMENTAL_PLAN_MODE +OPENCODE_FAKE_VCS +OPENCODE_GIT_BASH_PATH +OPENCODE_MODEL +OPENCODE_MODELS_URL +OPENCODE_PERMISSION +OPENCODE_PORT +OPENCODE_SERVER_PASSWORD +OPENCODE_SERVER_USERNAME +PROJECT_ROOT +RESOURCE_NAME +RUST_LOG +VARIABLE_NAME +VERTEX_LOCATION +XDG_CONFIG_HOME +``` + +## Package/module identifiers + +```text +../../../config.mjs +@astrojs/starlight/components +@opencode-ai/plugin +@opencode-ai/sdk +path +shescape +zod + +@ +@ai-sdk/anthropic +@ai-sdk/cerebras +@ai-sdk/google +@ai-sdk/openai +@ai-sdk/openai-compatible +@File#L37-42 +@modelcontextprotocol/server-everything +@opencode +``` + +## GitHub owner/repo slugs referenced in docs + +```text +24601/opencode-zellij-namer +angristan/opencode-wakatime +anomalyco/opencode +apps/opencode-agent +athal7/opencode-devcontainers +awesome-opencode/awesome-opencode +backnotprop/plannotator +ben-vargas/ai-sdk-provider-opencode-sdk +btriapitsyn/openchamber +BurntSushi/ripgrep +Cluster444/agentic +code-yeongyu/oh-my-opencode +darrenhinde/opencode-agents +different-ai/opencode-scheduler +different-ai/openwork +features/copilot +folke/tokyonight.nvim +franlol/opencode-md-table-formatter +ggml-org/llama.cpp +ghoulr/opencode-websearch-cited.git +H2Shami/opencode-helicone-session +hosenur/portal +jamesmurdza/daytona +jenslys/opencode-gemini-auth +JRedeker/opencode-morph-fast-apply +JRedeker/opencode-shell-strategy +kdcokenny/ocx +kdcokenny/opencode-background-agents +kdcokenny/opencode-notify +kdcokenny/opencode-workspace +kdcokenny/opencode-worktree +login/device +mohak34/opencode-notifier +morhetz/gruvbox +mtymek/opencode-obsidian +NeuralNomadsAI/CodeNomad +nick-vi/opencode-type-inject +NickvanDyke/opencode.nvim +NoeFabris/opencode-antigravity-auth +nordtheme/nord +numman-ali/opencode-openai-codex-auth +olimorris/codecompanion.nvim +panta82/opencode-notificator +rebelot/kanagawa.nvim +remorses/kimaki +sainnhe/everforest +shekohex/opencode-google-antigravity-auth +shekohex/opencode-pty.git +spoons-and-mirrors/subtask2 +sudo-tee/opencode.nvim +supermemoryai/opencode-supermemory +Tarquinen/opencode-dynamic-context-pruning +Th3Whit3Wolf/one-nvim +upstash/context7 +vtemian/micode +vtemian/octto +yetone/avante.nvim +zenobi-us/opencode-plugin-template +zenobi-us/opencode-skillful +``` + +## Paths, filenames, globs, and URLs + +```text +./.opencode/themes/*.json +.//storage/ +./config/#custom-directory +./global/storage/ +.agents/skills/*/SKILL.md +.agents/skills//SKILL.md +.clang-format +.claude +.claude/skills +.claude/skills/*/SKILL.md +.claude/skills//SKILL.md +.env +.github/workflows/opencode.yml +.gitignore +.gitlab-ci.yml +.ignore +.NET SDK +.npmrc +.ocamlformat +.opencode +.opencode/ +.opencode/agents/ +.opencode/commands/ +.opencode/commands/test.md +.opencode/modes/ +.opencode/plans/*.md +.opencode/plugins/ +.opencode/skills//SKILL.md +.opencode/skills/git-release/SKILL.md +.opencode/tools/ +.well-known/opencode +{ type: "raw" \| "patch", content: string } +{file:path/to/file} +**/*.js +%USERPROFILE%/intelephense/license.txt +%USERPROFILE%\.cache\opencode +%USERPROFILE%\.config\opencode\opencode.jsonc +%USERPROFILE%\.config\opencode\plugins +%USERPROFILE%\.local\share\opencode +%USERPROFILE%\.local\share\opencode\log +/.opencode/themes/*.json +/ +/.opencode/plugins/ +~ +~/... +~/.agents/skills/*/SKILL.md +~/.agents/skills//SKILL.md +~/.aws/credentials +~/.bashrc +~/.cache/opencode +~/.cache/opencode/node_modules/ +~/.claude/CLAUDE.md +~/.claude/skills/ +~/.claude/skills/*/SKILL.md +~/.claude/skills//SKILL.md +~/.config/opencode +~/.config/opencode/AGENTS.md +~/.config/opencode/agents/ +~/.config/opencode/commands/ +~/.config/opencode/modes/ +~/.config/opencode/opencode.json +~/.config/opencode/opencode.jsonc +~/.config/opencode/plugins/ +~/.config/opencode/skills/*/SKILL.md +~/.config/opencode/skills//SKILL.md +~/.config/opencode/themes/*.json +~/.config/opencode/tools/ +~/.config/zed/settings.json +~/.local/share +~/.local/share/opencode/ +~/.local/share/opencode/auth.json +~/.local/share/opencode/log/ +~/.local/share/opencode/mcp-auth.json +~/.local/share/opencode/opencode.jsonc +~/.npmrc +~/.zshrc +~/code/ +~/Library/Application Support +~/projects/* +~/projects/personal/ +${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts +$HOME/intelephense/license.txt +$HOME/projects/* +$XDG_CONFIG_HOME/opencode/themes/*.json +agent/ +agents/ +build/ +commands/ +dist/ +http://:4096 +http://127.0.0.1:8080/callback +http://localhost: +http://localhost:4096 +http://localhost:4096/doc +https://app.example.com +https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/ +https://opencode.ai/zen/v1/chat/completions +https://opencode.ai/zen/v1/messages +https://opencode.ai/zen/v1/models/gemini-3-flash +https://opencode.ai/zen/v1/models/gemini-3-pro +https://opencode.ai/zen/v1/responses +https://RESOURCE_NAME.openai.azure.com/ +laravel/pint +log/ +model: "anthropic/claude-sonnet-4-5" +modes/ +node_modules/ +openai/gpt-4.1 +opencode.ai/config.json +opencode/ +opencode/gpt-5.1-codex +opencode/gpt-5.2-codex +opencode/kimi-k2 +openrouter/google/gemini-2.5-flash +opncd.ai/s/ +packages/*/AGENTS.md +plugins/ +project/ +provider_id/model_id +provider/model +provider/model-id +rm -rf ~/.cache/opencode +skills/ +skills/*/SKILL.md +src/**/*.ts +themes/ +tools/ +``` + +## Keybind strings + +```text +alt+b +Alt+Ctrl+K +alt+d +alt+f +Cmd+Esc +Cmd+Option+K +Cmd+Shift+Esc +Cmd+Shift+G +Cmd+Shift+P +ctrl+a +ctrl+b +ctrl+d +ctrl+e +Ctrl+Esc +ctrl+f +ctrl+g +ctrl+k +Ctrl+Shift+Esc +Ctrl+Shift+P +ctrl+t +ctrl+u +ctrl+w +ctrl+x +DELETE +Shift+Enter +WIN+R +``` + +## Model ID strings referenced + +```text +{env:OPENCODE_MODEL} +anthropic/claude-3-5-sonnet-20241022 +anthropic/claude-haiku-4-20250514 +anthropic/claude-haiku-4-5 +anthropic/claude-sonnet-4-20250514 +anthropic/claude-sonnet-4-5 +gitlab/duo-chat-haiku-4-5 +lmstudio/google/gemma-3n-e4b +openai/gpt-4.1 +openai/gpt-5 +opencode/gpt-5.1-codex +opencode/gpt-5.2-codex +opencode/kimi-k2 +openrouter/google/gemini-2.5-flash +``` diff --git a/README.bs.md b/README.bs.md new file mode 100644 index 00000000000..56a1e72fb6a --- /dev/null +++ b/README.bs.md @@ -0,0 +1,136 @@ +

+ + + + + OpenCode logo + + +

+

OpenCode je open source AI agent za programiranje.

+

+ Discord + npm + Build status +

+ +

+ English | + 简体中文 | + 繁體中文 | + 한국어 | + Deutsch | + Español | + Français | + Italiano | + Dansk | + 日本語 | + Polski | + Русский | + Bosanski | + العربية | + Norsk | + Português (Brasil) | + ไทย | + Türkçe +

+ +[![OpenCode Terminal UI](packages/web/src/assets/lander/screenshot.png)](https://opencode.ai) + +--- + +### Instalacija + +```bash +# YOLO +curl -fsSL https://opencode.ai/install | bash + +# Package manageri +npm i -g opencode-ai@latest # ili bun/pnpm/yarn +scoop install opencode # Windows +choco install opencode # Windows +brew install anomalyco/tap/opencode # macOS i Linux (preporučeno, uvijek ažurno) +brew install opencode # macOS i Linux (zvanična brew formula, rjeđe se ažurira) +paru -S opencode-bin # Arch Linux +mise use -g opencode # Bilo koji OS +nix run nixpkgs#opencode # ili github:anomalyco/opencode za najnoviji dev branch +``` + +> [!TIP] +> Ukloni verzije starije od 0.1.x prije instalacije. + +### Desktop aplikacija (BETA) + +OpenCode je dostupan i kao desktop aplikacija. Preuzmi je direktno sa [stranice izdanja](https://github.com/anomalyco/opencode/releases) ili sa [opencode.ai/download](https://opencode.ai/download). + +| Platforma | Preuzimanje | +| --------------------- | ------------------------------------- | +| macOS (Apple Silicon) | `opencode-desktop-darwin-aarch64.dmg` | +| macOS (Intel) | `opencode-desktop-darwin-x64.dmg` | +| Windows | `opencode-desktop-windows-x64.exe` | +| Linux | `.deb`, `.rpm`, ili AppImage | + +```bash +# macOS (Homebrew) +brew install --cask opencode-desktop +# Windows (Scoop) +scoop bucket add extras; scoop install extras/opencode-desktop +``` + +#### Instalacijski direktorij + +Instalacijska skripta koristi sljedeći redoslijed prioriteta za putanju instalacije: + +1. `$OPENCODE_INSTALL_DIR` - Prilagođeni instalacijski direktorij +2. `$XDG_BIN_DIR` - Putanja usklađena sa XDG Base Directory specifikacijom +3. `$HOME/bin` - Standardni korisnički bin direktorij (ako postoji ili se može kreirati) +4. `$HOME/.opencode/bin` - Podrazumijevana rezervna lokacija + +```bash +# Primjeri +OPENCODE_INSTALL_DIR=/usr/local/bin curl -fsSL https://opencode.ai/install | bash +XDG_BIN_DIR=$HOME/.local/bin curl -fsSL https://opencode.ai/install | bash +``` + +### Agenti + +OpenCode uključuje dva ugrađena agenta između kojih možeš prebacivati tasterom `Tab`. + +- **build** - Podrazumijevani agent sa punim pristupom za razvoj +- **plan** - Agent samo za čitanje za analizu i istraživanje koda + - Podrazumijevano zabranjuje izmjene datoteka + - Traži dozvolu prije pokretanja bash komandi + - Idealan za istraživanje nepoznatih codebase-ova ili planiranje izmjena + +Uključen je i **general** pod-agent za složene pretrage i višekoračne zadatke. +Koristi se interno i može se pozvati pomoću `@general` u porukama. + +Saznaj više o [agentima](https://opencode.ai/docs/agents). + +### Dokumentacija + +Za više informacija o konfiguraciji OpenCode-a, [**pogledaj dokumentaciju**](https://opencode.ai/docs). + +### Doprinosi + +Ako želiš doprinositi OpenCode-u, pročitaj [upute za doprinošenje](./CONTRIBUTING.md) prije slanja pull requesta. + +### Gradnja na OpenCode-u + +Ako radiš na projektu koji je povezan s OpenCode-om i koristi "opencode" kao dio naziva, npr. "opencode-dashboard" ili "opencode-mobile", dodaj napomenu u svoj README da projekat nije napravio OpenCode tim i da nije povezan s nama. + +### FAQ + +#### Po čemu se razlikuje od Claude Code-a? + +Po mogućnostima je vrlo sličan Claude Code-u. Ključne razlike su: + +- 100% open source +- Nije vezan za jednog provajdera. Iako preporučujemo modele koje nudimo kroz [OpenCode Zen](https://opencode.ai/zen), OpenCode možeš koristiti s Claude, OpenAI, Google ili čak lokalnim modelima. Kako modeli napreduju, razlike među njima će se smanjivati, a cijene padati, zato je nezavisnost od provajdera važna. +- LSP podrška odmah po instalaciji +- Fokus na TUI. OpenCode grade neovim korisnici i kreatori [terminal.shop](https://terminal.shop); pomjeraćemo granice onoga što je moguće u terminalu. +- Klijent/server arhitektura. To, recimo, omogućava da OpenCode radi na tvom računaru dok ga daljinski koristiš iz mobilne aplikacije, što znači da je TUI frontend samo jedan od mogućih klijenata. + +--- + +**Pridruži se našoj zajednici** [Discord](https://discord.gg/opencode) | [X.com](https://x.com/opencode) diff --git a/README.tr.md b/README.tr.md new file mode 100644 index 00000000000..e3055e7a991 --- /dev/null +++ b/README.tr.md @@ -0,0 +1,135 @@ +

+ + + + + OpenCode logo + + +

+

Açık kaynaklı yapay zeka kodlama asistanı.

+

+ Discord + npm + Build status +

+ +

+ English | + 简体中文 | + 繁體中文 | + 한국어 | + Deutsch | + Español | + Français | + Italiano | + Dansk | + 日本語 | + Polski | + Русский | + العربية | + Norsk | + Português (Brasil) | + ไทย | + Türkçe +

+ +[![OpenCode Terminal UI](packages/web/src/assets/lander/screenshot.png)](https://opencode.ai) + +--- + +### Kurulum + +```bash +# YOLO +curl -fsSL https://opencode.ai/install | bash + +# Paket yöneticileri +npm i -g opencode-ai@latest # veya bun/pnpm/yarn +scoop install opencode # Windows +choco install opencode # Windows +brew install anomalyco/tap/opencode # macOS ve Linux (önerilir, her zaman güncel) +brew install opencode # macOS ve Linux (resmi brew formülü, daha az güncellenir) +paru -S opencode-bin # Arch Linux +mise use -g opencode # Tüm işletim sistemleri +nix run nixpkgs#opencode # veya en güncel geliştirme dalı için github:anomalyco/opencode +``` + +> [!TIP] +> Kurulumdan önce 0.1.x'ten eski sürümleri kaldırın. + +### Masaüstü Uygulaması (BETA) + +OpenCode ayrıca masaüstü uygulaması olarak da mevcuttur. Doğrudan [sürüm sayfasından](https://github.com/anomalyco/opencode/releases) veya [opencode.ai/download](https://opencode.ai/download) adresinden indirebilirsiniz. + +| Platform | İndirme | +| --------------------- | ------------------------------------- | +| macOS (Apple Silicon) | `opencode-desktop-darwin-aarch64.dmg` | +| macOS (Intel) | `opencode-desktop-darwin-x64.dmg` | +| Windows | `opencode-desktop-windows-x64.exe` | +| Linux | `.deb`, `.rpm` veya AppImage | + +```bash +# macOS (Homebrew) +brew install --cask opencode-desktop +# Windows (Scoop) +scoop bucket add extras; scoop install extras/opencode-desktop +``` + +#### Kurulum Dizini (Installation Directory) + +Kurulum betiği (install script), kurulum yolu (installation path) için aşağıdaki öncelik sırasını takip eder: + +1. `$OPENCODE_INSTALL_DIR` - Özel kurulum dizini +2. `$XDG_BIN_DIR` - XDG Base Directory Specification uyumlu yol +3. `$HOME/bin` - Standart kullanıcı binary dizini (varsa veya oluşturulabiliyorsa) +4. `$HOME/.opencode/bin` - Varsayılan yedek konum + +```bash +# Örnekler +OPENCODE_INSTALL_DIR=/usr/local/bin curl -fsSL https://opencode.ai/install | bash +XDG_BIN_DIR=$HOME/.local/bin curl -fsSL https://opencode.ai/install | bash +``` + +### Ajanlar + +OpenCode, `Tab` tuşuyla aralarında geçiş yapabileceğiniz iki yerleşik (built-in) ajan içerir. + +- **build** - Varsayılan, geliştirme çalışmaları için tam erişimli ajan +- **plan** - Analiz ve kod keşfi için salt okunur ajan + - Varsayılan olarak dosya düzenlemelerini reddeder + - Bash komutlarını çalıştırmadan önce izin ister + - Tanımadığınız kod tabanlarını keşfetmek veya değişiklikleri planlamak için ideal + +Ayrıca, karmaşık aramalar ve çok adımlı görevler için bir **genel** alt ajan bulunmaktadır. +Bu dahili olarak kullanılır ve mesajlarda `@general` ile çağrılabilir. + +[Ajanlar](https://opencode.ai/docs/agents) hakkında daha fazla bilgi edinin. + +### Dokümantasyon + +OpenCode'u nasıl yapılandıracağınız hakkında daha fazla bilgi için [**dokümantasyonumuza göz atın**](https://opencode.ai/docs). + +### Katkıda Bulunma + +OpenCode'a katkıda bulunmak istiyorsanız, lütfen bir pull request göndermeden önce [katkıda bulunma dokümanlarımızı](./CONTRIBUTING.md) okuyun. + +### OpenCode Üzerine Geliştirme + +OpenCode ile ilgili bir proje üzerinde çalışıyorsanız ve projenizin adının bir parçası olarak "opencode" kullanıyorsanız (örneğin, "opencode-dashboard" veya "opencode-mobile"), lütfen README dosyanıza projenin OpenCode ekibi tarafından geliştirilmediğini ve bizimle hiçbir şekilde bağlantılı olmadığını belirten bir not ekleyin. + +### SSS + +#### Bu Claude Code'dan nasıl farklı? + +Yetenekler açısından Claude Code'a çok benzer. İşte temel farklar: + +- %100 açık kaynak +- Herhangi bir sağlayıcıya bağlı değil. [OpenCode Zen](https://opencode.ai/zen) üzerinden sunduğumuz modelleri önermekle birlikte; OpenCode, Claude, OpenAI, Google veya hatta yerel modellerle kullanılabilir. Modeller geliştikçe aralarındaki farklar kapanacak ve fiyatlar düşecek, bu nedenle sağlayıcıdan bağımsız olmak önemlidir. +- Kurulum gerektirmeyen hazır LSP desteği +- TUI odaklı yaklaşım. OpenCode, neovim kullanıcıları ve [terminal.shop](https://terminal.shop)'un geliştiricileri tarafından geliştirilmektedir; terminalde olabileceklerin sınırlarını zorlayacağız. +- İstemci/sunucu (client/server) mimarisi. Bu, örneğin OpenCode'un bilgisayarınızda çalışması ve siz onu bir mobil uygulamadan uzaktan yönetmenizi sağlar. TUI arayüzü olası istemcilerden sadece biridir. + +--- + +**Topluluğumuza katılın** [Discord](https://discord.gg/opencode) | [X.com](https://x.com/opencode) diff --git a/docs/features/layouts.md b/docs/features/layouts.md new file mode 100644 index 00000000000..89597933206 --- /dev/null +++ b/docs/features/layouts.md @@ -0,0 +1,515 @@ +# Custom Layouts + +OpenCode's TUI layout system lets you customize spacing, padding, and UI element visibility to optimize your workspace for different terminal sizes and preferences. + +## Quick Start + +### Switching Layouts + +Use the `/layout` command to switch between available layouts: + +1. Type `/layout` in the prompt +2. Select from the list: + - **default** - Original OpenCode spacing (comfortable, spacious) + - **dense** - Compact mode for small terminals + - Your custom layouts (if any) + +Or use the command palette: + +- Press `Ctrl+P` (or your configured keybind) +- Search for "Switch layout" +- Select a layout + +### Built-in Layouts + +**default** - The original OpenCode layout + +- Comfortable spacing throughout +- Shows all UI elements (header, footer, agent info) +- Best for: Large terminals (100+ columns, 30+ rows) + +**dense** - Optimized for small terminals + +- Minimal spacing between messages +- Agent/model info on status line (not below input) +- No decorative borders +- Centered cursor in input box (blank line above and below) +- Best for: 80x24 terminals, scaled text, screen readers + +## Creating Custom Layouts + +### Location + +Create layout files in: `~/.config/opencode/layout/` + +Supported formats: + +- `.json` - Standard JSON +- `.jsonc` - JSON with comments (recommended) + +### Basic Structure + +```jsonc +{ + "$schema": "https://opencode.ai/layout.json", + "name": "my-layout", + "description": "Brief description of your layout", + "config": { + // Your configuration here + }, +} +``` + +### Example: Minimal Layout + +Create `~/.config/opencode/layout/minimal.jsonc`: + +```jsonc +{ + "$schema": "https://opencode.ai/layout.json", + "name": "minimal", + "description": "Ultra-compact layout for maximum content", + "config": { + // No spacing between messages + "messageSeparation": 0, + + // No padding in message containers + "userMessagePaddingTop": 0, + "userMessagePaddingBottom": 0, + "assistantMessagePaddingTop": 0, + "assistantMessagePaddingBottom": 0, + "messagePaddingLeft": 1, + + // Minimal container padding + "containerPaddingTop": 0, + "containerPaddingBottom": 0, + "containerPaddingLeft": 1, + "containerPaddingRight": 1, + + // No gaps + "containerGap": 0, + "toolMarginTop": 0, + "agentInfoMarginTop": 0, + + // Minimal indentation + "textIndent": 2, + "toolIndent": 1, + + // Hide UI chrome + "showHeader": false, + "showFooter": false, + "forceSidebarHidden": true, + + // Ultra-compact input box + "showInputAgentInfo": false, + "showInputBorder": false, + "inputAgentInfoPaddingTop": 0, + "inputBoxPaddingTop": 0, + "inputBoxPaddingBottom": 0, + }, +} +``` + +### Example: Comfortable Layout + +Create `~/.config/opencode/layout/comfortable.jsonc`: + +```jsonc +{ + "$schema": "https://opencode.ai/layout.json", + "name": "comfortable", + "description": "Extra breathing room for relaxed reading", + "config": { + // Extra spacing between messages + "messageSeparation": 2, + + // Generous padding + "userMessagePaddingTop": 2, + "userMessagePaddingBottom": 2, + "assistantMessagePaddingTop": 2, + "assistantMessagePaddingBottom": 2, + "messagePaddingLeft": 3, + + // Roomy containers + "containerPaddingTop": 2, + "containerPaddingBottom": 2, + "containerPaddingLeft": 3, + "containerPaddingRight": 3, + + // Generous gaps + "containerGap": 2, + "toolMarginTop": 2, + "agentInfoMarginTop": 2, + + // Clear indentation + "textIndent": 4, + "toolIndent": 3, + + // Show everything + "showHeader": true, + "showFooter": true, + "forceSidebarHidden": false, + + // Spacious input box + "showInputAgentInfo": true, + "showInputBorder": true, + "inputAgentInfoPaddingTop": 2, + "inputBoxPaddingTop": 2, + "inputBoxPaddingBottom": 1, + }, +} +``` + +## Configuration Reference + +### Message Spacing + +**`messageSeparation`** (number, default: 1) + +- Blank lines between consecutive messages (your questions and assistant replies) +- `0` = no spacing, `1` = one blank line, etc. + +**`userMessagePaddingTop`** (number, default: 1) + +- Blank lines above content inside user message boxes + +**`userMessagePaddingBottom`** (number, default: 0) + +- Blank lines below content inside user message boxes + +**`assistantMessagePaddingTop`** (number, default: 2) + +- Blank lines above content inside assistant message boxes + +**`assistantMessagePaddingBottom`** (number, default: 1) + +- Blank lines below content inside assistant message boxes + +**`messagePaddingLeft`** (number, default: 2) + +- Spaces of indentation inside message boxes (both user and assistant) + +### Container Spacing + +**`containerPaddingTop`** (number, default: 1) + +- Blank lines at top of session container + +**`containerPaddingBottom`** (number, default: 1) + +- Blank lines at bottom of session container + +**`containerPaddingLeft`** (number, default: 2) + +- Spaces of indentation at left edge + +**`containerPaddingRight`** (number, default: 2) + +- Spaces of indentation at right edge + +**`containerGap`** (number, default: 1) + +- Vertical spacing between container elements + +### Tool Output Spacing + +**`toolMarginTop`** (number, default: 1) + +- Blank lines above tool output blocks (like bash commands, file reads) + +**`agentInfoMarginTop`** (number, default: 1) + +- Blank lines above agent/model footer (e.g., "▣ Build · anthropic · claude-sonnet-4-5") + +### Text Indentation + +**`textIndent`** (number, default: 3) + +- Spaces to indent main message text + +**`toolIndent`** (number, default: 2) + +- Spaces to indent tool call/output text + +### UI Visibility + +**`showHeader`** (boolean, default: true) + +- Show/hide the session header at top + +**`showFooter`** (boolean, default: true) + +- Show/hide the status footer at bottom (LSP/MCP indicators) + +**`forceSidebarHidden`** (boolean, default: false) + +- Always hide the sidebar (useful for narrow terminals) + +### Input Box Styling + +**`showInputAgentInfo`** (boolean, default: true) + +- Show agent/model info below input box +- When `false`, info moves to status line + +**`showInputBorder`** (boolean, default: true) + +- Show decorative border below input box + +**`inputAgentInfoPaddingTop`** (number, default: 1) + +- Blank lines above agent info (when shown below input) + +**`inputBoxPaddingTop`** (number, default: 1) + +- Blank lines above cursor in input box +- `0` = cursor on first line, `1` = one blank line above cursor, etc. + +**`inputBoxPaddingBottom`** (number, default: 0) + +- Blank lines below cursor in input box + +## Understanding the TUI Elements + +The OpenCode TUI consists of several key elements you can customize: + +### Header (optional) + +- Location: Top of screen +- Content: Session title, navigation info +- Control: `showHeader` + +### Message History + +- Your messages: Gray background, left border in accent color +- Assistant messages: Transparent background, markdown-formatted text +- Tool outputs: Bordered boxes with command/file information +- Controls: `messageSeparation`, `messagePadding*`, `toolMarginTop` + +### Agent/Model Footer + +- Shows: "▣ Build · anthropic · claude-sonnet-4-5 · 2.3s" +- Location: Below each assistant message, or on status line +- Control: `agentInfoMarginTop`, `showInputAgentInfo` + +### Input Box + +- Where you type prompts +- Background: Gray box +- Optional elements: Agent info below, decorative border +- Controls: `inputBoxPadding*`, `showInputAgentInfo`, `showInputBorder` + +### Status Line + +- Shows spinner and status when assistant is thinking +- Shows agent/model info when input box doesn't +- Shows retry information when needed + +### Footer (optional) + +- Location: Bottom of screen +- Content: Directory, LSP count, MCP count +- Control: `showFooter` + +## Use Cases + +### Small Terminal / Screen Reader + +```jsonc +{ + "name": "compact", + "config": { + "messageSeparation": 0, + "userMessagePaddingTop": 0, + "userMessagePaddingBottom": 0, + "assistantMessagePaddingTop": 0, + "assistantMessagePaddingBottom": 0, + "toolMarginTop": 0, + "agentInfoMarginTop": 0, + "showHeader": false, + "showFooter": false, + "showInputAgentInfo": false, + "showInputBorder": false, + "inputBoxPaddingTop": 0, + "inputBoxPaddingBottom": 0, + }, +} +``` + +**Result**: Maximum content, minimal chrome. Every row counts. + +### Ultrawide Terminal + +```jsonc +{ + "name": "ultrawide", + "config": { + "containerPaddingLeft": 20, + "containerPaddingRight": 20, + "messagePaddingLeft": 5, + "textIndent": 6, + "toolIndent": 4, + }, +} +``` + +**Result**: Content centered with generous margins, preventing eye strain from edge-to-edge text. + +### Presentation Mode + +```jsonc +{ + "name": "presentation", + "config": { + "messageSeparation": 3, + "userMessagePaddingTop": 2, + "userMessagePaddingBottom": 2, + "assistantMessagePaddingTop": 2, + "assistantMessagePaddingBottom": 2, + "containerPaddingLeft": 10, + "containerPaddingRight": 10, + "textIndent": 5, + "showFooter": false, + }, +} +``` + +**Result**: Large, clear spacing for demos and screen sharing. + +### Focused Coding + +```jsonc +{ + "name": "focused", + "config": { + "showHeader": false, + "showFooter": false, + "forceSidebarHidden": true, + "messageSeparation": 1, + "toolMarginTop": 0, + "agentInfoMarginTop": 0, + "showInputBorder": false, + }, +} +``` + +**Result**: Hide distractions, show only messages and code. + +## Tips + +### Start with a Built-in Layout + +1. Copy `~/.config/opencode/layout/` from the OpenCode source +2. Find `context/layout/default.jsonc` or `dense.jsonc` +3. Copy to your config directory and modify +4. The inline comments explain each field + +### Iterate Quickly + +1. Edit your layout file +2. Switch to a different layout and back (to reload) + - `/layout` → select different layout → `/layout` → select yours +3. See changes immediately +4. No need to restart OpenCode + +### Common Patterns + +**Want more vertical space?** + +- Set `messageSeparation: 0` +- Set all `*PaddingTop` and `*PaddingBottom` to `0` +- Set `showHeader: false` and `showFooter: false` + +**Want clearer separation?** + +- Increase `messageSeparation` to `2` or `3` +- Increase `toolMarginTop` to `2` +- Increase `agentInfoMarginTop` to `2` + +**Want less horizontal indentation?** + +- Reduce `textIndent` and `toolIndent` +- Reduce `messagePaddingLeft` +- Reduce `containerPaddingLeft` + +**Want centered input cursor?** + +- Set `inputBoxPaddingTop: 1` and `inputBoxPaddingBottom: 1` + +### Validation + +Layouts are validated when loaded. If you: + +- **Misspell a field name**: Warning logged, field ignored +- **Use wrong type** (string instead of number): Warning logged, default used +- **Omit a field**: Default value used +- **Add unknown fields** (future version features): Warning logged, field ignored + +This means layouts are forward and backward compatible - old layouts work with new versions, new layouts degrade gracefully on old versions. + +## Troubleshooting + +**Layout not showing up in `/layout` menu?** + +- Check filename ends in `.json` or `.jsonc` +- Check file is in `~/.config/opencode/layout/` +- Check JSON syntax is valid (use a JSON validator) + +**Layout loads but looks wrong?** + +- Check console for validation warnings +- Compare with built-in layouts in source code +- Try starting with a copy of `default.jsonc` and modifying incrementally + +**Changes not taking effect?** + +- Switch to a different layout and back to reload +- Or restart OpenCode +- Layouts reload when you open the `/layout` dialog + +**Want to reset to defaults?** + +- Use `/layout` and select `default` +- Or remove your custom layout file + +## Sharing Layouts + +If you create a layout others might find useful: + +- Share the `.jsonc` file (includes helpful comments) +- Document the use case and terminal size you optimized for +- Consider contributing to a community layouts repository (if one exists) + +## Advanced: Programmatic Layouts + +For very specific needs, you can: + +- Generate layouts programmatically +- Use shell scripts to switch layouts based on terminal size +- Create per-project layouts (place in `.opencode/layout/` in project root) + +Example bash script to auto-select layout based on terminal height: + +```bash +#!/bin/bash +ROWS=$(tput lines) +if [ $ROWS -lt 30 ]; then + # Small terminal, use dense + echo '{"layout": "dense"}' > ~/.config/opencode/config.json +else + # Normal terminal, use default + echo '{"layout": "default"}' > ~/.config/opencode/config.json +fi +``` + +## Accessibility Notes + +The layout system was designed with accessibility in mind: + +- **Screen readers**: Use minimal layouts to reduce non-content elements +- **Low vision**: Increase spacing and padding for clarity +- **Terminal limitations**: Optimize for your specific terminal size +- **Reduced motion**: No animations, instant layout changes +- **Customization**: Every spacing value is configurable + +If you have accessibility needs not addressed by the current system, please open an issue describing your use case. diff --git a/packages/app/e2e/AGENTS.md b/packages/app/e2e/AGENTS.md new file mode 100644 index 00000000000..59662dbea56 --- /dev/null +++ b/packages/app/e2e/AGENTS.md @@ -0,0 +1,176 @@ +# E2E Testing Guide + +## Build/Lint/Test Commands + +```bash +# Run all e2e tests +bun test:e2e + +# Run specific test file +bun test:e2e -- app/home.spec.ts + +# Run single test by title +bun test:e2e -- -g "home renders and shows core entrypoints" + +# Run tests with UI mode (for debugging) +bun test:e2e:ui + +# Run tests locally with full server setup +bun test:e2e:local + +# View test report +bun test:e2e:report + +# Typecheck +bun typecheck +``` + +## Test Structure + +All tests live in `packages/app/e2e/`: + +``` +e2e/ +├── fixtures.ts # Test fixtures (test, expect, gotoSession, sdk) +├── actions.ts # Reusable action helpers +├── selectors.ts # DOM selectors +├── utils.ts # Utilities (serverUrl, modKey, path helpers) +└── [feature]/ + └── *.spec.ts # Test files +``` + +## Test Patterns + +### Basic Test Structure + +```typescript +import { test, expect } from "../fixtures" +import { promptSelector } from "../selectors" +import { withSession } from "../actions" + +test("test description", async ({ page, sdk, gotoSession }) => { + await gotoSession() // or gotoSession(sessionID) + + // Your test code + await expect(page.locator(promptSelector)).toBeVisible() +}) +``` + +### Using Fixtures + +- `page` - Playwright page +- `sdk` - OpenCode SDK client for API calls +- `gotoSession(sessionID?)` - Navigate to session + +### Helper Functions + +**Actions** (`actions.ts`): + +- `openPalette(page)` - Open command palette +- `openSettings(page)` - Open settings dialog +- `closeDialog(page, dialog)` - Close any dialog +- `openSidebar(page)` / `closeSidebar(page)` - Toggle sidebar +- `withSession(sdk, title, callback)` - Create temp session +- `clickListItem(container, filter)` - Click list item by key/text + +**Selectors** (`selectors.ts`): + +- `promptSelector` - Prompt input +- `terminalSelector` - Terminal panel +- `sessionItemSelector(id)` - Session in sidebar +- `listItemSelector` - Generic list items + +**Utils** (`utils.ts`): + +- `modKey` - Meta (Mac) or Control (Linux/Win) +- `serverUrl` - Backend server URL +- `sessionPath(dir, id?)` - Build session URL + +## Code Style Guidelines + +### Imports + +Always import from `../fixtures`, not `@playwright/test`: + +```typescript +// ✅ Good +import { test, expect } from "../fixtures" + +// ❌ Bad +import { test, expect } from "@playwright/test" +``` + +### Naming Conventions + +- Test files: `feature-name.spec.ts` +- Test names: lowercase, descriptive: `"sidebar can be toggled"` +- Variables: camelCase +- Constants: SCREAMING_SNAKE_CASE + +### Error Handling + +Tests should clean up after themselves: + +```typescript +test("test with cleanup", async ({ page, sdk, gotoSession }) => { + await withSession(sdk, "test session", async (session) => { + await gotoSession(session.id) + // Test code... + }) // Auto-deletes session +}) +``` + +### Timeouts + +Default: 60s per test, 10s per assertion. Override when needed: + +```typescript +test.setTimeout(120_000) // For long LLM operations +test("slow test", async () => { + await expect.poll(() => check(), { timeout: 90_000 }).toBe(true) +}) +``` + +### Selectors + +Use `data-component`, `data-action`, or semantic roles: + +```typescript +// ✅ Good +await page.locator('[data-component="prompt-input"]').click() +await page.getByRole("button", { name: "Open settings" }).click() + +// ❌ Bad +await page.locator(".css-class-name").click() +await page.locator("#id-name").click() +``` + +### Keyboard Shortcuts + +Use `modKey` for cross-platform compatibility: + +```typescript +import { modKey } from "../utils" + +await page.keyboard.press(`${modKey}+B`) // Toggle sidebar +await page.keyboard.press(`${modKey}+Comma`) // Open settings +``` + +## Writing New Tests + +1. Choose appropriate folder or create new one +2. Import from `../fixtures` +3. Use helper functions from `../actions` and `../selectors` +4. Clean up any created resources +5. Use specific selectors (avoid CSS classes) +6. Test one feature per test file + +## Local Development + +For UI debugging, use: + +```bash +bun test:e2e:ui +``` + +This opens Playwright's interactive UI for step-through debugging. diff --git a/packages/app/e2e/actions.ts b/packages/app/e2e/actions.ts new file mode 100644 index 00000000000..3467effa6b3 --- /dev/null +++ b/packages/app/e2e/actions.ts @@ -0,0 +1,421 @@ +import { expect, type Locator, type Page } from "@playwright/test" +import fs from "node:fs/promises" +import os from "node:os" +import path from "node:path" +import { execSync } from "node:child_process" +import { modKey, serverUrl } from "./utils" +import { + sessionItemSelector, + dropdownMenuTriggerSelector, + dropdownMenuContentSelector, + projectMenuTriggerSelector, + projectWorkspacesToggleSelector, + titlebarRightSelector, + popoverBodySelector, + listItemSelector, + listItemKeySelector, + listItemKeyStartsWithSelector, + workspaceItemSelector, + workspaceMenuTriggerSelector, +} from "./selectors" +import type { createSdk } from "./utils" + +export async function defocus(page: Page) { + await page + .evaluate(() => { + const el = document.activeElement + if (el instanceof HTMLElement) el.blur() + }) + .catch(() => undefined) +} + +export async function openPalette(page: Page) { + await defocus(page) + await page.keyboard.press(`${modKey}+P`) + + const dialog = page.getByRole("dialog") + await expect(dialog).toBeVisible() + await expect(dialog.getByRole("textbox").first()).toBeVisible() + return dialog +} + +export async function closeDialog(page: Page, dialog: Locator) { + await page.keyboard.press("Escape") + const closed = await dialog + .waitFor({ state: "detached", timeout: 1500 }) + .then(() => true) + .catch(() => false) + + if (closed) return + + await page.keyboard.press("Escape") + const closedSecond = await dialog + .waitFor({ state: "detached", timeout: 1500 }) + .then(() => true) + .catch(() => false) + + if (closedSecond) return + + await page.locator('[data-component="dialog-overlay"]').click({ position: { x: 5, y: 5 } }) + await expect(dialog).toHaveCount(0) +} + +export async function isSidebarClosed(page: Page) { + const main = page.locator("main") + const classes = (await main.getAttribute("class")) ?? "" + return classes.includes("xl:border-l") +} + +export async function toggleSidebar(page: Page) { + await defocus(page) + await page.keyboard.press(`${modKey}+B`) +} + +export async function openSidebar(page: Page) { + if (!(await isSidebarClosed(page))) return + + const button = page.getByRole("button", { name: /toggle sidebar/i }).first() + const visible = await button + .isVisible() + .then((x) => x) + .catch(() => false) + + if (visible) await button.click() + if (!visible) await toggleSidebar(page) + + const main = page.locator("main") + const opened = await expect(main) + .not.toHaveClass(/xl:border-l/, { timeout: 1500 }) + .then(() => true) + .catch(() => false) + + if (opened) return + + await toggleSidebar(page) + await expect(main).not.toHaveClass(/xl:border-l/) +} + +export async function closeSidebar(page: Page) { + if (await isSidebarClosed(page)) return + + const button = page.getByRole("button", { name: /toggle sidebar/i }).first() + const visible = await button + .isVisible() + .then((x) => x) + .catch(() => false) + + if (visible) await button.click() + if (!visible) await toggleSidebar(page) + + const main = page.locator("main") + const closed = await expect(main) + .toHaveClass(/xl:border-l/, { timeout: 1500 }) + .then(() => true) + .catch(() => false) + + if (closed) return + + await toggleSidebar(page) + await expect(main).toHaveClass(/xl:border-l/) +} + +export async function openSettings(page: Page) { + await defocus(page) + + const dialog = page.getByRole("dialog") + await page.keyboard.press(`${modKey}+Comma`).catch(() => undefined) + + const opened = await dialog + .waitFor({ state: "visible", timeout: 3000 }) + .then(() => true) + .catch(() => false) + + if (opened) return dialog + + await page.getByRole("button", { name: "Settings" }).first().click() + await expect(dialog).toBeVisible() + return dialog +} + +export async function seedProjects(page: Page, input: { directory: string; extra?: string[] }) { + await page.addInitScript( + (args: { directory: string; serverUrl: string; extra: string[] }) => { + const key = "opencode.global.dat:server" + const raw = localStorage.getItem(key) + const parsed = (() => { + if (!raw) return undefined + try { + return JSON.parse(raw) as unknown + } catch { + return undefined + } + })() + + const store = parsed && typeof parsed === "object" ? (parsed as Record) : {} + const list = Array.isArray(store.list) ? store.list : [] + const lastProject = store.lastProject && typeof store.lastProject === "object" ? store.lastProject : {} + const projects = store.projects && typeof store.projects === "object" ? store.projects : {} + const nextProjects = { ...(projects as Record) } + + const add = (origin: string, directory: string) => { + const current = nextProjects[origin] + const items = Array.isArray(current) ? current : [] + const existing = items.filter( + (p): p is { worktree: string; expanded?: boolean } => + !!p && + typeof p === "object" && + "worktree" in p && + typeof (p as { worktree?: unknown }).worktree === "string", + ) + + if (existing.some((p) => p.worktree === directory)) return + nextProjects[origin] = [{ worktree: directory, expanded: true }, ...existing] + } + + const directories = [args.directory, ...args.extra] + for (const directory of directories) { + add("local", directory) + add(args.serverUrl, directory) + } + + localStorage.setItem( + key, + JSON.stringify({ + list, + projects: nextProjects, + lastProject, + }), + ) + }, + { directory: input.directory, serverUrl, extra: input.extra ?? [] }, + ) +} + +export async function createTestProject() { + const root = await fs.mkdtemp(path.join(os.tmpdir(), "opencode-e2e-project-")) + + await fs.writeFile(path.join(root, "README.md"), "# e2e\n") + + execSync("git init", { cwd: root, stdio: "ignore" }) + execSync("git add -A", { cwd: root, stdio: "ignore" }) + execSync('git -c user.name="e2e" -c user.email="e2e@example.com" commit -m "init" --allow-empty', { + cwd: root, + stdio: "ignore", + }) + + return root +} + +export async function cleanupTestProject(directory: string) { + await fs.rm(directory, { recursive: true, force: true }).catch(() => undefined) +} + +export function sessionIDFromUrl(url: string) { + const match = /\/session\/([^/?#]+)/.exec(url) + return match?.[1] +} + +export async function hoverSessionItem(page: Page, sessionID: string) { + const sessionEl = page.locator(sessionItemSelector(sessionID)).first() + await expect(sessionEl).toBeVisible() + await sessionEl.hover() + return sessionEl +} + +export async function openSessionMoreMenu(page: Page, sessionID: string) { + await expect(page).toHaveURL(new RegExp(`/session/${sessionID}(?:[/?#]|$)`)) + + const scroller = page.locator(".session-scroller").first() + await expect(scroller).toBeVisible() + await expect(scroller.getByRole("heading", { level: 1 }).first()).toBeVisible({ timeout: 30_000 }) + + const menu = page + .locator(dropdownMenuContentSelector) + .filter({ has: page.getByRole("menuitem", { name: /rename/i }) }) + .filter({ has: page.getByRole("menuitem", { name: /archive/i }) }) + .filter({ has: page.getByRole("menuitem", { name: /delete/i }) }) + .first() + + const opened = await menu + .isVisible() + .then((x) => x) + .catch(() => false) + + if (opened) return menu + + const menuTrigger = scroller.getByRole("button", { name: /more options/i }).first() + await expect(menuTrigger).toBeVisible() + await menuTrigger.click() + + await expect(menu).toBeVisible() + return menu +} + +export async function clickMenuItem(menu: Locator, itemName: string | RegExp, options?: { force?: boolean }) { + const item = menu.getByRole("menuitem").filter({ hasText: itemName }).first() + await expect(item).toBeVisible() + await item.click({ force: options?.force }) +} + +export async function confirmDialog(page: Page, buttonName: string | RegExp) { + const dialog = page.getByRole("dialog").first() + await expect(dialog).toBeVisible() + + const button = dialog.getByRole("button").filter({ hasText: buttonName }).first() + await expect(button).toBeVisible() + await button.click() +} + +export async function openSharePopover(page: Page) { + const rightSection = page.locator(titlebarRightSelector) + const shareButton = rightSection.getByRole("button", { name: "Share" }).first() + await expect(shareButton).toBeVisible() + + const popoverBody = page + .locator(popoverBodySelector) + .filter({ has: page.getByRole("button", { name: /^(Publish|Unpublish)$/ }) }) + .first() + + const opened = await popoverBody + .isVisible() + .then((x) => x) + .catch(() => false) + + if (!opened) { + await shareButton.click() + await expect(popoverBody).toBeVisible() + } + return { rightSection, popoverBody } +} + +export async function clickPopoverButton(page: Page, buttonName: string | RegExp) { + const button = page.getByRole("button").filter({ hasText: buttonName }).first() + await expect(button).toBeVisible() + await button.click() +} + +export async function clickListItem( + container: Locator | Page, + filter: string | RegExp | { key?: string; text?: string | RegExp; keyStartsWith?: string }, +): Promise { + let item: Locator + + if (typeof filter === "string" || filter instanceof RegExp) { + item = container.locator(listItemSelector).filter({ hasText: filter }).first() + } else if (filter.keyStartsWith) { + item = container.locator(listItemKeyStartsWithSelector(filter.keyStartsWith)).first() + } else if (filter.key) { + item = container.locator(listItemKeySelector(filter.key)).first() + } else if (filter.text) { + item = container.locator(listItemSelector).filter({ hasText: filter.text }).first() + } else { + throw new Error("Invalid filter provided to clickListItem") + } + + await expect(item).toBeVisible() + await item.click() + return item +} + +export async function withSession( + sdk: ReturnType, + title: string, + callback: (session: { id: string; title: string }) => Promise, +): Promise { + const session = await sdk.session.create({ title }).then((r) => r.data) + if (!session?.id) throw new Error("Session create did not return an id") + + try { + return await callback(session) + } finally { + await sdk.session.delete({ sessionID: session.id }).catch(() => undefined) + } +} + +export async function openStatusPopover(page: Page) { + await defocus(page) + + const rightSection = page.locator(titlebarRightSelector) + const trigger = rightSection.getByRole("button", { name: /status/i }).first() + + const popoverBody = page.locator(popoverBodySelector).filter({ has: page.locator('[data-component="tabs"]') }) + + const opened = await popoverBody + .isVisible() + .then((x) => x) + .catch(() => false) + + if (!opened) { + await expect(trigger).toBeVisible() + await trigger.click() + await expect(popoverBody).toBeVisible() + } + + return { rightSection, popoverBody } +} + +export async function openProjectMenu(page: Page, projectSlug: string) { + const trigger = page.locator(projectMenuTriggerSelector(projectSlug)).first() + await expect(trigger).toHaveCount(1) + + await trigger.focus() + await page.keyboard.press("Enter") + + const menu = page.locator(dropdownMenuContentSelector).first() + const opened = await menu + .waitFor({ state: "visible", timeout: 1500 }) + .then(() => true) + .catch(() => false) + + if (opened) { + const viewport = page.viewportSize() + const x = viewport ? Math.max(viewport.width - 5, 0) : 1200 + const y = viewport ? Math.max(viewport.height - 5, 0) : 800 + await page.mouse.move(x, y) + return menu + } + + await trigger.click({ force: true }) + + await expect(menu).toBeVisible() + + const viewport = page.viewportSize() + const x = viewport ? Math.max(viewport.width - 5, 0) : 1200 + const y = viewport ? Math.max(viewport.height - 5, 0) : 800 + await page.mouse.move(x, y) + return menu +} + +export async function setWorkspacesEnabled(page: Page, projectSlug: string, enabled: boolean) { + const current = await page + .getByRole("button", { name: "New workspace" }) + .first() + .isVisible() + .then((x) => x) + .catch(() => false) + + if (current === enabled) return + + await openProjectMenu(page, projectSlug) + + const toggle = page.locator(projectWorkspacesToggleSelector(projectSlug)).first() + await expect(toggle).toBeVisible() + await toggle.click({ force: true }) + + const expected = enabled ? "New workspace" : "New session" + await expect(page.getByRole("button", { name: expected }).first()).toBeVisible() +} + +export async function openWorkspaceMenu(page: Page, workspaceSlug: string) { + const item = page.locator(workspaceItemSelector(workspaceSlug)).first() + await expect(item).toBeVisible() + await item.hover() + + const trigger = page.locator(workspaceMenuTriggerSelector(workspaceSlug)).first() + await expect(trigger).toBeVisible() + await trigger.click({ force: true }) + + const menu = page.locator(dropdownMenuContentSelector).first() + await expect(menu).toBeVisible() + return menu +} diff --git a/packages/app/e2e/app/home.spec.ts b/packages/app/e2e/app/home.spec.ts new file mode 100644 index 00000000000..f21dc40ec21 --- /dev/null +++ b/packages/app/e2e/app/home.spec.ts @@ -0,0 +1,21 @@ +import { test, expect } from "../fixtures" +import { serverName } from "../utils" + +test("home renders and shows core entrypoints", async ({ page }) => { + await page.goto("/") + + await expect(page.getByRole("button", { name: "Open project" }).first()).toBeVisible() + await expect(page.getByRole("button", { name: serverName })).toBeVisible() +}) + +test("server picker dialog opens from home", async ({ page }) => { + await page.goto("/") + + const trigger = page.getByRole("button", { name: serverName }) + await expect(trigger).toBeVisible() + await trigger.click() + + const dialog = page.getByRole("dialog") + await expect(dialog).toBeVisible() + await expect(dialog.getByRole("textbox").first()).toBeVisible() +}) diff --git a/packages/app/e2e/app/navigation.spec.ts b/packages/app/e2e/app/navigation.spec.ts new file mode 100644 index 00000000000..328c950df36 --- /dev/null +++ b/packages/app/e2e/app/navigation.spec.ts @@ -0,0 +1,10 @@ +import { test, expect } from "../fixtures" +import { promptSelector } from "../selectors" +import { dirPath } from "../utils" + +test("project route redirects to /session", async ({ page, directory, slug }) => { + await page.goto(dirPath(directory)) + + await expect(page).toHaveURL(new RegExp(`/${slug}/session`)) + await expect(page.locator(promptSelector)).toBeVisible() +}) diff --git a/packages/app/e2e/app/palette.spec.ts b/packages/app/e2e/app/palette.spec.ts new file mode 100644 index 00000000000..3ccfd7a9250 --- /dev/null +++ b/packages/app/e2e/app/palette.spec.ts @@ -0,0 +1,11 @@ +import { test, expect } from "../fixtures" +import { openPalette } from "../actions" + +test("search palette opens and closes", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openPalette(page) + + await page.keyboard.press("Escape") + await expect(dialog).toHaveCount(0) +}) diff --git a/packages/app/e2e/app/server-default.spec.ts b/packages/app/e2e/app/server-default.spec.ts new file mode 100644 index 00000000000..adbc83473be --- /dev/null +++ b/packages/app/e2e/app/server-default.spec.ts @@ -0,0 +1,55 @@ +import { test, expect } from "../fixtures" +import { serverName, serverUrl } from "../utils" +import { clickListItem, closeDialog, clickMenuItem } from "../actions" + +const DEFAULT_SERVER_URL_KEY = "opencode.settings.dat:defaultServerUrl" + +test("can set a default server on web", async ({ page, gotoSession }) => { + await page.addInitScript((key: string) => { + try { + localStorage.removeItem(key) + } catch { + return + } + }, DEFAULT_SERVER_URL_KEY) + + await gotoSession() + + const status = page.getByRole("button", { name: "Status" }) + await expect(status).toBeVisible() + const popover = page.locator('[data-component="popover-content"]').filter({ hasText: "Manage servers" }) + + const ensurePopoverOpen = async () => { + if (await popover.isVisible()) return + await status.click() + await expect(popover).toBeVisible() + } + + await ensurePopoverOpen() + await popover.getByRole("button", { name: "Manage servers" }).click() + + const dialog = page.getByRole("dialog") + await expect(dialog).toBeVisible() + + const row = dialog.locator('[data-slot="list-item"]').filter({ hasText: serverName }).first() + await expect(row).toBeVisible() + + const menuTrigger = row.locator('[data-slot="dropdown-menu-trigger"]').first() + await expect(menuTrigger).toBeVisible() + await menuTrigger.click({ force: true }) + + const menu = page.locator('[data-component="dropdown-menu-content"]').first() + await expect(menu).toBeVisible() + await clickMenuItem(menu, /set as default/i) + + await expect.poll(() => page.evaluate((key) => localStorage.getItem(key), DEFAULT_SERVER_URL_KEY)).toBe(serverUrl) + await expect(row.getByText("Default", { exact: true })).toBeVisible() + + await closeDialog(page, dialog) + + await ensurePopoverOpen() + + const serverRow = popover.locator("button").filter({ hasText: serverName }).first() + await expect(serverRow).toBeVisible() + await expect(serverRow.getByText("Default", { exact: true })).toBeVisible() +}) diff --git a/packages/app/e2e/app/session.spec.ts b/packages/app/e2e/app/session.spec.ts new file mode 100644 index 00000000000..c7fdfdc542b --- /dev/null +++ b/packages/app/e2e/app/session.spec.ts @@ -0,0 +1,16 @@ +import { test, expect } from "../fixtures" +import { promptSelector } from "../selectors" +import { withSession } from "../actions" + +test("can open an existing session and type into the prompt", async ({ page, sdk, gotoSession }) => { + const title = `e2e smoke ${Date.now()}` + + await withSession(sdk, title, async (session) => { + await gotoSession(session.id) + + const prompt = page.locator(promptSelector) + await prompt.click() + await page.keyboard.type("hello from e2e") + await expect(prompt).toContainText("hello from e2e") + }) +}) diff --git a/packages/app/e2e/app/titlebar-history.spec.ts b/packages/app/e2e/app/titlebar-history.spec.ts new file mode 100644 index 00000000000..9d6091176ec --- /dev/null +++ b/packages/app/e2e/app/titlebar-history.spec.ts @@ -0,0 +1,124 @@ +import { test, expect } from "../fixtures" +import { defocus, openSidebar, withSession } from "../actions" +import { promptSelector } from "../selectors" +import { modKey } from "../utils" + +test("titlebar back/forward navigates between sessions", async ({ page, slug, sdk, gotoSession }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + const stamp = Date.now() + + await withSession(sdk, `e2e titlebar history 1 ${stamp}`, async (one) => { + await withSession(sdk, `e2e titlebar history 2 ${stamp}`, async (two) => { + await gotoSession(one.id) + + await openSidebar(page) + + const link = page.locator(`[data-session-id="${two.id}"] a`).first() + await expect(link).toBeVisible() + await link.scrollIntoViewIfNeeded() + await link.click() + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${two.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + + const back = page.getByRole("button", { name: "Back" }) + const forward = page.getByRole("button", { name: "Forward" }) + + await expect(back).toBeVisible() + await expect(back).toBeEnabled() + await back.click() + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${one.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + + await expect(forward).toBeVisible() + await expect(forward).toBeEnabled() + await forward.click() + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${two.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + }) + }) +}) + +test("titlebar forward is cleared after branching history from sidebar", async ({ page, slug, sdk, gotoSession }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + const stamp = Date.now() + + await withSession(sdk, `e2e titlebar history a ${stamp}`, async (a) => { + await withSession(sdk, `e2e titlebar history b ${stamp}`, async (b) => { + await withSession(sdk, `e2e titlebar history c ${stamp}`, async (c) => { + await gotoSession(a.id) + + await openSidebar(page) + + const second = page.locator(`[data-session-id="${b.id}"] a`).first() + await expect(second).toBeVisible() + await second.scrollIntoViewIfNeeded() + await second.click() + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${b.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + + const back = page.getByRole("button", { name: "Back" }) + const forward = page.getByRole("button", { name: "Forward" }) + + await expect(back).toBeVisible() + await expect(back).toBeEnabled() + await back.click() + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${a.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + + await openSidebar(page) + + const third = page.locator(`[data-session-id="${c.id}"] a`).first() + await expect(third).toBeVisible() + await third.scrollIntoViewIfNeeded() + await third.click() + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${c.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + + await expect(forward).toBeVisible() + await expect(forward).toBeDisabled() + }) + }) + }) +}) + +test("keyboard shortcuts navigate titlebar history", async ({ page, slug, sdk, gotoSession }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + const stamp = Date.now() + + await withSession(sdk, `e2e titlebar shortcuts 1 ${stamp}`, async (one) => { + await withSession(sdk, `e2e titlebar shortcuts 2 ${stamp}`, async (two) => { + await gotoSession(one.id) + + await openSidebar(page) + + const link = page.locator(`[data-session-id="${two.id}"] a`).first() + await expect(link).toBeVisible() + await link.scrollIntoViewIfNeeded() + await link.click() + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${two.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + + await defocus(page) + await page.keyboard.press(`${modKey}+[`) + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${one.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + + await defocus(page) + await page.keyboard.press(`${modKey}+]`) + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${two.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + }) + }) +}) diff --git a/packages/app/e2e/files/file-open.spec.ts b/packages/app/e2e/files/file-open.spec.ts new file mode 100644 index 00000000000..3c636d748a7 --- /dev/null +++ b/packages/app/e2e/files/file-open.spec.ts @@ -0,0 +1,18 @@ +import { test, expect } from "../fixtures" +import { openPalette, clickListItem } from "../actions" + +test("can open a file tab from the search palette", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openPalette(page) + + const input = dialog.getByRole("textbox").first() + await input.fill("package.json") + + await clickListItem(dialog, { keyStartsWith: "file:" }) + + await expect(dialog).toHaveCount(0) + + const tabs = page.locator('[data-component="tabs"][data-variant="normal"]') + await expect(tabs.locator('[data-slot="tabs-trigger"]').first()).toBeVisible() +}) diff --git a/packages/app/e2e/files/file-tree.spec.ts b/packages/app/e2e/files/file-tree.spec.ts new file mode 100644 index 00000000000..321d96af57a --- /dev/null +++ b/packages/app/e2e/files/file-tree.spec.ts @@ -0,0 +1,49 @@ +import { test, expect } from "../fixtures" + +test("file tree can expand folders and open a file", async ({ page, gotoSession }) => { + await gotoSession() + + const toggle = page.getByRole("button", { name: "Toggle file tree" }) + const panel = page.locator("#file-tree-panel") + const treeTabs = panel.locator('[data-component="tabs"][data-variant="pill"][data-scope="filetree"]') + + await expect(toggle).toBeVisible() + if ((await toggle.getAttribute("aria-expanded")) !== "true") await toggle.click() + await expect(toggle).toHaveAttribute("aria-expanded", "true") + await expect(panel).toBeVisible() + await expect(treeTabs).toBeVisible() + + const allTab = treeTabs.getByRole("tab", { name: /^all files$/i }) + await expect(allTab).toBeVisible() + await allTab.click() + await expect(allTab).toHaveAttribute("aria-selected", "true") + + const tree = treeTabs.locator('[data-slot="tabs-content"]:not([hidden])') + await expect(tree).toBeVisible() + + const expand = async (name: string) => { + const folder = tree.getByRole("button", { name, exact: true }).first() + await expect(folder).toBeVisible() + await expect(folder).toHaveAttribute("aria-expanded", /true|false/) + if ((await folder.getAttribute("aria-expanded")) === "false") await folder.click() + await expect(folder).toHaveAttribute("aria-expanded", "true") + } + + await expand("packages") + await expand("app") + await expand("src") + await expand("components") + + const file = tree.getByRole("button", { name: "file-tree.tsx", exact: true }).first() + await expect(file).toBeVisible() + await file.click() + + const tab = page.getByRole("tab", { name: "file-tree.tsx" }) + await expect(tab).toBeVisible() + await tab.click() + await expect(tab).toHaveAttribute("aria-selected", "true") + + const code = page.locator('[data-component="code"]').first() + await expect(code).toBeVisible() + await expect(code).toContainText("export default function FileTree") +}) diff --git a/packages/app/e2e/files/file-viewer.spec.ts b/packages/app/e2e/files/file-viewer.spec.ts new file mode 100644 index 00000000000..52838449759 --- /dev/null +++ b/packages/app/e2e/files/file-viewer.spec.ts @@ -0,0 +1,26 @@ +import { test, expect } from "../fixtures" +import { openPalette, clickListItem } from "../actions" + +test("smoke file viewer renders real file content", async ({ page, gotoSession }) => { + await gotoSession() + + const sep = process.platform === "win32" ? "\\" : "/" + const file = ["packages", "app", "package.json"].join(sep) + + const dialog = await openPalette(page) + + const input = dialog.getByRole("textbox").first() + await input.fill(file) + + await clickListItem(dialog, { text: /packages.*app.*package.json/ }) + + await expect(dialog).toHaveCount(0) + + const tab = page.getByRole("tab", { name: "package.json" }) + await expect(tab).toBeVisible() + await tab.click() + + const code = page.locator('[data-component="code"]').first() + await expect(code).toBeVisible() + await expect(code.getByText("@opencode-ai/app")).toBeVisible() +}) diff --git a/packages/app/e2e/models/model-picker.spec.ts b/packages/app/e2e/models/model-picker.spec.ts new file mode 100644 index 00000000000..01e72464cc5 --- /dev/null +++ b/packages/app/e2e/models/model-picker.spec.ts @@ -0,0 +1,42 @@ +import { test, expect } from "../fixtures" +import { promptSelector } from "../selectors" +import { clickListItem } from "../actions" + +test("smoke model selection updates prompt footer", async ({ page, gotoSession }) => { + await gotoSession() + + await page.locator(promptSelector).click() + await page.keyboard.type("/model") + + const command = page.locator('[data-slash-id="model.choose"]') + await expect(command).toBeVisible() + await command.hover() + + await page.keyboard.press("Enter") + + const dialog = page.getByRole("dialog") + await expect(dialog).toBeVisible() + + const input = dialog.getByRole("textbox").first() + + const selected = dialog.locator('[data-slot="list-item"][data-selected="true"]').first() + await expect(selected).toBeVisible() + + const other = dialog.locator('[data-slot="list-item"]:not([data-selected="true"])').first() + const target = (await other.count()) > 0 ? other : selected + + const key = await target.getAttribute("data-key") + if (!key) throw new Error("Failed to resolve model key from list item") + + const name = (await target.locator("span").first().innerText()).trim() + const model = key.split(":").slice(1).join(":") + + await input.fill(model) + + await clickListItem(dialog, { key }) + + await expect(dialog).toHaveCount(0) + + const form = page.locator(promptSelector).locator("xpath=ancestor::form[1]") + await expect(form.locator('[data-component="button"]').filter({ hasText: name }).first()).toBeVisible() +}) diff --git a/packages/app/e2e/models/models-visibility.spec.ts b/packages/app/e2e/models/models-visibility.spec.ts new file mode 100644 index 00000000000..c6991117937 --- /dev/null +++ b/packages/app/e2e/models/models-visibility.spec.ts @@ -0,0 +1,61 @@ +import { test, expect } from "../fixtures" +import { promptSelector } from "../selectors" +import { closeDialog, openSettings, clickListItem } from "../actions" + +test("hiding a model removes it from the model picker", async ({ page, gotoSession }) => { + await gotoSession() + + await page.locator(promptSelector).click() + await page.keyboard.type("/model") + + const command = page.locator('[data-slash-id="model.choose"]') + await expect(command).toBeVisible() + await command.hover() + await page.keyboard.press("Enter") + + const picker = page.getByRole("dialog") + await expect(picker).toBeVisible() + + const target = picker.locator('[data-slot="list-item"]').first() + await expect(target).toBeVisible() + + const key = await target.getAttribute("data-key") + if (!key) throw new Error("Failed to resolve model key from list item") + + const name = (await target.locator("span").first().innerText()).trim() + if (!name) throw new Error("Failed to resolve model name from list item") + + await page.keyboard.press("Escape") + await expect(picker).toHaveCount(0) + + const settings = await openSettings(page) + + await settings.getByRole("tab", { name: "Models" }).click() + const search = settings.getByPlaceholder("Search models") + await expect(search).toBeVisible() + await search.fill(name) + + const toggle = settings.locator('[data-component="switch"]').filter({ hasText: name }).first() + const input = toggle.locator('[data-slot="switch-input"]') + await expect(toggle).toBeVisible() + await expect(input).toHaveAttribute("aria-checked", "true") + await toggle.locator('[data-slot="switch-control"]').click() + await expect(input).toHaveAttribute("aria-checked", "false") + + await closeDialog(page, settings) + + await page.locator(promptSelector).click() + await page.keyboard.type("/model") + await expect(command).toBeVisible() + await command.hover() + await page.keyboard.press("Enter") + + const pickerAgain = page.getByRole("dialog") + await expect(pickerAgain).toBeVisible() + await expect(pickerAgain.locator('[data-slot="list-item"]').first()).toBeVisible() + + await expect(pickerAgain.locator(`[data-slot="list-item"][data-key="${key}"]`)).toHaveCount(0) + + await page.keyboard.press("Escape") + await expect(pickerAgain).toHaveCount(0) +}) diff --git a/packages/app/e2e/projects/project-edit.spec.ts b/packages/app/e2e/projects/project-edit.spec.ts new file mode 100644 index 00000000000..4a286fea75f --- /dev/null +++ b/packages/app/e2e/projects/project-edit.spec.ts @@ -0,0 +1,53 @@ +import { test, expect } from "../fixtures" +import { openSidebar } from "../actions" + +test("dialog edit project updates name and startup script", async ({ page, withProject }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + await withProject(async () => { + await openSidebar(page) + + const open = async () => { + const header = page.locator(".group\\/project").first() + await header.hover() + const trigger = header.getByRole("button", { name: "More options" }).first() + await expect(trigger).toBeVisible() + await trigger.click({ force: true }) + + const menu = page.locator('[data-component="dropdown-menu-content"]').first() + await expect(menu).toBeVisible() + + const editItem = menu.getByRole("menuitem", { name: "Edit" }).first() + await expect(editItem).toBeVisible() + await editItem.click({ force: true }) + + const dialog = page.getByRole("dialog") + await expect(dialog).toBeVisible() + await expect(dialog.getByRole("heading", { level: 2 })).toHaveText("Edit project") + return dialog + } + + const name = `e2e project ${Date.now()}` + const startup = `echo e2e_${Date.now()}` + + const dialog = await open() + + const nameInput = dialog.getByLabel("Name") + await nameInput.fill(name) + + const startupInput = dialog.getByLabel("Workspace startup script") + await startupInput.fill(startup) + + await dialog.getByRole("button", { name: "Save" }).click() + await expect(dialog).toHaveCount(0) + + const header = page.locator(".group\\/project").first() + await expect(header).toContainText(name) + + const reopened = await open() + await expect(reopened.getByLabel("Name")).toHaveValue(name) + await expect(reopened.getByLabel("Workspace startup script")).toHaveValue(startup) + await reopened.getByRole("button", { name: "Cancel" }).click() + await expect(reopened).toHaveCount(0) + }) +}) diff --git a/packages/app/e2e/projects/projects-close.spec.ts b/packages/app/e2e/projects/projects-close.spec.ts new file mode 100644 index 00000000000..4b39ed82c37 --- /dev/null +++ b/packages/app/e2e/projects/projects-close.spec.ts @@ -0,0 +1,72 @@ +import { test, expect } from "../fixtures" +import { createTestProject, cleanupTestProject, openSidebar, clickMenuItem, openProjectMenu } from "../actions" +import { projectCloseHoverSelector, projectSwitchSelector } from "../selectors" +import { dirSlug } from "../utils" + +test("can close a project via hover card close button", async ({ page, withProject }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + const other = await createTestProject() + const otherSlug = dirSlug(other) + + try { + await withProject( + async () => { + await openSidebar(page) + + const otherButton = page.locator(projectSwitchSelector(otherSlug)).first() + await expect(otherButton).toBeVisible() + await otherButton.hover() + + const close = page.locator(projectCloseHoverSelector(otherSlug)).first() + await expect(close).toBeVisible() + await close.click() + + await expect(otherButton).toHaveCount(0) + }, + { extra: [other] }, + ) + } finally { + await cleanupTestProject(other) + } +}) + +test("closing active project navigates to another open project", async ({ page, withProject }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + const other = await createTestProject() + const otherSlug = dirSlug(other) + + try { + await withProject( + async ({ slug }) => { + await openSidebar(page) + + const otherButton = page.locator(projectSwitchSelector(otherSlug)).first() + await expect(otherButton).toBeVisible() + await otherButton.click() + + await expect(page).toHaveURL(new RegExp(`/${otherSlug}/session`)) + + const menu = await openProjectMenu(page, otherSlug) + + await clickMenuItem(menu, /^Close$/i, { force: true }) + + await expect + .poll(() => { + const pathname = new URL(page.url()).pathname + if (new RegExp(`^/${slug}/session(?:/[^/]+)?/?$`).test(pathname)) return "project" + if (pathname === "/") return "home" + return "" + }) + .toMatch(/^(project|home)$/) + + await expect(page).not.toHaveURL(new RegExp(`/${otherSlug}/session(?:[/?#]|$)`)) + await expect(otherButton).toHaveCount(0) + }, + { extra: [other] }, + ) + } finally { + await cleanupTestProject(other) + } +}) diff --git a/packages/app/e2e/projects/projects-switch.spec.ts b/packages/app/e2e/projects/projects-switch.spec.ts new file mode 100644 index 00000000000..a817412cde2 --- /dev/null +++ b/packages/app/e2e/projects/projects-switch.spec.ts @@ -0,0 +1,35 @@ +import { test, expect } from "../fixtures" +import { defocus, createTestProject, cleanupTestProject } from "../actions" +import { projectSwitchSelector } from "../selectors" +import { dirSlug } from "../utils" + +test("can switch between projects from sidebar", async ({ page, withProject }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + const other = await createTestProject() + const otherSlug = dirSlug(other) + + try { + await withProject( + async ({ directory }) => { + await defocus(page) + + const currentSlug = dirSlug(directory) + const otherButton = page.locator(projectSwitchSelector(otherSlug)).first() + await expect(otherButton).toBeVisible() + await otherButton.click() + + await expect(page).toHaveURL(new RegExp(`/${otherSlug}/session`)) + + const currentButton = page.locator(projectSwitchSelector(currentSlug)).first() + await expect(currentButton).toBeVisible() + await currentButton.click() + + await expect(page).toHaveURL(new RegExp(`/${currentSlug}/session`)) + }, + { extra: [other] }, + ) + } finally { + await cleanupTestProject(other) + } +}) diff --git a/packages/app/e2e/projects/workspace-new-session.spec.ts b/packages/app/e2e/projects/workspace-new-session.spec.ts new file mode 100644 index 00000000000..5af314cafae --- /dev/null +++ b/packages/app/e2e/projects/workspace-new-session.spec.ts @@ -0,0 +1,140 @@ +import { base64Decode } from "@opencode-ai/util/encode" +import type { Page } from "@playwright/test" +import { test, expect } from "../fixtures" +import { cleanupTestProject, openSidebar, sessionIDFromUrl, setWorkspacesEnabled } from "../actions" +import { promptSelector, workspaceItemSelector, workspaceNewSessionSelector } from "../selectors" +import { createSdk } from "../utils" + +function slugFromUrl(url: string) { + return /\/([^/]+)\/session(?:\/|$)/.exec(url)?.[1] ?? "" +} + +async function waitWorkspaceReady(page: Page, slug: string) { + await openSidebar(page) + await expect + .poll( + async () => { + const item = page.locator(workspaceItemSelector(slug)).first() + try { + await item.hover({ timeout: 500 }) + return true + } catch { + return false + } + }, + { timeout: 60_000 }, + ) + .toBe(true) +} + +async function createWorkspace(page: Page, root: string, seen: string[]) { + await openSidebar(page) + await page.getByRole("button", { name: "New workspace" }).first().click() + + await expect + .poll( + () => { + const slug = slugFromUrl(page.url()) + if (!slug) return "" + if (slug === root) return "" + if (seen.includes(slug)) return "" + return slug + }, + { timeout: 45_000 }, + ) + .not.toBe("") + + const slug = slugFromUrl(page.url()) + const directory = base64Decode(slug) + if (!directory) throw new Error(`Failed to decode workspace slug: ${slug}`) + return { slug, directory } +} + +async function openWorkspaceNewSession(page: Page, slug: string) { + await waitWorkspaceReady(page, slug) + + const item = page.locator(workspaceItemSelector(slug)).first() + await item.hover() + + const button = page.locator(workspaceNewSessionSelector(slug)).first() + await expect(button).toBeVisible() + await button.click({ force: true }) + + await expect.poll(() => slugFromUrl(page.url())).toBe(slug) + await expect(page).toHaveURL(new RegExp(`/${slug}/session(?:[/?#]|$)`)) +} + +async function createSessionFromWorkspace(page: Page, slug: string, text: string) { + await openWorkspaceNewSession(page, slug) + + const prompt = page.locator(promptSelector) + await expect(prompt).toBeVisible() + await prompt.click() + await page.keyboard.type(text) + await page.keyboard.press("Enter") + + await expect.poll(() => slugFromUrl(page.url())).toBe(slug) + await expect(page).toHaveURL(new RegExp(`/${slug}/session/[^/?#]+`), { timeout: 30_000 }) + + const sessionID = sessionIDFromUrl(page.url()) + if (!sessionID) throw new Error(`Failed to parse session id from url: ${page.url()}`) + return sessionID +} + +async function sessionDirectory(directory: string, sessionID: string) { + const info = await createSdk(directory) + .session.get({ sessionID }) + .then((x) => x.data) + .catch(() => undefined) + if (!info) return "" + return info.directory +} + +test("new sessions from sidebar workspace actions stay in selected workspace", async ({ page, withProject }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + await withProject(async ({ directory, slug: root }) => { + const workspaces = [] as { slug: string; directory: string }[] + const sessions = [] as string[] + + try { + await openSidebar(page) + await setWorkspacesEnabled(page, root, true) + + const first = await createWorkspace(page, root, []) + workspaces.push(first) + await waitWorkspaceReady(page, first.slug) + + const second = await createWorkspace(page, root, [first.slug]) + workspaces.push(second) + await waitWorkspaceReady(page, second.slug) + + const firstSession = await createSessionFromWorkspace(page, first.slug, `workspace one ${Date.now()}`) + sessions.push(firstSession) + + const secondSession = await createSessionFromWorkspace(page, second.slug, `workspace two ${Date.now()}`) + sessions.push(secondSession) + + const thirdSession = await createSessionFromWorkspace(page, first.slug, `workspace one again ${Date.now()}`) + sessions.push(thirdSession) + + await expect.poll(() => sessionDirectory(first.directory, firstSession)).toBe(first.directory) + await expect.poll(() => sessionDirectory(second.directory, secondSession)).toBe(second.directory) + await expect.poll(() => sessionDirectory(first.directory, thirdSession)).toBe(first.directory) + } finally { + const dirs = [directory, ...workspaces.map((workspace) => workspace.directory)] + await Promise.all( + sessions.map((sessionID) => + Promise.all( + dirs.map((dir) => + createSdk(dir) + .session.delete({ sessionID }) + .catch(() => undefined), + ), + ), + ), + ) + await Promise.all(workspaces.map((workspace) => cleanupTestProject(workspace.directory))) + } + }) +}) diff --git a/packages/app/e2e/projects/workspaces.spec.ts b/packages/app/e2e/projects/workspaces.spec.ts new file mode 100644 index 00000000000..071c398b22d --- /dev/null +++ b/packages/app/e2e/projects/workspaces.spec.ts @@ -0,0 +1,375 @@ +import { base64Decode } from "@opencode-ai/util/encode" +import fs from "node:fs/promises" +import os from "node:os" +import path from "node:path" +import type { Page } from "@playwright/test" + +import { test, expect } from "../fixtures" + +test.describe.configure({ mode: "serial" }) +import { + cleanupTestProject, + clickMenuItem, + confirmDialog, + openProjectMenu, + openSidebar, + openWorkspaceMenu, + setWorkspacesEnabled, +} from "../actions" +import { + inlineInputSelector, + projectSwitchSelector, + projectWorkspacesToggleSelector, + workspaceItemSelector, +} from "../selectors" +import { dirSlug } from "../utils" + +function slugFromUrl(url: string) { + return /\/([^/]+)\/session(?:\/|$)/.exec(url)?.[1] ?? "" +} + +async function setupWorkspaceTest(page: Page, project: { slug: string }) { + const rootSlug = project.slug + await openSidebar(page) + + await setWorkspacesEnabled(page, rootSlug, true) + + await page.getByRole("button", { name: "New workspace" }).first().click() + await expect + .poll( + () => { + const slug = slugFromUrl(page.url()) + return slug.length > 0 && slug !== rootSlug + }, + { timeout: 45_000 }, + ) + .toBe(true) + + const slug = slugFromUrl(page.url()) + const dir = base64Decode(slug) + + await openSidebar(page) + + await expect + .poll( + async () => { + const item = page.locator(workspaceItemSelector(slug)).first() + try { + await item.hover({ timeout: 500 }) + return true + } catch { + return false + } + }, + { timeout: 60_000 }, + ) + .toBe(true) + + return { rootSlug, slug, directory: dir } +} + +test("can enable and disable workspaces from project menu", async ({ page, withProject }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + await withProject(async ({ slug }) => { + await openSidebar(page) + + await expect(page.getByRole("button", { name: "New session" }).first()).toBeVisible() + await expect(page.getByRole("button", { name: "New workspace" })).toHaveCount(0) + + await setWorkspacesEnabled(page, slug, true) + await expect(page.getByRole("button", { name: "New workspace" }).first()).toBeVisible() + await expect(page.locator(workspaceItemSelector(slug)).first()).toBeVisible() + + await setWorkspacesEnabled(page, slug, false) + await expect(page.getByRole("button", { name: "New session" }).first()).toBeVisible() + await expect(page.locator(workspaceItemSelector(slug))).toHaveCount(0) + }) +}) + +test("can create a workspace", async ({ page, withProject }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + await withProject(async ({ slug }) => { + await openSidebar(page) + await setWorkspacesEnabled(page, slug, true) + + await expect(page.getByRole("button", { name: "New workspace" }).first()).toBeVisible() + + await page.getByRole("button", { name: "New workspace" }).first().click() + + await expect + .poll( + () => { + const currentSlug = slugFromUrl(page.url()) + return currentSlug.length > 0 && currentSlug !== slug + }, + { timeout: 45_000 }, + ) + .toBe(true) + + const workspaceSlug = slugFromUrl(page.url()) + const workspaceDir = base64Decode(workspaceSlug) + + await openSidebar(page) + + await expect + .poll( + async () => { + const item = page.locator(workspaceItemSelector(workspaceSlug)).first() + try { + await item.hover({ timeout: 500 }) + return true + } catch { + return false + } + }, + { timeout: 60_000 }, + ) + .toBe(true) + + await expect(page.locator(workspaceItemSelector(workspaceSlug)).first()).toBeVisible() + + await cleanupTestProject(workspaceDir) + }) +}) + +test("non-git projects keep workspace mode disabled", async ({ page, withProject }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + const nonGit = await fs.mkdtemp(path.join(os.tmpdir(), "opencode-e2e-project-nongit-")) + const nonGitSlug = dirSlug(nonGit) + + await fs.writeFile(path.join(nonGit, "README.md"), "# e2e nongit\n") + + try { + await withProject( + async () => { + await openSidebar(page) + + const nonGitButton = page.locator(projectSwitchSelector(nonGitSlug)).first() + await expect(nonGitButton).toBeVisible() + await nonGitButton.click() + await expect(page).toHaveURL(new RegExp(`/${nonGitSlug}/session`)) + + const menu = await openProjectMenu(page, nonGitSlug) + const toggle = menu.locator(projectWorkspacesToggleSelector(nonGitSlug)).first() + + await expect(toggle).toBeVisible() + await expect(toggle).toBeDisabled() + + await expect(menu.getByRole("menuitem", { name: "New workspace" })).toHaveCount(0) + await expect(page.getByRole("button", { name: "New workspace" })).toHaveCount(0) + }, + { extra: [nonGit] }, + ) + } finally { + await cleanupTestProject(nonGit) + } +}) + +test("can rename a workspace", async ({ page, withProject }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + await withProject(async (project) => { + const { slug } = await setupWorkspaceTest(page, project) + + const rename = `e2e workspace ${Date.now()}` + const menu = await openWorkspaceMenu(page, slug) + await clickMenuItem(menu, /^Rename$/i, { force: true }) + + await expect(menu).toHaveCount(0) + + const item = page.locator(workspaceItemSelector(slug)).first() + await expect(item).toBeVisible() + const input = item.locator(inlineInputSelector).first() + await expect(input).toBeVisible() + await input.fill(rename) + await input.press("Enter") + await expect(item).toContainText(rename) + }) +}) + +test("can reset a workspace", async ({ page, sdk, withProject }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + await withProject(async (project) => { + const { slug, directory: createdDir } = await setupWorkspaceTest(page, project) + + const readme = path.join(createdDir, "README.md") + const extra = path.join(createdDir, `e2e_reset_${Date.now()}.txt`) + const original = await fs.readFile(readme, "utf8") + const dirty = `${original.trimEnd()}\n\nchange_${Date.now()}\n` + await fs.writeFile(readme, dirty, "utf8") + await fs.writeFile(extra, `created_${Date.now()}\n`, "utf8") + + await expect + .poll(async () => { + return await fs + .stat(extra) + .then(() => true) + .catch(() => false) + }) + .toBe(true) + + await expect + .poll(async () => { + const files = await sdk.file + .status({ directory: createdDir }) + .then((r) => r.data ?? []) + .catch(() => []) + return files.length + }) + .toBeGreaterThan(0) + + const menu = await openWorkspaceMenu(page, slug) + await clickMenuItem(menu, /^Reset$/i, { force: true }) + await confirmDialog(page, /^Reset workspace$/i) + + await expect + .poll( + async () => { + const files = await sdk.file + .status({ directory: createdDir }) + .then((r) => r.data ?? []) + .catch(() => []) + return files.length + }, + { timeout: 60_000 }, + ) + .toBe(0) + + await expect.poll(() => fs.readFile(readme, "utf8"), { timeout: 60_000 }).toBe(original) + + await expect + .poll(async () => { + return await fs + .stat(extra) + .then(() => true) + .catch(() => false) + }) + .toBe(false) + }) +}) + +test("can delete a workspace", async ({ page, withProject }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + await withProject(async (project) => { + const { rootSlug, slug } = await setupWorkspaceTest(page, project) + + const menu = await openWorkspaceMenu(page, slug) + await clickMenuItem(menu, /^Delete$/i, { force: true }) + await confirmDialog(page, /^Delete workspace$/i) + + await expect(page).toHaveURL(new RegExp(`/${rootSlug}/session`)) + await expect(page.locator(workspaceItemSelector(slug))).toHaveCount(0) + await expect(page.locator(workspaceItemSelector(rootSlug)).first()).toBeVisible() + }) +}) + +test("can reorder workspaces by drag and drop", async ({ page, withProject }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + await withProject(async ({ slug: rootSlug }) => { + const workspaces = [] as { directory: string; slug: string }[] + + const listSlugs = async () => { + const nodes = page.locator('[data-component="sidebar-nav-desktop"] [data-component="workspace-item"]') + const slugs = await nodes.evaluateAll((els) => { + return els.map((el) => el.getAttribute("data-workspace") ?? "").filter((x) => x.length > 0) + }) + return slugs + } + + const waitReady = async (slug: string) => { + await expect + .poll( + async () => { + const item = page.locator(workspaceItemSelector(slug)).first() + try { + await item.hover({ timeout: 500 }) + return true + } catch { + return false + } + }, + { timeout: 60_000 }, + ) + .toBe(true) + } + + const drag = async (from: string, to: string) => { + const src = page.locator(workspaceItemSelector(from)).first() + const dst = page.locator(workspaceItemSelector(to)).first() + + await src.scrollIntoViewIfNeeded() + await dst.scrollIntoViewIfNeeded() + + const a = await src.boundingBox() + const b = await dst.boundingBox() + if (!a || !b) throw new Error("Failed to resolve workspace drag bounds") + + await page.mouse.move(a.x + a.width / 2, a.y + a.height / 2) + await page.mouse.down() + await page.mouse.move(b.x + b.width / 2, b.y + b.height / 2, { steps: 12 }) + await page.mouse.up() + } + + try { + await openSidebar(page) + + await setWorkspacesEnabled(page, rootSlug, true) + + for (const _ of [0, 1]) { + const prev = slugFromUrl(page.url()) + await page.getByRole("button", { name: "New workspace" }).first().click() + await expect + .poll( + () => { + const slug = slugFromUrl(page.url()) + return slug.length > 0 && slug !== rootSlug && slug !== prev + }, + { timeout: 45_000 }, + ) + .toBe(true) + + const slug = slugFromUrl(page.url()) + const dir = base64Decode(slug) + workspaces.push({ slug, directory: dir }) + + await openSidebar(page) + } + + if (workspaces.length !== 2) throw new Error("Expected two created workspaces") + + const a = workspaces[0].slug + const b = workspaces[1].slug + + await waitReady(a) + await waitReady(b) + + const list = async () => { + const slugs = await listSlugs() + return slugs.filter((s) => s !== rootSlug && (s === a || s === b)).slice(0, 2) + } + + await expect + .poll(async () => { + const slugs = await list() + return slugs.length === 2 + }) + .toBe(true) + + const before = await list() + const from = before[1] + const to = before[0] + if (!from || !to) throw new Error("Failed to resolve initial workspace order") + + await drag(from, to) + + await expect.poll(async () => await list()).toEqual([from, to]) + } finally { + await Promise.all(workspaces.map((w) => cleanupTestProject(w.directory))) + } + }) +}) diff --git a/packages/app/e2e/prompt/context.spec.ts b/packages/app/e2e/prompt/context.spec.ts new file mode 100644 index 00000000000..80aa9ea334d --- /dev/null +++ b/packages/app/e2e/prompt/context.spec.ts @@ -0,0 +1,40 @@ +import { test, expect } from "../fixtures" +import { promptSelector } from "../selectors" +import { withSession } from "../actions" + +test("context panel can be opened from the prompt", async ({ page, sdk, gotoSession }) => { + const title = `e2e smoke context ${Date.now()}` + + await withSession(sdk, title, async (session) => { + await sdk.session.promptAsync({ + sessionID: session.id, + noReply: true, + parts: [ + { + type: "text", + text: "seed context", + }, + ], + }) + + await expect + .poll(async () => { + const messages = await sdk.session.messages({ sessionID: session.id, limit: 1 }).then((r) => r.data ?? []) + return messages.length + }) + .toBeGreaterThan(0) + + await gotoSession(session.id) + + const contextButton = page + .locator('[data-component="button"]') + .filter({ has: page.locator('[data-component="progress-circle"]').first() }) + .first() + + await expect(contextButton).toBeVisible() + await contextButton.click() + + const tabs = page.locator('[data-component="tabs"][data-variant="normal"]') + await expect(tabs.getByRole("tab", { name: "Context" })).toBeVisible() + }) +}) diff --git a/packages/app/e2e/prompt/prompt-mention.spec.ts b/packages/app/e2e/prompt/prompt-mention.spec.ts new file mode 100644 index 00000000000..5cc9f6e6850 --- /dev/null +++ b/packages/app/e2e/prompt/prompt-mention.spec.ts @@ -0,0 +1,26 @@ +import { test, expect } from "../fixtures" +import { promptSelector } from "../selectors" + +test("smoke @mention inserts file pill token", async ({ page, gotoSession }) => { + await gotoSession() + + await page.locator(promptSelector).click() + const sep = process.platform === "win32" ? "\\" : "/" + const file = ["packages", "app", "package.json"].join(sep) + const filePattern = /packages[\\/]+app[\\/]+\s*package\.json/ + + await page.keyboard.type(`@${file}`) + + const suggestion = page.getByRole("button", { name: filePattern }).first() + await expect(suggestion).toBeVisible() + await suggestion.hover() + + await page.keyboard.press("Tab") + + const pill = page.locator(`${promptSelector} [data-type="file"]`).first() + await expect(pill).toBeVisible() + await expect(pill).toHaveAttribute("data-path", filePattern) + + await page.keyboard.type(" ok") + await expect(page.locator(promptSelector)).toContainText("ok") +}) diff --git a/packages/app/e2e/prompt/prompt-slash-open.spec.ts b/packages/app/e2e/prompt/prompt-slash-open.spec.ts new file mode 100644 index 00000000000..b4a93099d9d --- /dev/null +++ b/packages/app/e2e/prompt/prompt-slash-open.spec.ts @@ -0,0 +1,22 @@ +import { test, expect } from "../fixtures" +import { promptSelector } from "../selectors" + +test("smoke /open opens file picker dialog", async ({ page, gotoSession }) => { + await gotoSession() + + await page.locator(promptSelector).click() + await page.keyboard.type("/open") + + const command = page.locator('[data-slash-id="file.open"]') + await expect(command).toBeVisible() + await command.hover() + + await page.keyboard.press("Enter") + + const dialog = page.getByRole("dialog") + await expect(dialog).toBeVisible() + await expect(dialog.getByRole("textbox").first()).toBeVisible() + + await page.keyboard.press("Escape") + await expect(dialog).toHaveCount(0) +}) diff --git a/packages/app/e2e/prompt/prompt.spec.ts b/packages/app/e2e/prompt/prompt.spec.ts new file mode 100644 index 00000000000..07d242c6342 --- /dev/null +++ b/packages/app/e2e/prompt/prompt.spec.ts @@ -0,0 +1,58 @@ +import { test, expect } from "../fixtures" +import { promptSelector } from "../selectors" +import { sessionIDFromUrl, withSession } from "../actions" + +test("can send a prompt and receive a reply", async ({ page, sdk, gotoSession }) => { + test.setTimeout(120_000) + + const pageErrors: string[] = [] + const onPageError = (err: Error) => { + pageErrors.push(err.message) + } + page.on("pageerror", onPageError) + + await gotoSession() + + const token = `E2E_OK_${Date.now()}` + + const prompt = page.locator(promptSelector) + await prompt.click() + await page.keyboard.type(`Reply with exactly: ${token}`) + await page.keyboard.press("Enter") + + await expect(page).toHaveURL(/\/session\/[^/?#]+/, { timeout: 30_000 }) + + const sessionID = (() => { + const id = sessionIDFromUrl(page.url()) + if (!id) throw new Error(`Failed to parse session id from url: ${page.url()}`) + return id + })() + + try { + await expect + .poll( + async () => { + const messages = await sdk.session.messages({ sessionID, limit: 50 }).then((r) => r.data ?? []) + return messages + .filter((m) => m.info.role === "assistant") + .flatMap((m) => m.parts) + .filter((p) => p.type === "text") + .map((p) => p.text) + .join("\n") + }, + { timeout: 90_000 }, + ) + + .toContain(token) + + const reply = page.locator('[data-slot="session-turn-summary-section"]').filter({ hasText: token }).first() + await expect(reply).toBeVisible({ timeout: 90_000 }) + } finally { + page.off("pageerror", onPageError) + await sdk.session.delete({ sessionID }).catch(() => undefined) + } + + if (pageErrors.length > 0) { + throw new Error(`Page error(s):\n${pageErrors.join("\n")}`) + } +}) diff --git a/packages/app/e2e/selectors.ts b/packages/app/e2e/selectors.ts new file mode 100644 index 00000000000..842433891e2 --- /dev/null +++ b/packages/app/e2e/selectors.ts @@ -0,0 +1,60 @@ +export const promptSelector = '[data-component="prompt-input"]' +export const terminalSelector = '[data-component="terminal"]' + +export const modelVariantCycleSelector = '[data-action="model-variant-cycle"]' +export const settingsLanguageSelectSelector = '[data-action="settings-language"]' +export const settingsColorSchemeSelector = '[data-action="settings-color-scheme"]' +export const settingsThemeSelector = '[data-action="settings-theme"]' +export const settingsFontSelector = '[data-action="settings-font"]' +export const settingsNotificationsAgentSelector = '[data-action="settings-notifications-agent"]' +export const settingsNotificationsPermissionsSelector = '[data-action="settings-notifications-permissions"]' +export const settingsNotificationsErrorsSelector = '[data-action="settings-notifications-errors"]' +export const settingsSoundsAgentSelector = '[data-action="settings-sounds-agent"]' +export const settingsSoundsPermissionsSelector = '[data-action="settings-sounds-permissions"]' +export const settingsSoundsErrorsSelector = '[data-action="settings-sounds-errors"]' +export const settingsUpdatesStartupSelector = '[data-action="settings-updates-startup"]' +export const settingsReleaseNotesSelector = '[data-action="settings-release-notes"]' + +export const sidebarNavSelector = '[data-component="sidebar-nav-desktop"]' + +export const projectSwitchSelector = (slug: string) => + `${sidebarNavSelector} [data-action="project-switch"][data-project="${slug}"]` + +export const projectCloseHoverSelector = (slug: string) => `[data-action="project-close-hover"][data-project="${slug}"]` + +export const projectMenuTriggerSelector = (slug: string) => + `${sidebarNavSelector} [data-action="project-menu"][data-project="${slug}"]` + +export const projectCloseMenuSelector = (slug: string) => `[data-action="project-close-menu"][data-project="${slug}"]` + +export const projectWorkspacesToggleSelector = (slug: string) => + `[data-action="project-workspaces-toggle"][data-project="${slug}"]` + +export const titlebarRightSelector = "#opencode-titlebar-right" + +export const popoverBodySelector = '[data-slot="popover-body"]' + +export const dropdownMenuTriggerSelector = '[data-slot="dropdown-menu-trigger"]' + +export const dropdownMenuContentSelector = '[data-component="dropdown-menu-content"]' + +export const inlineInputSelector = '[data-component="inline-input"]' + +export const sessionItemSelector = (sessionID: string) => `${sidebarNavSelector} [data-session-id="${sessionID}"]` + +export const workspaceItemSelector = (slug: string) => + `${sidebarNavSelector} [data-component="workspace-item"][data-workspace="${slug}"]` + +export const workspaceMenuTriggerSelector = (slug: string) => + `${sidebarNavSelector} [data-action="workspace-menu"][data-workspace="${slug}"]` + +export const workspaceNewSessionSelector = (slug: string) => + `${sidebarNavSelector} [data-action="workspace-new-session"][data-workspace="${slug}"]` + +export const listItemSelector = '[data-slot="list-item"]' + +export const listItemKeyStartsWithSelector = (prefix: string) => `${listItemSelector}[data-key^="${prefix}"]` + +export const listItemKeySelector = (key: string) => `${listItemSelector}[data-key="${key}"]` + +export const keybindButtonSelector = (id: string) => `[data-keybind-id="${id}"]` diff --git a/packages/app/e2e/session/session-undo-redo.spec.ts b/packages/app/e2e/session/session-undo-redo.spec.ts new file mode 100644 index 00000000000..2a250dd866a --- /dev/null +++ b/packages/app/e2e/session/session-undo-redo.spec.ts @@ -0,0 +1,235 @@ +import type { Page } from "@playwright/test" +import { test, expect } from "../fixtures" +import { withSession } from "../actions" +import { createSdk, modKey } from "../utils" +import { promptSelector } from "../selectors" + +async function seedConversation(input: { + page: Page + sdk: ReturnType + sessionID: string + token: string +}) { + const prompt = input.page.locator(promptSelector) + await expect(prompt).toBeVisible() + await prompt.click() + await input.page.keyboard.type(`Reply with exactly: ${input.token}`) + await input.page.keyboard.press("Enter") + + let userMessageID: string | undefined + await expect + .poll( + async () => { + const messages = await input.sdk.session + .messages({ sessionID: input.sessionID, limit: 50 }) + .then((r) => r.data ?? []) + const users = messages.filter( + (m) => + m.info.role === "user" && + m.parts.filter((p) => p.type === "text").some((p) => p.text.includes(input.token)), + ) + if (users.length === 0) return false + + const user = users[users.length - 1] + if (!user) return false + userMessageID = user.info.id + + const assistantText = messages + .filter((m) => m.info.role === "assistant") + .flatMap((m) => m.parts) + .filter((p) => p.type === "text") + .map((p) => p.text) + .join("\n") + + return assistantText.includes(input.token) + }, + { timeout: 90_000 }, + ) + .toBe(true) + + if (!userMessageID) throw new Error("Expected a user message id") + return { prompt, userMessageID } +} + +test("slash undo sets revert and restores prior prompt", async ({ page, withProject }) => { + test.setTimeout(120_000) + + const token = `undo_${Date.now()}` + + await withProject(async (project) => { + const sdk = createSdk(project.directory) + + await withSession(sdk, `e2e undo ${Date.now()}`, async (session) => { + await project.gotoSession(session.id) + + const seeded = await seedConversation({ page, sdk, sessionID: session.id, token }) + + await seeded.prompt.click() + await page.keyboard.type("/undo") + + const undo = page.locator('[data-slash-id="session.undo"]').first() + await expect(undo).toBeVisible() + await page.keyboard.press("Enter") + + await expect + .poll(async () => await sdk.session.get({ sessionID: session.id }).then((r) => r.data?.revert?.messageID), { + timeout: 30_000, + }) + .toBe(seeded.userMessageID) + + await expect(seeded.prompt).toContainText(token) + await expect(page.locator(`[data-message-id="${seeded.userMessageID}"]`)).toHaveCount(0) + }) + }) +}) + +test("slash redo clears revert and restores latest state", async ({ page, withProject }) => { + test.setTimeout(120_000) + + const token = `redo_${Date.now()}` + + await withProject(async (project) => { + const sdk = createSdk(project.directory) + + await withSession(sdk, `e2e redo ${Date.now()}`, async (session) => { + await project.gotoSession(session.id) + + const seeded = await seedConversation({ page, sdk, sessionID: session.id, token }) + + await seeded.prompt.click() + await page.keyboard.type("/undo") + + const undo = page.locator('[data-slash-id="session.undo"]').first() + await expect(undo).toBeVisible() + await page.keyboard.press("Enter") + + await expect + .poll(async () => await sdk.session.get({ sessionID: session.id }).then((r) => r.data?.revert?.messageID), { + timeout: 30_000, + }) + .toBe(seeded.userMessageID) + + await seeded.prompt.click() + await page.keyboard.press(`${modKey}+A`) + await page.keyboard.press("Backspace") + await page.keyboard.type("/redo") + + const redo = page.locator('[data-slash-id="session.redo"]').first() + await expect(redo).toBeVisible() + await page.keyboard.press("Enter") + + await expect + .poll(async () => await sdk.session.get({ sessionID: session.id }).then((r) => r.data?.revert?.messageID), { + timeout: 30_000, + }) + .toBeUndefined() + + await expect(seeded.prompt).not.toContainText(token) + await expect(page.locator(`[data-message-id="${seeded.userMessageID}"]`).first()).toBeVisible() + }) + }) +}) + +test("slash undo/redo traverses multi-step revert stack", async ({ page, withProject }) => { + test.setTimeout(120_000) + + const firstToken = `undo_redo_first_${Date.now()}` + const secondToken = `undo_redo_second_${Date.now()}` + + await withProject(async (project) => { + const sdk = createSdk(project.directory) + + await withSession(sdk, `e2e undo redo stack ${Date.now()}`, async (session) => { + await project.gotoSession(session.id) + + const first = await seedConversation({ + page, + sdk, + sessionID: session.id, + token: firstToken, + }) + const second = await seedConversation({ + page, + sdk, + sessionID: session.id, + token: secondToken, + }) + + expect(first.userMessageID).not.toBe(second.userMessageID) + + const firstMessage = page.locator(`[data-message-id="${first.userMessageID}"]`) + const secondMessage = page.locator(`[data-message-id="${second.userMessageID}"]`) + + await expect(firstMessage.first()).toBeVisible() + await expect(secondMessage.first()).toBeVisible() + + await second.prompt.click() + await page.keyboard.press(`${modKey}+A`) + await page.keyboard.press("Backspace") + await page.keyboard.type("/undo") + + const undo = page.locator('[data-slash-id="session.undo"]').first() + await expect(undo).toBeVisible() + await page.keyboard.press("Enter") + + await expect + .poll(async () => await sdk.session.get({ sessionID: session.id }).then((r) => r.data?.revert?.messageID), { + timeout: 30_000, + }) + .toBe(second.userMessageID) + + await expect(firstMessage.first()).toBeVisible() + await expect(secondMessage).toHaveCount(0) + + await second.prompt.click() + await page.keyboard.press(`${modKey}+A`) + await page.keyboard.press("Backspace") + await page.keyboard.type("/undo") + await expect(undo).toBeVisible() + await page.keyboard.press("Enter") + + await expect + .poll(async () => await sdk.session.get({ sessionID: session.id }).then((r) => r.data?.revert?.messageID), { + timeout: 30_000, + }) + .toBe(first.userMessageID) + + await expect(firstMessage).toHaveCount(0) + await expect(secondMessage).toHaveCount(0) + + await second.prompt.click() + await page.keyboard.press(`${modKey}+A`) + await page.keyboard.press("Backspace") + await page.keyboard.type("/redo") + + const redo = page.locator('[data-slash-id="session.redo"]').first() + await expect(redo).toBeVisible() + await page.keyboard.press("Enter") + + await expect + .poll(async () => await sdk.session.get({ sessionID: session.id }).then((r) => r.data?.revert?.messageID), { + timeout: 30_000, + }) + .toBe(second.userMessageID) + + await expect(firstMessage.first()).toBeVisible() + await expect(secondMessage).toHaveCount(0) + + await second.prompt.click() + await page.keyboard.press(`${modKey}+A`) + await page.keyboard.press("Backspace") + await page.keyboard.type("/redo") + await expect(redo).toBeVisible() + await page.keyboard.press("Enter") + + await expect + .poll(async () => await sdk.session.get({ sessionID: session.id }).then((r) => r.data?.revert?.messageID), { + timeout: 30_000, + }) + .toBeUndefined() + + await expect(firstMessage.first()).toBeVisible() + await expect(secondMessage.first()).toBeVisible() + }) + }) +}) diff --git a/packages/app/e2e/session/session.spec.ts b/packages/app/e2e/session/session.spec.ts new file mode 100644 index 00000000000..4610fb33152 --- /dev/null +++ b/packages/app/e2e/session/session.spec.ts @@ -0,0 +1,157 @@ +import { test, expect } from "../fixtures" +import { + openSidebar, + openSessionMoreMenu, + clickMenuItem, + confirmDialog, + openSharePopover, + withSession, +} from "../actions" +import { sessionItemSelector, inlineInputSelector } from "../selectors" + +const shareDisabled = process.env.OPENCODE_DISABLE_SHARE === "true" || process.env.OPENCODE_DISABLE_SHARE === "1" + +type Sdk = Parameters[0] + +async function seedMessage(sdk: Sdk, sessionID: string) { + await sdk.session.promptAsync({ + sessionID, + noReply: true, + parts: [{ type: "text", text: "e2e seed" }], + }) + + await expect + .poll( + async () => { + const messages = await sdk.session.messages({ sessionID, limit: 1 }).then((r) => r.data ?? []) + return messages.length + }, + { timeout: 30_000 }, + ) + .toBeGreaterThan(0) +} + +test("session can be renamed via header menu", async ({ page, sdk, gotoSession }) => { + const stamp = Date.now() + const originalTitle = `e2e rename test ${stamp}` + const newTitle = `e2e renamed ${stamp}` + + await withSession(sdk, originalTitle, async (session) => { + await seedMessage(sdk, session.id) + await gotoSession(session.id) + + const menu = await openSessionMoreMenu(page, session.id) + await clickMenuItem(menu, /rename/i) + + const input = page.locator(".session-scroller").locator(inlineInputSelector).first() + await expect(input).toBeVisible() + await input.fill(newTitle) + await input.press("Enter") + + await expect(page.getByRole("heading", { level: 1 }).first()).toContainText(newTitle) + }) +}) + +test("session can be archived via header menu", async ({ page, sdk, gotoSession }) => { + const stamp = Date.now() + const title = `e2e archive test ${stamp}` + + await withSession(sdk, title, async (session) => { + await seedMessage(sdk, session.id) + await gotoSession(session.id) + const menu = await openSessionMoreMenu(page, session.id) + await clickMenuItem(menu, /archive/i) + + await expect + .poll( + async () => { + const data = await sdk.session.get({ sessionID: session.id }).then((r) => r.data) + return data?.time?.archived + }, + { timeout: 30_000 }, + ) + .not.toBeUndefined() + + await openSidebar(page) + await expect(page.locator(sessionItemSelector(session.id))).toHaveCount(0) + }) +}) + +test("session can be deleted via header menu", async ({ page, sdk, gotoSession }) => { + const stamp = Date.now() + const title = `e2e delete test ${stamp}` + + await withSession(sdk, title, async (session) => { + await seedMessage(sdk, session.id) + await gotoSession(session.id) + const menu = await openSessionMoreMenu(page, session.id) + await clickMenuItem(menu, /delete/i) + await confirmDialog(page, /delete/i) + + await expect + .poll( + async () => { + const data = await sdk.session + .get({ sessionID: session.id }) + .then((r) => r.data) + .catch(() => undefined) + return data?.id + }, + { timeout: 30_000 }, + ) + .toBeUndefined() + + await openSidebar(page) + await expect(page.locator(sessionItemSelector(session.id))).toHaveCount(0) + }) +}) + +test("session can be shared and unshared via header button", async ({ page, sdk, gotoSession }) => { + test.skip(shareDisabled, "Share is disabled in this environment (OPENCODE_DISABLE_SHARE).") + + const stamp = Date.now() + const title = `e2e share test ${stamp}` + + await withSession(sdk, title, async (session) => { + await seedMessage(sdk, session.id) + await gotoSession(session.id) + + const { rightSection, popoverBody } = await openSharePopover(page) + await popoverBody.getByRole("button", { name: "Publish" }).first().click() + + await expect + .poll( + async () => { + const data = await sdk.session.get({ sessionID: session.id }).then((r) => r.data) + return data?.share?.url || undefined + }, + { timeout: 30_000 }, + ) + .not.toBeUndefined() + + const copyButton = rightSection.locator('button[aria-label="Copy link"]').first() + await expect(copyButton).toBeVisible({ timeout: 30_000 }) + + const sharedPopover = await openSharePopover(page) + const unpublish = sharedPopover.popoverBody.getByRole("button", { name: "Unpublish" }).first() + await expect(unpublish).toBeVisible({ timeout: 30_000 }) + await unpublish.click() + + await expect + .poll( + async () => { + const data = await sdk.session.get({ sessionID: session.id }).then((r) => r.data) + return data?.share?.url || undefined + }, + { timeout: 30_000 }, + ) + .toBeUndefined() + + await expect(copyButton).not.toBeVisible({ timeout: 30_000 }) + + const unsharedPopover = await openSharePopover(page) + await expect(unsharedPopover.popoverBody.getByRole("button", { name: "Publish" }).first()).toBeVisible({ + timeout: 30_000, + }) + }) +}) diff --git a/packages/app/e2e/settings/settings-keybinds.spec.ts b/packages/app/e2e/settings/settings-keybinds.spec.ts new file mode 100644 index 00000000000..5e98bd158a1 --- /dev/null +++ b/packages/app/e2e/settings/settings-keybinds.spec.ts @@ -0,0 +1,392 @@ +import { test, expect } from "../fixtures" +import { openSettings, closeDialog, withSession } from "../actions" +import { keybindButtonSelector, terminalSelector } from "../selectors" +import { modKey } from "../utils" + +test("changing sidebar toggle keybind works", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + await dialog.getByRole("tab", { name: "Shortcuts" }).click() + + const keybindButton = dialog.locator(keybindButtonSelector("sidebar.toggle")).first() + await expect(keybindButton).toBeVisible() + + const initialKeybind = await keybindButton.textContent() + expect(initialKeybind).toContain("B") + + await keybindButton.click() + await expect(keybindButton).toHaveText(/press/i) + + await page.keyboard.press(`${modKey}+Shift+KeyH`) + await page.waitForTimeout(100) + + const newKeybind = await keybindButton.textContent() + expect(newKeybind).toContain("H") + + const stored = await page.evaluate(() => { + const raw = localStorage.getItem("settings.v3") + return raw ? JSON.parse(raw) : null + }) + expect(stored?.keybinds?.["sidebar.toggle"]).toBe("mod+shift+h") + + await closeDialog(page, dialog) + + const main = page.locator("main") + const initialClasses = (await main.getAttribute("class")) ?? "" + const initiallyClosed = initialClasses.includes("xl:border-l") + + await page.keyboard.press(`${modKey}+Shift+H`) + await page.waitForTimeout(100) + + const afterToggleClasses = (await main.getAttribute("class")) ?? "" + const afterToggleClosed = afterToggleClasses.includes("xl:border-l") + expect(afterToggleClosed).toBe(!initiallyClosed) + + await page.keyboard.press(`${modKey}+Shift+H`) + await page.waitForTimeout(100) + + const finalClasses = (await main.getAttribute("class")) ?? "" + const finalClosed = finalClasses.includes("xl:border-l") + expect(finalClosed).toBe(initiallyClosed) +}) + +test("sidebar toggle keybind guards against shortcut conflicts", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + await dialog.getByRole("tab", { name: "Shortcuts" }).click() + + const keybindButton = dialog.locator(keybindButtonSelector("sidebar.toggle")) + await expect(keybindButton).toBeVisible() + + const initialKeybind = await keybindButton.textContent() + expect(initialKeybind).toContain("B") + + await keybindButton.click() + await expect(keybindButton).toHaveText(/press/i) + + await page.keyboard.press(`${modKey}+Shift+KeyP`) + await page.waitForTimeout(100) + + const toast = page.locator('[data-component="toast"]').last() + await expect(toast).toBeVisible() + await expect(toast).toContainText(/already/i) + + await keybindButton.click() + await expect(keybindButton).toContainText("B") + + const stored = await page.evaluate(() => { + const raw = localStorage.getItem("settings.v3") + return raw ? JSON.parse(raw) : null + }) + expect(stored?.keybinds?.["sidebar.toggle"]).toBeUndefined() + + await closeDialog(page, dialog) +}) + +test("resetting all keybinds to defaults works", async ({ page, gotoSession }) => { + await page.addInitScript(() => { + localStorage.setItem("settings.v3", JSON.stringify({ keybinds: { "sidebar.toggle": "mod+shift+x" } })) + }) + + await gotoSession() + + const dialog = await openSettings(page) + await dialog.getByRole("tab", { name: "Shortcuts" }).click() + + const keybindButton = dialog.locator(keybindButtonSelector("sidebar.toggle")) + await expect(keybindButton).toBeVisible() + + const customKeybind = await keybindButton.textContent() + expect(customKeybind).toContain("X") + + const resetButton = dialog.getByRole("button", { name: "Reset to defaults" }) + await expect(resetButton).toBeVisible() + await expect(resetButton).toBeEnabled() + await resetButton.click() + await page.waitForTimeout(100) + + const restoredKeybind = await keybindButton.textContent() + expect(restoredKeybind).toContain("B") + + const stored = await page.evaluate(() => { + const raw = localStorage.getItem("settings.v3") + return raw ? JSON.parse(raw) : null + }) + expect(stored?.keybinds?.["sidebar.toggle"]).toBeUndefined() + + await closeDialog(page, dialog) +}) + +test("clearing a keybind works", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + await dialog.getByRole("tab", { name: "Shortcuts" }).click() + + const keybindButton = dialog.locator(keybindButtonSelector("sidebar.toggle")) + await expect(keybindButton).toBeVisible() + + const initialKeybind = await keybindButton.textContent() + expect(initialKeybind).toContain("B") + + await keybindButton.click() + await expect(keybindButton).toHaveText(/press/i) + + await page.keyboard.press("Delete") + await page.waitForTimeout(100) + + const clearedKeybind = await keybindButton.textContent() + expect(clearedKeybind).toMatch(/unassigned|press/i) + + const stored = await page.evaluate(() => { + const raw = localStorage.getItem("settings.v3") + return raw ? JSON.parse(raw) : null + }) + expect(stored?.keybinds?.["sidebar.toggle"]).toBe("none") + + await closeDialog(page, dialog) + + await page.keyboard.press(`${modKey}+B`) + await page.waitForTimeout(100) + + const stillOnSession = page.url().includes("/session") + expect(stillOnSession).toBe(true) +}) + +test("changing settings open keybind works", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + await dialog.getByRole("tab", { name: "Shortcuts" }).click() + + const keybindButton = dialog.locator(keybindButtonSelector("settings.open")) + await expect(keybindButton).toBeVisible() + + const initialKeybind = await keybindButton.textContent() + expect(initialKeybind).toContain(",") + + await keybindButton.click() + await expect(keybindButton).toHaveText(/press/i) + + await page.keyboard.press(`${modKey}+Slash`) + await page.waitForTimeout(100) + + const newKeybind = await keybindButton.textContent() + expect(newKeybind).toContain("/") + + const stored = await page.evaluate(() => { + const raw = localStorage.getItem("settings.v3") + return raw ? JSON.parse(raw) : null + }) + expect(stored?.keybinds?.["settings.open"]).toBe("mod+/") + + await closeDialog(page, dialog) + + const settingsDialog = page.getByRole("dialog") + await expect(settingsDialog).toHaveCount(0) + + await page.keyboard.press(`${modKey}+Slash`) + await page.waitForTimeout(100) + + await expect(settingsDialog).toBeVisible() + + await closeDialog(page, settingsDialog) +}) + +test("changing new session keybind works", async ({ page, sdk, gotoSession }) => { + await withSession(sdk, "test session for keybind", async (session) => { + await gotoSession(session.id) + + const initialUrl = page.url() + expect(initialUrl).toContain(`/session/${session.id}`) + + const dialog = await openSettings(page) + await dialog.getByRole("tab", { name: "Shortcuts" }).click() + + const keybindButton = dialog.locator(keybindButtonSelector("session.new")) + await expect(keybindButton).toBeVisible() + + await keybindButton.click() + await expect(keybindButton).toHaveText(/press/i) + + await page.keyboard.press(`${modKey}+Shift+KeyN`) + await page.waitForTimeout(100) + + const newKeybind = await keybindButton.textContent() + expect(newKeybind).toContain("N") + + const stored = await page.evaluate(() => { + const raw = localStorage.getItem("settings.v3") + return raw ? JSON.parse(raw) : null + }) + expect(stored?.keybinds?.["session.new"]).toBe("mod+shift+n") + + await closeDialog(page, dialog) + + await page.keyboard.press(`${modKey}+Shift+N`) + await page.waitForTimeout(200) + + const newUrl = page.url() + expect(newUrl).toMatch(/\/session\/?$/) + expect(newUrl).not.toContain(session.id) + }) +}) + +test("changing file open keybind works", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + await dialog.getByRole("tab", { name: "Shortcuts" }).click() + + const keybindButton = dialog.locator(keybindButtonSelector("file.open")) + await expect(keybindButton).toBeVisible() + + const initialKeybind = await keybindButton.textContent() + expect(initialKeybind).toContain("P") + + await keybindButton.click() + await expect(keybindButton).toHaveText(/press/i) + + await page.keyboard.press(`${modKey}+Shift+KeyF`) + await page.waitForTimeout(100) + + const newKeybind = await keybindButton.textContent() + expect(newKeybind).toContain("F") + + const stored = await page.evaluate(() => { + const raw = localStorage.getItem("settings.v3") + return raw ? JSON.parse(raw) : null + }) + expect(stored?.keybinds?.["file.open"]).toBe("mod+shift+f") + + await closeDialog(page, dialog) + + const filePickerDialog = page.getByRole("dialog").filter({ has: page.getByPlaceholder(/search files/i) }) + await expect(filePickerDialog).toHaveCount(0) + + await page.keyboard.press(`${modKey}+Shift+F`) + await page.waitForTimeout(100) + + await expect(filePickerDialog).toBeVisible() + + await page.keyboard.press("Escape") + await expect(filePickerDialog).toHaveCount(0) +}) + +test("changing terminal toggle keybind works", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + await dialog.getByRole("tab", { name: "Shortcuts" }).click() + + const keybindButton = dialog.locator(keybindButtonSelector("terminal.toggle")) + await expect(keybindButton).toBeVisible() + + await keybindButton.click() + await expect(keybindButton).toHaveText(/press/i) + + await page.keyboard.press(`${modKey}+KeyY`) + await page.waitForTimeout(100) + + const newKeybind = await keybindButton.textContent() + expect(newKeybind).toContain("Y") + + const stored = await page.evaluate(() => { + const raw = localStorage.getItem("settings.v3") + return raw ? JSON.parse(raw) : null + }) + expect(stored?.keybinds?.["terminal.toggle"]).toBe("mod+y") + + await closeDialog(page, dialog) + + const terminal = page.locator(terminalSelector) + await expect(terminal).not.toBeVisible() + + await page.keyboard.press(`${modKey}+Y`) + await expect(terminal).toBeVisible() + + await page.keyboard.press(`${modKey}+Y`) + await expect(terminal).not.toBeVisible() +}) + +test("terminal toggle keybind persists after reload", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + await dialog.getByRole("tab", { name: "Shortcuts" }).click() + + const keybindButton = dialog.locator(keybindButtonSelector("terminal.toggle")) + await expect(keybindButton).toBeVisible() + + await keybindButton.click() + await expect(keybindButton).toHaveText(/press/i) + + await page.keyboard.press(`${modKey}+Shift+KeyY`) + await page.waitForTimeout(100) + + await expect(keybindButton).toContainText("Y") + await closeDialog(page, dialog) + + await page.reload() + + await expect + .poll(async () => { + return await page.evaluate(() => { + const raw = localStorage.getItem("settings.v3") + if (!raw) return + const parsed = JSON.parse(raw) + return parsed?.keybinds?.["terminal.toggle"] + }) + }) + .toBe("mod+shift+y") + + const reloaded = await openSettings(page) + await reloaded.getByRole("tab", { name: "Shortcuts" }).click() + const reloadedKeybind = reloaded.locator(keybindButtonSelector("terminal.toggle")).first() + await expect(reloadedKeybind).toContainText("Y") + await closeDialog(page, reloaded) +}) + +test("changing command palette keybind works", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + await dialog.getByRole("tab", { name: "Shortcuts" }).click() + + const keybindButton = dialog.locator(keybindButtonSelector("command.palette")) + await expect(keybindButton).toBeVisible() + + const initialKeybind = await keybindButton.textContent() + expect(initialKeybind).toContain("P") + + await keybindButton.click() + await expect(keybindButton).toHaveText(/press/i) + + await page.keyboard.press(`${modKey}+Shift+KeyK`) + await page.waitForTimeout(100) + + const newKeybind = await keybindButton.textContent() + expect(newKeybind).toContain("K") + + const stored = await page.evaluate(() => { + const raw = localStorage.getItem("settings.v3") + return raw ? JSON.parse(raw) : null + }) + expect(stored?.keybinds?.["command.palette"]).toBe("mod+shift+k") + + await closeDialog(page, dialog) + + const palette = page.getByRole("dialog").filter({ has: page.getByRole("textbox").first() }) + await expect(palette).toHaveCount(0) + + await page.keyboard.press(`${modKey}+Shift+K`) + await page.waitForTimeout(100) + + await expect(palette).toBeVisible() + await expect(palette.getByRole("textbox").first()).toBeVisible() + + await page.keyboard.press("Escape") + await expect(palette).toHaveCount(0) +}) diff --git a/packages/app/e2e/settings/settings-models.spec.ts b/packages/app/e2e/settings/settings-models.spec.ts new file mode 100644 index 00000000000..f7397abe867 --- /dev/null +++ b/packages/app/e2e/settings/settings-models.spec.ts @@ -0,0 +1,122 @@ +import { test, expect } from "../fixtures" +import { promptSelector } from "../selectors" +import { closeDialog, openSettings } from "../actions" + +test("hiding a model removes it from the model picker", async ({ page, gotoSession }) => { + await gotoSession() + + await page.locator(promptSelector).click() + await page.keyboard.type("/model") + + const command = page.locator('[data-slash-id="model.choose"]') + await expect(command).toBeVisible() + await command.hover() + await page.keyboard.press("Enter") + + const picker = page.getByRole("dialog") + await expect(picker).toBeVisible() + + const target = picker.locator('[data-slot="list-item"]').first() + await expect(target).toBeVisible() + + const key = await target.getAttribute("data-key") + if (!key) throw new Error("Failed to resolve model key from list item") + + const name = (await target.locator("span").first().innerText()).trim() + if (!name) throw new Error("Failed to resolve model name from list item") + + await page.keyboard.press("Escape") + await expect(picker).toHaveCount(0) + + const settings = await openSettings(page) + + await settings.getByRole("tab", { name: "Models" }).click() + const search = settings.getByPlaceholder("Search models") + await expect(search).toBeVisible() + await search.fill(name) + + const toggle = settings.locator('[data-component="switch"]').filter({ hasText: name }).first() + const input = toggle.locator('[data-slot="switch-input"]') + await expect(toggle).toBeVisible() + await expect(input).toHaveAttribute("aria-checked", "true") + await toggle.locator('[data-slot="switch-control"]').click() + await expect(input).toHaveAttribute("aria-checked", "false") + + await closeDialog(page, settings) + + await page.locator(promptSelector).click() + await page.keyboard.type("/model") + await expect(command).toBeVisible() + await command.hover() + await page.keyboard.press("Enter") + + const pickerAgain = page.getByRole("dialog") + await expect(pickerAgain).toBeVisible() + await expect(pickerAgain.locator('[data-slot="list-item"]').first()).toBeVisible() + + await expect(pickerAgain.locator(`[data-slot="list-item"][data-key="${key}"]`)).toHaveCount(0) + + await page.keyboard.press("Escape") + await expect(pickerAgain).toHaveCount(0) +}) + +test("showing a hidden model restores it to the model picker", async ({ page, gotoSession }) => { + await gotoSession() + + await page.locator(promptSelector).click() + await page.keyboard.type("/model") + + const command = page.locator('[data-slash-id="model.choose"]') + await expect(command).toBeVisible() + await command.hover() + await page.keyboard.press("Enter") + + const picker = page.getByRole("dialog") + await expect(picker).toBeVisible() + + const target = picker.locator('[data-slot="list-item"]').first() + await expect(target).toBeVisible() + + const key = await target.getAttribute("data-key") + if (!key) throw new Error("Failed to resolve model key from list item") + + const name = (await target.locator("span").first().innerText()).trim() + if (!name) throw new Error("Failed to resolve model name from list item") + + await page.keyboard.press("Escape") + await expect(picker).toHaveCount(0) + + const settings = await openSettings(page) + + await settings.getByRole("tab", { name: "Models" }).click() + const search = settings.getByPlaceholder("Search models") + await expect(search).toBeVisible() + await search.fill(name) + + const toggle = settings.locator('[data-component="switch"]').filter({ hasText: name }).first() + const input = toggle.locator('[data-slot="switch-input"]') + await expect(toggle).toBeVisible() + await expect(input).toHaveAttribute("aria-checked", "true") + + await toggle.locator('[data-slot="switch-control"]').click() + await expect(input).toHaveAttribute("aria-checked", "false") + + await toggle.locator('[data-slot="switch-control"]').click() + await expect(input).toHaveAttribute("aria-checked", "true") + + await closeDialog(page, settings) + + await page.locator(promptSelector).click() + await page.keyboard.type("/model") + await expect(command).toBeVisible() + await command.hover() + await page.keyboard.press("Enter") + + const pickerAgain = page.getByRole("dialog") + await expect(pickerAgain).toBeVisible() + + await expect(pickerAgain.locator(`[data-slot="list-item"][data-key="${key}"]`)).toBeVisible() + + await page.keyboard.press("Escape") + await expect(pickerAgain).toHaveCount(0) +}) diff --git a/packages/app/e2e/settings/settings-providers.spec.ts b/packages/app/e2e/settings/settings-providers.spec.ts new file mode 100644 index 00000000000..a55eb34981e --- /dev/null +++ b/packages/app/e2e/settings/settings-providers.spec.ts @@ -0,0 +1,136 @@ +import { test, expect } from "../fixtures" +import { closeDialog, openSettings } from "../actions" + +test("custom provider form can be filled and validates input", async ({ page, gotoSession }) => { + await gotoSession() + + const settings = await openSettings(page) + await settings.getByRole("tab", { name: "Providers" }).click() + + const customProviderSection = settings.locator('[data-component="custom-provider-section"]') + await expect(customProviderSection).toBeVisible() + + const connectButton = customProviderSection.getByRole("button", { name: "Connect" }) + await connectButton.click() + + const providerDialog = page.getByRole("dialog").filter({ has: page.getByText("Custom provider") }) + await expect(providerDialog).toBeVisible() + + await providerDialog.getByLabel("Provider ID").fill("test-provider") + await providerDialog.getByLabel("Display name").fill("Test Provider") + await providerDialog.getByLabel("Base URL").fill("http://localhost:9999/fake") + await providerDialog.getByLabel("API key").fill("fake-key") + + await providerDialog.getByPlaceholder("model-id").first().fill("test-model") + await providerDialog.getByPlaceholder("Display Name").first().fill("Test Model") + + await expect(providerDialog.getByRole("textbox", { name: "Provider ID" })).toHaveValue("test-provider") + await expect(providerDialog.getByRole("textbox", { name: "Display name" })).toHaveValue("Test Provider") + await expect(providerDialog.getByRole("textbox", { name: "Base URL" })).toHaveValue("http://localhost:9999/fake") + await expect(providerDialog.getByRole("textbox", { name: "API key" })).toHaveValue("fake-key") + await expect(providerDialog.getByPlaceholder("model-id").first()).toHaveValue("test-model") + await expect(providerDialog.getByPlaceholder("Display Name").first()).toHaveValue("Test Model") + + await page.keyboard.press("Escape") + await expect(providerDialog).toHaveCount(0) + + await closeDialog(page, settings) +}) + +test("custom provider form shows validation errors", async ({ page, gotoSession }) => { + await gotoSession() + + const settings = await openSettings(page) + await settings.getByRole("tab", { name: "Providers" }).click() + + const customProviderSection = settings.locator('[data-component="custom-provider-section"]') + await customProviderSection.getByRole("button", { name: "Connect" }).click() + + const providerDialog = page.getByRole("dialog").filter({ has: page.getByText("Custom provider") }) + await expect(providerDialog).toBeVisible() + + await providerDialog.getByLabel("Provider ID").fill("invalid provider id") + await providerDialog.getByLabel("Base URL").fill("not-a-url") + + await providerDialog.getByRole("button", { name: /submit|save/i }).click() + + await expect(providerDialog.locator('[data-slot="input-error"]').filter({ hasText: /lowercase/i })).toBeVisible() + await expect(providerDialog.locator('[data-slot="input-error"]').filter({ hasText: /http/i })).toBeVisible() + + await page.keyboard.press("Escape") + await expect(providerDialog).toHaveCount(0) + + await closeDialog(page, settings) +}) + +test("custom provider form can add and remove models", async ({ page, gotoSession }) => { + await gotoSession() + + const settings = await openSettings(page) + await settings.getByRole("tab", { name: "Providers" }).click() + + const customProviderSection = settings.locator('[data-component="custom-provider-section"]') + await customProviderSection.getByRole("button", { name: "Connect" }).click() + + const providerDialog = page.getByRole("dialog").filter({ has: page.getByText("Custom provider") }) + await expect(providerDialog).toBeVisible() + + await providerDialog.getByLabel("Provider ID").fill("multi-model-test") + await providerDialog.getByLabel("Display name").fill("Multi Model Test") + await providerDialog.getByLabel("Base URL").fill("http://localhost:9999/multi") + + await providerDialog.getByPlaceholder("model-id").first().fill("model-1") + await providerDialog.getByPlaceholder("Display Name").first().fill("Model 1") + + const idInputsBefore = await providerDialog.getByPlaceholder("model-id").count() + await providerDialog.getByRole("button", { name: "Add model" }).click() + const idInputsAfter = await providerDialog.getByPlaceholder("model-id").count() + expect(idInputsAfter).toBe(idInputsBefore + 1) + + await providerDialog.getByPlaceholder("model-id").nth(1).fill("model-2") + await providerDialog.getByPlaceholder("Display Name").nth(1).fill("Model 2") + + await expect(providerDialog.getByPlaceholder("model-id").nth(1)).toHaveValue("model-2") + await expect(providerDialog.getByPlaceholder("Display Name").nth(1)).toHaveValue("Model 2") + + await page.keyboard.press("Escape") + await expect(providerDialog).toHaveCount(0) + + await closeDialog(page, settings) +}) + +test("custom provider form can add and remove headers", async ({ page, gotoSession }) => { + await gotoSession() + + const settings = await openSettings(page) + await settings.getByRole("tab", { name: "Providers" }).click() + + const customProviderSection = settings.locator('[data-component="custom-provider-section"]') + await customProviderSection.getByRole("button", { name: "Connect" }).click() + + const providerDialog = page.getByRole("dialog").filter({ has: page.getByText("Custom provider") }) + await expect(providerDialog).toBeVisible() + + await providerDialog.getByLabel("Provider ID").fill("header-test") + await providerDialog.getByLabel("Display name").fill("Header Test") + await providerDialog.getByLabel("Base URL").fill("http://localhost:9999/headers") + + await providerDialog.getByPlaceholder("model-id").first().fill("model-x") + await providerDialog.getByPlaceholder("Display Name").first().fill("Model X") + + const headerInputsBefore = await providerDialog.getByPlaceholder("Header-Name").count() + await providerDialog.getByRole("button", { name: "Add header" }).click() + const headerInputsAfter = await providerDialog.getByPlaceholder("Header-Name").count() + expect(headerInputsAfter).toBe(headerInputsBefore + 1) + + await providerDialog.getByPlaceholder("Header-Name").first().fill("Authorization") + await providerDialog.getByPlaceholder("value").first().fill("Bearer token123") + + await expect(providerDialog.getByPlaceholder("Header-Name").first()).toHaveValue("Authorization") + await expect(providerDialog.getByPlaceholder("value").first()).toHaveValue("Bearer token123") + + await page.keyboard.press("Escape") + await expect(providerDialog).toHaveCount(0) + + await closeDialog(page, settings) +}) diff --git a/packages/app/e2e/settings/settings.spec.ts b/packages/app/e2e/settings/settings.spec.ts new file mode 100644 index 00000000000..42534968b21 --- /dev/null +++ b/packages/app/e2e/settings/settings.spec.ts @@ -0,0 +1,454 @@ +import { test, expect, settingsKey } from "../fixtures" +import { closeDialog, openSettings } from "../actions" +import { + settingsColorSchemeSelector, + settingsFontSelector, + settingsLanguageSelectSelector, + settingsNotificationsAgentSelector, + settingsNotificationsErrorsSelector, + settingsNotificationsPermissionsSelector, + settingsReleaseNotesSelector, + settingsSoundsAgentSelector, + settingsSoundsErrorsSelector, + settingsSoundsPermissionsSelector, + settingsThemeSelector, + settingsUpdatesStartupSelector, +} from "../selectors" + +test("smoke settings dialog opens, switches tabs, closes", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + + await dialog.getByRole("tab", { name: "Shortcuts" }).click() + await expect(dialog.getByRole("button", { name: "Reset to defaults" })).toBeVisible() + await expect(dialog.getByPlaceholder("Search shortcuts")).toBeVisible() + + await closeDialog(page, dialog) +}) + +test("changing language updates settings labels", async ({ page, gotoSession }) => { + await page.addInitScript(() => { + localStorage.setItem("opencode.global.dat:language", JSON.stringify({ locale: "en" })) + }) + + await gotoSession() + + const dialog = await openSettings(page) + + const heading = dialog.getByRole("heading", { level: 2 }) + await expect(heading).toHaveText("General") + + const select = dialog.locator(settingsLanguageSelectSelector) + await expect(select).toBeVisible() + await select.locator('[data-slot="select-select-trigger"]').click() + + await page.locator('[data-slot="select-select-item"]').filter({ hasText: "Deutsch" }).click() + + await expect(heading).toHaveText("Allgemein") + + await select.locator('[data-slot="select-select-trigger"]').click() + await page.locator('[data-slot="select-select-item"]').filter({ hasText: "English" }).click() + await expect(heading).toHaveText("General") +}) + +test("changing color scheme persists in localStorage", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + const select = dialog.locator(settingsColorSchemeSelector) + await expect(select).toBeVisible() + + await select.locator('[data-slot="select-select-trigger"]').click() + await page.locator('[data-slot="select-select-item"]').filter({ hasText: "Dark" }).click() + + const colorScheme = await page.evaluate(() => { + return document.documentElement.getAttribute("data-color-scheme") + }) + expect(colorScheme).toBe("dark") + + await select.locator('[data-slot="select-select-trigger"]').click() + await page.locator('[data-slot="select-select-item"]').filter({ hasText: "Light" }).click() + + const lightColorScheme = await page.evaluate(() => { + return document.documentElement.getAttribute("data-color-scheme") + }) + expect(lightColorScheme).toBe("light") +}) + +test("changing theme persists in localStorage", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + const select = dialog.locator(settingsThemeSelector) + await expect(select).toBeVisible() + + await select.locator('[data-slot="select-select-trigger"]').click() + + const items = page.locator('[data-slot="select-select-item"]') + const count = await items.count() + expect(count).toBeGreaterThan(1) + + const firstTheme = await items.nth(1).locator('[data-slot="select-select-item-label"]').textContent() + expect(firstTheme).toBeTruthy() + + await items.nth(1).click() + + await page.keyboard.press("Escape") + + const storedThemeId = await page.evaluate(() => { + return localStorage.getItem("opencode-theme-id") + }) + + expect(storedThemeId).not.toBeNull() + expect(storedThemeId).not.toBe("oc-1") + + const dataTheme = await page.evaluate(() => { + return document.documentElement.getAttribute("data-theme") + }) + expect(dataTheme).toBe(storedThemeId) +}) + +test("changing font persists in localStorage and updates CSS variable", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + const select = dialog.locator(settingsFontSelector) + await expect(select).toBeVisible() + + const initialFontFamily = await page.evaluate(() => { + return getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono") + }) + expect(initialFontFamily).toContain("IBM Plex Mono") + + await select.locator('[data-slot="select-select-trigger"]').click() + + const items = page.locator('[data-slot="select-select-item"]') + await items.nth(2).click() + + await page.waitForTimeout(100) + + const stored = await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + + expect(stored?.appearance?.font).not.toBe("ibm-plex-mono") + + const newFontFamily = await page.evaluate(() => { + return getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono") + }) + expect(newFontFamily).not.toBe(initialFontFamily) +}) + +test("color scheme and font rehydrate after reload", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + + const colorSchemeSelect = dialog.locator(settingsColorSchemeSelector) + await expect(colorSchemeSelect).toBeVisible() + await colorSchemeSelect.locator('[data-slot="select-select-trigger"]').click() + await page.locator('[data-slot="select-select-item"]').filter({ hasText: "Dark" }).click() + await expect(page.locator("html")).toHaveAttribute("data-color-scheme", "dark") + + const fontSelect = dialog.locator(settingsFontSelector) + await expect(fontSelect).toBeVisible() + + const initialFontFamily = await page.evaluate(() => { + return getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono").trim() + }) + + const initialSettings = await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + + const currentFont = + (await fontSelect.locator('[data-slot="select-select-trigger-value"]').textContent())?.trim() ?? "" + await fontSelect.locator('[data-slot="select-select-trigger"]').click() + + const fontItems = page.locator('[data-slot="select-select-item"]') + expect(await fontItems.count()).toBeGreaterThan(1) + + if (currentFont) { + await fontItems.filter({ hasNotText: currentFont }).first().click() + } + if (!currentFont) { + await fontItems.nth(1).click() + } + + await expect + .poll(async () => { + return await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + }) + .toMatchObject({ + appearance: { + font: expect.any(String), + }, + }) + + const updatedSettings = await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + + const updatedFontFamily = await page.evaluate(() => { + return getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono").trim() + }) + expect(updatedFontFamily).not.toBe(initialFontFamily) + expect(updatedSettings?.appearance?.font).not.toBe(initialSettings?.appearance?.font) + + await closeDialog(page, dialog) + await page.reload() + + await expect(page.locator("html")).toHaveAttribute("data-color-scheme", "dark") + + await expect + .poll(async () => { + return await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + }) + .toMatchObject({ + appearance: { + font: updatedSettings?.appearance?.font, + }, + }) + + const rehydratedSettings = await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + + await expect + .poll(async () => { + return await page.evaluate(() => { + return getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono").trim() + }) + }) + .not.toBe(initialFontFamily) + + const rehydratedFontFamily = await page.evaluate(() => { + return getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono").trim() + }) + expect(rehydratedFontFamily).not.toBe(initialFontFamily) + expect(rehydratedSettings?.appearance?.font).toBe(updatedSettings?.appearance?.font) +}) + +test("toggling notification agent switch updates localStorage", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + const switchContainer = dialog.locator(settingsNotificationsAgentSelector) + await expect(switchContainer).toBeVisible() + + const toggleInput = switchContainer.locator('[data-slot="switch-input"]') + const initialState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) + expect(initialState).toBe(true) + + await switchContainer.locator('[data-slot="switch-control"]').click() + await page.waitForTimeout(100) + + const newState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) + expect(newState).toBe(false) + + const stored = await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + + expect(stored?.notifications?.agent).toBe(false) +}) + +test("toggling notification permissions switch updates localStorage", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + const switchContainer = dialog.locator(settingsNotificationsPermissionsSelector) + await expect(switchContainer).toBeVisible() + + const toggleInput = switchContainer.locator('[data-slot="switch-input"]') + const initialState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) + expect(initialState).toBe(true) + + await switchContainer.locator('[data-slot="switch-control"]').click() + await page.waitForTimeout(100) + + const newState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) + expect(newState).toBe(false) + + const stored = await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + + expect(stored?.notifications?.permissions).toBe(false) +}) + +test("toggling notification errors switch updates localStorage", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + const switchContainer = dialog.locator(settingsNotificationsErrorsSelector) + await expect(switchContainer).toBeVisible() + + const toggleInput = switchContainer.locator('[data-slot="switch-input"]') + const initialState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) + expect(initialState).toBe(false) + + await switchContainer.locator('[data-slot="switch-control"]').click() + await page.waitForTimeout(100) + + const newState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) + expect(newState).toBe(true) + + const stored = await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + + expect(stored?.notifications?.errors).toBe(true) +}) + +test("changing sound agent selection persists in localStorage", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + const select = dialog.locator(settingsSoundsAgentSelector) + await expect(select).toBeVisible() + + await select.locator('[data-slot="select-select-trigger"]').click() + + const items = page.locator('[data-slot="select-select-item"]') + await items.nth(2).click() + + const stored = await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + + expect(stored?.sounds?.agent).not.toBe("staplebops-01") +}) + +test("changing permissions and errors sounds updates localStorage", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + const permissionsSelect = dialog.locator(settingsSoundsPermissionsSelector) + const errorsSelect = dialog.locator(settingsSoundsErrorsSelector) + await expect(permissionsSelect).toBeVisible() + await expect(errorsSelect).toBeVisible() + + const initial = await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + + const permissionsCurrent = + (await permissionsSelect.locator('[data-slot="select-select-trigger-value"]').textContent())?.trim() ?? "" + await permissionsSelect.locator('[data-slot="select-select-trigger"]').click() + const permissionItems = page.locator('[data-slot="select-select-item"]') + expect(await permissionItems.count()).toBeGreaterThan(1) + if (permissionsCurrent) { + await permissionItems.filter({ hasNotText: permissionsCurrent }).first().click() + } + if (!permissionsCurrent) { + await permissionItems.nth(1).click() + } + + const errorsCurrent = + (await errorsSelect.locator('[data-slot="select-select-trigger-value"]').textContent())?.trim() ?? "" + await errorsSelect.locator('[data-slot="select-select-trigger"]').click() + const errorItems = page.locator('[data-slot="select-select-item"]') + expect(await errorItems.count()).toBeGreaterThan(1) + if (errorsCurrent) { + await errorItems.filter({ hasNotText: errorsCurrent }).first().click() + } + if (!errorsCurrent) { + await errorItems.nth(1).click() + } + + await expect + .poll(async () => { + return await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + }) + .toMatchObject({ + sounds: { + permissions: expect.any(String), + errors: expect.any(String), + }, + }) + + const stored = await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + + expect(stored?.sounds?.permissions).not.toBe(initial?.sounds?.permissions) + expect(stored?.sounds?.errors).not.toBe(initial?.sounds?.errors) +}) + +test("toggling updates startup switch updates localStorage", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + const switchContainer = dialog.locator(settingsUpdatesStartupSelector) + await expect(switchContainer).toBeVisible() + + const toggleInput = switchContainer.locator('[data-slot="switch-input"]') + + const isDisabled = await toggleInput.evaluate((el: HTMLInputElement) => el.disabled) + if (isDisabled) { + test.skip() + return + } + + const initialState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) + expect(initialState).toBe(true) + + await switchContainer.locator('[data-slot="switch-control"]').click() + await page.waitForTimeout(100) + + const newState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) + expect(newState).toBe(false) + + const stored = await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + + expect(stored?.updates?.startup).toBe(false) +}) + +test("toggling release notes switch updates localStorage", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = await openSettings(page) + const switchContainer = dialog.locator(settingsReleaseNotesSelector) + await expect(switchContainer).toBeVisible() + + const toggleInput = switchContainer.locator('[data-slot="switch-input"]') + const initialState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) + expect(initialState).toBe(true) + + await switchContainer.locator('[data-slot="switch-control"]').click() + await page.waitForTimeout(100) + + const newState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) + expect(newState).toBe(false) + + const stored = await page.evaluate((key) => { + const raw = localStorage.getItem(key) + return raw ? JSON.parse(raw) : null + }, settingsKey) + + expect(stored?.general?.releaseNotes).toBe(false) +}) diff --git a/packages/app/e2e/sidebar/sidebar-popover-actions.spec.ts b/packages/app/e2e/sidebar/sidebar-popover-actions.spec.ts new file mode 100644 index 00000000000..e37f94f3a7a --- /dev/null +++ b/packages/app/e2e/sidebar/sidebar-popover-actions.spec.ts @@ -0,0 +1,36 @@ +import { test, expect } from "../fixtures" +import { closeSidebar, hoverSessionItem } from "../actions" +import { projectSwitchSelector, sessionItemSelector } from "../selectors" + +test("collapsed sidebar popover stays open when archiving a session", async ({ page, slug, sdk, gotoSession }) => { + const stamp = Date.now() + + const one = await sdk.session.create({ title: `e2e sidebar popover archive 1 ${stamp}` }).then((r) => r.data) + const two = await sdk.session.create({ title: `e2e sidebar popover archive 2 ${stamp}` }).then((r) => r.data) + + if (!one?.id) throw new Error("Session create did not return an id") + if (!two?.id) throw new Error("Session create did not return an id") + + try { + await gotoSession(one.id) + await closeSidebar(page) + + const project = page.locator(projectSwitchSelector(slug)).first() + await expect(project).toBeVisible() + await project.hover() + + await expect(page.locator(sessionItemSelector(one.id)).first()).toBeVisible() + await expect(page.locator(sessionItemSelector(two.id)).first()).toBeVisible() + + const item = await hoverSessionItem(page, one.id) + await item + .getByRole("button", { name: /archive/i }) + .first() + .click() + + await expect(page.locator(sessionItemSelector(two.id)).first()).toBeVisible() + } finally { + await sdk.session.delete({ sessionID: one.id }).catch(() => undefined) + await sdk.session.delete({ sessionID: two.id }).catch(() => undefined) + } +}) diff --git a/packages/app/e2e/sidebar/sidebar-session-links.spec.ts b/packages/app/e2e/sidebar/sidebar-session-links.spec.ts new file mode 100644 index 00000000000..cda2278a950 --- /dev/null +++ b/packages/app/e2e/sidebar/sidebar-session-links.spec.ts @@ -0,0 +1,31 @@ +import { test, expect } from "../fixtures" +import { openSidebar, withSession } from "../actions" +import { promptSelector } from "../selectors" + +test("sidebar session links navigate to the selected session", async ({ page, slug, sdk, gotoSession }) => { + const stamp = Date.now() + + const one = await sdk.session.create({ title: `e2e sidebar nav 1 ${stamp}` }).then((r) => r.data) + const two = await sdk.session.create({ title: `e2e sidebar nav 2 ${stamp}` }).then((r) => r.data) + + if (!one?.id) throw new Error("Session create did not return an id") + if (!two?.id) throw new Error("Session create did not return an id") + + try { + await gotoSession(one.id) + + await openSidebar(page) + + const target = page.locator(`[data-session-id="${two.id}"] a`).first() + await expect(target).toBeVisible() + await target.scrollIntoViewIfNeeded() + await target.click() + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${two.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + await expect(page.locator(`[data-session-id="${two.id}"] a`).first()).toHaveClass(/\bactive\b/) + } finally { + await sdk.session.delete({ sessionID: one.id }).catch(() => undefined) + await sdk.session.delete({ sessionID: two.id }).catch(() => undefined) + } +}) diff --git a/packages/app/e2e/sidebar/sidebar.spec.ts b/packages/app/e2e/sidebar/sidebar.spec.ts new file mode 100644 index 00000000000..5c78c2220d2 --- /dev/null +++ b/packages/app/e2e/sidebar/sidebar.spec.ts @@ -0,0 +1,37 @@ +import { test, expect } from "../fixtures" +import { openSidebar, toggleSidebar, withSession } from "../actions" + +test("sidebar can be collapsed and expanded", async ({ page, gotoSession }) => { + await gotoSession() + + await openSidebar(page) + + await toggleSidebar(page) + await expect(page.locator("main")).toHaveClass(/xl:border-l/) + + await toggleSidebar(page) + await expect(page.locator("main")).not.toHaveClass(/xl:border-l/) +}) + +test("sidebar collapsed state persists across navigation and reload", async ({ page, sdk, gotoSession }) => { + await withSession(sdk, "sidebar persist session 1", async (session1) => { + await withSession(sdk, "sidebar persist session 2", async (session2) => { + await gotoSession(session1.id) + + await openSidebar(page) + await toggleSidebar(page) + await expect(page.locator("main")).toHaveClass(/xl:border-l/) + + await gotoSession(session2.id) + await expect(page.locator("main")).toHaveClass(/xl:border-l/) + + await page.reload() + await expect(page.locator("main")).toHaveClass(/xl:border-l/) + + const opened = await page.evaluate( + () => JSON.parse(localStorage.getItem("opencode.global.dat:layout") ?? "{}").sidebar?.opened, + ) + await expect(opened).toBe(false) + }) + }) +}) diff --git a/packages/app/e2e/status/status-popover.spec.ts b/packages/app/e2e/status/status-popover.spec.ts new file mode 100644 index 00000000000..d53578a4910 --- /dev/null +++ b/packages/app/e2e/status/status-popover.spec.ts @@ -0,0 +1,94 @@ +import { test, expect } from "../fixtures" +import { openStatusPopover } from "../actions" + +test("status popover opens and shows tabs", async ({ page, gotoSession }) => { + await gotoSession() + + const { popoverBody } = await openStatusPopover(page) + + await expect(popoverBody.getByRole("tab", { name: /servers/i })).toBeVisible() + await expect(popoverBody.getByRole("tab", { name: /mcp/i })).toBeVisible() + await expect(popoverBody.getByRole("tab", { name: /lsp/i })).toBeVisible() + await expect(popoverBody.getByRole("tab", { name: /plugins/i })).toBeVisible() + + await page.keyboard.press("Escape") + await expect(popoverBody).toHaveCount(0) +}) + +test("status popover servers tab shows current server", async ({ page, gotoSession }) => { + await gotoSession() + + const { popoverBody } = await openStatusPopover(page) + + const serversTab = popoverBody.getByRole("tab", { name: /servers/i }) + await expect(serversTab).toHaveAttribute("aria-selected", "true") + + const serverList = popoverBody.locator('[role="tabpanel"]').first() + await expect(serverList.locator("button").first()).toBeVisible() +}) + +test("status popover can switch to mcp tab", async ({ page, gotoSession }) => { + await gotoSession() + + const { popoverBody } = await openStatusPopover(page) + + const mcpTab = popoverBody.getByRole("tab", { name: /mcp/i }) + await mcpTab.click() + + const ariaSelected = await mcpTab.getAttribute("aria-selected") + expect(ariaSelected).toBe("true") + + const mcpContent = popoverBody.locator('[role="tabpanel"]:visible').first() + await expect(mcpContent).toBeVisible() +}) + +test("status popover can switch to lsp tab", async ({ page, gotoSession }) => { + await gotoSession() + + const { popoverBody } = await openStatusPopover(page) + + const lspTab = popoverBody.getByRole("tab", { name: /lsp/i }) + await lspTab.click() + + const ariaSelected = await lspTab.getAttribute("aria-selected") + expect(ariaSelected).toBe("true") + + const lspContent = popoverBody.locator('[role="tabpanel"]:visible').first() + await expect(lspContent).toBeVisible() +}) + +test("status popover can switch to plugins tab", async ({ page, gotoSession }) => { + await gotoSession() + + const { popoverBody } = await openStatusPopover(page) + + const pluginsTab = popoverBody.getByRole("tab", { name: /plugins/i }) + await pluginsTab.click() + + const ariaSelected = await pluginsTab.getAttribute("aria-selected") + expect(ariaSelected).toBe("true") + + const pluginsContent = popoverBody.locator('[role="tabpanel"]:visible').first() + await expect(pluginsContent).toBeVisible() +}) + +test("status popover closes on escape", async ({ page, gotoSession }) => { + await gotoSession() + + const { popoverBody } = await openStatusPopover(page) + await expect(popoverBody).toBeVisible() + + await page.keyboard.press("Escape") + await expect(popoverBody).toHaveCount(0) +}) + +test("status popover closes when clicking outside", async ({ page, gotoSession }) => { + await gotoSession() + + const { popoverBody } = await openStatusPopover(page) + await expect(popoverBody).toBeVisible() + + await page.getByRole("main").click({ position: { x: 5, y: 5 } }) + + await expect(popoverBody).toHaveCount(0) +}) diff --git a/packages/app/e2e/terminal/terminal-init.spec.ts b/packages/app/e2e/terminal/terminal-init.spec.ts new file mode 100644 index 00000000000..87934b66e38 --- /dev/null +++ b/packages/app/e2e/terminal/terminal-init.spec.ts @@ -0,0 +1,26 @@ +import { test, expect } from "../fixtures" +import { promptSelector, terminalSelector } from "../selectors" +import { terminalToggleKey } from "../utils" + +test("smoke terminal mounts and can create a second tab", async ({ page, gotoSession }) => { + await gotoSession() + + const terminals = page.locator(terminalSelector) + const opened = await terminals.first().isVisible() + + if (!opened) { + await page.keyboard.press(terminalToggleKey) + } + + await expect(terminals.first()).toBeVisible() + await expect(terminals.first().locator("textarea")).toHaveCount(1) + await expect(terminals).toHaveCount(1) + + // Ghostty captures a lot of keybinds when focused; move focus back + // to the app shell before triggering `terminal.new`. + await page.locator(promptSelector).click() + await page.keyboard.press("Control+Alt+T") + + await expect(terminals).toHaveCount(2) + await expect(terminals.nth(1).locator("textarea")).toHaveCount(1) +}) diff --git a/packages/app/e2e/terminal/terminal.spec.ts b/packages/app/e2e/terminal/terminal.spec.ts new file mode 100644 index 00000000000..ef88aa34e52 --- /dev/null +++ b/packages/app/e2e/terminal/terminal.spec.ts @@ -0,0 +1,17 @@ +import { test, expect } from "../fixtures" +import { terminalSelector } from "../selectors" +import { terminalToggleKey } from "../utils" + +test("terminal panel can be toggled", async ({ page, gotoSession }) => { + await gotoSession() + + const terminal = page.locator(terminalSelector) + const initiallyOpen = await terminal.isVisible() + if (initiallyOpen) { + await page.keyboard.press(terminalToggleKey) + await expect(terminal).toHaveCount(0) + } + + await page.keyboard.press(terminalToggleKey) + await expect(terminal).toBeVisible() +}) diff --git a/packages/app/src/components/file-tree.test.ts b/packages/app/src/components/file-tree.test.ts new file mode 100644 index 00000000000..29e20b4807c --- /dev/null +++ b/packages/app/src/components/file-tree.test.ts @@ -0,0 +1,78 @@ +import { beforeAll, describe, expect, mock, test } from "bun:test" + +let shouldListRoot: typeof import("./file-tree").shouldListRoot +let shouldListExpanded: typeof import("./file-tree").shouldListExpanded +let dirsToExpand: typeof import("./file-tree").dirsToExpand + +beforeAll(async () => { + mock.module("@solidjs/router", () => ({ + useNavigate: () => () => undefined, + useParams: () => ({}), + })) + mock.module("@/context/file", () => ({ + useFile: () => ({ + tree: { + state: () => undefined, + list: () => Promise.resolve(), + children: () => [], + expand: () => {}, + collapse: () => {}, + }, + }), + })) + mock.module("@opencode-ai/ui/collapsible", () => ({ + Collapsible: { + Trigger: (props: { children?: unknown }) => props.children, + Content: (props: { children?: unknown }) => props.children, + }, + })) + mock.module("@opencode-ai/ui/file-icon", () => ({ FileIcon: () => null })) + mock.module("@opencode-ai/ui/icon", () => ({ Icon: () => null })) + mock.module("@opencode-ai/ui/tooltip", () => ({ Tooltip: (props: { children?: unknown }) => props.children })) + const mod = await import("./file-tree") + shouldListRoot = mod.shouldListRoot + shouldListExpanded = mod.shouldListExpanded + dirsToExpand = mod.dirsToExpand +}) + +describe("file tree fetch discipline", () => { + test("root lists on mount unless already loaded or loading", () => { + expect(shouldListRoot({ level: 0 })).toBe(true) + expect(shouldListRoot({ level: 0, dir: { loaded: true } })).toBe(false) + expect(shouldListRoot({ level: 0, dir: { loading: true } })).toBe(false) + expect(shouldListRoot({ level: 1 })).toBe(false) + }) + + test("nested dirs list only when expanded and stale", () => { + expect(shouldListExpanded({ level: 1 })).toBe(false) + expect(shouldListExpanded({ level: 1, dir: { expanded: false } })).toBe(false) + expect(shouldListExpanded({ level: 1, dir: { expanded: true } })).toBe(true) + expect(shouldListExpanded({ level: 1, dir: { expanded: true, loaded: true } })).toBe(false) + expect(shouldListExpanded({ level: 1, dir: { expanded: true, loading: true } })).toBe(false) + expect(shouldListExpanded({ level: 0, dir: { expanded: true } })).toBe(false) + }) + + test("allowed auto-expand picks only collapsed dirs", () => { + const expanded = new Set() + const filter = { dirs: new Set(["src", "src/components"]) } + + const first = dirsToExpand({ + level: 0, + filter, + expanded: (dir) => expanded.has(dir), + }) + + expect(first).toEqual(["src", "src/components"]) + + for (const dir of first) expanded.add(dir) + + const second = dirsToExpand({ + level: 0, + filter, + expanded: (dir) => expanded.has(dir), + }) + + expect(second).toEqual([]) + expect(dirsToExpand({ level: 1, filter, expanded: () => false })).toEqual([]) + }) +}) diff --git a/packages/app/src/components/prompt-input/attachments.ts b/packages/app/src/components/prompt-input/attachments.ts new file mode 100644 index 00000000000..232b7557df6 --- /dev/null +++ b/packages/app/src/components/prompt-input/attachments.ts @@ -0,0 +1,157 @@ +import { onCleanup, onMount } from "solid-js" +import { showToast } from "@opencode-ai/ui/toast" +import { usePrompt, type ContentPart, type ImageAttachmentPart } from "@/context/prompt" +import { useLanguage } from "@/context/language" +import { uuid } from "@/utils/uuid" +import { getCursorPosition } from "./editor-dom" + +export const ACCEPTED_IMAGE_TYPES = ["image/png", "image/jpeg", "image/gif", "image/webp"] +export const ACCEPTED_FILE_TYPES = [...ACCEPTED_IMAGE_TYPES, "application/pdf"] + +type PromptAttachmentsInput = { + editor: () => HTMLDivElement | undefined + isFocused: () => boolean + isDialogActive: () => boolean + setDraggingType: (type: "image" | "@mention" | null) => void + focusEditor: () => void + addPart: (part: ContentPart) => void + readClipboardImage?: () => Promise +} + +export function createPromptAttachments(input: PromptAttachmentsInput) { + const prompt = usePrompt() + const language = useLanguage() + + const addImageAttachment = async (file: File) => { + if (!ACCEPTED_FILE_TYPES.includes(file.type)) return + + const reader = new FileReader() + reader.onload = () => { + const editor = input.editor() + if (!editor) return + const dataUrl = reader.result as string + const attachment: ImageAttachmentPart = { + type: "image", + id: uuid(), + filename: file.name, + mime: file.type, + dataUrl, + } + const cursorPosition = prompt.cursor() ?? getCursorPosition(editor) + prompt.set([...prompt.current(), attachment], cursorPosition) + } + reader.readAsDataURL(file) + } + + const removeImageAttachment = (id: string) => { + const current = prompt.current() + const next = current.filter((part) => part.type !== "image" || part.id !== id) + prompt.set(next, prompt.cursor()) + } + + const handlePaste = async (event: ClipboardEvent) => { + if (!input.isFocused()) return + const clipboardData = event.clipboardData + if (!clipboardData) return + + event.preventDefault() + event.stopPropagation() + + const items = Array.from(clipboardData.items) + const fileItems = items.filter((item) => item.kind === "file") + const imageItems = fileItems.filter((item) => ACCEPTED_FILE_TYPES.includes(item.type)) + + if (imageItems.length > 0) { + for (const item of imageItems) { + const file = item.getAsFile() + if (file) await addImageAttachment(file) + } + return + } + + if (fileItems.length > 0) { + showToast({ + title: language.t("prompt.toast.pasteUnsupported.title"), + description: language.t("prompt.toast.pasteUnsupported.description"), + }) + return + } + + const plainText = clipboardData.getData("text/plain") ?? "" + + // Desktop: Browser clipboard has no images and no text, try platform's native clipboard for images + if (input.readClipboardImage && !plainText) { + const file = await input.readClipboardImage() + if (file) { + await addImageAttachment(file) + return + } + } + + if (!plainText) return + input.addPart({ type: "text", content: plainText, start: 0, end: 0 }) + } + + const handleGlobalDragOver = (event: DragEvent) => { + if (input.isDialogActive()) return + + event.preventDefault() + const hasFiles = event.dataTransfer?.types.includes("Files") + const hasText = event.dataTransfer?.types.includes("text/plain") + if (hasFiles) { + input.setDraggingType("image") + } else if (hasText) { + input.setDraggingType("@mention") + } + } + + const handleGlobalDragLeave = (event: DragEvent) => { + if (input.isDialogActive()) return + if (!event.relatedTarget) { + input.setDraggingType(null) + } + } + + const handleGlobalDrop = async (event: DragEvent) => { + if (input.isDialogActive()) return + + event.preventDefault() + input.setDraggingType(null) + + const plainText = event.dataTransfer?.getData("text/plain") + const filePrefix = "file:" + if (plainText?.startsWith(filePrefix)) { + const filePath = plainText.slice(filePrefix.length) + input.focusEditor() + input.addPart({ type: "file", path: filePath, content: "@" + filePath, start: 0, end: 0 }) + return + } + + const dropped = event.dataTransfer?.files + if (!dropped) return + + for (const file of Array.from(dropped)) { + if (ACCEPTED_FILE_TYPES.includes(file.type)) { + await addImageAttachment(file) + } + } + } + + onMount(() => { + document.addEventListener("dragover", handleGlobalDragOver) + document.addEventListener("dragleave", handleGlobalDragLeave) + document.addEventListener("drop", handleGlobalDrop) + }) + + onCleanup(() => { + document.removeEventListener("dragover", handleGlobalDragOver) + document.removeEventListener("dragleave", handleGlobalDragLeave) + document.removeEventListener("drop", handleGlobalDrop) + }) + + return { + addImageAttachment, + removeImageAttachment, + handlePaste, + } +} diff --git a/packages/app/src/components/prompt-input/build-request-parts.test.ts b/packages/app/src/components/prompt-input/build-request-parts.test.ts new file mode 100644 index 00000000000..72bdecc01f3 --- /dev/null +++ b/packages/app/src/components/prompt-input/build-request-parts.test.ts @@ -0,0 +1,277 @@ +import { describe, expect, test } from "bun:test" +import type { Prompt } from "@/context/prompt" +import { buildRequestParts } from "./build-request-parts" + +describe("buildRequestParts", () => { + test("builds typed request and optimistic parts without cast path", () => { + const prompt: Prompt = [ + { type: "text", content: "hello", start: 0, end: 5 }, + { + type: "file", + path: "src/foo.ts", + content: "@src/foo.ts", + start: 5, + end: 16, + selection: { startLine: 4, startChar: 1, endLine: 6, endChar: 1 }, + }, + { type: "agent", name: "planner", content: "@planner", start: 16, end: 24 }, + ] + + const result = buildRequestParts({ + prompt, + context: [{ key: "ctx:1", type: "file", path: "src/bar.ts", comment: "check this" }], + images: [ + { type: "image", id: "img_1", filename: "a.png", mime: "image/png", dataUrl: "data:image/png;base64,AAA" }, + ], + text: "hello @src/foo.ts @planner", + messageID: "msg_1", + sessionID: "ses_1", + sessionDirectory: "/repo", + }) + + expect(result.requestParts[0]?.type).toBe("text") + expect(result.requestParts.some((part) => part.type === "agent")).toBe(true) + expect( + result.requestParts.some((part) => part.type === "file" && part.url.startsWith("file:///repo/src/foo.ts")), + ).toBe(true) + expect(result.requestParts.some((part) => part.type === "text" && part.synthetic)).toBe(true) + + expect(result.optimisticParts).toHaveLength(result.requestParts.length) + expect(result.optimisticParts.every((part) => part.sessionID === "ses_1" && part.messageID === "msg_1")).toBe(true) + }) + + test("deduplicates context files when prompt already includes same path", () => { + const prompt: Prompt = [{ type: "file", path: "src/foo.ts", content: "@src/foo.ts", start: 0, end: 11 }] + + const result = buildRequestParts({ + prompt, + context: [ + { key: "ctx:dup", type: "file", path: "src/foo.ts" }, + { key: "ctx:comment", type: "file", path: "src/foo.ts", comment: "focus here" }, + ], + images: [], + text: "@src/foo.ts", + messageID: "msg_2", + sessionID: "ses_2", + sessionDirectory: "/repo", + }) + + const fooFiles = result.requestParts.filter( + (part) => part.type === "file" && part.url.startsWith("file:///repo/src/foo.ts"), + ) + const synthetic = result.requestParts.filter((part) => part.type === "text" && part.synthetic) + + expect(fooFiles).toHaveLength(2) + expect(synthetic).toHaveLength(1) + }) + + test("handles Windows paths correctly (simulated on macOS)", () => { + const prompt: Prompt = [{ type: "file", path: "src\\foo.ts", content: "@src\\foo.ts", start: 0, end: 11 }] + + const result = buildRequestParts({ + prompt, + context: [], + images: [], + text: "@src\\foo.ts", + messageID: "msg_win_1", + sessionID: "ses_win_1", + sessionDirectory: "D:\\projects\\myapp", // Windows path + }) + + // Should create valid file URLs + const filePart = result.requestParts.find((part) => part.type === "file") + expect(filePart).toBeDefined() + if (filePart?.type === "file") { + // URL should be parseable + expect(() => new URL(filePart.url)).not.toThrow() + // Should not have encoded backslashes in wrong place + expect(filePart.url).not.toContain("%5C") + // Should have normalized to forward slashes + expect(filePart.url).toContain("/src/foo.ts") + } + }) + + test("handles Windows absolute path with special characters", () => { + const prompt: Prompt = [{ type: "file", path: "file#name.txt", content: "@file#name.txt", start: 0, end: 14 }] + + const result = buildRequestParts({ + prompt, + context: [], + images: [], + text: "@file#name.txt", + messageID: "msg_win_2", + sessionID: "ses_win_2", + sessionDirectory: "C:\\Users\\test\\Documents", // Windows path + }) + + const filePart = result.requestParts.find((part) => part.type === "file") + expect(filePart).toBeDefined() + if (filePart?.type === "file") { + // URL should be parseable + expect(() => new URL(filePart.url)).not.toThrow() + // Special chars should be encoded + expect(filePart.url).toContain("file%23name.txt") + // Should have Windows drive letter properly encoded + expect(filePart.url).toMatch(/file:\/\/\/[A-Z]:/) + } + }) + + test("handles Linux absolute paths correctly", () => { + const prompt: Prompt = [{ type: "file", path: "src/app.ts", content: "@src/app.ts", start: 0, end: 10 }] + + const result = buildRequestParts({ + prompt, + context: [], + images: [], + text: "@src/app.ts", + messageID: "msg_linux_1", + sessionID: "ses_linux_1", + sessionDirectory: "/home/user/project", + }) + + const filePart = result.requestParts.find((part) => part.type === "file") + expect(filePart).toBeDefined() + if (filePart?.type === "file") { + // URL should be parseable + expect(() => new URL(filePart.url)).not.toThrow() + // Should be a normal Unix path + expect(filePart.url).toBe("file:///home/user/project/src/app.ts") + } + }) + + test("handles macOS paths correctly", () => { + const prompt: Prompt = [{ type: "file", path: "README.md", content: "@README.md", start: 0, end: 9 }] + + const result = buildRequestParts({ + prompt, + context: [], + images: [], + text: "@README.md", + messageID: "msg_mac_1", + sessionID: "ses_mac_1", + sessionDirectory: "/Users/kelvin/Projects/opencode", + }) + + const filePart = result.requestParts.find((part) => part.type === "file") + expect(filePart).toBeDefined() + if (filePart?.type === "file") { + // URL should be parseable + expect(() => new URL(filePart.url)).not.toThrow() + // Should be a normal Unix path + expect(filePart.url).toBe("file:///Users/kelvin/Projects/opencode/README.md") + } + }) + + test("handles context files with Windows paths", () => { + const prompt: Prompt = [] + + const result = buildRequestParts({ + prompt, + context: [ + { key: "ctx:1", type: "file", path: "src\\utils\\helper.ts" }, + { key: "ctx:2", type: "file", path: "test\\unit.test.ts", comment: "check tests" }, + ], + images: [], + text: "test", + messageID: "msg_win_ctx", + sessionID: "ses_win_ctx", + sessionDirectory: "D:\\workspace\\app", + }) + + const fileParts = result.requestParts.filter((part) => part.type === "file") + expect(fileParts).toHaveLength(2) + + // All file URLs should be valid + fileParts.forEach((part) => { + if (part.type === "file") { + expect(() => new URL(part.url)).not.toThrow() + expect(part.url).not.toContain("%5C") // No encoded backslashes + } + }) + }) + + test("handles absolute Windows paths (user manually specifies full path)", () => { + const prompt: Prompt = [ + { type: "file", path: "D:\\other\\project\\file.ts", content: "@D:\\other\\project\\file.ts", start: 0, end: 25 }, + ] + + const result = buildRequestParts({ + prompt, + context: [], + images: [], + text: "@D:\\other\\project\\file.ts", + messageID: "msg_abs", + sessionID: "ses_abs", + sessionDirectory: "C:\\current\\project", + }) + + const filePart = result.requestParts.find((part) => part.type === "file") + expect(filePart).toBeDefined() + if (filePart?.type === "file") { + // Should handle absolute path that differs from sessionDirectory + expect(() => new URL(filePart.url)).not.toThrow() + expect(filePart.url).toContain("/D:/other/project/file.ts") + } + }) + + test("handles selection with query parameters on Windows", () => { + const prompt: Prompt = [ + { + type: "file", + path: "src\\App.tsx", + content: "@src\\App.tsx", + start: 0, + end: 11, + selection: { startLine: 10, startChar: 0, endLine: 20, endChar: 5 }, + }, + ] + + const result = buildRequestParts({ + prompt, + context: [], + images: [], + text: "@src\\App.tsx", + messageID: "msg_sel", + sessionID: "ses_sel", + sessionDirectory: "C:\\project", + }) + + const filePart = result.requestParts.find((part) => part.type === "file") + expect(filePart).toBeDefined() + if (filePart?.type === "file") { + // Should have query parameters + expect(filePart.url).toContain("?start=10&end=20") + // Should be valid URL + expect(() => new URL(filePart.url)).not.toThrow() + // Query params should parse correctly + const url = new URL(filePart.url) + expect(url.searchParams.get("start")).toBe("10") + expect(url.searchParams.get("end")).toBe("20") + } + }) + + test("handles file paths with dots and special segments on Windows", () => { + const prompt: Prompt = [ + { type: "file", path: "..\\..\\shared\\util.ts", content: "@..\\..\\shared\\util.ts", start: 0, end: 21 }, + ] + + const result = buildRequestParts({ + prompt, + context: [], + images: [], + text: "@..\\..\\shared\\util.ts", + messageID: "msg_dots", + sessionID: "ses_dots", + sessionDirectory: "C:\\projects\\myapp\\src", + }) + + const filePart = result.requestParts.find((part) => part.type === "file") + expect(filePart).toBeDefined() + if (filePart?.type === "file") { + // Should be valid URL + expect(() => new URL(filePart.url)).not.toThrow() + // Should preserve .. segments (backend normalizes) + expect(filePart.url).toContain("/..") + } + }) +}) diff --git a/packages/app/src/components/prompt-input/build-request-parts.ts b/packages/app/src/components/prompt-input/build-request-parts.ts new file mode 100644 index 00000000000..0cc54dc2b78 --- /dev/null +++ b/packages/app/src/components/prompt-input/build-request-parts.ts @@ -0,0 +1,179 @@ +import { getFilename } from "@opencode-ai/util/path" +import { type AgentPartInput, type FilePartInput, type Part, type TextPartInput } from "@opencode-ai/sdk/v2/client" +import type { FileSelection } from "@/context/file" +import { encodeFilePath } from "@/context/file/path" +import type { AgentPart, FileAttachmentPart, ImageAttachmentPart, Prompt } from "@/context/prompt" +import { Identifier } from "@/utils/id" + +type PromptRequestPart = (TextPartInput | FilePartInput | AgentPartInput) & { id: string } + +type ContextFile = { + key: string + type: "file" + path: string + selection?: FileSelection + comment?: string + commentID?: string + commentOrigin?: "review" | "file" + preview?: string +} + +type BuildRequestPartsInput = { + prompt: Prompt + context: ContextFile[] + images: ImageAttachmentPart[] + text: string + messageID: string + sessionID: string + sessionDirectory: string +} + +const absolute = (directory: string, path: string) => { + if (path.startsWith("/")) return path + if (/^[A-Za-z]:[\\/]/.test(path) || /^[A-Za-z]:$/.test(path)) return path + if (path.startsWith("\\\\") || path.startsWith("//")) return path + return `${directory.replace(/[\\/]+$/, "")}/${path}` +} + +const fileQuery = (selection: FileSelection | undefined) => + selection ? `?start=${selection.startLine}&end=${selection.endLine}` : "" + +const isFileAttachment = (part: Prompt[number]): part is FileAttachmentPart => part.type === "file" +const isAgentAttachment = (part: Prompt[number]): part is AgentPart => part.type === "agent" + +const commentNote = (path: string, selection: FileSelection | undefined, comment: string) => { + const start = selection ? Math.min(selection.startLine, selection.endLine) : undefined + const end = selection ? Math.max(selection.startLine, selection.endLine) : undefined + const range = + start === undefined || end === undefined + ? "this file" + : start === end + ? `line ${start}` + : `lines ${start} through ${end}` + return `The user made the following comment regarding ${range} of ${path}: ${comment}` +} + +const toOptimisticPart = (part: PromptRequestPart, sessionID: string, messageID: string): Part => { + if (part.type === "text") { + return { + id: part.id, + type: "text", + text: part.text, + synthetic: part.synthetic, + ignored: part.ignored, + time: part.time, + metadata: part.metadata, + sessionID, + messageID, + } + } + if (part.type === "file") { + return { + id: part.id, + type: "file", + mime: part.mime, + filename: part.filename, + url: part.url, + source: part.source, + sessionID, + messageID, + } + } + return { + id: part.id, + type: "agent", + name: part.name, + source: part.source, + sessionID, + messageID, + } +} + +export function buildRequestParts(input: BuildRequestPartsInput) { + const requestParts: PromptRequestPart[] = [ + { + id: Identifier.ascending("part"), + type: "text", + text: input.text, + }, + ] + + const files = input.prompt.filter(isFileAttachment).map((attachment) => { + const path = absolute(input.sessionDirectory, attachment.path) + return { + id: Identifier.ascending("part"), + type: "file", + mime: "text/plain", + url: `file://${encodeFilePath(path)}${fileQuery(attachment.selection)}`, + filename: getFilename(attachment.path), + source: { + type: "file", + text: { + value: attachment.content, + start: attachment.start, + end: attachment.end, + }, + path, + }, + } satisfies PromptRequestPart + }) + + const agents = input.prompt.filter(isAgentAttachment).map((attachment) => { + return { + id: Identifier.ascending("part"), + type: "agent", + name: attachment.name, + source: { + value: attachment.content, + start: attachment.start, + end: attachment.end, + }, + } satisfies PromptRequestPart + }) + + const used = new Set(files.map((part) => part.url)) + const context = input.context.flatMap((item) => { + const path = absolute(input.sessionDirectory, item.path) + const url = `file://${encodeFilePath(path)}${fileQuery(item.selection)}` + const comment = item.comment?.trim() + if (!comment && used.has(url)) return [] + used.add(url) + + const filePart = { + id: Identifier.ascending("part"), + type: "file", + mime: "text/plain", + url, + filename: getFilename(item.path), + } satisfies PromptRequestPart + + if (!comment) return [filePart] + + return [ + { + id: Identifier.ascending("part"), + type: "text", + text: commentNote(item.path, item.selection, comment), + synthetic: true, + } satisfies PromptRequestPart, + filePart, + ] + }) + + const images = input.images.map((attachment) => { + return { + id: Identifier.ascending("part"), + type: "file", + mime: attachment.mime, + url: attachment.dataUrl, + filename: attachment.filename, + } satisfies PromptRequestPart + }) + + requestParts.push(...files, ...context, ...agents, ...images) + + return { + requestParts, + optimisticParts: requestParts.map((part) => toOptimisticPart(part, input.sessionID, input.messageID)), + } +} diff --git a/packages/app/src/components/prompt-input/context-items.tsx b/packages/app/src/components/prompt-input/context-items.tsx new file mode 100644 index 00000000000..a843e109d82 --- /dev/null +++ b/packages/app/src/components/prompt-input/context-items.tsx @@ -0,0 +1,82 @@ +import { Component, For, Show } from "solid-js" +import { FileIcon } from "@opencode-ai/ui/file-icon" +import { IconButton } from "@opencode-ai/ui/icon-button" +import { Tooltip } from "@opencode-ai/ui/tooltip" +import { getDirectory, getFilename, getFilenameTruncated } from "@opencode-ai/util/path" +import type { ContextItem } from "@/context/prompt" + +type PromptContextItem = ContextItem & { key: string } + +type ContextItemsProps = { + items: PromptContextItem[] + active: (item: PromptContextItem) => boolean + openComment: (item: PromptContextItem) => void + remove: (item: PromptContextItem) => void + t: (key: string) => string +} + +export const PromptContextItems: Component = (props) => { + return ( + 0}> +
+ + {(item) => ( + + + {getDirectory(item.path)} + + {getFilename(item.path)} + + } + placement="top" + openDelay={2000} + > +
props.openComment(item)} + > +
+ +
+ {getFilenameTruncated(item.path, 14)} + + {(sel) => ( + + {sel().startLine === sel().endLine + ? `:${sel().startLine}` + : `:${sel().startLine}-${sel().endLine}`} + + )} + +
+ { + e.stopPropagation() + props.remove(item) + }} + aria-label={props.t("prompt.context.removeFile")} + /> +
+ + {(comment) =>
{comment()}
} +
+
+
+ )} +
+
+
+ ) +} diff --git a/packages/app/src/components/prompt-input/drag-overlay.tsx b/packages/app/src/components/prompt-input/drag-overlay.tsx new file mode 100644 index 00000000000..e05b47d7cf1 --- /dev/null +++ b/packages/app/src/components/prompt-input/drag-overlay.tsx @@ -0,0 +1,20 @@ +import { Component, Show } from "solid-js" +import { Icon } from "@opencode-ai/ui/icon" + +type PromptDragOverlayProps = { + type: "image" | "@mention" | null + label: string +} + +export const PromptDragOverlay: Component = (props) => { + return ( + +
+
+ + {props.label} +
+
+
+ ) +} diff --git a/packages/app/src/components/prompt-input/editor-dom.test.ts b/packages/app/src/components/prompt-input/editor-dom.test.ts new file mode 100644 index 00000000000..fce8b4b9538 --- /dev/null +++ b/packages/app/src/components/prompt-input/editor-dom.test.ts @@ -0,0 +1,51 @@ +import { describe, expect, test } from "bun:test" +import { createTextFragment, getCursorPosition, getNodeLength, getTextLength, setCursorPosition } from "./editor-dom" + +describe("prompt-input editor dom", () => { + test("createTextFragment preserves newlines with br and zero-width placeholders", () => { + const fragment = createTextFragment("foo\n\nbar") + const container = document.createElement("div") + container.appendChild(fragment) + + expect(container.childNodes.length).toBe(5) + expect(container.childNodes[0]?.textContent).toBe("foo") + expect((container.childNodes[1] as HTMLElement).tagName).toBe("BR") + expect(container.childNodes[2]?.textContent).toBe("\u200B") + expect((container.childNodes[3] as HTMLElement).tagName).toBe("BR") + expect(container.childNodes[4]?.textContent).toBe("bar") + }) + + test("length helpers treat breaks as one char and ignore zero-width chars", () => { + const container = document.createElement("div") + container.appendChild(document.createTextNode("ab\u200B")) + container.appendChild(document.createElement("br")) + container.appendChild(document.createTextNode("cd")) + + expect(getNodeLength(container.childNodes[0]!)).toBe(2) + expect(getNodeLength(container.childNodes[1]!)).toBe(1) + expect(getTextLength(container)).toBe(5) + }) + + test("setCursorPosition and getCursorPosition round-trip with pills and breaks", () => { + const container = document.createElement("div") + const pill = document.createElement("span") + pill.dataset.type = "file" + pill.textContent = "@file" + container.appendChild(document.createTextNode("ab")) + container.appendChild(pill) + container.appendChild(document.createElement("br")) + container.appendChild(document.createTextNode("cd")) + document.body.appendChild(container) + + setCursorPosition(container, 2) + expect(getCursorPosition(container)).toBe(2) + + setCursorPosition(container, 7) + expect(getCursorPosition(container)).toBe(7) + + setCursorPosition(container, 8) + expect(getCursorPosition(container)).toBe(8) + + container.remove() + }) +}) diff --git a/packages/app/src/components/prompt-input/editor-dom.ts b/packages/app/src/components/prompt-input/editor-dom.ts new file mode 100644 index 00000000000..3116ceb1268 --- /dev/null +++ b/packages/app/src/components/prompt-input/editor-dom.ts @@ -0,0 +1,135 @@ +export function createTextFragment(content: string): DocumentFragment { + const fragment = document.createDocumentFragment() + const segments = content.split("\n") + segments.forEach((segment, index) => { + if (segment) { + fragment.appendChild(document.createTextNode(segment)) + } else if (segments.length > 1) { + fragment.appendChild(document.createTextNode("\u200B")) + } + if (index < segments.length - 1) { + fragment.appendChild(document.createElement("br")) + } + }) + return fragment +} + +export function getNodeLength(node: Node): number { + if (node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).tagName === "BR") return 1 + return (node.textContent ?? "").replace(/\u200B/g, "").length +} + +export function getTextLength(node: Node): number { + if (node.nodeType === Node.TEXT_NODE) return (node.textContent ?? "").replace(/\u200B/g, "").length + if (node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).tagName === "BR") return 1 + let length = 0 + for (const child of Array.from(node.childNodes)) { + length += getTextLength(child) + } + return length +} + +export function getCursorPosition(parent: HTMLElement): number { + const selection = window.getSelection() + if (!selection || selection.rangeCount === 0) return 0 + const range = selection.getRangeAt(0) + if (!parent.contains(range.startContainer)) return 0 + const preCaretRange = range.cloneRange() + preCaretRange.selectNodeContents(parent) + preCaretRange.setEnd(range.startContainer, range.startOffset) + return getTextLength(preCaretRange.cloneContents()) +} + +export function setCursorPosition(parent: HTMLElement, position: number) { + let remaining = position + let node = parent.firstChild + while (node) { + const length = getNodeLength(node) + const isText = node.nodeType === Node.TEXT_NODE + const isPill = + node.nodeType === Node.ELEMENT_NODE && + ((node as HTMLElement).dataset.type === "file" || (node as HTMLElement).dataset.type === "agent") + const isBreak = node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).tagName === "BR" + + if (isText && remaining <= length) { + const range = document.createRange() + const selection = window.getSelection() + range.setStart(node, remaining) + range.collapse(true) + selection?.removeAllRanges() + selection?.addRange(range) + return + } + + if ((isPill || isBreak) && remaining <= length) { + const range = document.createRange() + const selection = window.getSelection() + if (remaining === 0) { + range.setStartBefore(node) + } + if (remaining > 0 && isPill) { + range.setStartAfter(node) + } + if (remaining > 0 && isBreak) { + const next = node.nextSibling + if (next && next.nodeType === Node.TEXT_NODE) { + range.setStart(next, 0) + } + if (!next || next.nodeType !== Node.TEXT_NODE) { + range.setStartAfter(node) + } + } + range.collapse(true) + selection?.removeAllRanges() + selection?.addRange(range) + return + } + + remaining -= length + node = node.nextSibling + } + + const fallbackRange = document.createRange() + const fallbackSelection = window.getSelection() + const last = parent.lastChild + if (last && last.nodeType === Node.TEXT_NODE) { + const len = last.textContent ? last.textContent.length : 0 + fallbackRange.setStart(last, len) + } + if (!last || last.nodeType !== Node.TEXT_NODE) { + fallbackRange.selectNodeContents(parent) + } + fallbackRange.collapse(false) + fallbackSelection?.removeAllRanges() + fallbackSelection?.addRange(fallbackRange) +} + +export function setRangeEdge(parent: HTMLElement, range: Range, edge: "start" | "end", offset: number) { + let remaining = offset + const nodes = Array.from(parent.childNodes) + + for (const node of nodes) { + const length = getNodeLength(node) + const isText = node.nodeType === Node.TEXT_NODE + const isPill = + node.nodeType === Node.ELEMENT_NODE && + ((node as HTMLElement).dataset.type === "file" || (node as HTMLElement).dataset.type === "agent") + const isBreak = node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).tagName === "BR" + + if (isText && remaining <= length) { + if (edge === "start") range.setStart(node, remaining) + if (edge === "end") range.setEnd(node, remaining) + return + } + + if ((isPill || isBreak) && remaining <= length) { + if (edge === "start" && remaining === 0) range.setStartBefore(node) + if (edge === "start" && remaining > 0) range.setStartAfter(node) + if (edge === "end" && remaining === 0) range.setEndBefore(node) + if (edge === "end" && remaining > 0) range.setEndAfter(node) + return + } + + remaining -= length + } +} diff --git a/packages/app/src/components/prompt-input/history.test.ts b/packages/app/src/components/prompt-input/history.test.ts new file mode 100644 index 00000000000..54be9cb75b2 --- /dev/null +++ b/packages/app/src/components/prompt-input/history.test.ts @@ -0,0 +1,69 @@ +import { describe, expect, test } from "bun:test" +import type { Prompt } from "@/context/prompt" +import { clonePromptParts, navigatePromptHistory, prependHistoryEntry, promptLength } from "./history" + +const DEFAULT_PROMPT: Prompt = [{ type: "text", content: "", start: 0, end: 0 }] + +const text = (value: string): Prompt => [{ type: "text", content: value, start: 0, end: value.length }] + +describe("prompt-input history", () => { + test("prependHistoryEntry skips empty prompt and deduplicates consecutive entries", () => { + const first = prependHistoryEntry([], DEFAULT_PROMPT) + expect(first).toEqual([]) + + const withOne = prependHistoryEntry([], text("hello")) + expect(withOne).toHaveLength(1) + + const deduped = prependHistoryEntry(withOne, text("hello")) + expect(deduped).toBe(withOne) + }) + + test("navigatePromptHistory restores saved prompt when moving down from newest", () => { + const entries = [text("third"), text("second"), text("first")] + const up = navigatePromptHistory({ + direction: "up", + entries, + historyIndex: -1, + currentPrompt: text("draft"), + savedPrompt: null, + }) + expect(up.handled).toBe(true) + if (!up.handled) throw new Error("expected handled") + expect(up.historyIndex).toBe(0) + expect(up.cursor).toBe("start") + + const down = navigatePromptHistory({ + direction: "down", + entries, + historyIndex: up.historyIndex, + currentPrompt: text("ignored"), + savedPrompt: up.savedPrompt, + }) + expect(down.handled).toBe(true) + if (!down.handled) throw new Error("expected handled") + expect(down.historyIndex).toBe(-1) + expect(down.prompt[0]?.type === "text" ? down.prompt[0].content : "").toBe("draft") + }) + + test("helpers clone prompt and count text content length", () => { + const original: Prompt = [ + { type: "text", content: "one", start: 0, end: 3 }, + { + type: "file", + path: "src/a.ts", + content: "@src/a.ts", + start: 3, + end: 12, + selection: { startLine: 1, startChar: 1, endLine: 2, endChar: 1 }, + }, + { type: "image", id: "1", filename: "img.png", mime: "image/png", dataUrl: "data:image/png;base64,abc" }, + ] + const copy = clonePromptParts(original) + expect(copy).not.toBe(original) + expect(promptLength(copy)).toBe(12) + if (copy[1]?.type !== "file") throw new Error("expected file") + copy[1].selection!.startLine = 9 + if (original[1]?.type !== "file") throw new Error("expected file") + expect(original[1].selection?.startLine).toBe(1) + }) +}) diff --git a/packages/app/src/components/prompt-input/history.ts b/packages/app/src/components/prompt-input/history.ts new file mode 100644 index 00000000000..63164f0ba3c --- /dev/null +++ b/packages/app/src/components/prompt-input/history.ts @@ -0,0 +1,160 @@ +import type { Prompt } from "@/context/prompt" + +const DEFAULT_PROMPT: Prompt = [{ type: "text", content: "", start: 0, end: 0 }] + +export const MAX_HISTORY = 100 + +export function clonePromptParts(prompt: Prompt): Prompt { + return prompt.map((part) => { + if (part.type === "text") return { ...part } + if (part.type === "image") return { ...part } + if (part.type === "agent") return { ...part } + return { + ...part, + selection: part.selection ? { ...part.selection } : undefined, + } + }) +} + +export function promptLength(prompt: Prompt) { + return prompt.reduce((len, part) => len + ("content" in part ? part.content.length : 0), 0) +} + +export function prependHistoryEntry(entries: Prompt[], prompt: Prompt, max = MAX_HISTORY) { + const text = prompt + .map((part) => ("content" in part ? part.content : "")) + .join("") + .trim() + const hasImages = prompt.some((part) => part.type === "image") + if (!text && !hasImages) return entries + + const entry = clonePromptParts(prompt) + const last = entries[0] + if (last && isPromptEqual(last, entry)) return entries + return [entry, ...entries].slice(0, max) +} + +function isPromptEqual(promptA: Prompt, promptB: Prompt) { + if (promptA.length !== promptB.length) return false + for (let i = 0; i < promptA.length; i++) { + const partA = promptA[i] + const partB = promptB[i] + if (partA.type !== partB.type) return false + if (partA.type === "text" && partA.content !== (partB.type === "text" ? partB.content : "")) return false + if (partA.type === "file") { + if (partA.path !== (partB.type === "file" ? partB.path : "")) return false + const a = partA.selection + const b = partB.type === "file" ? partB.selection : undefined + const sameSelection = + (!a && !b) || + (!!a && + !!b && + a.startLine === b.startLine && + a.startChar === b.startChar && + a.endLine === b.endLine && + a.endChar === b.endChar) + if (!sameSelection) return false + } + if (partA.type === "agent" && partA.name !== (partB.type === "agent" ? partB.name : "")) return false + if (partA.type === "image" && partA.id !== (partB.type === "image" ? partB.id : "")) return false + } + return true +} + +type HistoryNavInput = { + direction: "up" | "down" + entries: Prompt[] + historyIndex: number + currentPrompt: Prompt + savedPrompt: Prompt | null +} + +type HistoryNavResult = + | { + handled: false + historyIndex: number + savedPrompt: Prompt | null + } + | { + handled: true + historyIndex: number + savedPrompt: Prompt | null + prompt: Prompt + cursor: "start" | "end" + } + +export function navigatePromptHistory(input: HistoryNavInput): HistoryNavResult { + if (input.direction === "up") { + if (input.entries.length === 0) { + return { + handled: false, + historyIndex: input.historyIndex, + savedPrompt: input.savedPrompt, + } + } + + if (input.historyIndex === -1) { + return { + handled: true, + historyIndex: 0, + savedPrompt: clonePromptParts(input.currentPrompt), + prompt: input.entries[0], + cursor: "start", + } + } + + if (input.historyIndex < input.entries.length - 1) { + const next = input.historyIndex + 1 + return { + handled: true, + historyIndex: next, + savedPrompt: input.savedPrompt, + prompt: input.entries[next], + cursor: "start", + } + } + + return { + handled: false, + historyIndex: input.historyIndex, + savedPrompt: input.savedPrompt, + } + } + + if (input.historyIndex > 0) { + const next = input.historyIndex - 1 + return { + handled: true, + historyIndex: next, + savedPrompt: input.savedPrompt, + prompt: input.entries[next], + cursor: "end", + } + } + + if (input.historyIndex === 0) { + if (input.savedPrompt) { + return { + handled: true, + historyIndex: -1, + savedPrompt: null, + prompt: input.savedPrompt, + cursor: "end", + } + } + + return { + handled: true, + historyIndex: -1, + savedPrompt: null, + prompt: DEFAULT_PROMPT, + cursor: "end", + } + } + + return { + handled: false, + historyIndex: input.historyIndex, + savedPrompt: input.savedPrompt, + } +} diff --git a/packages/app/src/components/prompt-input/image-attachments.tsx b/packages/app/src/components/prompt-input/image-attachments.tsx new file mode 100644 index 00000000000..ba3addf0a16 --- /dev/null +++ b/packages/app/src/components/prompt-input/image-attachments.tsx @@ -0,0 +1,51 @@ +import { Component, For, Show } from "solid-js" +import { Icon } from "@opencode-ai/ui/icon" +import type { ImageAttachmentPart } from "@/context/prompt" + +type PromptImageAttachmentsProps = { + attachments: ImageAttachmentPart[] + onOpen: (attachment: ImageAttachmentPart) => void + onRemove: (id: string) => void + removeLabel: string +} + +export const PromptImageAttachments: Component = (props) => { + return ( + 0}> +
+ + {(attachment) => ( +
+ + +
+ } + > + {attachment.filename} props.onOpen(attachment)} + /> + + +
+ {attachment.filename} +
+
+ )} + + +
+ ) +} diff --git a/packages/app/src/components/prompt-input/placeholder.test.ts b/packages/app/src/components/prompt-input/placeholder.test.ts new file mode 100644 index 00000000000..b633df82956 --- /dev/null +++ b/packages/app/src/components/prompt-input/placeholder.test.ts @@ -0,0 +1,35 @@ +import { describe, expect, test } from "bun:test" +import { promptPlaceholder } from "./placeholder" + +describe("promptPlaceholder", () => { + const t = (key: string, params?: Record) => `${key}${params?.example ? `:${params.example}` : ""}` + + test("returns shell placeholder in shell mode", () => { + const value = promptPlaceholder({ + mode: "shell", + commentCount: 0, + example: "example", + t, + }) + expect(value).toBe("prompt.placeholder.shell") + }) + + test("returns summarize placeholders for comment context", () => { + expect(promptPlaceholder({ mode: "normal", commentCount: 1, example: "example", t })).toBe( + "prompt.placeholder.summarizeComment", + ) + expect(promptPlaceholder({ mode: "normal", commentCount: 2, example: "example", t })).toBe( + "prompt.placeholder.summarizeComments", + ) + }) + + test("returns default placeholder with example", () => { + const value = promptPlaceholder({ + mode: "normal", + commentCount: 0, + example: "translated-example", + t, + }) + expect(value).toBe("prompt.placeholder.normal:translated-example") + }) +}) diff --git a/packages/app/src/components/prompt-input/placeholder.ts b/packages/app/src/components/prompt-input/placeholder.ts new file mode 100644 index 00000000000..07f6a43b510 --- /dev/null +++ b/packages/app/src/components/prompt-input/placeholder.ts @@ -0,0 +1,13 @@ +type PromptPlaceholderInput = { + mode: "normal" | "shell" + commentCount: number + example: string + t: (key: string, params?: Record) => string +} + +export function promptPlaceholder(input: PromptPlaceholderInput) { + if (input.mode === "shell") return input.t("prompt.placeholder.shell") + if (input.commentCount > 1) return input.t("prompt.placeholder.summarizeComments") + if (input.commentCount === 1) return input.t("prompt.placeholder.summarizeComment") + return input.t("prompt.placeholder.normal", { example: input.example }) +} diff --git a/packages/app/src/components/prompt-input/slash-popover.tsx b/packages/app/src/components/prompt-input/slash-popover.tsx new file mode 100644 index 00000000000..b97bb675223 --- /dev/null +++ b/packages/app/src/components/prompt-input/slash-popover.tsx @@ -0,0 +1,144 @@ +import { Component, For, Match, Show, Switch } from "solid-js" +import { FileIcon } from "@opencode-ai/ui/file-icon" +import { Icon } from "@opencode-ai/ui/icon" +import { getDirectory, getFilename } from "@opencode-ai/util/path" + +export type AtOption = + | { type: "agent"; name: string; display: string } + | { type: "file"; path: string; display: string; recent?: boolean } + +export interface SlashCommand { + id: string + trigger: string + title: string + description?: string + keybind?: string + type: "builtin" | "custom" + source?: "command" | "mcp" | "skill" +} + +type PromptPopoverProps = { + popover: "at" | "slash" | null + setSlashPopoverRef: (el: HTMLDivElement) => void + atFlat: AtOption[] + atActive?: string + atKey: (item: AtOption) => string + setAtActive: (id: string) => void + onAtSelect: (item: AtOption) => void + slashFlat: SlashCommand[] + slashActive?: string + setSlashActive: (id: string) => void + onSlashSelect: (item: SlashCommand) => void + commandKeybind: (id: string) => string | undefined + t: (key: string) => string +} + +export const PromptPopover: Component = (props) => { + return ( + +
{ + if (props.popover === "slash") props.setSlashPopoverRef(el) + }} + class="absolute inset-x-0 -top-3 -translate-y-full origin-bottom-left max-h-80 min-h-10 + overflow-auto no-scrollbar flex flex-col p-2 rounded-md + border border-border-base bg-surface-raised-stronger-non-alpha shadow-md" + onMouseDown={(e) => e.preventDefault()} + > + + + 0} + fallback={
{props.t("prompt.popover.emptyResults")}
} + > + + {(item) => ( + + )} + +
+
+ + 0} + fallback={
{props.t("prompt.popover.emptyCommands")}
} + > + + {(cmd) => ( + + )} + +
+
+
+
+
+ ) +} diff --git a/packages/app/src/components/prompt-input/submit.test.ts b/packages/app/src/components/prompt-input/submit.test.ts new file mode 100644 index 00000000000..475a0e20f29 --- /dev/null +++ b/packages/app/src/components/prompt-input/submit.test.ts @@ -0,0 +1,175 @@ +import { beforeAll, beforeEach, describe, expect, mock, test } from "bun:test" +import type { Prompt } from "@/context/prompt" + +let createPromptSubmit: typeof import("./submit").createPromptSubmit + +const createdClients: string[] = [] +const createdSessions: string[] = [] +const sentShell: string[] = [] +const syncedDirectories: string[] = [] + +let selected = "/repo/worktree-a" + +const promptValue: Prompt = [{ type: "text", content: "ls", start: 0, end: 2 }] + +const clientFor = (directory: string) => ({ + session: { + create: async () => { + createdSessions.push(directory) + return { data: { id: `session-${createdSessions.length}` } } + }, + shell: async () => { + sentShell.push(directory) + return { data: undefined } + }, + prompt: async () => ({ data: undefined }), + command: async () => ({ data: undefined }), + abort: async () => ({ data: undefined }), + }, + worktree: { + create: async () => ({ data: { directory: `${directory}/new` } }), + }, +}) + +beforeAll(async () => { + const rootClient = clientFor("/repo/main") + + mock.module("@solidjs/router", () => ({ + useNavigate: () => () => undefined, + useParams: () => ({}), + })) + + mock.module("@opencode-ai/sdk/v2/client", () => ({ + createOpencodeClient: (input: { directory: string }) => { + createdClients.push(input.directory) + return clientFor(input.directory) + }, + })) + + mock.module("@opencode-ai/ui/toast", () => ({ + showToast: () => 0, + })) + + mock.module("@opencode-ai/util/encode", () => ({ + base64Encode: (value: string) => value, + })) + + mock.module("@/context/local", () => ({ + useLocal: () => ({ + model: { + current: () => ({ id: "model", provider: { id: "provider" } }), + variant: { current: () => undefined }, + }, + agent: { + current: () => ({ name: "agent" }), + }, + }), + })) + + mock.module("@/context/prompt", () => ({ + usePrompt: () => ({ + current: () => promptValue, + reset: () => undefined, + set: () => undefined, + context: { + add: () => undefined, + remove: () => undefined, + items: () => [], + }, + }), + })) + + mock.module("@/context/layout", () => ({ + useLayout: () => ({ + handoff: { + setTabs: () => undefined, + }, + }), + })) + + mock.module("@/context/sdk", () => ({ + useSDK: () => ({ + directory: "/repo/main", + client: rootClient, + url: "http://localhost:4096", + }), + })) + + mock.module("@/context/sync", () => ({ + useSync: () => ({ + data: { command: [] }, + session: { + optimistic: { + add: () => undefined, + remove: () => undefined, + }, + }, + set: () => undefined, + }), + })) + + mock.module("@/context/global-sync", () => ({ + useGlobalSync: () => ({ + child: (directory: string) => { + syncedDirectories.push(directory) + return [{}, () => undefined] + }, + }), + })) + + mock.module("@/context/platform", () => ({ + usePlatform: () => ({ + fetch: fetch, + }), + })) + + mock.module("@/context/language", () => ({ + useLanguage: () => ({ + t: (key: string) => key, + }), + })) + + const mod = await import("./submit") + createPromptSubmit = mod.createPromptSubmit +}) + +beforeEach(() => { + createdClients.length = 0 + createdSessions.length = 0 + sentShell.length = 0 + syncedDirectories.length = 0 + selected = "/repo/worktree-a" +}) + +describe("prompt submit worktree selection", () => { + test("reads the latest worktree accessor value per submit", async () => { + const submit = createPromptSubmit({ + info: () => undefined, + imageAttachments: () => [], + commentCount: () => 0, + mode: () => "shell", + working: () => false, + editor: () => undefined, + queueScroll: () => undefined, + promptLength: (value) => value.reduce((sum, part) => sum + ("content" in part ? part.content.length : 0), 0), + addToHistory: () => undefined, + resetHistoryNavigation: () => undefined, + setMode: () => undefined, + setPopover: () => undefined, + newSessionWorktree: () => selected, + onNewSessionWorktreeReset: () => undefined, + onSubmit: () => undefined, + }) + + const event = { preventDefault: () => undefined } as unknown as Event + + await submit.handleSubmit(event) + selected = "/repo/worktree-b" + await submit.handleSubmit(event) + + expect(createdClients).toEqual(["/repo/worktree-a", "/repo/worktree-b"]) + expect(createdSessions).toEqual(["/repo/worktree-a", "/repo/worktree-b"]) + expect(sentShell).toEqual(["/repo/worktree-a", "/repo/worktree-b"]) + expect(syncedDirectories).toEqual(["/repo/worktree-a", "/repo/worktree-b"]) + }) +}) diff --git a/packages/app/src/components/prompt-input/submit.ts b/packages/app/src/components/prompt-input/submit.ts new file mode 100644 index 00000000000..49d75a95ecc --- /dev/null +++ b/packages/app/src/components/prompt-input/submit.ts @@ -0,0 +1,417 @@ +import { Accessor } from "solid-js" +import { useNavigate, useParams } from "@solidjs/router" +import { createOpencodeClient, type Message } from "@opencode-ai/sdk/v2/client" +import { showToast } from "@opencode-ai/ui/toast" +import { base64Encode } from "@opencode-ai/util/encode" +import { useLocal } from "@/context/local" +import { usePrompt, type ImageAttachmentPart, type Prompt } from "@/context/prompt" +import { useLayout } from "@/context/layout" +import { useSDK } from "@/context/sdk" +import { useSync } from "@/context/sync" +import { useGlobalSync } from "@/context/global-sync" +import { usePlatform } from "@/context/platform" +import { useLanguage } from "@/context/language" +import { Identifier } from "@/utils/id" +import { Worktree as WorktreeState } from "@/utils/worktree" +import type { FileSelection } from "@/context/file" +import { setCursorPosition } from "./editor-dom" +import { buildRequestParts } from "./build-request-parts" + +type PendingPrompt = { + abort: AbortController + cleanup: VoidFunction +} + +const pending = new Map() + +type PromptSubmitInput = { + info: Accessor<{ id: string } | undefined> + imageAttachments: Accessor + commentCount: Accessor + mode: Accessor<"normal" | "shell"> + working: Accessor + editor: () => HTMLDivElement | undefined + queueScroll: () => void + promptLength: (prompt: Prompt) => number + addToHistory: (prompt: Prompt, mode: "normal" | "shell") => void + resetHistoryNavigation: () => void + setMode: (mode: "normal" | "shell") => void + setPopover: (popover: "at" | "slash" | null) => void + newSessionWorktree?: Accessor + onNewSessionWorktreeReset?: () => void + onSubmit?: () => void +} + +type CommentItem = { + path: string + selection?: FileSelection + comment?: string + commentID?: string + commentOrigin?: "review" | "file" + preview?: string +} + +export function createPromptSubmit(input: PromptSubmitInput) { + const navigate = useNavigate() + const sdk = useSDK() + const sync = useSync() + const globalSync = useGlobalSync() + const platform = usePlatform() + const local = useLocal() + const prompt = usePrompt() + const layout = useLayout() + const language = useLanguage() + const params = useParams() + + const errorMessage = (err: unknown) => { + if (err && typeof err === "object" && "data" in err) { + const data = (err as { data?: { message?: string } }).data + if (data?.message) return data.message + } + if (err instanceof Error) return err.message + return language.t("common.requestFailed") + } + + const abort = async () => { + const sessionID = params.id + if (!sessionID) return Promise.resolve() + const queued = pending.get(sessionID) + if (queued) { + queued.abort.abort() + queued.cleanup() + pending.delete(sessionID) + return Promise.resolve() + } + return sdk.client.session + .abort({ + sessionID, + }) + .catch(() => {}) + } + + const restoreCommentItems = (items: CommentItem[]) => { + for (const item of items) { + prompt.context.add({ + type: "file", + path: item.path, + selection: item.selection, + comment: item.comment, + commentID: item.commentID, + commentOrigin: item.commentOrigin, + preview: item.preview, + }) + } + } + + const removeCommentItems = (items: { key: string }[]) => { + for (const item of items) { + prompt.context.remove(item.key) + } + } + + const handleSubmit = async (event: Event) => { + event.preventDefault() + + const currentPrompt = prompt.current() + const text = currentPrompt.map((part) => ("content" in part ? part.content : "")).join("") + const images = input.imageAttachments().slice() + const mode = input.mode() + + if (text.trim().length === 0 && images.length === 0 && input.commentCount() === 0) { + if (input.working()) abort() + return + } + + const currentModel = local.model.current() + const currentAgent = local.agent.current() + if (!currentModel || !currentAgent) { + showToast({ + title: language.t("prompt.toast.modelAgentRequired.title"), + description: language.t("prompt.toast.modelAgentRequired.description"), + }) + return + } + + input.addToHistory(currentPrompt, mode) + input.resetHistoryNavigation() + + const projectDirectory = sdk.directory + const isNewSession = !params.id + const worktreeSelection = input.newSessionWorktree?.() || "main" + + let sessionDirectory = projectDirectory + let client = sdk.client + + if (isNewSession) { + if (worktreeSelection === "create") { + const createdWorktree = await client.worktree + .create({ directory: projectDirectory }) + .then((x) => x.data) + .catch((err) => { + showToast({ + title: language.t("prompt.toast.worktreeCreateFailed.title"), + description: errorMessage(err), + }) + return undefined + }) + + if (!createdWorktree?.directory) { + showToast({ + title: language.t("prompt.toast.worktreeCreateFailed.title"), + description: language.t("common.requestFailed"), + }) + return + } + WorktreeState.pending(createdWorktree.directory) + sessionDirectory = createdWorktree.directory + } + + if (worktreeSelection !== "main" && worktreeSelection !== "create") { + sessionDirectory = worktreeSelection + } + + if (sessionDirectory !== projectDirectory) { + client = createOpencodeClient({ + baseUrl: sdk.url, + fetch: platform.fetch, + directory: sessionDirectory, + throwOnError: true, + }) + globalSync.child(sessionDirectory) + } + + input.onNewSessionWorktreeReset?.() + } + + let session = input.info() + if (!session && isNewSession) { + session = await client.session + .create() + .then((x) => x.data ?? undefined) + .catch((err) => { + showToast({ + title: language.t("prompt.toast.sessionCreateFailed.title"), + description: errorMessage(err), + }) + return undefined + }) + if (session) { + layout.handoff.setTabs(base64Encode(sessionDirectory), session.id) + navigate(`/${base64Encode(sessionDirectory)}/session/${session.id}`) + } + } + if (!session) { + showToast({ + title: language.t("prompt.toast.promptSendFailed.title"), + description: language.t("prompt.toast.promptSendFailed.description"), + }) + return + } + + input.onSubmit?.() + + const model = { + modelID: currentModel.id, + providerID: currentModel.provider.id, + } + const agent = currentAgent.name + const variant = local.model.variant.current() + + const clearInput = () => { + prompt.reset() + input.setMode("normal") + input.setPopover(null) + } + + const restoreInput = () => { + prompt.set(currentPrompt, input.promptLength(currentPrompt)) + input.setMode(mode) + input.setPopover(null) + requestAnimationFrame(() => { + const editor = input.editor() + if (!editor) return + editor.focus() + setCursorPosition(editor, input.promptLength(currentPrompt)) + input.queueScroll() + }) + } + + if (mode === "shell") { + clearInput() + client.session + .shell({ + sessionID: session.id, + agent, + model, + command: text, + }) + .catch((err) => { + showToast({ + title: language.t("prompt.toast.shellSendFailed.title"), + description: errorMessage(err), + }) + restoreInput() + }) + return + } + + if (text.startsWith("/")) { + const [cmdName, ...args] = text.split(" ") + const commandName = cmdName.slice(1) + const customCommand = sync.data.command.find((c) => c.name === commandName) + if (customCommand) { + clearInput() + client.session + .command({ + sessionID: session.id, + command: commandName, + arguments: args.join(" "), + agent, + model: `${model.providerID}/${model.modelID}`, + variant, + parts: images.map((attachment) => ({ + id: Identifier.ascending("part"), + type: "file" as const, + mime: attachment.mime, + url: attachment.dataUrl, + filename: attachment.filename, + })), + }) + .catch((err) => { + showToast({ + title: language.t("prompt.toast.commandSendFailed.title"), + description: errorMessage(err), + }) + restoreInput() + }) + return + } + } + + const context = prompt.context.items().slice() + const commentItems = context.filter((item) => item.type === "file" && !!item.comment?.trim()) + + const messageID = Identifier.ascending("message") + const { requestParts, optimisticParts } = buildRequestParts({ + prompt: currentPrompt, + context, + images, + text, + sessionID: session.id, + messageID, + sessionDirectory, + }) + + const optimisticMessage: Message = { + id: messageID, + sessionID: session.id, + role: "user", + time: { created: Date.now() }, + agent, + model, + } + + const addOptimisticMessage = () => + sync.session.optimistic.add({ + directory: sessionDirectory, + sessionID: session.id, + message: optimisticMessage, + parts: optimisticParts, + }) + + const removeOptimisticMessage = () => + sync.session.optimistic.remove({ + directory: sessionDirectory, + sessionID: session.id, + messageID, + }) + + removeCommentItems(commentItems) + clearInput() + addOptimisticMessage() + + const waitForWorktree = async () => { + const worktree = WorktreeState.get(sessionDirectory) + if (!worktree || worktree.status !== "pending") return true + + if (sessionDirectory === projectDirectory) { + sync.set("session_status", session.id, { type: "busy" }) + } + + const controller = new AbortController() + const cleanup = () => { + if (sessionDirectory === projectDirectory) { + sync.set("session_status", session.id, { type: "idle" }) + } + removeOptimisticMessage() + restoreCommentItems(commentItems) + restoreInput() + } + + pending.set(session.id, { abort: controller, cleanup }) + + const abortWait = new Promise>>((resolve) => { + if (controller.signal.aborted) { + resolve({ status: "failed", message: "aborted" }) + return + } + controller.signal.addEventListener( + "abort", + () => { + resolve({ status: "failed", message: "aborted" }) + }, + { once: true }, + ) + }) + + const timeoutMs = 5 * 60 * 1000 + const timer = { id: undefined as number | undefined } + const timeout = new Promise>>((resolve) => { + timer.id = window.setTimeout(() => { + resolve({ status: "failed", message: language.t("workspace.error.stillPreparing") }) + }, timeoutMs) + }) + + const result = await Promise.race([WorktreeState.wait(sessionDirectory), abortWait, timeout]).finally(() => { + if (timer.id === undefined) return + clearTimeout(timer.id) + }) + pending.delete(session.id) + if (controller.signal.aborted) return false + if (result.status === "failed") throw new Error(result.message) + return true + } + + const send = async () => { + const ok = await waitForWorktree() + if (!ok) return + await client.session.prompt({ + sessionID: session.id, + agent, + model, + messageID, + parts: requestParts, + variant, + }) + } + + void send().catch((err) => { + pending.delete(session.id) + if (sessionDirectory === projectDirectory) { + sync.set("session_status", session.id, { type: "idle" }) + } + showToast({ + title: language.t("prompt.toast.promptSendFailed.title"), + description: errorMessage(err), + }) + removeOptimisticMessage() + restoreCommentItems(commentItems) + restoreInput() + }) + } + + return { + abort, + handleSubmit, + } +} diff --git a/packages/app/src/components/question-dock.tsx b/packages/app/src/components/question-dock.tsx new file mode 100644 index 00000000000..f626fcc9b27 --- /dev/null +++ b/packages/app/src/components/question-dock.tsx @@ -0,0 +1,295 @@ +import { For, Show, createMemo, type Component } from "solid-js" +import { createStore } from "solid-js/store" +import { Button } from "@opencode-ai/ui/button" +import { Icon } from "@opencode-ai/ui/icon" +import { showToast } from "@opencode-ai/ui/toast" +import type { QuestionAnswer, QuestionRequest } from "@opencode-ai/sdk/v2" +import { useLanguage } from "@/context/language" +import { useSDK } from "@/context/sdk" + +export const QuestionDock: Component<{ request: QuestionRequest }> = (props) => { + const sdk = useSDK() + const language = useLanguage() + + const questions = createMemo(() => props.request.questions) + const single = createMemo(() => questions().length === 1 && questions()[0]?.multiple !== true) + + const [store, setStore] = createStore({ + tab: 0, + answers: [] as QuestionAnswer[], + custom: [] as string[], + editing: false, + sending: false, + }) + + const question = createMemo(() => questions()[store.tab]) + const confirm = createMemo(() => !single() && store.tab === questions().length) + const options = createMemo(() => question()?.options ?? []) + const input = createMemo(() => store.custom[store.tab] ?? "") + const multi = createMemo(() => question()?.multiple === true) + const customPicked = createMemo(() => { + const value = input() + if (!value) return false + return store.answers[store.tab]?.includes(value) ?? false + }) + + const fail = (err: unknown) => { + const message = err instanceof Error ? err.message : String(err) + showToast({ title: language.t("common.requestFailed"), description: message }) + } + + const reply = (answers: QuestionAnswer[]) => { + if (store.sending) return + + setStore("sending", true) + sdk.client.question + .reply({ requestID: props.request.id, answers }) + .catch(fail) + .finally(() => setStore("sending", false)) + } + + const reject = () => { + if (store.sending) return + + setStore("sending", true) + sdk.client.question + .reject({ requestID: props.request.id }) + .catch(fail) + .finally(() => setStore("sending", false)) + } + + const submit = () => { + reply(questions().map((_, i) => store.answers[i] ?? [])) + } + + const pick = (answer: string, custom: boolean = false) => { + const answers = [...store.answers] + answers[store.tab] = [answer] + setStore("answers", answers) + + if (custom) { + const inputs = [...store.custom] + inputs[store.tab] = answer + setStore("custom", inputs) + } + + if (single()) { + reply([[answer]]) + return + } + + setStore("tab", store.tab + 1) + } + + const toggle = (answer: string) => { + const existing = store.answers[store.tab] ?? [] + const next = [...existing] + const index = next.indexOf(answer) + if (index === -1) next.push(answer) + if (index !== -1) next.splice(index, 1) + + const answers = [...store.answers] + answers[store.tab] = next + setStore("answers", answers) + } + + const selectTab = (index: number) => { + setStore("tab", index) + setStore("editing", false) + } + + const selectOption = (optIndex: number) => { + if (store.sending) return + + if (optIndex === options().length) { + setStore("editing", true) + return + } + + const opt = options()[optIndex] + if (!opt) return + if (multi()) { + toggle(opt.label) + return + } + pick(opt.label) + } + + const handleCustomSubmit = (e: Event) => { + e.preventDefault() + if (store.sending) return + + const value = input().trim() + if (!value) { + setStore("editing", false) + return + } + + if (multi()) { + const existing = store.answers[store.tab] ?? [] + const next = [...existing] + if (!next.includes(value)) next.push(value) + + const answers = [...store.answers] + answers[store.tab] = next + setStore("answers", answers) + setStore("editing", false) + return + } + + pick(value, true) + setStore("editing", false) + } + + return ( +
+ +
+ + {(q, index) => { + const active = () => index() === store.tab + const answered = () => (store.answers[index()]?.length ?? 0) > 0 + return ( + + ) + }} + + +
+
+ + +
+
+ {question()?.question} + {multi() ? " " + language.t("ui.question.multiHint") : ""} +
+
+ + {(opt, i) => { + const picked = () => store.answers[store.tab]?.includes(opt.label) ?? false + return ( + + ) + }} + + + +
+ setTimeout(() => el.focus(), 0)} + type="text" + data-slot="custom-input" + placeholder={language.t("ui.question.custom.placeholder")} + value={input()} + disabled={store.sending} + onInput={(e) => { + const inputs = [...store.custom] + inputs[store.tab] = e.currentTarget.value + setStore("custom", inputs) + }} + /> + + +
+
+
+
+
+ + +
+
{language.t("ui.messagePart.review.title")}
+ + {(q, index) => { + const value = () => store.answers[index()]?.join(", ") ?? "" + const answered = () => Boolean(value()) + return ( +
+ {q.question} + + {answered() ? value() : language.t("ui.question.review.notAnswered")} + +
+ ) + }} +
+
+
+ +
+ + + + + + + + + +
+
+ ) +} diff --git a/packages/app/src/components/server/server-row.tsx b/packages/app/src/components/server/server-row.tsx new file mode 100644 index 00000000000..b43c07882ce --- /dev/null +++ b/packages/app/src/components/server/server-row.tsx @@ -0,0 +1,77 @@ +import { Tooltip } from "@opencode-ai/ui/tooltip" +import { JSXElement, ParentProps, Show, createEffect, createSignal, onCleanup, onMount } from "solid-js" +import { serverDisplayName } from "@/context/server" +import type { ServerHealth } from "@/utils/server-health" + +interface ServerRowProps extends ParentProps { + url: string + status?: ServerHealth + class?: string + nameClass?: string + versionClass?: string + dimmed?: boolean + badge?: JSXElement +} + +export function ServerRow(props: ServerRowProps) { + const [truncated, setTruncated] = createSignal(false) + let nameRef: HTMLSpanElement | undefined + let versionRef: HTMLSpanElement | undefined + + const check = () => { + const nameTruncated = nameRef ? nameRef.scrollWidth > nameRef.clientWidth : false + const versionTruncated = versionRef ? versionRef.scrollWidth > versionRef.clientWidth : false + setTruncated(nameTruncated || versionTruncated) + } + + createEffect(() => { + props.url + props.status?.version + if (typeof requestAnimationFrame === "function") { + requestAnimationFrame(check) + return + } + check() + }) + + onMount(() => { + check() + if (typeof window === "undefined") return + window.addEventListener("resize", check) + onCleanup(() => window.removeEventListener("resize", check)) + }) + + const tooltipValue = () => ( + + {serverDisplayName(props.url)} + + {props.status?.version} + + + ) + + return ( + +
+
+ + {serverDisplayName(props.url)} + + + + {props.status?.version} + + + {props.badge} + {props.children} +
+ + ) +} diff --git a/packages/app/src/components/session/session-context-metrics.test.ts b/packages/app/src/components/session/session-context-metrics.test.ts new file mode 100644 index 00000000000..e90df9a9486 --- /dev/null +++ b/packages/app/src/components/session/session-context-metrics.test.ts @@ -0,0 +1,94 @@ +import { describe, expect, test } from "bun:test" +import type { Message } from "@opencode-ai/sdk/v2/client" +import { getSessionContextMetrics } from "./session-context-metrics" + +const assistant = ( + id: string, + tokens: { input: number; output: number; reasoning: number; read: number; write: number }, + cost: number, + providerID = "openai", + modelID = "gpt-4.1", +) => { + return { + id, + role: "assistant", + providerID, + modelID, + cost, + tokens: { + input: tokens.input, + output: tokens.output, + reasoning: tokens.reasoning, + cache: { + read: tokens.read, + write: tokens.write, + }, + }, + time: { created: 1 }, + } as unknown as Message +} + +const user = (id: string) => { + return { + id, + role: "user", + cost: 0, + time: { created: 1 }, + } as unknown as Message +} + +describe("getSessionContextMetrics", () => { + test("computes totals and usage from latest assistant with tokens", () => { + const messages = [ + user("u1"), + assistant("a1", { input: 0, output: 0, reasoning: 0, read: 0, write: 0 }, 0.5), + assistant("a2", { input: 300, output: 100, reasoning: 50, read: 25, write: 25 }, 1.25), + ] + const providers = [ + { + id: "openai", + name: "OpenAI", + models: { + "gpt-4.1": { + name: "GPT-4.1", + limit: { context: 1000 }, + }, + }, + }, + ] + + const metrics = getSessionContextMetrics(messages, providers) + + expect(metrics.totalCost).toBe(1.75) + expect(metrics.context?.message.id).toBe("a2") + expect(metrics.context?.total).toBe(500) + expect(metrics.context?.usage).toBe(50) + expect(metrics.context?.providerLabel).toBe("OpenAI") + expect(metrics.context?.modelLabel).toBe("GPT-4.1") + }) + + test("preserves fallback labels and null usage when model metadata is missing", () => { + const messages = [assistant("a1", { input: 40, output: 10, reasoning: 0, read: 0, write: 0 }, 0.1, "p-1", "m-1")] + const providers = [{ id: "p-1", models: {} }] + + const metrics = getSessionContextMetrics(messages, providers) + + expect(metrics.context?.providerLabel).toBe("p-1") + expect(metrics.context?.modelLabel).toBe("m-1") + expect(metrics.context?.limit).toBeUndefined() + expect(metrics.context?.usage).toBeNull() + }) + + test("recomputes when message array is mutated in place", () => { + const messages = [assistant("a1", { input: 10, output: 10, reasoning: 10, read: 10, write: 10 }, 0.25)] + const providers = [{ id: "openai", models: {} }] + + const one = getSessionContextMetrics(messages, providers) + messages.push(assistant("a2", { input: 100, output: 20, reasoning: 0, read: 0, write: 0 }, 0.75)) + const two = getSessionContextMetrics(messages, providers) + + expect(one.context?.message.id).toBe("a1") + expect(two.context?.message.id).toBe("a2") + expect(two.totalCost).toBe(1) + }) +}) diff --git a/packages/app/src/components/session/session-context-metrics.ts b/packages/app/src/components/session/session-context-metrics.ts new file mode 100644 index 00000000000..357205afb59 --- /dev/null +++ b/packages/app/src/components/session/session-context-metrics.ts @@ -0,0 +1,82 @@ +import type { AssistantMessage, Message } from "@opencode-ai/sdk/v2/client" + +type Provider = { + id: string + name?: string + models: Record +} + +type Model = { + name?: string + limit: { + context: number + } +} + +type Context = { + message: AssistantMessage + provider?: Provider + model?: Model + providerLabel: string + modelLabel: string + limit: number | undefined + input: number + output: number + reasoning: number + cacheRead: number + cacheWrite: number + total: number + usage: number | null +} + +type Metrics = { + totalCost: number + context: Context | undefined +} + +const tokenTotal = (msg: AssistantMessage) => { + return msg.tokens.input + msg.tokens.output + msg.tokens.reasoning + msg.tokens.cache.read + msg.tokens.cache.write +} + +const lastAssistantWithTokens = (messages: Message[]) => { + for (let i = messages.length - 1; i >= 0; i--) { + const msg = messages[i] + if (msg.role !== "assistant") continue + if (tokenTotal(msg) <= 0) continue + return msg + } +} + +const build = (messages: Message[], providers: Provider[]): Metrics => { + const totalCost = messages.reduce((sum, msg) => sum + (msg.role === "assistant" ? msg.cost : 0), 0) + const message = lastAssistantWithTokens(messages) + if (!message) return { totalCost, context: undefined } + + const provider = providers.find((item) => item.id === message.providerID) + const model = provider?.models[message.modelID] + const limit = model?.limit.context + const total = tokenTotal(message) + + return { + totalCost, + context: { + message, + provider, + model, + providerLabel: provider?.name ?? message.providerID, + modelLabel: model?.name ?? message.modelID, + limit, + input: message.tokens.input, + output: message.tokens.output, + reasoning: message.tokens.reasoning, + cacheRead: message.tokens.cache.read, + cacheWrite: message.tokens.cache.write, + total, + usage: limit ? Math.round((total / limit) * 100) : null, + }, + } +} + +export function getSessionContextMetrics(messages: Message[], providers: Provider[]) { + return build(messages, providers) +} diff --git a/packages/app/src/components/titlebar-history.test.ts b/packages/app/src/components/titlebar-history.test.ts new file mode 100644 index 00000000000..25035d7ccf7 --- /dev/null +++ b/packages/app/src/components/titlebar-history.test.ts @@ -0,0 +1,63 @@ +import { describe, expect, test } from "bun:test" +import { applyPath, backPath, forwardPath, type TitlebarHistory } from "./titlebar-history" + +function history(): TitlebarHistory { + return { stack: [], index: 0, action: undefined } +} + +describe("titlebar history", () => { + test("append and trim keeps max bounded", () => { + let state = history() + state = applyPath(state, "/", 3) + state = applyPath(state, "/a", 3) + state = applyPath(state, "/b", 3) + state = applyPath(state, "/c", 3) + + expect(state.stack).toEqual(["/a", "/b", "/c"]) + expect(state.stack.length).toBe(3) + expect(state.index).toBe(2) + }) + + test("back and forward indexes stay correct after trimming", () => { + let state = history() + state = applyPath(state, "/", 3) + state = applyPath(state, "/a", 3) + state = applyPath(state, "/b", 3) + state = applyPath(state, "/c", 3) + + expect(state.stack).toEqual(["/a", "/b", "/c"]) + expect(state.index).toBe(2) + + const back = backPath(state) + expect(back?.to).toBe("/b") + expect(back?.state.index).toBe(1) + + const afterBack = applyPath(back!.state, back!.to, 3) + expect(afterBack.stack).toEqual(["/a", "/b", "/c"]) + expect(afterBack.index).toBe(1) + + const forward = forwardPath(afterBack) + expect(forward?.to).toBe("/c") + expect(forward?.state.index).toBe(2) + + const afterForward = applyPath(forward!.state, forward!.to, 3) + expect(afterForward.stack).toEqual(["/a", "/b", "/c"]) + expect(afterForward.index).toBe(2) + }) + + test("action-driven navigation does not push duplicate history entries", () => { + const state: TitlebarHistory = { + stack: ["/", "/a", "/b"], + index: 2, + action: undefined, + } + + const back = backPath(state) + expect(back?.to).toBe("/a") + + const next = applyPath(back!.state, back!.to, 10) + expect(next.stack).toEqual(["/", "/a", "/b"]) + expect(next.index).toBe(1) + expect(next.action).toBeUndefined() + }) +}) diff --git a/packages/app/src/components/titlebar-history.ts b/packages/app/src/components/titlebar-history.ts new file mode 100644 index 00000000000..44dbbfa3a49 --- /dev/null +++ b/packages/app/src/components/titlebar-history.ts @@ -0,0 +1,57 @@ +export const MAX_TITLEBAR_HISTORY = 100 + +export type TitlebarAction = "back" | "forward" | undefined + +export type TitlebarHistory = { + stack: string[] + index: number + action: TitlebarAction +} + +export function applyPath(state: TitlebarHistory, current: string, max = MAX_TITLEBAR_HISTORY): TitlebarHistory { + if (!state.stack.length) { + const stack = current === "/" ? ["/"] : ["/", current] + return { stack, index: stack.length - 1, action: undefined } + } + + const active = state.stack[state.index] + if (current === active) { + if (!state.action) return state + return { ...state, action: undefined } + } + + if (state.action) return { ...state, action: undefined } + + return pushPath(state, current, max) +} + +export function pushPath(state: TitlebarHistory, path: string, max = MAX_TITLEBAR_HISTORY): TitlebarHistory { + const stack = state.stack.slice(0, state.index + 1).concat(path) + const next = trimHistory(stack, stack.length - 1, max) + return { ...state, ...next, action: undefined } +} + +export function trimHistory(stack: string[], index: number, max = MAX_TITLEBAR_HISTORY) { + if (stack.length <= max) return { stack, index } + const cut = stack.length - max + return { + stack: stack.slice(cut), + index: Math.max(0, index - cut), + } +} + +export function backPath(state: TitlebarHistory) { + if (state.index <= 0) return + const index = state.index - 1 + const to = state.stack[index] + if (!to) return + return { state: { ...state, index, action: "back" as const }, to } +} + +export function forwardPath(state: TitlebarHistory) { + if (state.index >= state.stack.length - 1) return + const index = state.index + 1 + const to = state.stack[index] + if (!to) return + return { state: { ...state, index, action: "forward" as const }, to } +} diff --git a/packages/app/src/context/command-keybind.test.ts b/packages/app/src/context/command-keybind.test.ts new file mode 100644 index 00000000000..4e38efd8da8 --- /dev/null +++ b/packages/app/src/context/command-keybind.test.ts @@ -0,0 +1,43 @@ +import { describe, expect, test } from "bun:test" +import { formatKeybind, matchKeybind, parseKeybind } from "./command" + +describe("command keybind helpers", () => { + test("parseKeybind handles aliases and multiple combos", () => { + const keybinds = parseKeybind("control+option+k, mod+shift+comma") + + expect(keybinds).toHaveLength(2) + expect(keybinds[0]).toEqual({ + key: "k", + ctrl: true, + meta: false, + shift: false, + alt: true, + }) + expect(keybinds[1]?.shift).toBe(true) + expect(keybinds[1]?.key).toBe("comma") + expect(Boolean(keybinds[1]?.ctrl || keybinds[1]?.meta)).toBe(true) + }) + + test("parseKeybind treats none and empty as disabled", () => { + expect(parseKeybind("none")).toEqual([]) + expect(parseKeybind("")).toEqual([]) + }) + + test("matchKeybind normalizes punctuation keys", () => { + const keybinds = parseKeybind("ctrl+comma, shift+plus, meta+space") + + expect(matchKeybind(keybinds, new KeyboardEvent("keydown", { key: ",", ctrlKey: true }))).toBe(true) + expect(matchKeybind(keybinds, new KeyboardEvent("keydown", { key: "+", shiftKey: true }))).toBe(true) + expect(matchKeybind(keybinds, new KeyboardEvent("keydown", { key: " ", metaKey: true }))).toBe(true) + expect(matchKeybind(keybinds, new KeyboardEvent("keydown", { key: ",", ctrlKey: true, altKey: true }))).toBe(false) + }) + + test("formatKeybind returns human readable output", () => { + const display = formatKeybind("ctrl+alt+arrowup") + + expect(display).toContain("↑") + expect(display.includes("Ctrl") || display.includes("⌃")).toBe(true) + expect(display.includes("Alt") || display.includes("⌥")).toBe(true) + expect(formatKeybind("none")).toBe("") + }) +}) diff --git a/packages/app/src/context/command.test.ts b/packages/app/src/context/command.test.ts new file mode 100644 index 00000000000..2b956287c54 --- /dev/null +++ b/packages/app/src/context/command.test.ts @@ -0,0 +1,25 @@ +import { describe, expect, test } from "bun:test" +import { upsertCommandRegistration } from "./command" + +describe("upsertCommandRegistration", () => { + test("replaces keyed registrations", () => { + const one = () => [{ id: "one", title: "One" }] + const two = () => [{ id: "two", title: "Two" }] + + const next = upsertCommandRegistration([{ key: "layout", options: one }], { key: "layout", options: two }) + + expect(next).toHaveLength(1) + expect(next[0]?.options).toBe(two) + }) + + test("keeps unkeyed registrations additive", () => { + const one = () => [{ id: "one", title: "One" }] + const two = () => [{ id: "two", title: "Two" }] + + const next = upsertCommandRegistration([{ options: one }], { options: two }) + + expect(next).toHaveLength(2) + expect(next[0]?.options).toBe(two) + expect(next[1]?.options).toBe(one) + }) +}) diff --git a/packages/app/src/context/comments.test.ts b/packages/app/src/context/comments.test.ts new file mode 100644 index 00000000000..4f223e5f869 --- /dev/null +++ b/packages/app/src/context/comments.test.ts @@ -0,0 +1,112 @@ +import { beforeAll, describe, expect, mock, test } from "bun:test" +import { createRoot } from "solid-js" +import type { LineComment } from "./comments" + +let createCommentSessionForTest: typeof import("./comments").createCommentSessionForTest + +beforeAll(async () => { + mock.module("@solidjs/router", () => ({ + useNavigate: () => () => undefined, + useParams: () => ({}), + })) + mock.module("@opencode-ai/ui/context", () => ({ + createSimpleContext: () => ({ + use: () => undefined, + provider: () => undefined, + }), + })) + const mod = await import("./comments") + createCommentSessionForTest = mod.createCommentSessionForTest +}) + +function line(file: string, id: string, time: number): LineComment { + return { + id, + file, + comment: id, + time, + selection: { start: 1, end: 1 }, + } +} + +describe("comments session indexing", () => { + test("keeps file list behavior and aggregate chronological order", () => { + createRoot((dispose) => { + const now = Date.now() + const comments = createCommentSessionForTest({ + "a.ts": [line("a.ts", "a-late", now + 20_000), line("a.ts", "a-early", now + 1_000)], + "b.ts": [line("b.ts", "b-mid", now + 10_000)], + }) + + expect(comments.list("a.ts").map((item) => item.id)).toEqual(["a-late", "a-early"]) + expect(comments.all().map((item) => item.id)).toEqual(["a-early", "b-mid", "a-late"]) + + const next = comments.add({ + file: "b.ts", + comment: "next", + selection: { start: 2, end: 2 }, + }) + + expect(comments.list("b.ts").at(-1)?.id).toBe(next.id) + expect(comments.all().map((item) => item.time)).toEqual( + comments + .all() + .map((item) => item.time) + .slice() + .sort((a, b) => a - b), + ) + + dispose() + }) + }) + + test("remove updates file and aggregate indexes consistently", () => { + createRoot((dispose) => { + const comments = createCommentSessionForTest({ + "a.ts": [line("a.ts", "a1", 10), line("a.ts", "shared", 20)], + "b.ts": [line("b.ts", "shared", 30)], + }) + + comments.setFocus({ file: "a.ts", id: "shared" }) + comments.setActive({ file: "a.ts", id: "shared" }) + comments.remove("a.ts", "shared") + + expect(comments.list("a.ts").map((item) => item.id)).toEqual(["a1"]) + expect( + comments + .all() + .filter((item) => item.id === "shared") + .map((item) => item.file), + ).toEqual(["b.ts"]) + expect(comments.focus()).toBeNull() + expect(comments.active()).toEqual({ file: "a.ts", id: "shared" }) + + dispose() + }) + }) + + test("clear resets file and aggregate indexes plus focus state", () => { + createRoot((dispose) => { + const comments = createCommentSessionForTest({ + "a.ts": [line("a.ts", "a1", 10)], + }) + + const next = comments.add({ + file: "b.ts", + comment: "next", + selection: { start: 2, end: 2 }, + }) + + comments.setActive({ file: "b.ts", id: next.id }) + comments.clear() + + expect(comments.list("a.ts")).toEqual([]) + expect(comments.list("b.ts")).toEqual([]) + expect(comments.all()).toEqual([]) + expect(comments.focus()).toBeNull() + expect(comments.active()).toBeNull() + + dispose() + }) + }) +}) diff --git a/packages/app/src/context/file-content-eviction-accounting.test.ts b/packages/app/src/context/file-content-eviction-accounting.test.ts new file mode 100644 index 00000000000..4ef5f947c7d --- /dev/null +++ b/packages/app/src/context/file-content-eviction-accounting.test.ts @@ -0,0 +1,65 @@ +import { afterEach, describe, expect, test } from "bun:test" +import { + evictContentLru, + getFileContentBytesTotal, + getFileContentEntryCount, + removeFileContentBytes, + resetFileContentLru, + setFileContentBytes, + touchFileContent, +} from "./file/content-cache" + +describe("file content eviction accounting", () => { + afterEach(() => { + resetFileContentLru() + }) + + test("updates byte totals incrementally for set, overwrite, remove, and reset", () => { + setFileContentBytes("a", 10) + setFileContentBytes("b", 15) + expect(getFileContentBytesTotal()).toBe(25) + expect(getFileContentEntryCount()).toBe(2) + + setFileContentBytes("a", 5) + expect(getFileContentBytesTotal()).toBe(20) + expect(getFileContentEntryCount()).toBe(2) + + touchFileContent("a") + expect(getFileContentBytesTotal()).toBe(20) + + removeFileContentBytes("b") + expect(getFileContentBytesTotal()).toBe(5) + expect(getFileContentEntryCount()).toBe(1) + + resetFileContentLru() + expect(getFileContentBytesTotal()).toBe(0) + expect(getFileContentEntryCount()).toBe(0) + }) + + test("evicts by entry cap using LRU order", () => { + for (const i of Array.from({ length: 41 }, (_, n) => n)) { + setFileContentBytes(`f-${i}`, 1) + } + + const evicted: string[] = [] + evictContentLru(undefined, (path) => evicted.push(path)) + + expect(evicted).toEqual(["f-0"]) + expect(getFileContentEntryCount()).toBe(40) + expect(getFileContentBytesTotal()).toBe(40) + }) + + test("evicts by byte cap while preserving protected entries", () => { + const chunk = 8 * 1024 * 1024 + setFileContentBytes("a", chunk) + setFileContentBytes("b", chunk) + setFileContentBytes("c", chunk) + + const evicted: string[] = [] + evictContentLru(new Set(["a"]), (path) => evicted.push(path)) + + expect(evicted).toEqual(["b"]) + expect(getFileContentEntryCount()).toBe(2) + expect(getFileContentBytesTotal()).toBe(chunk * 2) + }) +}) diff --git a/packages/app/src/context/file/content-cache.ts b/packages/app/src/context/file/content-cache.ts new file mode 100644 index 00000000000..4b724068834 --- /dev/null +++ b/packages/app/src/context/file/content-cache.ts @@ -0,0 +1,88 @@ +import type { FileContent } from "@opencode-ai/sdk/v2" + +const MAX_FILE_CONTENT_ENTRIES = 40 +const MAX_FILE_CONTENT_BYTES = 20 * 1024 * 1024 + +const lru = new Map() +let total = 0 + +export function approxBytes(content: FileContent) { + const patchBytes = + content.patch?.hunks.reduce((sum, hunk) => { + return sum + hunk.lines.reduce((lineSum, line) => lineSum + line.length, 0) + }, 0) ?? 0 + + return (content.content.length + (content.diff?.length ?? 0) + patchBytes) * 2 +} + +function setBytes(path: string, nextBytes: number) { + const prev = lru.get(path) + if (prev !== undefined) total -= prev + lru.delete(path) + lru.set(path, nextBytes) + total += nextBytes +} + +function touch(path: string, bytes?: number) { + const prev = lru.get(path) + if (prev === undefined && bytes === undefined) return + setBytes(path, bytes ?? prev ?? 0) +} + +function remove(path: string) { + const prev = lru.get(path) + if (prev === undefined) return + lru.delete(path) + total -= prev +} + +function reset() { + lru.clear() + total = 0 +} + +export function evictContentLru(keep: Set | undefined, evict: (path: string) => void) { + const set = keep ?? new Set() + + while (lru.size > MAX_FILE_CONTENT_ENTRIES || total > MAX_FILE_CONTENT_BYTES) { + const path = lru.keys().next().value + if (!path) return + + if (set.has(path)) { + touch(path) + if (lru.size <= set.size) return + continue + } + + remove(path) + evict(path) + } +} + +export function resetFileContentLru() { + reset() +} + +export function setFileContentBytes(path: string, bytes: number) { + setBytes(path, bytes) +} + +export function removeFileContentBytes(path: string) { + remove(path) +} + +export function touchFileContent(path: string, bytes?: number) { + touch(path, bytes) +} + +export function getFileContentBytesTotal() { + return total +} + +export function getFileContentEntryCount() { + return lru.size +} + +export function hasFileContent(path: string) { + return lru.has(path) +} diff --git a/packages/app/src/context/file/path.test.ts b/packages/app/src/context/file/path.test.ts new file mode 100644 index 00000000000..f2a3c44b6c4 --- /dev/null +++ b/packages/app/src/context/file/path.test.ts @@ -0,0 +1,352 @@ +import { describe, expect, test } from "bun:test" +import { createPathHelpers, stripQueryAndHash, unquoteGitPath, encodeFilePath } from "./path" + +describe("file path helpers", () => { + test("normalizes file inputs against workspace root", () => { + const path = createPathHelpers(() => "/repo") + expect(path.normalize("file:///repo/src/app.ts?x=1#h")).toBe("src/app.ts") + expect(path.normalize("/repo/src/app.ts")).toBe("src/app.ts") + expect(path.normalize("./src/app.ts")).toBe("src/app.ts") + expect(path.normalizeDir("src/components///")).toBe("src/components") + expect(path.tab("src/app.ts")).toBe("file://src/app.ts") + expect(path.pathFromTab("file://src/app.ts")).toBe("src/app.ts") + expect(path.pathFromTab("other://src/app.ts")).toBeUndefined() + }) + + test("keeps query/hash stripping behavior stable", () => { + expect(stripQueryAndHash("a/b.ts#L12?x=1")).toBe("a/b.ts") + expect(stripQueryAndHash("a/b.ts?x=1#L12")).toBe("a/b.ts") + expect(stripQueryAndHash("a/b.ts")).toBe("a/b.ts") + }) + + test("unquotes git escaped octal path strings", () => { + expect(unquoteGitPath('"a/\\303\\251.txt"')).toBe("a/\u00e9.txt") + expect(unquoteGitPath('"plain\\nname"')).toBe("plain\nname") + expect(unquoteGitPath("a/b/c.ts")).toBe("a/b/c.ts") + }) +}) + +describe("encodeFilePath", () => { + describe("Linux/Unix paths", () => { + test("should handle Linux absolute path", () => { + const linuxPath = "/home/user/project/README.md" + const result = encodeFilePath(linuxPath) + const fileUrl = `file://${result}` + + // Should create a valid URL + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toBe("/home/user/project/README.md") + + const url = new URL(fileUrl) + expect(url.protocol).toBe("file:") + expect(url.pathname).toBe("/home/user/project/README.md") + }) + + test("should handle Linux path with special characters", () => { + const linuxPath = "/home/user/file#name with spaces.txt" + const result = encodeFilePath(linuxPath) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toBe("/home/user/file%23name%20with%20spaces.txt") + }) + + test("should handle Linux relative path", () => { + const relativePath = "src/components/App.tsx" + const result = encodeFilePath(relativePath) + + expect(result).toBe("src/components/App.tsx") + }) + + test("should handle Linux root directory", () => { + const result = encodeFilePath("/") + expect(result).toBe("/") + }) + + test("should handle Linux path with all special chars", () => { + const path = "/path/to/file#with?special%chars&more.txt" + const result = encodeFilePath(path) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toContain("%23") // # + expect(result).toContain("%3F") // ? + expect(result).toContain("%25") // % + expect(result).toContain("%26") // & + }) + }) + + describe("macOS paths", () => { + test("should handle macOS absolute path", () => { + const macPath = "/Users/kelvin/Projects/opencode/README.md" + const result = encodeFilePath(macPath) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toBe("/Users/kelvin/Projects/opencode/README.md") + }) + + test("should handle macOS path with spaces", () => { + const macPath = "/Users/kelvin/My Documents/file.txt" + const result = encodeFilePath(macPath) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toContain("My%20Documents") + }) + }) + + describe("Windows paths", () => { + test("should handle Windows absolute path with backslashes", () => { + const windowsPath = "D:\\dev\\projects\\opencode\\README.bs.md" + const result = encodeFilePath(windowsPath) + const fileUrl = `file://${result}` + + // Should create a valid, parseable URL + expect(() => new URL(fileUrl)).not.toThrow() + + const url = new URL(fileUrl) + expect(url.protocol).toBe("file:") + expect(url.pathname).toContain("README.bs.md") + expect(result).toBe("/D:/dev/projects/opencode/README.bs.md") + }) + + test("should handle mixed separator path (Windows + Unix)", () => { + // This is what happens in build-request-parts.ts when concatenating paths + const mixedPath = "D:\\dev\\projects\\opencode/README.bs.md" + const result = encodeFilePath(mixedPath) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toBe("/D:/dev/projects/opencode/README.bs.md") + }) + + test("should handle Windows path with spaces", () => { + const windowsPath = "C:\\Program Files\\MyApp\\file with spaces.txt" + const result = encodeFilePath(windowsPath) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toContain("Program%20Files") + expect(result).toContain("file%20with%20spaces.txt") + }) + + test("should handle Windows path with special chars in filename", () => { + const windowsPath = "D:\\projects\\file#name with ?marks.txt" + const result = encodeFilePath(windowsPath) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toContain("file%23name%20with%20%3Fmarks.txt") + }) + + test("should handle Windows root directory", () => { + const windowsPath = "C:\\" + const result = encodeFilePath(windowsPath) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toBe("/C:/") + }) + + test("should handle Windows relative path with backslashes", () => { + const windowsPath = "src\\components\\App.tsx" + const result = encodeFilePath(windowsPath) + + // Relative paths shouldn't get the leading slash + expect(result).toBe("src/components/App.tsx") + }) + + test("should NOT create invalid URL like the bug report", () => { + // This is the exact scenario from bug report by @alexyaroshuk + const windowsPath = "D:\\dev\\projects\\opencode\\README.bs.md" + const result = encodeFilePath(windowsPath) + const fileUrl = `file://${result}` + + // The bug was creating: file://D%3A%5Cdev%5Cprojects%5Copencode/README.bs.md + expect(result).not.toContain("%5C") // Should not have encoded backslashes + expect(result).not.toBe("D%3A%5Cdev%5Cprojects%5Copencode/README.bs.md") + + // Should be valid + expect(() => new URL(fileUrl)).not.toThrow() + }) + + test("should handle lowercase drive letters", () => { + const windowsPath = "c:\\users\\test\\file.txt" + const result = encodeFilePath(windowsPath) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toBe("/c:/users/test/file.txt") + }) + }) + + describe("Cross-platform compatibility", () => { + test("should preserve Unix paths unchanged (except encoding)", () => { + const unixPath = "/usr/local/bin/app" + const result = encodeFilePath(unixPath) + expect(result).toBe("/usr/local/bin/app") + }) + + test("should normalize Windows paths for cross-platform use", () => { + const windowsPath = "C:\\Users\\test\\file.txt" + const result = encodeFilePath(windowsPath) + // Should convert to forward slashes and add leading / + expect(result).not.toContain("\\") + expect(result).toMatch(/^\/[A-Za-z]:\//) + }) + + test("should handle relative paths the same on all platforms", () => { + const unixRelative = "src/app.ts" + const windowsRelative = "src\\app.ts" + + const unixResult = encodeFilePath(unixRelative) + const windowsResult = encodeFilePath(windowsRelative) + + // Both should normalize to forward slashes + expect(unixResult).toBe("src/app.ts") + expect(windowsResult).toBe("src/app.ts") + }) + }) + + describe("Edge cases", () => { + test("should handle empty path", () => { + const result = encodeFilePath("") + expect(result).toBe("") + }) + + test("should handle path with multiple consecutive slashes", () => { + const result = encodeFilePath("//path//to///file.txt") + // Multiple slashes should be preserved (backend handles normalization) + expect(result).toBe("//path//to///file.txt") + }) + + test("should encode Unicode characters", () => { + const unicodePath = "/home/user/文档/README.md" + const result = encodeFilePath(unicodePath) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + // Unicode should be encoded + expect(result).toContain("%E6%96%87%E6%A1%A3") + }) + + test("should handle already normalized Windows path", () => { + // Path that's already been normalized (has / before drive letter) + const alreadyNormalized = "/D:/path/file.txt" + const result = encodeFilePath(alreadyNormalized) + + // Should not add another leading slash + expect(result).toBe("/D:/path/file.txt") + expect(result).not.toContain("//D") + }) + + test("should handle just drive letter", () => { + const justDrive = "D:" + const result = encodeFilePath(justDrive) + const fileUrl = `file://${result}` + + expect(result).toBe("/D:") + expect(() => new URL(fileUrl)).not.toThrow() + }) + + test("should handle Windows path with trailing backslash", () => { + const trailingBackslash = "C:\\Users\\test\\" + const result = encodeFilePath(trailingBackslash) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toBe("/C:/Users/test/") + }) + + test("should handle very long paths", () => { + const longPath = "C:\\Users\\test\\" + "verylongdirectoryname\\".repeat(20) + "file.txt" + const result = encodeFilePath(longPath) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).not.toContain("\\") + }) + + test("should handle paths with dots", () => { + const pathWithDots = "C:\\Users\\..\\test\\.\\file.txt" + const result = encodeFilePath(pathWithDots) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + // Dots should be preserved (backend normalizes) + expect(result).toContain("..") + expect(result).toContain("/./") + }) + }) + + describe("Regression tests for PR #12424", () => { + test("should handle file with # in name", () => { + const path = "/path/to/file#name.txt" + const result = encodeFilePath(path) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toBe("/path/to/file%23name.txt") + }) + + test("should handle file with ? in name", () => { + const path = "/path/to/file?name.txt" + const result = encodeFilePath(path) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toBe("/path/to/file%3Fname.txt") + }) + + test("should handle file with % in name", () => { + const path = "/path/to/file%name.txt" + const result = encodeFilePath(path) + const fileUrl = `file://${result}` + + expect(() => new URL(fileUrl)).not.toThrow() + expect(result).toBe("/path/to/file%25name.txt") + }) + }) + + describe("Integration with file:// URL construction", () => { + test("should work with query parameters (Linux)", () => { + const path = "/home/user/file.txt" + const encoded = encodeFilePath(path) + const fileUrl = `file://${encoded}?start=10&end=20` + + const url = new URL(fileUrl) + expect(url.searchParams.get("start")).toBe("10") + expect(url.searchParams.get("end")).toBe("20") + expect(url.pathname).toBe("/home/user/file.txt") + }) + + test("should work with query parameters (Windows)", () => { + const path = "C:\\Users\\test\\file.txt" + const encoded = encodeFilePath(path) + const fileUrl = `file://${encoded}?start=10&end=20` + + const url = new URL(fileUrl) + expect(url.searchParams.get("start")).toBe("10") + expect(url.searchParams.get("end")).toBe("20") + }) + + test("should parse correctly in URL constructor (Linux)", () => { + const path = "/var/log/app.log" + const fileUrl = `file://${encodeFilePath(path)}` + const url = new URL(fileUrl) + + expect(url.protocol).toBe("file:") + expect(url.pathname).toBe("/var/log/app.log") + }) + + test("should parse correctly in URL constructor (Windows)", () => { + const path = "D:\\logs\\app.log" + const fileUrl = `file://${encodeFilePath(path)}` + const url = new URL(fileUrl) + + expect(url.protocol).toBe("file:") + expect(url.pathname).toContain("app.log") + }) + }) +}) diff --git a/packages/app/src/context/file/path.ts b/packages/app/src/context/file/path.ts new file mode 100644 index 00000000000..859fdc04062 --- /dev/null +++ b/packages/app/src/context/file/path.ts @@ -0,0 +1,148 @@ +export function stripFileProtocol(input: string) { + if (!input.startsWith("file://")) return input + return input.slice("file://".length) +} + +export function stripQueryAndHash(input: string) { + const hashIndex = input.indexOf("#") + const queryIndex = input.indexOf("?") + + if (hashIndex !== -1 && queryIndex !== -1) { + return input.slice(0, Math.min(hashIndex, queryIndex)) + } + + if (hashIndex !== -1) return input.slice(0, hashIndex) + if (queryIndex !== -1) return input.slice(0, queryIndex) + return input +} + +export function unquoteGitPath(input: string) { + if (!input.startsWith('"')) return input + if (!input.endsWith('"')) return input + const body = input.slice(1, -1) + const bytes: number[] = [] + + for (let i = 0; i < body.length; i++) { + const char = body[i]! + if (char !== "\\") { + bytes.push(char.charCodeAt(0)) + continue + } + + const next = body[i + 1] + if (!next) { + bytes.push("\\".charCodeAt(0)) + continue + } + + if (next >= "0" && next <= "7") { + const chunk = body.slice(i + 1, i + 4) + const match = chunk.match(/^[0-7]{1,3}/) + if (!match) { + bytes.push(next.charCodeAt(0)) + i++ + continue + } + bytes.push(parseInt(match[0], 8)) + i += match[0].length + continue + } + + const escaped = + next === "n" + ? "\n" + : next === "r" + ? "\r" + : next === "t" + ? "\t" + : next === "b" + ? "\b" + : next === "f" + ? "\f" + : next === "v" + ? "\v" + : next === "\\" || next === '"' + ? next + : undefined + + bytes.push((escaped ?? next).charCodeAt(0)) + i++ + } + + return new TextDecoder().decode(new Uint8Array(bytes)) +} + +export function decodeFilePath(input: string) { + try { + return decodeURIComponent(input) + } catch { + return input + } +} + +export function encodeFilePath(filepath: string): string { + // Normalize Windows paths: convert backslashes to forward slashes + let normalized = filepath.replace(/\\/g, "/") + + // Handle Windows absolute paths (D:/path -> /D:/path for proper file:// URLs) + if (/^[A-Za-z]:/.test(normalized)) { + normalized = "/" + normalized + } + + // Encode each path segment (preserving forward slashes as path separators) + // Keep the colon in Windows drive letters (`/C:/...`) so downstream file URL parsers + // can reliably detect drives. + return normalized + .split("/") + .map((segment, index) => { + if (index === 1 && /^[A-Za-z]:$/.test(segment)) return segment + return encodeURIComponent(segment) + }) + .join("/") +} + +export function createPathHelpers(scope: () => string) { + const normalize = (input: string) => { + const root = scope() + const prefix = root.endsWith("/") ? root : root + "/" + + let path = unquoteGitPath(decodeFilePath(stripQueryAndHash(stripFileProtocol(input)))) + + if (path.startsWith(prefix)) { + path = path.slice(prefix.length) + } + + if (path.startsWith(root)) { + path = path.slice(root.length) + } + + if (path.startsWith("./")) { + path = path.slice(2) + } + + if (path.startsWith("/")) { + path = path.slice(1) + } + + return path + } + + const tab = (input: string) => { + const path = normalize(input) + return `file://${encodeFilePath(path)}` + } + + const pathFromTab = (tabValue: string) => { + if (!tabValue.startsWith("file://")) return + return normalize(tabValue) + } + + const normalizeDir = (input: string) => normalize(input).replace(/\/+$/, "") + + return { + normalize, + tab, + pathFromTab, + normalizeDir, + } +} diff --git a/packages/app/src/context/file/tree-store.ts b/packages/app/src/context/file/tree-store.ts new file mode 100644 index 00000000000..a86051d286e --- /dev/null +++ b/packages/app/src/context/file/tree-store.ts @@ -0,0 +1,170 @@ +import { createStore, produce, reconcile } from "solid-js/store" +import type { FileNode } from "@opencode-ai/sdk/v2" + +type DirectoryState = { + expanded: boolean + loaded?: boolean + loading?: boolean + error?: string + children?: string[] +} + +type TreeStoreOptions = { + scope: () => string + normalizeDir: (input: string) => string + list: (input: string) => Promise + onError: (message: string) => void +} + +export function createFileTreeStore(options: TreeStoreOptions) { + const [tree, setTree] = createStore<{ + node: Record + dir: Record + }>({ + node: {}, + dir: { "": { expanded: true } }, + }) + + const inflight = new Map>() + + const reset = () => { + inflight.clear() + setTree("node", reconcile({})) + setTree("dir", reconcile({})) + setTree("dir", "", { expanded: true }) + } + + const ensureDir = (path: string) => { + if (tree.dir[path]) return + setTree("dir", path, { expanded: false }) + } + + const listDir = (input: string, opts?: { force?: boolean }) => { + const dir = options.normalizeDir(input) + ensureDir(dir) + + const current = tree.dir[dir] + if (!opts?.force && current?.loaded) return Promise.resolve() + + const pending = inflight.get(dir) + if (pending) return pending + + setTree( + "dir", + dir, + produce((draft) => { + draft.loading = true + draft.error = undefined + }), + ) + + const directory = options.scope() + + const promise = options + .list(dir) + .then((nodes) => { + if (options.scope() !== directory) return + const prevChildren = tree.dir[dir]?.children ?? [] + const nextChildren = nodes.map((node) => node.path) + const nextSet = new Set(nextChildren) + + setTree( + "node", + produce((draft) => { + const removedDirs: string[] = [] + + for (const child of prevChildren) { + if (nextSet.has(child)) continue + const existing = draft[child] + if (existing?.type === "directory") removedDirs.push(child) + delete draft[child] + } + + if (removedDirs.length > 0) { + const keys = Object.keys(draft) + for (const key of keys) { + for (const removed of removedDirs) { + if (!key.startsWith(removed + "/")) continue + delete draft[key] + break + } + } + } + + for (const node of nodes) { + draft[node.path] = node + } + }), + ) + + setTree( + "dir", + dir, + produce((draft) => { + draft.loaded = true + draft.loading = false + draft.children = nextChildren + }), + ) + }) + .catch((e) => { + if (options.scope() !== directory) return + setTree( + "dir", + dir, + produce((draft) => { + draft.loading = false + draft.error = e.message + }), + ) + options.onError(e.message) + }) + .finally(() => { + inflight.delete(dir) + }) + + inflight.set(dir, promise) + return promise + } + + const expandDir = (input: string) => { + const dir = options.normalizeDir(input) + ensureDir(dir) + setTree("dir", dir, "expanded", true) + void listDir(dir) + } + + const collapseDir = (input: string) => { + const dir = options.normalizeDir(input) + ensureDir(dir) + setTree("dir", dir, "expanded", false) + } + + const dirState = (input: string) => { + const dir = options.normalizeDir(input) + return tree.dir[dir] + } + + const children = (input: string) => { + const dir = options.normalizeDir(input) + const ids = tree.dir[dir]?.children + if (!ids) return [] + const out: FileNode[] = [] + for (const id of ids) { + const node = tree.node[id] + if (node) out.push(node) + } + return out + } + + return { + listDir, + expandDir, + collapseDir, + dirState, + children, + node: (path: string) => tree.node[path], + isLoaded: (path: string) => Boolean(tree.dir[path]?.loaded), + reset, + } +} diff --git a/packages/app/src/context/file/types.ts b/packages/app/src/context/file/types.ts new file mode 100644 index 00000000000..7ce8a37c25e --- /dev/null +++ b/packages/app/src/context/file/types.ts @@ -0,0 +1,41 @@ +import type { FileContent } from "@opencode-ai/sdk/v2" + +export type FileSelection = { + startLine: number + startChar: number + endLine: number + endChar: number +} + +export type SelectedLineRange = { + start: number + end: number + side?: "additions" | "deletions" + endSide?: "additions" | "deletions" +} + +export type FileViewState = { + scrollTop?: number + scrollLeft?: number + selectedLines?: SelectedLineRange | null +} + +export type FileState = { + path: string + name: string + loaded?: boolean + loading?: boolean + error?: string + content?: FileContent +} + +export function selectionFromLines(range: SelectedLineRange): FileSelection { + const startLine = Math.min(range.start, range.end) + const endLine = Math.max(range.start, range.end) + return { + startLine, + endLine, + startChar: 0, + endChar: 0, + } +} diff --git a/packages/app/src/context/file/view-cache.ts b/packages/app/src/context/file/view-cache.ts new file mode 100644 index 00000000000..2614b2fb533 --- /dev/null +++ b/packages/app/src/context/file/view-cache.ts @@ -0,0 +1,136 @@ +import { createEffect, createRoot } from "solid-js" +import { createStore, produce } from "solid-js/store" +import { Persist, persisted } from "@/utils/persist" +import { createScopedCache } from "@/utils/scoped-cache" +import type { FileViewState, SelectedLineRange } from "./types" + +const WORKSPACE_KEY = "__workspace__" +const MAX_FILE_VIEW_SESSIONS = 20 +const MAX_VIEW_FILES = 500 + +function normalizeSelectedLines(range: SelectedLineRange): SelectedLineRange { + if (range.start <= range.end) return range + + const startSide = range.side + const endSide = range.endSide ?? startSide + + return { + ...range, + start: range.end, + end: range.start, + side: endSide, + endSide: startSide !== endSide ? startSide : undefined, + } +} + +function createViewSession(dir: string, id: string | undefined) { + const legacyViewKey = `${dir}/file${id ? "/" + id : ""}.v1` + + const [view, setView, _, ready] = persisted( + Persist.scoped(dir, id, "file-view", [legacyViewKey]), + createStore<{ + file: Record + }>({ + file: {}, + }), + ) + + const meta = { pruned: false } + + const pruneView = (keep?: string) => { + const keys = Object.keys(view.file) + if (keys.length <= MAX_VIEW_FILES) return + + const drop = keys.filter((key) => key !== keep).slice(0, keys.length - MAX_VIEW_FILES) + if (drop.length === 0) return + + setView( + produce((draft) => { + for (const key of drop) { + delete draft.file[key] + } + }), + ) + } + + createEffect(() => { + if (!ready()) return + if (meta.pruned) return + meta.pruned = true + pruneView() + }) + + const scrollTop = (path: string) => view.file[path]?.scrollTop + const scrollLeft = (path: string) => view.file[path]?.scrollLeft + const selectedLines = (path: string) => view.file[path]?.selectedLines + + const setScrollTop = (path: string, top: number) => { + setView("file", path, (current) => { + if (current?.scrollTop === top) return current + return { + ...(current ?? {}), + scrollTop: top, + } + }) + pruneView(path) + } + + const setScrollLeft = (path: string, left: number) => { + setView("file", path, (current) => { + if (current?.scrollLeft === left) return current + return { + ...(current ?? {}), + scrollLeft: left, + } + }) + pruneView(path) + } + + const setSelectedLines = (path: string, range: SelectedLineRange | null) => { + const next = range ? normalizeSelectedLines(range) : null + setView("file", path, (current) => { + if (current?.selectedLines === next) return current + return { + ...(current ?? {}), + selectedLines: next, + } + }) + pruneView(path) + } + + return { + ready, + scrollTop, + scrollLeft, + selectedLines, + setScrollTop, + setScrollLeft, + setSelectedLines, + } +} + +export function createFileViewCache() { + const cache = createScopedCache( + (key) => { + const split = key.lastIndexOf("\n") + const dir = split >= 0 ? key.slice(0, split) : key + const id = split >= 0 ? key.slice(split + 1) : WORKSPACE_KEY + return createRoot((dispose) => ({ + value: createViewSession(dir, id === WORKSPACE_KEY ? undefined : id), + dispose, + })) + }, + { + maxEntries: MAX_FILE_VIEW_SESSIONS, + dispose: (entry) => entry.dispose(), + }, + ) + + return { + load: (dir: string, id: string | undefined) => { + const key = `${dir}\n${id ?? WORKSPACE_KEY}` + return cache.get(key).value + }, + clear: () => cache.clear(), + } +} diff --git a/packages/app/src/context/file/watcher.test.ts b/packages/app/src/context/file/watcher.test.ts new file mode 100644 index 00000000000..9536b52536b --- /dev/null +++ b/packages/app/src/context/file/watcher.test.ts @@ -0,0 +1,149 @@ +import { describe, expect, test } from "bun:test" +import { invalidateFromWatcher } from "./watcher" + +describe("file watcher invalidation", () => { + test("reloads open files and refreshes loaded parent on add", () => { + const loads: string[] = [] + const refresh: string[] = [] + invalidateFromWatcher( + { + type: "file.watcher.updated", + properties: { + file: "src/new.ts", + event: "add", + }, + }, + { + normalize: (input) => input, + hasFile: (path) => path === "src/new.ts", + loadFile: (path) => loads.push(path), + node: () => undefined, + isDirLoaded: (path) => path === "src", + refreshDir: (path) => refresh.push(path), + }, + ) + + expect(loads).toEqual(["src/new.ts"]) + expect(refresh).toEqual(["src"]) + }) + + test("reloads files that are open in tabs", () => { + const loads: string[] = [] + + invalidateFromWatcher( + { + type: "file.watcher.updated", + properties: { + file: "src/open.ts", + event: "change", + }, + }, + { + normalize: (input) => input, + hasFile: () => false, + isOpen: (path) => path === "src/open.ts", + loadFile: (path) => loads.push(path), + node: () => ({ + path: "src/open.ts", + type: "file", + name: "open.ts", + absolute: "/repo/src/open.ts", + ignored: false, + }), + isDirLoaded: () => false, + refreshDir: () => {}, + }, + ) + + expect(loads).toEqual(["src/open.ts"]) + }) + + test("refreshes only changed loaded directory nodes", () => { + const refresh: string[] = [] + + invalidateFromWatcher( + { + type: "file.watcher.updated", + properties: { + file: "src", + event: "change", + }, + }, + { + normalize: (input) => input, + hasFile: () => false, + loadFile: () => {}, + node: () => ({ path: "src", type: "directory", name: "src", absolute: "/repo/src", ignored: false }), + isDirLoaded: (path) => path === "src", + refreshDir: (path) => refresh.push(path), + }, + ) + + invalidateFromWatcher( + { + type: "file.watcher.updated", + properties: { + file: "src/file.ts", + event: "change", + }, + }, + { + normalize: (input) => input, + hasFile: () => false, + loadFile: () => {}, + node: () => ({ + path: "src/file.ts", + type: "file", + name: "file.ts", + absolute: "/repo/src/file.ts", + ignored: false, + }), + isDirLoaded: () => true, + refreshDir: (path) => refresh.push(path), + }, + ) + + expect(refresh).toEqual(["src"]) + }) + + test("ignores invalid or git watcher updates", () => { + const refresh: string[] = [] + + invalidateFromWatcher( + { + type: "file.watcher.updated", + properties: { + file: ".git/index.lock", + event: "change", + }, + }, + { + normalize: (input) => input, + hasFile: () => true, + loadFile: () => { + throw new Error("should not load") + }, + node: () => undefined, + isDirLoaded: () => true, + refreshDir: (path) => refresh.push(path), + }, + ) + + invalidateFromWatcher( + { + type: "project.updated", + properties: {}, + }, + { + normalize: (input) => input, + hasFile: () => false, + loadFile: () => {}, + node: () => undefined, + isDirLoaded: () => true, + refreshDir: (path) => refresh.push(path), + }, + ) + + expect(refresh).toEqual([]) + }) +}) diff --git a/packages/app/src/context/file/watcher.ts b/packages/app/src/context/file/watcher.ts new file mode 100644 index 00000000000..fbf71992791 --- /dev/null +++ b/packages/app/src/context/file/watcher.ts @@ -0,0 +1,53 @@ +import type { FileNode } from "@opencode-ai/sdk/v2" + +type WatcherEvent = { + type: string + properties: unknown +} + +type WatcherOps = { + normalize: (input: string) => string + hasFile: (path: string) => boolean + isOpen?: (path: string) => boolean + loadFile: (path: string) => void + node: (path: string) => FileNode | undefined + isDirLoaded: (path: string) => boolean + refreshDir: (path: string) => void +} + +export function invalidateFromWatcher(event: WatcherEvent, ops: WatcherOps) { + if (event.type !== "file.watcher.updated") return + const props = + typeof event.properties === "object" && event.properties ? (event.properties as Record) : undefined + const rawPath = typeof props?.file === "string" ? props.file : undefined + const kind = typeof props?.event === "string" ? props.event : undefined + if (!rawPath) return + if (!kind) return + + const path = ops.normalize(rawPath) + if (!path) return + if (path.startsWith(".git/")) return + + if (ops.hasFile(path) || ops.isOpen?.(path)) { + ops.loadFile(path) + } + + if (kind === "change") { + const dir = (() => { + if (path === "") return "" + const node = ops.node(path) + if (node?.type !== "directory") return + return path + })() + if (dir === undefined) return + if (!ops.isDirLoaded(dir)) return + ops.refreshDir(dir) + return + } + if (kind !== "add" && kind !== "unlink") return + + const parent = path.split("/").slice(0, -1).join("/") + if (!ops.isDirLoaded(parent)) return + + ops.refreshDir(parent) +} diff --git a/packages/app/src/context/global-sync.test.ts b/packages/app/src/context/global-sync.test.ts new file mode 100644 index 00000000000..396b412318b --- /dev/null +++ b/packages/app/src/context/global-sync.test.ts @@ -0,0 +1,136 @@ +import { describe, expect, test } from "bun:test" +import { + canDisposeDirectory, + estimateRootSessionTotal, + loadRootSessionsWithFallback, + pickDirectoriesToEvict, +} from "./global-sync" + +describe("pickDirectoriesToEvict", () => { + test("keeps pinned stores and evicts idle stores", () => { + const now = 5_000 + const picks = pickDirectoriesToEvict({ + stores: ["a", "b", "c", "d"], + state: new Map([ + ["a", { lastAccessAt: 1_000 }], + ["b", { lastAccessAt: 4_900 }], + ["c", { lastAccessAt: 4_800 }], + ["d", { lastAccessAt: 3_000 }], + ]), + pins: new Set(["a"]), + max: 2, + ttl: 1_500, + now, + }) + + expect(picks).toEqual(["d", "c"]) + }) +}) + +describe("loadRootSessionsWithFallback", () => { + test("uses limited roots query when supported", async () => { + const calls: Array<{ directory: string; roots: true; limit?: number }> = [] + let fallback = 0 + + const result = await loadRootSessionsWithFallback({ + directory: "dir", + limit: 10, + list: async (query) => { + calls.push(query) + return { data: [] } + }, + onFallback: () => { + fallback += 1 + }, + }) + + expect(result.data).toEqual([]) + expect(result.limited).toBe(true) + expect(calls).toEqual([{ directory: "dir", roots: true, limit: 10 }]) + expect(fallback).toBe(0) + }) + + test("falls back to full roots query on limited-query failure", async () => { + const calls: Array<{ directory: string; roots: true; limit?: number }> = [] + let fallback = 0 + + const result = await loadRootSessionsWithFallback({ + directory: "dir", + limit: 25, + list: async (query) => { + calls.push(query) + if (query.limit) throw new Error("unsupported") + return { data: [] } + }, + onFallback: () => { + fallback += 1 + }, + }) + + expect(result.data).toEqual([]) + expect(result.limited).toBe(false) + expect(calls).toEqual([ + { directory: "dir", roots: true, limit: 25 }, + { directory: "dir", roots: true }, + ]) + expect(fallback).toBe(1) + }) +}) + +describe("estimateRootSessionTotal", () => { + test("keeps exact total for full fetches", () => { + expect(estimateRootSessionTotal({ count: 42, limit: 10, limited: false })).toBe(42) + }) + + test("marks has-more for full-limit limited fetches", () => { + expect(estimateRootSessionTotal({ count: 10, limit: 10, limited: true })).toBe(11) + }) + + test("keeps exact total when limited fetch is under limit", () => { + expect(estimateRootSessionTotal({ count: 9, limit: 10, limited: true })).toBe(9) + }) +}) + +describe("canDisposeDirectory", () => { + test("rejects pinned or inflight directories", () => { + expect( + canDisposeDirectory({ + directory: "dir", + hasStore: true, + pinned: true, + booting: false, + loadingSessions: false, + }), + ).toBe(false) + expect( + canDisposeDirectory({ + directory: "dir", + hasStore: true, + pinned: false, + booting: true, + loadingSessions: false, + }), + ).toBe(false) + expect( + canDisposeDirectory({ + directory: "dir", + hasStore: true, + pinned: false, + booting: false, + loadingSessions: true, + }), + ).toBe(false) + }) + + test("accepts idle unpinned directory store", () => { + expect( + canDisposeDirectory({ + directory: "dir", + hasStore: true, + pinned: false, + booting: false, + loadingSessions: false, + }), + ).toBe(true) + }) +}) diff --git a/packages/app/src/context/global-sync/bootstrap.ts b/packages/app/src/context/global-sync/bootstrap.ts new file mode 100644 index 00000000000..2137a19a823 --- /dev/null +++ b/packages/app/src/context/global-sync/bootstrap.ts @@ -0,0 +1,195 @@ +import { + type Config, + type Path, + type PermissionRequest, + type Project, + type ProviderAuthResponse, + type ProviderListResponse, + type QuestionRequest, + createOpencodeClient, +} from "@opencode-ai/sdk/v2/client" +import { batch } from "solid-js" +import { reconcile, type SetStoreFunction, type Store } from "solid-js/store" +import { retry } from "@opencode-ai/util/retry" +import { getFilename } from "@opencode-ai/util/path" +import { showToast } from "@opencode-ai/ui/toast" +import { cmp, normalizeProviderList } from "./utils" +import type { State, VcsCache } from "./types" + +type GlobalStore = { + ready: boolean + path: Path + project: Project[] + provider: ProviderListResponse + provider_auth: ProviderAuthResponse + config: Config + reload: undefined | "pending" | "complete" +} + +export async function bootstrapGlobal(input: { + globalSDK: ReturnType + connectErrorTitle: string + connectErrorDescription: string + requestFailedTitle: string + setGlobalStore: SetStoreFunction +}) { + const health = await input.globalSDK.global + .health() + .then((x) => x.data) + .catch(() => undefined) + if (!health?.healthy) { + showToast({ + variant: "error", + title: input.connectErrorTitle, + description: input.connectErrorDescription, + }) + input.setGlobalStore("ready", true) + return + } + + const tasks = [ + retry(() => + input.globalSDK.path.get().then((x) => { + input.setGlobalStore("path", x.data!) + }), + ), + retry(() => + input.globalSDK.global.config.get().then((x) => { + input.setGlobalStore("config", x.data!) + }), + ), + retry(() => + input.globalSDK.project.list().then((x) => { + const projects = (x.data ?? []) + .filter((p) => !!p?.id) + .filter((p) => !!p.worktree && !p.worktree.includes("opencode-test")) + .slice() + .sort((a, b) => cmp(a.id, b.id)) + input.setGlobalStore("project", projects) + }), + ), + retry(() => + input.globalSDK.provider.list().then((x) => { + input.setGlobalStore("provider", normalizeProviderList(x.data!)) + }), + ), + retry(() => + input.globalSDK.provider.auth().then((x) => { + input.setGlobalStore("provider_auth", x.data ?? {}) + }), + ), + ] + + const results = await Promise.allSettled(tasks) + const errors = results.filter((r): r is PromiseRejectedResult => r.status === "rejected").map((r) => r.reason) + if (errors.length) { + const message = errors[0] instanceof Error ? errors[0].message : String(errors[0]) + const more = errors.length > 1 ? ` (+${errors.length - 1} more)` : "" + showToast({ + variant: "error", + title: input.requestFailedTitle, + description: message + more, + }) + } + input.setGlobalStore("ready", true) +} + +function groupBySession(input: T[]) { + return input.reduce>((acc, item) => { + if (!item?.id || !item.sessionID) return acc + const list = acc[item.sessionID] + if (list) list.push(item) + if (!list) acc[item.sessionID] = [item] + return acc + }, {}) +} + +export async function bootstrapDirectory(input: { + directory: string + sdk: ReturnType + store: Store + setStore: SetStoreFunction + vcsCache: VcsCache + loadSessions: (directory: string) => Promise | void +}) { + input.setStore("status", "loading") + + const blockingRequests = { + project: () => input.sdk.project.current().then((x) => input.setStore("project", x.data!.id)), + provider: () => + input.sdk.provider.list().then((x) => { + input.setStore("provider", normalizeProviderList(x.data!)) + }), + agent: () => input.sdk.app.agents().then((x) => input.setStore("agent", x.data ?? [])), + config: () => input.sdk.config.get().then((x) => input.setStore("config", x.data!)), + } + + try { + await Promise.all(Object.values(blockingRequests).map((p) => retry(p))) + } catch (err) { + console.error("Failed to bootstrap instance", err) + const project = getFilename(input.directory) + const message = err instanceof Error ? err.message : String(err) + showToast({ title: `Failed to reload ${project}`, description: message }) + input.setStore("status", "partial") + return + } + + if (input.store.status !== "complete") input.setStore("status", "partial") + + Promise.all([ + input.sdk.path.get().then((x) => input.setStore("path", x.data!)), + input.sdk.command.list().then((x) => input.setStore("command", x.data ?? [])), + input.sdk.session.status().then((x) => input.setStore("session_status", x.data!)), + input.loadSessions(input.directory), + input.sdk.mcp.status().then((x) => input.setStore("mcp", x.data!)), + input.sdk.lsp.status().then((x) => input.setStore("lsp", x.data!)), + input.sdk.vcs.get().then((x) => { + const next = x.data ?? input.store.vcs + input.setStore("vcs", next) + if (next?.branch) input.vcsCache.setStore("value", next) + }), + input.sdk.permission.list().then((x) => { + const grouped = groupBySession( + (x.data ?? []).filter((perm): perm is PermissionRequest => !!perm?.id && !!perm.sessionID), + ) + batch(() => { + for (const sessionID of Object.keys(input.store.permission)) { + if (grouped[sessionID]) continue + input.setStore("permission", sessionID, []) + } + for (const [sessionID, permissions] of Object.entries(grouped)) { + input.setStore( + "permission", + sessionID, + reconcile( + permissions.filter((p) => !!p?.id).sort((a, b) => cmp(a.id, b.id)), + { key: "id" }, + ), + ) + } + }) + }), + input.sdk.question.list().then((x) => { + const grouped = groupBySession((x.data ?? []).filter((q): q is QuestionRequest => !!q?.id && !!q.sessionID)) + batch(() => { + for (const sessionID of Object.keys(input.store.question)) { + if (grouped[sessionID]) continue + input.setStore("question", sessionID, []) + } + for (const [sessionID, questions] of Object.entries(grouped)) { + input.setStore( + "question", + sessionID, + reconcile( + questions.filter((q) => !!q?.id).sort((a, b) => cmp(a.id, b.id)), + { key: "id" }, + ), + ) + } + }) + }), + ]).then(() => { + input.setStore("status", "complete") + }) +} diff --git a/packages/app/src/context/global-sync/child-store.ts b/packages/app/src/context/global-sync/child-store.ts new file mode 100644 index 00000000000..2feb7fe0884 --- /dev/null +++ b/packages/app/src/context/global-sync/child-store.ts @@ -0,0 +1,263 @@ +import { createRoot, createEffect, getOwner, onCleanup, runWithOwner, type Accessor, type Owner } from "solid-js" +import { createStore, type SetStoreFunction, type Store } from "solid-js/store" +import { Persist, persisted } from "@/utils/persist" +import type { VcsInfo } from "@opencode-ai/sdk/v2/client" +import { + DIR_IDLE_TTL_MS, + MAX_DIR_STORES, + type ChildOptions, + type DirState, + type IconCache, + type MetaCache, + type ProjectMeta, + type State, + type VcsCache, +} from "./types" +import { canDisposeDirectory, pickDirectoriesToEvict } from "./eviction" + +export function createChildStoreManager(input: { + owner: Owner + markStats: (activeDirectoryStores: number) => void + incrementEvictions: () => void + isBooting: (directory: string) => boolean + isLoadingSessions: (directory: string) => boolean + onBootstrap: (directory: string) => void + onDispose: (directory: string) => void +}) { + const children: Record, SetStoreFunction]> = {} + const vcsCache = new Map() + const metaCache = new Map() + const iconCache = new Map() + const lifecycle = new Map() + const pins = new Map() + const ownerPins = new WeakMap>() + const disposers = new Map void>() + + const mark = (directory: string) => { + if (!directory) return + lifecycle.set(directory, { lastAccessAt: Date.now() }) + runEviction() + } + + const pin = (directory: string) => { + if (!directory) return + pins.set(directory, (pins.get(directory) ?? 0) + 1) + mark(directory) + } + + const unpin = (directory: string) => { + if (!directory) return + const next = (pins.get(directory) ?? 0) - 1 + if (next > 0) { + pins.set(directory, next) + return + } + pins.delete(directory) + runEviction() + } + + const pinned = (directory: string) => (pins.get(directory) ?? 0) > 0 + + const pinForOwner = (directory: string) => { + const current = getOwner() + if (!current) return + if (current === input.owner) return + const key = current as object + const set = ownerPins.get(key) + if (set?.has(directory)) return + if (set) set.add(directory) + if (!set) ownerPins.set(key, new Set([directory])) + pin(directory) + onCleanup(() => { + const set = ownerPins.get(key) + if (set) { + set.delete(directory) + if (set.size === 0) ownerPins.delete(key) + } + unpin(directory) + }) + } + + function disposeDirectory(directory: string) { + if ( + !canDisposeDirectory({ + directory, + hasStore: !!children[directory], + pinned: pinned(directory), + booting: input.isBooting(directory), + loadingSessions: input.isLoadingSessions(directory), + }) + ) { + return false + } + + vcsCache.delete(directory) + metaCache.delete(directory) + iconCache.delete(directory) + lifecycle.delete(directory) + const dispose = disposers.get(directory) + if (dispose) { + dispose() + disposers.delete(directory) + } + delete children[directory] + input.onDispose(directory) + input.markStats(Object.keys(children).length) + return true + } + + function runEviction() { + const stores = Object.keys(children) + if (stores.length === 0) return + const list = pickDirectoriesToEvict({ + stores, + state: lifecycle, + pins: new Set(stores.filter(pinned)), + max: MAX_DIR_STORES, + ttl: DIR_IDLE_TTL_MS, + now: Date.now(), + }) + if (list.length === 0) return + for (const directory of list) { + if (!disposeDirectory(directory)) continue + input.incrementEvictions() + } + } + + function ensureChild(directory: string) { + if (!directory) console.error("No directory provided") + if (!children[directory]) { + const vcs = runWithOwner(input.owner, () => + persisted( + Persist.workspace(directory, "vcs", ["vcs.v1"]), + createStore({ value: undefined as VcsInfo | undefined }), + ), + ) + if (!vcs) throw new Error("Failed to create persisted cache") + const vcsStore = vcs[0] + const vcsReady = vcs[3] + vcsCache.set(directory, { store: vcsStore, setStore: vcs[1], ready: vcsReady }) + + const meta = runWithOwner(input.owner, () => + persisted( + Persist.workspace(directory, "project", ["project.v1"]), + createStore({ value: undefined as ProjectMeta | undefined }), + ), + ) + if (!meta) throw new Error("Failed to create persisted project metadata") + metaCache.set(directory, { store: meta[0], setStore: meta[1], ready: meta[3] }) + + const icon = runWithOwner(input.owner, () => + persisted( + Persist.workspace(directory, "icon", ["icon.v1"]), + createStore({ value: undefined as string | undefined }), + ), + ) + if (!icon) throw new Error("Failed to create persisted project icon") + iconCache.set(directory, { store: icon[0], setStore: icon[1], ready: icon[3] }) + + const init = () => + createRoot((dispose) => { + const child = createStore({ + project: "", + projectMeta: meta[0].value, + icon: icon[0].value, + provider: { all: [], connected: [], default: {} }, + config: {}, + path: { state: "", config: "", worktree: "", directory: "", home: "" }, + status: "loading" as const, + agent: [], + command: [], + session: [], + sessionTotal: 0, + session_status: {}, + session_diff: {}, + todo: {}, + permission: {}, + question: {}, + mcp: {}, + lsp: [], + vcs: vcsStore.value, + limit: 5, + message: {}, + part: {}, + }) + children[directory] = child + disposers.set(directory, dispose) + + createEffect(() => { + if (!vcsReady()) return + const cached = vcsStore.value + if (!cached?.branch) return + child[1]("vcs", (value) => value ?? cached) + }) + createEffect(() => { + child[1]("projectMeta", meta[0].value) + }) + createEffect(() => { + child[1]("icon", icon[0].value) + }) + }) + + runWithOwner(input.owner, init) + input.markStats(Object.keys(children).length) + } + mark(directory) + const childStore = children[directory] + if (!childStore) throw new Error("Failed to create store") + return childStore + } + + function child(directory: string, options: ChildOptions = {}) { + const childStore = ensureChild(directory) + pinForOwner(directory) + const shouldBootstrap = options.bootstrap ?? true + if (shouldBootstrap && childStore[0].status === "loading") { + input.onBootstrap(directory) + } + return childStore + } + + function projectMeta(directory: string, patch: ProjectMeta) { + const [store, setStore] = ensureChild(directory) + const cached = metaCache.get(directory) + if (!cached) return + const previous = store.projectMeta ?? {} + const icon = patch.icon ? { ...(previous.icon ?? {}), ...patch.icon } : previous.icon + const commands = patch.commands ? { ...(previous.commands ?? {}), ...patch.commands } : previous.commands + const next = { + ...previous, + ...patch, + icon, + commands, + } + cached.setStore("value", next) + setStore("projectMeta", next) + } + + function projectIcon(directory: string, value: string | undefined) { + const [store, setStore] = ensureChild(directory) + const cached = iconCache.get(directory) + if (!cached) return + if (store.icon === value) return + cached.setStore("value", value) + setStore("icon", value) + } + + return { + children, + ensureChild, + child, + projectMeta, + projectIcon, + mark, + pin, + unpin, + pinned, + disposeDirectory, + runEviction, + vcsCache, + metaCache, + iconCache, + } +} diff --git a/packages/app/src/context/global-sync/event-reducer.test.ts b/packages/app/src/context/global-sync/event-reducer.test.ts new file mode 100644 index 00000000000..ad63f3c202e --- /dev/null +++ b/packages/app/src/context/global-sync/event-reducer.test.ts @@ -0,0 +1,482 @@ +import { describe, expect, test } from "bun:test" +import type { Message, Part, PermissionRequest, Project, QuestionRequest, Session } from "@opencode-ai/sdk/v2/client" +import { createStore } from "solid-js/store" +import type { State } from "./types" +import { applyDirectoryEvent, applyGlobalEvent } from "./event-reducer" + +const rootSession = (input: { id: string; parentID?: string; archived?: number }) => + ({ + id: input.id, + parentID: input.parentID, + time: { + created: 1, + updated: 1, + archived: input.archived, + }, + }) as Session + +const userMessage = (id: string, sessionID: string) => + ({ + id, + sessionID, + role: "user", + time: { created: 1 }, + agent: "assistant", + model: { providerID: "openai", modelID: "gpt" }, + }) as Message + +const textPart = (id: string, sessionID: string, messageID: string) => + ({ + id, + sessionID, + messageID, + type: "text", + text: id, + }) as Part + +const permissionRequest = (id: string, sessionID: string, title = id) => + ({ + id, + sessionID, + permission: title, + patterns: ["*"], + metadata: {}, + always: [], + }) as PermissionRequest + +const questionRequest = (id: string, sessionID: string, title = id) => + ({ + id, + sessionID, + questions: [ + { + question: title, + header: title, + options: [{ label: title, description: title }], + }, + ], + }) as QuestionRequest + +const baseState = (input: Partial = {}) => + ({ + status: "complete", + agent: [], + command: [], + project: "", + projectMeta: undefined, + icon: undefined, + provider: {} as State["provider"], + config: {} as State["config"], + path: { directory: "/tmp" } as State["path"], + session: [], + sessionTotal: 0, + session_status: {}, + session_diff: {}, + todo: {}, + permission: {}, + question: {}, + mcp: {}, + lsp: [], + vcs: undefined, + limit: 10, + message: {}, + part: {}, + ...input, + }) as State + +describe("applyGlobalEvent", () => { + test("upserts project.updated in sorted position", () => { + const project = [{ id: "a" }, { id: "c" }] as Project[] + let refreshCount = 0 + applyGlobalEvent({ + event: { type: "project.updated", properties: { id: "b" } }, + project, + refresh: () => { + refreshCount += 1 + }, + setGlobalProject(next) { + if (typeof next === "function") next(project) + }, + }) + + expect(project.map((x) => x.id)).toEqual(["a", "b", "c"]) + expect(refreshCount).toBe(0) + }) + + test("handles global.disposed by triggering refresh", () => { + let refreshCount = 0 + applyGlobalEvent({ + event: { type: "global.disposed" }, + project: [], + refresh: () => { + refreshCount += 1 + }, + setGlobalProject() {}, + }) + + expect(refreshCount).toBe(1) + }) +}) + +describe("applyDirectoryEvent", () => { + test("inserts root sessions in sorted order and updates sessionTotal", () => { + const [store, setStore] = createStore( + baseState({ + session: [rootSession({ id: "b" })], + sessionTotal: 1, + }), + ) + + applyDirectoryEvent({ + event: { type: "session.created", properties: { info: rootSession({ id: "a" }) } }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + + expect(store.session.map((x) => x.id)).toEqual(["a", "b"]) + expect(store.sessionTotal).toBe(2) + + applyDirectoryEvent({ + event: { type: "session.created", properties: { info: rootSession({ id: "c", parentID: "a" }) } }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + + expect(store.sessionTotal).toBe(2) + }) + + test("cleans session caches when archived", () => { + const message = userMessage("msg_1", "ses_1") + const [store, setStore] = createStore( + baseState({ + session: [rootSession({ id: "ses_1" }), rootSession({ id: "ses_2" })], + sessionTotal: 2, + message: { ses_1: [message] }, + part: { [message.id]: [textPart("prt_1", "ses_1", message.id)] }, + session_diff: { ses_1: [] }, + todo: { ses_1: [] }, + permission: { ses_1: [] }, + question: { ses_1: [] }, + session_status: { ses_1: { type: "busy" } }, + }), + ) + + applyDirectoryEvent({ + event: { type: "session.updated", properties: { info: rootSession({ id: "ses_1", archived: 10 }) } }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + + expect(store.session.map((x) => x.id)).toEqual(["ses_2"]) + expect(store.sessionTotal).toBe(1) + expect(store.message.ses_1).toBeUndefined() + expect(store.part[message.id]).toBeUndefined() + expect(store.session_diff.ses_1).toBeUndefined() + expect(store.todo.ses_1).toBeUndefined() + expect(store.permission.ses_1).toBeUndefined() + expect(store.question.ses_1).toBeUndefined() + expect(store.session_status.ses_1).toBeUndefined() + }) + + test("cleans session caches when deleted and decrements only root totals", () => { + const cases = [ + { info: rootSession({ id: "ses_1" }), expectedTotal: 1 }, + { info: rootSession({ id: "ses_2", parentID: "ses_1" }), expectedTotal: 2 }, + ] + + for (const item of cases) { + const message = userMessage("msg_1", item.info.id) + const [store, setStore] = createStore( + baseState({ + session: [ + rootSession({ id: "ses_1" }), + rootSession({ id: "ses_2", parentID: "ses_1" }), + rootSession({ id: "ses_3" }), + ], + sessionTotal: 2, + message: { [item.info.id]: [message] }, + part: { [message.id]: [textPart("prt_1", item.info.id, message.id)] }, + session_diff: { [item.info.id]: [] }, + todo: { [item.info.id]: [] }, + permission: { [item.info.id]: [] }, + question: { [item.info.id]: [] }, + session_status: { [item.info.id]: { type: "busy" } }, + }), + ) + + applyDirectoryEvent({ + event: { type: "session.deleted", properties: { info: item.info } }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + + expect(store.session.find((x) => x.id === item.info.id)).toBeUndefined() + expect(store.sessionTotal).toBe(item.expectedTotal) + expect(store.message[item.info.id]).toBeUndefined() + expect(store.part[message.id]).toBeUndefined() + expect(store.session_diff[item.info.id]).toBeUndefined() + expect(store.todo[item.info.id]).toBeUndefined() + expect(store.permission[item.info.id]).toBeUndefined() + expect(store.question[item.info.id]).toBeUndefined() + expect(store.session_status[item.info.id]).toBeUndefined() + } + }) + + test("upserts and removes messages while clearing orphaned parts", () => { + const sessionID = "ses_1" + const [store, setStore] = createStore( + baseState({ + message: { [sessionID]: [userMessage("msg_1", sessionID), userMessage("msg_3", sessionID)] }, + part: { msg_2: [textPart("prt_1", sessionID, "msg_2")] }, + }), + ) + + applyDirectoryEvent({ + event: { type: "message.updated", properties: { info: userMessage("msg_2", sessionID) } }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + + expect(store.message[sessionID]?.map((x) => x.id)).toEqual(["msg_1", "msg_2", "msg_3"]) + + applyDirectoryEvent({ + event: { + type: "message.updated", + properties: { + info: { + ...userMessage("msg_2", sessionID), + role: "assistant", + } as Message, + }, + }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + + expect(store.message[sessionID]?.find((x) => x.id === "msg_2")?.role).toBe("assistant") + + applyDirectoryEvent({ + event: { type: "message.removed", properties: { sessionID, messageID: "msg_2" } }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + + expect(store.message[sessionID]?.map((x) => x.id)).toEqual(["msg_1", "msg_3"]) + expect(store.part.msg_2).toBeUndefined() + }) + + test("upserts and prunes message parts", () => { + const sessionID = "ses_1" + const messageID = "msg_1" + const [store, setStore] = createStore( + baseState({ + part: { [messageID]: [textPart("prt_1", sessionID, messageID), textPart("prt_3", sessionID, messageID)] }, + }), + ) + + applyDirectoryEvent({ + event: { type: "message.part.updated", properties: { part: textPart("prt_2", sessionID, messageID) } }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + expect(store.part[messageID]?.map((x) => x.id)).toEqual(["prt_1", "prt_2", "prt_3"]) + + applyDirectoryEvent({ + event: { + type: "message.part.updated", + properties: { + part: { + ...textPart("prt_2", sessionID, messageID), + text: "changed", + } as Part, + }, + }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + const updated = store.part[messageID]?.find((x) => x.id === "prt_2") + expect(updated?.type).toBe("text") + if (updated?.type === "text") expect(updated.text).toBe("changed") + + applyDirectoryEvent({ + event: { type: "message.part.removed", properties: { messageID, partID: "prt_1" } }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + applyDirectoryEvent({ + event: { type: "message.part.removed", properties: { messageID, partID: "prt_2" } }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + applyDirectoryEvent({ + event: { type: "message.part.removed", properties: { messageID, partID: "prt_3" } }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + + expect(store.part[messageID]).toBeUndefined() + }) + + test("tracks permission and question request lifecycles", () => { + const sessionID = "ses_1" + const [store, setStore] = createStore( + baseState({ + permission: { [sessionID]: [permissionRequest("perm_1", sessionID), permissionRequest("perm_3", sessionID)] }, + question: { [sessionID]: [questionRequest("q_1", sessionID), questionRequest("q_3", sessionID)] }, + }), + ) + + applyDirectoryEvent({ + event: { type: "permission.asked", properties: permissionRequest("perm_2", sessionID) }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + expect(store.permission[sessionID]?.map((x) => x.id)).toEqual(["perm_1", "perm_2", "perm_3"]) + + applyDirectoryEvent({ + event: { type: "permission.asked", properties: permissionRequest("perm_2", sessionID, "updated") }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + expect(store.permission[sessionID]?.find((x) => x.id === "perm_2")?.permission).toBe("updated") + + applyDirectoryEvent({ + event: { type: "permission.replied", properties: { sessionID, requestID: "perm_2" } }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + expect(store.permission[sessionID]?.map((x) => x.id)).toEqual(["perm_1", "perm_3"]) + + applyDirectoryEvent({ + event: { type: "question.asked", properties: questionRequest("q_2", sessionID) }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + expect(store.question[sessionID]?.map((x) => x.id)).toEqual(["q_1", "q_2", "q_3"]) + + applyDirectoryEvent({ + event: { type: "question.asked", properties: questionRequest("q_2", sessionID, "updated") }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + expect(store.question[sessionID]?.find((x) => x.id === "q_2")?.questions[0]?.header).toBe("updated") + + applyDirectoryEvent({ + event: { type: "question.rejected", properties: { sessionID, requestID: "q_2" } }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + }) + expect(store.question[sessionID]?.map((x) => x.id)).toEqual(["q_1", "q_3"]) + }) + + test("updates vcs branch in store and cache", () => { + const [store, setStore] = createStore(baseState()) + const [cacheStore, setCacheStore] = createStore({ value: undefined as State["vcs"] }) + + applyDirectoryEvent({ + event: { type: "vcs.branch.updated", properties: { branch: "feature/test" } }, + store, + setStore, + push() {}, + directory: "/tmp", + loadLsp() {}, + vcsCache: { + store: cacheStore, + setStore: setCacheStore, + ready: () => true, + }, + }) + + expect(store.vcs).toEqual({ branch: "feature/test" }) + expect(cacheStore.value).toEqual({ branch: "feature/test" }) + }) + + test("routes disposal and lsp events to side-effect handlers", () => { + const [store, setStore] = createStore(baseState()) + const pushes: string[] = [] + let lspLoads = 0 + + applyDirectoryEvent({ + event: { type: "server.instance.disposed" }, + store, + setStore, + push(directory) { + pushes.push(directory) + }, + directory: "/tmp", + loadLsp() { + lspLoads += 1 + }, + }) + + applyDirectoryEvent({ + event: { type: "lsp.updated" }, + store, + setStore, + push(directory) { + pushes.push(directory) + }, + directory: "/tmp", + loadLsp() { + lspLoads += 1 + }, + }) + + expect(pushes).toEqual(["/tmp"]) + expect(lspLoads).toBe(1) + }) +}) diff --git a/packages/app/src/context/global-sync/event-reducer.ts b/packages/app/src/context/global-sync/event-reducer.ts new file mode 100644 index 00000000000..c658d82c8b7 --- /dev/null +++ b/packages/app/src/context/global-sync/event-reducer.ts @@ -0,0 +1,319 @@ +import { Binary } from "@opencode-ai/util/binary" +import { produce, reconcile, type SetStoreFunction, type Store } from "solid-js/store" +import type { + FileDiff, + Message, + Part, + PermissionRequest, + Project, + QuestionRequest, + Session, + SessionStatus, + Todo, +} from "@opencode-ai/sdk/v2/client" +import type { State, VcsCache } from "./types" +import { trimSessions } from "./session-trim" + +export function applyGlobalEvent(input: { + event: { type: string; properties?: unknown } + project: Project[] + setGlobalProject: (next: Project[] | ((draft: Project[]) => void)) => void + refresh: () => void +}) { + if (input.event.type === "global.disposed") { + input.refresh() + return + } + + if (input.event.type !== "project.updated") return + const properties = input.event.properties as Project + const result = Binary.search(input.project, properties.id, (s) => s.id) + if (result.found) { + input.setGlobalProject((draft) => { + draft[result.index] = { ...draft[result.index], ...properties } + }) + return + } + input.setGlobalProject((draft) => { + draft.splice(result.index, 0, properties) + }) +} + +function cleanupSessionCaches(store: Store, setStore: SetStoreFunction, sessionID: string) { + if (!sessionID) return + const hasAny = + store.message[sessionID] !== undefined || + store.session_diff[sessionID] !== undefined || + store.todo[sessionID] !== undefined || + store.permission[sessionID] !== undefined || + store.question[sessionID] !== undefined || + store.session_status[sessionID] !== undefined + if (!hasAny) return + setStore( + produce((draft) => { + const messages = draft.message[sessionID] + if (messages) { + for (const message of messages) { + const id = message?.id + if (!id) continue + delete draft.part[id] + } + } + delete draft.message[sessionID] + delete draft.session_diff[sessionID] + delete draft.todo[sessionID] + delete draft.permission[sessionID] + delete draft.question[sessionID] + delete draft.session_status[sessionID] + }), + ) +} + +export function applyDirectoryEvent(input: { + event: { type: string; properties?: unknown } + store: Store + setStore: SetStoreFunction + push: (directory: string) => void + directory: string + loadLsp: () => void + vcsCache?: VcsCache +}) { + const event = input.event + switch (event.type) { + case "server.instance.disposed": { + input.push(input.directory) + return + } + case "session.created": { + const info = (event.properties as { info: Session }).info + const result = Binary.search(input.store.session, info.id, (s) => s.id) + if (result.found) { + input.setStore("session", result.index, reconcile(info)) + break + } + const next = input.store.session.slice() + next.splice(result.index, 0, info) + const trimmed = trimSessions(next, { limit: input.store.limit, permission: input.store.permission }) + input.setStore("session", reconcile(trimmed, { key: "id" })) + if (!info.parentID) input.setStore("sessionTotal", (value) => value + 1) + break + } + case "session.updated": { + const info = (event.properties as { info: Session }).info + const result = Binary.search(input.store.session, info.id, (s) => s.id) + if (info.time.archived) { + if (result.found) { + input.setStore( + "session", + produce((draft) => { + draft.splice(result.index, 1) + }), + ) + } + cleanupSessionCaches(input.store, input.setStore, info.id) + if (info.parentID) break + input.setStore("sessionTotal", (value) => Math.max(0, value - 1)) + break + } + if (result.found) { + input.setStore("session", result.index, reconcile(info)) + break + } + const next = input.store.session.slice() + next.splice(result.index, 0, info) + const trimmed = trimSessions(next, { limit: input.store.limit, permission: input.store.permission }) + input.setStore("session", reconcile(trimmed, { key: "id" })) + break + } + case "session.deleted": { + const info = (event.properties as { info: Session }).info + const result = Binary.search(input.store.session, info.id, (s) => s.id) + if (result.found) { + input.setStore( + "session", + produce((draft) => { + draft.splice(result.index, 1) + }), + ) + } + cleanupSessionCaches(input.store, input.setStore, info.id) + if (info.parentID) break + input.setStore("sessionTotal", (value) => Math.max(0, value - 1)) + break + } + case "session.diff": { + const props = event.properties as { sessionID: string; diff: FileDiff[] } + input.setStore("session_diff", props.sessionID, reconcile(props.diff, { key: "file" })) + break + } + case "todo.updated": { + const props = event.properties as { sessionID: string; todos: Todo[] } + input.setStore("todo", props.sessionID, reconcile(props.todos, { key: "id" })) + break + } + case "session.status": { + const props = event.properties as { sessionID: string; status: SessionStatus } + input.setStore("session_status", props.sessionID, reconcile(props.status)) + break + } + case "message.updated": { + const info = (event.properties as { info: Message }).info + const messages = input.store.message[info.sessionID] + if (!messages) { + input.setStore("message", info.sessionID, [info]) + break + } + const result = Binary.search(messages, info.id, (m) => m.id) + if (result.found) { + input.setStore("message", info.sessionID, result.index, reconcile(info)) + break + } + input.setStore( + "message", + info.sessionID, + produce((draft) => { + draft.splice(result.index, 0, info) + }), + ) + break + } + case "message.removed": { + const props = event.properties as { sessionID: string; messageID: string } + input.setStore( + produce((draft) => { + const messages = draft.message[props.sessionID] + if (messages) { + const result = Binary.search(messages, props.messageID, (m) => m.id) + if (result.found) messages.splice(result.index, 1) + } + delete draft.part[props.messageID] + }), + ) + break + } + case "message.part.updated": { + const part = (event.properties as { part: Part }).part + const parts = input.store.part[part.messageID] + if (!parts) { + input.setStore("part", part.messageID, [part]) + break + } + const result = Binary.search(parts, part.id, (p) => p.id) + if (result.found) { + input.setStore("part", part.messageID, result.index, reconcile(part)) + break + } + input.setStore( + "part", + part.messageID, + produce((draft) => { + draft.splice(result.index, 0, part) + }), + ) + break + } + case "message.part.removed": { + const props = event.properties as { messageID: string; partID: string } + const parts = input.store.part[props.messageID] + if (!parts) break + const result = Binary.search(parts, props.partID, (p) => p.id) + if (result.found) { + input.setStore( + produce((draft) => { + const list = draft.part[props.messageID] + if (!list) return + const next = Binary.search(list, props.partID, (p) => p.id) + if (!next.found) return + list.splice(next.index, 1) + if (list.length === 0) delete draft.part[props.messageID] + }), + ) + } + break + } + case "vcs.branch.updated": { + const props = event.properties as { branch: string } + const next = { branch: props.branch } + input.setStore("vcs", next) + if (input.vcsCache) input.vcsCache.setStore("value", next) + break + } + case "permission.asked": { + const permission = event.properties as PermissionRequest + const permissions = input.store.permission[permission.sessionID] + if (!permissions) { + input.setStore("permission", permission.sessionID, [permission]) + break + } + const result = Binary.search(permissions, permission.id, (p) => p.id) + if (result.found) { + input.setStore("permission", permission.sessionID, result.index, reconcile(permission)) + break + } + input.setStore( + "permission", + permission.sessionID, + produce((draft) => { + draft.splice(result.index, 0, permission) + }), + ) + break + } + case "permission.replied": { + const props = event.properties as { sessionID: string; requestID: string } + const permissions = input.store.permission[props.sessionID] + if (!permissions) break + const result = Binary.search(permissions, props.requestID, (p) => p.id) + if (!result.found) break + input.setStore( + "permission", + props.sessionID, + produce((draft) => { + draft.splice(result.index, 1) + }), + ) + break + } + case "question.asked": { + const question = event.properties as QuestionRequest + const questions = input.store.question[question.sessionID] + if (!questions) { + input.setStore("question", question.sessionID, [question]) + break + } + const result = Binary.search(questions, question.id, (q) => q.id) + if (result.found) { + input.setStore("question", question.sessionID, result.index, reconcile(question)) + break + } + input.setStore( + "question", + question.sessionID, + produce((draft) => { + draft.splice(result.index, 0, question) + }), + ) + break + } + case "question.replied": + case "question.rejected": { + const props = event.properties as { sessionID: string; requestID: string } + const questions = input.store.question[props.sessionID] + if (!questions) break + const result = Binary.search(questions, props.requestID, (q) => q.id) + if (!result.found) break + input.setStore( + "question", + props.sessionID, + produce((draft) => { + draft.splice(result.index, 1) + }), + ) + break + } + case "lsp.updated": { + input.loadLsp() + break + } + } +} diff --git a/packages/app/src/context/global-sync/eviction.ts b/packages/app/src/context/global-sync/eviction.ts new file mode 100644 index 00000000000..676a6ee17e1 --- /dev/null +++ b/packages/app/src/context/global-sync/eviction.ts @@ -0,0 +1,28 @@ +import type { DisposeCheck, EvictPlan } from "./types" + +export function pickDirectoriesToEvict(input: EvictPlan) { + const overflow = Math.max(0, input.stores.length - input.max) + let pendingOverflow = overflow + const sorted = input.stores + .filter((dir) => !input.pins.has(dir)) + .slice() + .sort((a, b) => (input.state.get(a)?.lastAccessAt ?? 0) - (input.state.get(b)?.lastAccessAt ?? 0)) + const output: string[] = [] + for (const dir of sorted) { + const last = input.state.get(dir)?.lastAccessAt ?? 0 + const idle = input.now - last >= input.ttl + if (!idle && pendingOverflow <= 0) continue + output.push(dir) + if (pendingOverflow > 0) pendingOverflow -= 1 + } + return output +} + +export function canDisposeDirectory(input: DisposeCheck) { + if (!input.directory) return false + if (!input.hasStore) return false + if (input.pinned) return false + if (input.booting) return false + if (input.loadingSessions) return false + return true +} diff --git a/packages/app/src/context/global-sync/queue.ts b/packages/app/src/context/global-sync/queue.ts new file mode 100644 index 00000000000..c3468583b93 --- /dev/null +++ b/packages/app/src/context/global-sync/queue.ts @@ -0,0 +1,83 @@ +type QueueInput = { + paused: () => boolean + bootstrap: () => Promise + bootstrapInstance: (directory: string) => Promise | void +} + +export function createRefreshQueue(input: QueueInput) { + const queued = new Set() + let root = false + let running = false + let timer: ReturnType | undefined + + const tick = () => new Promise((resolve) => setTimeout(resolve, 0)) + + const take = (count: number) => { + if (queued.size === 0) return [] as string[] + const items: string[] = [] + for (const item of queued) { + queued.delete(item) + items.push(item) + if (items.length >= count) break + } + return items + } + + const schedule = () => { + if (timer) return + timer = setTimeout(() => { + timer = undefined + void drain() + }, 0) + } + + const push = (directory: string) => { + if (!directory) return + queued.add(directory) + if (input.paused()) return + schedule() + } + + const refresh = () => { + root = true + if (input.paused()) return + schedule() + } + + async function drain() { + if (running) return + running = true + try { + while (true) { + if (input.paused()) return + if (root) { + root = false + await input.bootstrap() + await tick() + continue + } + const dirs = take(2) + if (dirs.length === 0) return + await Promise.all(dirs.map((dir) => input.bootstrapInstance(dir))) + await tick() + } + } finally { + running = false + if (input.paused()) return + if (root || queued.size) schedule() + } + } + + return { + push, + refresh, + clear(directory: string) { + queued.delete(directory) + }, + dispose() { + if (!timer) return + clearTimeout(timer) + timer = undefined + }, + } +} diff --git a/packages/app/src/context/global-sync/session-load.ts b/packages/app/src/context/global-sync/session-load.ts new file mode 100644 index 00000000000..443aa845020 --- /dev/null +++ b/packages/app/src/context/global-sync/session-load.ts @@ -0,0 +1,26 @@ +import type { RootLoadArgs } from "./types" + +export async function loadRootSessionsWithFallback(input: RootLoadArgs) { + try { + const result = await input.list({ directory: input.directory, roots: true, limit: input.limit }) + return { + data: result.data, + limit: input.limit, + limited: true, + } as const + } catch { + input.onFallback() + const result = await input.list({ directory: input.directory, roots: true }) + return { + data: result.data, + limit: input.limit, + limited: false, + } as const + } +} + +export function estimateRootSessionTotal(input: { count: number; limit: number; limited: boolean }) { + if (!input.limited) return input.count + if (input.count < input.limit) return input.count + return input.count + 1 +} diff --git a/packages/app/src/context/global-sync/session-trim.test.ts b/packages/app/src/context/global-sync/session-trim.test.ts new file mode 100644 index 00000000000..be12c074b5d --- /dev/null +++ b/packages/app/src/context/global-sync/session-trim.test.ts @@ -0,0 +1,59 @@ +import { describe, expect, test } from "bun:test" +import type { PermissionRequest, Session } from "@opencode-ai/sdk/v2/client" +import { trimSessions } from "./session-trim" + +const session = (input: { id: string; parentID?: string; created: number; updated?: number; archived?: number }) => + ({ + id: input.id, + parentID: input.parentID, + time: { + created: input.created, + updated: input.updated, + archived: input.archived, + }, + }) as Session + +describe("trimSessions", () => { + test("keeps base roots and recent roots beyond the limit", () => { + const now = 1_000_000 + const list = [ + session({ id: "a", created: now - 100_000 }), + session({ id: "b", created: now - 90_000 }), + session({ id: "c", created: now - 80_000 }), + session({ id: "d", created: now - 70_000, updated: now - 1_000 }), + session({ id: "e", created: now - 60_000, archived: now - 10 }), + ] + + const result = trimSessions(list, { limit: 2, permission: {}, now }) + expect(result.map((x) => x.id)).toEqual(["a", "b", "c", "d"]) + }) + + test("keeps children when root is kept, permission exists, or child is recent", () => { + const now = 1_000_000 + const list = [ + session({ id: "root-1", created: now - 1000 }), + session({ id: "root-2", created: now - 2000 }), + session({ id: "z-root", created: now - 30_000_000 }), + session({ id: "child-kept-by-root", parentID: "root-1", created: now - 20_000_000 }), + session({ id: "child-kept-by-permission", parentID: "z-root", created: now - 20_000_000 }), + session({ id: "child-kept-by-recency", parentID: "z-root", created: now - 500 }), + session({ id: "child-trimmed", parentID: "z-root", created: now - 20_000_000 }), + ] + + const result = trimSessions(list, { + limit: 2, + permission: { + "child-kept-by-permission": [{ id: "perm-1" } as PermissionRequest], + }, + now, + }) + + expect(result.map((x) => x.id)).toEqual([ + "child-kept-by-permission", + "child-kept-by-recency", + "child-kept-by-root", + "root-1", + "root-2", + ]) + }) +}) diff --git a/packages/app/src/context/global-sync/session-trim.ts b/packages/app/src/context/global-sync/session-trim.ts new file mode 100644 index 00000000000..800ba74a684 --- /dev/null +++ b/packages/app/src/context/global-sync/session-trim.ts @@ -0,0 +1,56 @@ +import type { PermissionRequest, Session } from "@opencode-ai/sdk/v2/client" +import { cmp } from "./utils" +import { SESSION_RECENT_LIMIT, SESSION_RECENT_WINDOW } from "./types" + +export function sessionUpdatedAt(session: Session) { + return session.time.updated ?? session.time.created +} + +export function compareSessionRecent(a: Session, b: Session) { + const aUpdated = sessionUpdatedAt(a) + const bUpdated = sessionUpdatedAt(b) + if (aUpdated !== bUpdated) return bUpdated - aUpdated + return cmp(a.id, b.id) +} + +export function takeRecentSessions(sessions: Session[], limit: number, cutoff: number) { + if (limit <= 0) return [] as Session[] + const selected: Session[] = [] + const seen = new Set() + for (const session of sessions) { + if (!session?.id) continue + if (seen.has(session.id)) continue + seen.add(session.id) + if (sessionUpdatedAt(session) <= cutoff) continue + const index = selected.findIndex((x) => compareSessionRecent(session, x) < 0) + if (index === -1) selected.push(session) + if (index !== -1) selected.splice(index, 0, session) + if (selected.length > limit) selected.pop() + } + return selected +} + +export function trimSessions( + input: Session[], + options: { limit: number; permission: Record; now?: number }, +) { + const limit = Math.max(0, options.limit) + const cutoff = (options.now ?? Date.now()) - SESSION_RECENT_WINDOW + const all = input + .filter((s) => !!s?.id) + .filter((s) => !s.time?.archived) + .sort((a, b) => cmp(a.id, b.id)) + const roots = all.filter((s) => !s.parentID) + const children = all.filter((s) => !!s.parentID) + const base = roots.slice(0, limit) + const recent = takeRecentSessions(roots.slice(limit), SESSION_RECENT_LIMIT, cutoff) + const keepRoots = [...base, ...recent] + const keepRootIds = new Set(keepRoots.map((s) => s.id)) + const keepChildren = children.filter((s) => { + if (s.parentID && keepRootIds.has(s.parentID)) return true + const perms = options.permission[s.id] ?? [] + if (perms.length > 0) return true + return sessionUpdatedAt(s) > cutoff + }) + return [...keepRoots, ...keepChildren].sort((a, b) => cmp(a.id, b.id)) +} diff --git a/packages/app/src/context/global-sync/types.ts b/packages/app/src/context/global-sync/types.ts new file mode 100644 index 00000000000..ade0b973a2a --- /dev/null +++ b/packages/app/src/context/global-sync/types.ts @@ -0,0 +1,134 @@ +import type { + Agent, + Command, + Config, + FileDiff, + LspStatus, + McpStatus, + Message, + Part, + Path, + PermissionRequest, + Project, + ProviderListResponse, + QuestionRequest, + Session, + SessionStatus, + Todo, + VcsInfo, +} from "@opencode-ai/sdk/v2/client" +import type { Accessor } from "solid-js" +import type { SetStoreFunction, Store } from "solid-js/store" + +export type ProjectMeta = { + name?: string + icon?: { + override?: string + color?: string + } + commands?: { + start?: string + } +} + +export type State = { + status: "loading" | "partial" | "complete" + agent: Agent[] + command: Command[] + project: string + projectMeta: ProjectMeta | undefined + icon: string | undefined + provider: ProviderListResponse + config: Config + path: Path + session: Session[] + sessionTotal: number + session_status: { + [sessionID: string]: SessionStatus + } + session_diff: { + [sessionID: string]: FileDiff[] + } + todo: { + [sessionID: string]: Todo[] + } + permission: { + [sessionID: string]: PermissionRequest[] + } + question: { + [sessionID: string]: QuestionRequest[] + } + mcp: { + [name: string]: McpStatus + } + lsp: LspStatus[] + vcs: VcsInfo | undefined + limit: number + message: { + [sessionID: string]: Message[] + } + part: { + [messageID: string]: Part[] + } +} + +export type VcsCache = { + store: Store<{ value: VcsInfo | undefined }> + setStore: SetStoreFunction<{ value: VcsInfo | undefined }> + ready: Accessor +} + +export type MetaCache = { + store: Store<{ value: ProjectMeta | undefined }> + setStore: SetStoreFunction<{ value: ProjectMeta | undefined }> + ready: Accessor +} + +export type IconCache = { + store: Store<{ value: string | undefined }> + setStore: SetStoreFunction<{ value: string | undefined }> + ready: Accessor +} + +export type ChildOptions = { + bootstrap?: boolean +} + +export type DirState = { + lastAccessAt: number +} + +export type EvictPlan = { + stores: string[] + state: Map + pins: Set + max: number + ttl: number + now: number +} + +export type DisposeCheck = { + directory: string + hasStore: boolean + pinned: boolean + booting: boolean + loadingSessions: boolean +} + +export type RootLoadArgs = { + directory: string + limit: number + list: (query: { directory: string; roots: true; limit?: number }) => Promise<{ data?: Session[] }> + onFallback: () => void +} + +export type RootLoadResult = { + data?: Session[] + limit: number + limited: boolean +} + +export const MAX_DIR_STORES = 30 +export const DIR_IDLE_TTL_MS = 20 * 60 * 1000 +export const SESSION_RECENT_WINDOW = 4 * 60 * 60 * 1000 +export const SESSION_RECENT_LIMIT = 50 diff --git a/packages/app/src/context/global-sync/utils.ts b/packages/app/src/context/global-sync/utils.ts new file mode 100644 index 00000000000..6b78134a611 --- /dev/null +++ b/packages/app/src/context/global-sync/utils.ts @@ -0,0 +1,25 @@ +import type { Project, ProviderListResponse } from "@opencode-ai/sdk/v2/client" + +export const cmp = (a: string, b: string) => (a < b ? -1 : a > b ? 1 : 0) + +export function normalizeProviderList(input: ProviderListResponse): ProviderListResponse { + return { + ...input, + all: input.all.map((provider) => ({ + ...provider, + models: Object.fromEntries(Object.entries(provider.models).filter(([, info]) => info.status !== "deprecated")), + })), + } +} + +export function sanitizeProject(project: Project) { + if (!project.icon?.url && !project.icon?.override) return project + return { + ...project, + icon: { + ...project.icon, + url: undefined, + override: undefined, + }, + } +} diff --git a/packages/app/src/context/layout.test.ts b/packages/app/src/context/layout.test.ts new file mode 100644 index 00000000000..582d5edbd29 --- /dev/null +++ b/packages/app/src/context/layout.test.ts @@ -0,0 +1,69 @@ +import { describe, expect, test } from "bun:test" +import { createRoot, createSignal } from "solid-js" +import { createSessionKeyReader, ensureSessionKey, pruneSessionKeys } from "./layout" + +describe("layout session-key helpers", () => { + test("couples touch and scroll seed in order", () => { + const calls: string[] = [] + const result = ensureSessionKey( + "dir/a", + (key) => calls.push(`touch:${key}`), + (key) => calls.push(`seed:${key}`), + ) + + expect(result).toBe("dir/a") + expect(calls).toEqual(["touch:dir/a", "seed:dir/a"]) + }) + + test("reads dynamic accessor keys lazily", () => { + const seen: string[] = [] + + createRoot((dispose) => { + const [key, setKey] = createSignal("dir/one") + const read = createSessionKeyReader(key, (value) => seen.push(value)) + + expect(read()).toBe("dir/one") + setKey("dir/two") + expect(read()).toBe("dir/two") + + dispose() + }) + + expect(seen).toEqual(["dir/one", "dir/two"]) + }) +}) + +describe("pruneSessionKeys", () => { + test("keeps active key and drops lowest-used keys", () => { + const drop = pruneSessionKeys({ + keep: "k4", + max: 3, + used: new Map([ + ["k1", 1], + ["k2", 2], + ["k3", 3], + ["k4", 4], + ]), + view: ["k1", "k2", "k4"], + tabs: ["k1", "k3", "k4"], + }) + + expect(drop).toEqual(["k1"]) + expect(drop.includes("k4")).toBe(false) + }) + + test("does not prune without keep key", () => { + const drop = pruneSessionKeys({ + keep: undefined, + max: 1, + used: new Map([ + ["k1", 1], + ["k2", 2], + ]), + view: ["k1"], + tabs: ["k2"], + }) + + expect(drop).toEqual([]) + }) +}) diff --git a/packages/app/src/context/model-variant.test.ts b/packages/app/src/context/model-variant.test.ts new file mode 100644 index 00000000000..01b149fd267 --- /dev/null +++ b/packages/app/src/context/model-variant.test.ts @@ -0,0 +1,66 @@ +import { describe, expect, test } from "bun:test" +import { cycleModelVariant, getConfiguredAgentVariant, resolveModelVariant } from "./model-variant" + +describe("model variant", () => { + test("resolves configured agent variant when model matches", () => { + const value = getConfiguredAgentVariant({ + agent: { + model: { providerID: "openai", modelID: "gpt-5.2" }, + variant: "xhigh", + }, + model: { + providerID: "openai", + modelID: "gpt-5.2", + variants: { low: {}, high: {}, xhigh: {} }, + }, + }) + + expect(value).toBe("xhigh") + }) + + test("ignores configured variant when model does not match", () => { + const value = getConfiguredAgentVariant({ + agent: { + model: { providerID: "openai", modelID: "gpt-5.2" }, + variant: "xhigh", + }, + model: { + providerID: "anthropic", + modelID: "claude-sonnet-4", + variants: { low: {}, high: {}, xhigh: {} }, + }, + }) + + expect(value).toBeUndefined() + }) + + test("prefers selected variant over configured variant", () => { + const value = resolveModelVariant({ + variants: ["low", "high", "xhigh"], + selected: "high", + configured: "xhigh", + }) + + expect(value).toBe("high") + }) + + test("cycles from configured variant to next", () => { + const value = cycleModelVariant({ + variants: ["low", "high", "xhigh"], + selected: undefined, + configured: "high", + }) + + expect(value).toBe("xhigh") + }) + + test("wraps from configured last variant to first", () => { + const value = cycleModelVariant({ + variants: ["low", "high", "xhigh"], + selected: undefined, + configured: "xhigh", + }) + + expect(value).toBe("low") + }) +}) diff --git a/packages/app/src/context/model-variant.ts b/packages/app/src/context/model-variant.ts new file mode 100644 index 00000000000..6b7ae725640 --- /dev/null +++ b/packages/app/src/context/model-variant.ts @@ -0,0 +1,50 @@ +type AgentModel = { + providerID: string + modelID: string +} + +type Agent = { + model?: AgentModel + variant?: string +} + +type Model = AgentModel & { + variants?: Record +} + +type VariantInput = { + variants: string[] + selected: string | undefined + configured: string | undefined +} + +export function getConfiguredAgentVariant(input: { agent: Agent | undefined; model: Model | undefined }) { + if (!input.agent?.variant) return undefined + if (!input.agent.model) return undefined + if (!input.model?.variants) return undefined + if (input.agent.model.providerID !== input.model.providerID) return undefined + if (input.agent.model.modelID !== input.model.modelID) return undefined + if (!(input.agent.variant in input.model.variants)) return undefined + return input.agent.variant +} + +export function resolveModelVariant(input: VariantInput) { + if (input.selected && input.variants.includes(input.selected)) return input.selected + if (input.configured && input.variants.includes(input.configured)) return input.configured + return undefined +} + +export function cycleModelVariant(input: VariantInput) { + if (input.variants.length === 0) return undefined + if (input.selected && input.variants.includes(input.selected)) { + const index = input.variants.indexOf(input.selected) + if (index === input.variants.length - 1) return undefined + return input.variants[index + 1] + } + if (input.configured && input.variants.includes(input.configured)) { + const index = input.variants.indexOf(input.configured) + if (index === input.variants.length - 1) return input.variants[0] + return input.variants[index + 1] + } + return input.variants[0] +} diff --git a/packages/app/src/context/notification-index.ts b/packages/app/src/context/notification-index.ts new file mode 100644 index 00000000000..0b316e7ec10 --- /dev/null +++ b/packages/app/src/context/notification-index.ts @@ -0,0 +1,66 @@ +type NotificationIndexItem = { + directory?: string + session?: string + viewed: boolean + type: string +} + +export function buildNotificationIndex(list: T[]) { + const sessionAll = new Map() + const sessionUnseen = new Map() + const sessionUnseenCount = new Map() + const sessionUnseenHasError = new Map() + const projectAll = new Map() + const projectUnseen = new Map() + const projectUnseenCount = new Map() + const projectUnseenHasError = new Map() + + for (const notification of list) { + const session = notification.session + if (session) { + const all = sessionAll.get(session) + if (all) all.push(notification) + else sessionAll.set(session, [notification]) + + if (!notification.viewed) { + const unseen = sessionUnseen.get(session) + if (unseen) unseen.push(notification) + else sessionUnseen.set(session, [notification]) + + sessionUnseenCount.set(session, (sessionUnseenCount.get(session) ?? 0) + 1) + if (notification.type === "error") sessionUnseenHasError.set(session, true) + } + } + + const directory = notification.directory + if (directory) { + const all = projectAll.get(directory) + if (all) all.push(notification) + else projectAll.set(directory, [notification]) + + if (!notification.viewed) { + const unseen = projectUnseen.get(directory) + if (unseen) unseen.push(notification) + else projectUnseen.set(directory, [notification]) + + projectUnseenCount.set(directory, (projectUnseenCount.get(directory) ?? 0) + 1) + if (notification.type === "error") projectUnseenHasError.set(directory, true) + } + } + } + + return { + session: { + all: sessionAll, + unseen: sessionUnseen, + unseenCount: sessionUnseenCount, + unseenHasError: sessionUnseenHasError, + }, + project: { + all: projectAll, + unseen: projectUnseen, + unseenCount: projectUnseenCount, + unseenHasError: projectUnseenHasError, + }, + } +} diff --git a/packages/app/src/context/notification.test.ts b/packages/app/src/context/notification.test.ts new file mode 100644 index 00000000000..44bacb70493 --- /dev/null +++ b/packages/app/src/context/notification.test.ts @@ -0,0 +1,73 @@ +import { describe, expect, test } from "bun:test" +import { buildNotificationIndex } from "./notification-index" + +type Notification = { + type: "turn-complete" | "error" + session: string + directory: string + viewed: boolean + time: number +} + +const turn = (session: string, directory: string, viewed = false): Notification => ({ + type: "turn-complete", + session, + directory, + viewed, + time: 1, +}) + +const error = (session: string, directory: string, viewed = false): Notification => ({ + type: "error", + session, + directory, + viewed, + time: 1, +}) + +describe("buildNotificationIndex", () => { + test("builds unseen counts and unseen error flags", () => { + const list = [ + turn("s1", "d1", false), + error("s1", "d1", false), + turn("s1", "d1", true), + turn("s2", "d1", false), + error("s3", "d2", true), + ] + + const index = buildNotificationIndex(list) + + expect(index.session.all.get("s1")?.length).toBe(3) + expect(index.session.unseen.get("s1")?.length).toBe(2) + expect(index.session.unseenCount.get("s1")).toBe(2) + expect(index.session.unseenHasError.get("s1")).toBe(true) + + expect(index.session.unseenCount.get("s2")).toBe(1) + expect(index.session.unseenHasError.get("s2") ?? false).toBe(false) + expect(index.session.unseenCount.get("s3") ?? 0).toBe(0) + expect(index.session.unseenHasError.get("s3") ?? false).toBe(false) + + expect(index.project.unseenCount.get("d1")).toBe(3) + expect(index.project.unseenHasError.get("d1")).toBe(true) + expect(index.project.unseenCount.get("d2") ?? 0).toBe(0) + expect(index.project.unseenHasError.get("d2") ?? false).toBe(false) + }) + + test("updates selectors after viewed transitions", () => { + const list = [turn("s1", "d1", false), error("s1", "d1", false), turn("s2", "d1", false)] + const next = list.map((item) => (item.session === "s1" ? { ...item, viewed: true } : item)) + + const before = buildNotificationIndex(list) + const after = buildNotificationIndex(next) + + expect(before.session.unseenCount.get("s1")).toBe(2) + expect(before.session.unseenHasError.get("s1")).toBe(true) + expect(before.project.unseenCount.get("d1")).toBe(3) + expect(before.project.unseenHasError.get("d1")).toBe(true) + + expect(after.session.unseenCount.get("s1") ?? 0).toBe(0) + expect(after.session.unseenHasError.get("s1") ?? false).toBe(false) + expect(after.project.unseenCount.get("d1")).toBe(1) + expect(after.project.unseenHasError.get("d1") ?? false).toBe(false) + }) +}) diff --git a/packages/app/src/context/sync-optimistic.test.ts b/packages/app/src/context/sync-optimistic.test.ts new file mode 100644 index 00000000000..7deeddd6ee6 --- /dev/null +++ b/packages/app/src/context/sync-optimistic.test.ts @@ -0,0 +1,56 @@ +import { describe, expect, test } from "bun:test" +import type { Message, Part } from "@opencode-ai/sdk/v2/client" +import { applyOptimisticAdd, applyOptimisticRemove } from "./sync" + +const userMessage = (id: string, sessionID: string): Message => ({ + id, + sessionID, + role: "user", + time: { created: 1 }, + agent: "assistant", + model: { providerID: "openai", modelID: "gpt" }, +}) + +const textPart = (id: string, sessionID: string, messageID: string): Part => ({ + id, + sessionID, + messageID, + type: "text", + text: id, +}) + +describe("sync optimistic reducers", () => { + test("applyOptimisticAdd inserts message in sorted order and stores parts", () => { + const sessionID = "ses_1" + const draft = { + message: { [sessionID]: [userMessage("msg_2", sessionID)] }, + part: {} as Record, + } + + applyOptimisticAdd(draft, { + sessionID, + message: userMessage("msg_1", sessionID), + parts: [textPart("prt_2", sessionID, "msg_1"), textPart("prt_1", sessionID, "msg_1")], + }) + + expect(draft.message[sessionID]?.map((x) => x.id)).toEqual(["msg_1", "msg_2"]) + expect(draft.part.msg_1?.map((x) => x.id)).toEqual(["prt_1", "prt_2"]) + }) + + test("applyOptimisticRemove removes message and part entries", () => { + const sessionID = "ses_1" + const draft = { + message: { [sessionID]: [userMessage("msg_1", sessionID), userMessage("msg_2", sessionID)] }, + part: { + msg_1: [textPart("prt_1", sessionID, "msg_1")], + msg_2: [textPart("prt_2", sessionID, "msg_2")], + } as Record, + } + + applyOptimisticRemove(draft, { sessionID, messageID: "msg_1" }) + + expect(draft.message[sessionID]?.map((x) => x.id)).toEqual(["msg_2"]) + expect(draft.part.msg_1).toBeUndefined() + expect(draft.part.msg_2).toHaveLength(1) + }) +}) diff --git a/packages/app/src/context/terminal.test.ts b/packages/app/src/context/terminal.test.ts new file mode 100644 index 00000000000..a250de57c0d --- /dev/null +++ b/packages/app/src/context/terminal.test.ts @@ -0,0 +1,39 @@ +import { beforeAll, describe, expect, mock, test } from "bun:test" + +let getWorkspaceTerminalCacheKey: (dir: string) => string +let getLegacyTerminalStorageKeys: (dir: string, legacySessionID?: string) => string[] + +beforeAll(async () => { + mock.module("@solidjs/router", () => ({ + useNavigate: () => () => undefined, + useParams: () => ({}), + })) + mock.module("@opencode-ai/ui/context", () => ({ + createSimpleContext: () => ({ + use: () => undefined, + provider: () => undefined, + }), + })) + const mod = await import("./terminal") + getWorkspaceTerminalCacheKey = mod.getWorkspaceTerminalCacheKey + getLegacyTerminalStorageKeys = mod.getLegacyTerminalStorageKeys +}) + +describe("getWorkspaceTerminalCacheKey", () => { + test("uses workspace-only directory cache key", () => { + expect(getWorkspaceTerminalCacheKey("/repo")).toBe("/repo:__workspace__") + }) +}) + +describe("getLegacyTerminalStorageKeys", () => { + test("keeps workspace storage path when no legacy session id", () => { + expect(getLegacyTerminalStorageKeys("/repo")).toEqual(["/repo/terminal.v1"]) + }) + + test("includes legacy session path before workspace path", () => { + expect(getLegacyTerminalStorageKeys("/repo", "session-123")).toEqual([ + "/repo/terminal/session-123.v1", + "/repo/terminal.v1", + ]) + }) +}) diff --git a/packages/app/src/i18n/bs.ts b/packages/app/src/i18n/bs.ts new file mode 100644 index 00000000000..7d10da6ed87 --- /dev/null +++ b/packages/app/src/i18n/bs.ts @@ -0,0 +1,803 @@ +export const dict = { + "command.category.suggested": "Predloženo", + "command.category.view": "Prikaz", + "command.category.project": "Projekat", + "command.category.provider": "Provajder", + "command.category.server": "Server", + "command.category.session": "Sesija", + "command.category.theme": "Tema", + "command.category.language": "Jezik", + "command.category.file": "Datoteka", + "command.category.context": "Kontekst", + "command.category.terminal": "Terminal", + "command.category.model": "Model", + "command.category.mcp": "MCP", + "command.category.agent": "Agent", + "command.category.permissions": "Dozvole", + "command.category.workspace": "Radni prostor", + "command.category.settings": "Postavke", + + "theme.scheme.system": "Sistem", + "theme.scheme.light": "Svijetlo", + "theme.scheme.dark": "Tamno", + + "command.sidebar.toggle": "Prikaži/sakrij bočnu traku", + "command.project.open": "Otvori projekat", + "command.provider.connect": "Poveži provajdera", + "command.server.switch": "Promijeni server", + "command.settings.open": "Otvori postavke", + "command.session.previous": "Prethodna sesija", + "command.session.next": "Sljedeća sesija", + "command.session.previous.unseen": "Prethodna nepročitana sesija", + "command.session.next.unseen": "Sljedeća nepročitana sesija", + "command.session.archive": "Arhiviraj sesiju", + + "command.palette": "Paleta komandi", + + "command.theme.cycle": "Promijeni temu", + "command.theme.set": "Koristi temu: {{theme}}", + "command.theme.scheme.cycle": "Promijeni šemu boja", + "command.theme.scheme.set": "Koristi šemu boja: {{scheme}}", + + "command.language.cycle": "Promijeni jezik", + "command.language.set": "Koristi jezik: {{language}}", + + "command.session.new": "Nova sesija", + "command.file.open": "Otvori datoteku", + "command.tab.close": "Zatvori karticu", + "command.context.addSelection": "Dodaj odabir u kontekst", + "command.context.addSelection.description": "Dodaj odabrane linije iz trenutne datoteke", + "command.input.focus": "Fokusiraj polje za unos", + "command.terminal.toggle": "Prikaži/sakrij terminal", + "command.fileTree.toggle": "Prikaži/sakrij stablo datoteka", + "command.review.toggle": "Prikaži/sakrij pregled", + "command.terminal.new": "Novi terminal", + "command.terminal.new.description": "Kreiraj novu karticu terminala", + "command.steps.toggle": "Prikaži/sakrij korake", + "command.steps.toggle.description": "Prikaži ili sakrij korake za trenutnu poruku", + "command.message.previous": "Prethodna poruka", + "command.message.previous.description": "Idi na prethodnu korisničku poruku", + "command.message.next": "Sljedeća poruka", + "command.message.next.description": "Idi na sljedeću korisničku poruku", + "command.model.choose": "Odaberi model", + "command.model.choose.description": "Odaberi drugi model", + "command.mcp.toggle": "Prikaži/sakrij MCP-ove", + "command.mcp.toggle.description": "Prikaži/sakrij MCP-ove", + "command.agent.cycle": "Promijeni agenta", + "command.agent.cycle.description": "Prebaci na sljedećeg agenta", + "command.agent.cycle.reverse": "Promijeni agenta unazad", + "command.agent.cycle.reverse.description": "Prebaci na prethodnog agenta", + "command.model.variant.cycle": "Promijeni nivo razmišljanja", + "command.model.variant.cycle.description": "Prebaci na sljedeći nivo", + "command.permissions.autoaccept.enable": "Automatski prihvataj izmjene", + "command.permissions.autoaccept.disable": "Zaustavi automatsko prihvatanje izmjena", + "command.workspace.toggle": "Prikaži/sakrij radne prostore", + "command.workspace.toggle.description": "Omogući ili onemogući više radnih prostora u bočnoj traci", + "command.session.undo": "Poništi", + "command.session.undo.description": "Poništi posljednju poruku", + "command.session.redo": "Vrati", + "command.session.redo.description": "Vrati posljednju poništenu poruku", + "command.session.compact": "Sažmi sesiju", + "command.session.compact.description": "Sažmi sesiju kako bi se smanjio kontekst", + "command.session.fork": "Fork iz poruke", + "command.session.fork.description": "Kreiraj novu sesiju iz prethodne poruke", + "command.session.share": "Podijeli sesiju", + "command.session.share.description": "Podijeli ovu sesiju i kopiraj URL u međuspremnik", + "command.session.unshare": "Ukini dijeljenje sesije", + "command.session.unshare.description": "Zaustavi dijeljenje ove sesije", + + "palette.search.placeholder": "Pretraži datoteke, komande i sesije", + "palette.empty": "Nema rezultata", + "palette.group.commands": "Komande", + "palette.group.files": "Datoteke", + + "dialog.provider.search.placeholder": "Pretraži provajdere", + "dialog.provider.empty": "Nema pronađenih provajdera", + "dialog.provider.group.popular": "Popularno", + "dialog.provider.group.other": "Ostalo", + "dialog.provider.tag.recommended": "Preporučeno", + "dialog.provider.opencode.note": "Kurirani modeli uključujući Claude, GPT, Gemini i druge", + "dialog.provider.anthropic.note": "Direktan pristup Claude modelima, uključujući Pro i Max", + "dialog.provider.copilot.note": "Claude modeli za pomoć pri kodiranju", + "dialog.provider.openai.note": "GPT modeli za brze, sposobne opšte AI zadatke", + "dialog.provider.google.note": "Gemini modeli za brze, strukturirane odgovore", + "dialog.provider.openrouter.note": "Pristup svim podržanim modelima preko jednog provajdera", + "dialog.provider.vercel.note": "Jedinstven pristup AI modelima uz pametno rutiranje", + + "dialog.model.select.title": "Odaberi model", + "dialog.model.search.placeholder": "Pretraži modele", + "dialog.model.empty": "Nema rezultata za modele", + "dialog.model.manage": "Upravljaj modelima", + "dialog.model.manage.description": "Prilagodi koji se modeli prikazuju u izborniku modela.", + + "dialog.model.unpaid.freeModels.title": "Besplatni modeli koje obezbjeđuje OpenCode", + "dialog.model.unpaid.addMore.title": "Dodaj još modela od popularnih provajdera", + + "dialog.provider.viewAll": "Prikaži više provajdera", + + "provider.connect.title": "Poveži {{provider}}", + "provider.connect.title.anthropicProMax": "Prijavi se putem Claude Pro/Max", + "provider.connect.selectMethod": "Odaberi način prijave za {{provider}}.", + "provider.connect.method.apiKey": "API ključ", + "provider.connect.status.inProgress": "Autorizacija je u toku...", + "provider.connect.status.waiting": "Čekanje na autorizaciju...", + "provider.connect.status.failed": "Autorizacija nije uspjela: {{error}}", + "provider.connect.apiKey.description": + "Unesi svoj {{provider}} API ključ da povežeš račun i koristiš {{provider}} modele u OpenCode-u.", + "provider.connect.apiKey.label": "{{provider}} API ključ", + "provider.connect.apiKey.placeholder": "API ključ", + "provider.connect.apiKey.required": "API ključ je obavezan", + "provider.connect.opencodeZen.line1": + "OpenCode Zen ti daje pristup kuriranom skupu pouzdanih, optimizovanih modela za coding agente.", + "provider.connect.opencodeZen.line2": + "Sa jednim API ključem dobijaš pristup modelima kao što su Claude, GPT, Gemini, GLM i drugi.", + "provider.connect.opencodeZen.visit.prefix": "Posjeti ", + "provider.connect.opencodeZen.visit.link": "opencode.ai/zen", + "provider.connect.opencodeZen.visit.suffix": " da preuzmeš svoj API ključ.", + "provider.connect.oauth.code.visit.prefix": "Posjeti ", + "provider.connect.oauth.code.visit.link": "ovaj link", + "provider.connect.oauth.code.visit.suffix": + " da preuzmeš autorizacijski kod i povežeš račun te koristiš {{provider}} modele u OpenCode-u.", + "provider.connect.oauth.code.label": "{{method}} autorizacijski kod", + "provider.connect.oauth.code.placeholder": "Autorizacijski kod", + "provider.connect.oauth.code.required": "Autorizacijski kod je obavezan", + "provider.connect.oauth.code.invalid": "Nevažeći autorizacijski kod", + "provider.connect.oauth.auto.visit.prefix": "Posjeti ", + "provider.connect.oauth.auto.visit.link": "ovaj link", + "provider.connect.oauth.auto.visit.suffix": + " i unesi kod ispod da povežeš račun i koristiš {{provider}} modele u OpenCode-u.", + "provider.connect.oauth.auto.confirmationCode": "Kod za potvrdu", + "provider.connect.toast.connected.title": "{{provider}} povezan", + "provider.connect.toast.connected.description": "{{provider}} modeli su sada dostupni za korištenje.", + + "provider.custom.title": "Prilagođeni provajder", + "provider.custom.description.prefix": "Konfiguriši OpenAI-kompatibilnog provajdera. Pogledaj ", + "provider.custom.description.link": "dokumentaciju za konfiguraciju provajdera", + "provider.custom.description.suffix": ".", + "provider.custom.field.providerID.label": "ID provajdera", + "provider.custom.field.providerID.placeholder": "mojprovajder", + "provider.custom.field.providerID.description": "Mala slova, brojevi, crtice ili donje crte", + "provider.custom.field.name.label": "Prikazano ime", + "provider.custom.field.name.placeholder": "Moj AI Provajder", + "provider.custom.field.baseURL.label": "Bazni URL", + "provider.custom.field.baseURL.placeholder": "https://api.mojprovajder.com/v1", + "provider.custom.field.apiKey.label": "API ključ", + "provider.custom.field.apiKey.placeholder": "API ključ", + "provider.custom.field.apiKey.description": + "Opcionalno. Ostavi prazno ako upravljaš autentifikacijom putem zaglavlja.", + "provider.custom.models.label": "Modeli", + "provider.custom.models.id.label": "ID", + "provider.custom.models.id.placeholder": "model-id", + "provider.custom.models.name.label": "Ime", + "provider.custom.models.name.placeholder": "Prikazano ime", + "provider.custom.models.remove": "Ukloni model", + "provider.custom.models.add": "Dodaj model", + "provider.custom.headers.label": "Zaglavlja (opcionalno)", + "provider.custom.headers.key.label": "Zaglavlje", + "provider.custom.headers.key.placeholder": "Ime-Zaglavlja", + "provider.custom.headers.value.label": "Vrijednost", + "provider.custom.headers.value.placeholder": "vrijednost", + "provider.custom.headers.remove": "Ukloni zaglavlje", + "provider.custom.headers.add": "Dodaj zaglavlje", + "provider.custom.error.providerID.required": "ID provajdera je obavezan", + "provider.custom.error.providerID.format": "Koristi mala slova, brojeve, crtice ili donje crte", + "provider.custom.error.providerID.exists": "Taj ID provajdera već postoji", + "provider.custom.error.name.required": "Prikazano ime je obavezno", + "provider.custom.error.baseURL.required": "Bazni URL je obavezan", + "provider.custom.error.baseURL.format": "Mora početi sa http:// ili https://", + "provider.custom.error.required": "Obavezno", + "provider.custom.error.duplicate": "Duplikat", + + "provider.disconnect.toast.disconnected.title": "{{provider}} odspojen", + "provider.disconnect.toast.disconnected.description": "{{provider}} modeli više nisu dostupni.", + + "model.tag.free": "Besplatno", + "model.tag.latest": "Najnovije", + "model.provider.anthropic": "Anthropic", + "model.provider.openai": "OpenAI", + "model.provider.google": "Google", + "model.provider.xai": "xAI", + "model.provider.meta": "Meta", + "model.input.text": "tekst", + "model.input.image": "slika", + "model.input.audio": "zvuk", + "model.input.video": "video", + "model.input.pdf": "pdf", + "model.tooltip.allows": "Podržava: {{inputs}}", + "model.tooltip.reasoning.allowed": "Podržava rasuđivanje", + "model.tooltip.reasoning.none": "Bez rasuđivanja", + "model.tooltip.context": "Limit konteksta {{limit}}", + + "common.search.placeholder": "Pretraži", + "common.goBack": "Nazad", + "common.goForward": "Naprijed", + "common.loading": "Učitavanje", + "common.loading.ellipsis": "...", + "common.cancel": "Otkaži", + "common.connect": "Poveži", + "common.disconnect": "Prekini vezu", + "common.submit": "Pošalji", + "common.save": "Sačuvaj", + "common.saving": "Čuvanje...", + "common.default": "Podrazumijevano", + "common.attachment": "prilog", + + "prompt.placeholder.shell": "Unesi shell naredbu...", + "prompt.placeholder.normal": 'Pitaj bilo šta... "{{example}}"', + "prompt.placeholder.summarizeComments": "Sažmi komentare…", + "prompt.placeholder.summarizeComment": "Sažmi komentar…", + "prompt.mode.shell": "Shell", + "prompt.mode.shell.exit": "esc za izlaz", + + "prompt.example.1": "Popravi TODO u bazi koda", + "prompt.example.2": "Koji je tehnološki stack ovog projekta?", + "prompt.example.3": "Popravi pokvarene testove", + "prompt.example.4": "Objasni kako radi autentifikacija", + "prompt.example.5": "Pronađi i popravi sigurnosne ranjivosti", + "prompt.example.6": "Dodaj jedinične testove za servis korisnika", + "prompt.example.7": "Refaktoriši ovu funkciju da bude čitljivija", + "prompt.example.8": "Šta znači ova greška?", + "prompt.example.9": "Pomozi mi da otklonim ovu grešku", + "prompt.example.10": "Generiši API dokumentaciju", + "prompt.example.11": "Optimizuj upite prema bazi podataka", + "prompt.example.12": "Dodaj validaciju ulaza", + "prompt.example.13": "Napravi novu komponentu za...", + "prompt.example.14": "Kako da deployam ovaj projekat?", + "prompt.example.15": "Pregledaj moj kod prema najboljim praksama", + "prompt.example.16": "Dodaj obradu grešaka u ovu funkciju", + "prompt.example.17": "Objasni ovaj regex obrazac", + "prompt.example.18": "Pretvori ovo u TypeScript", + "prompt.example.19": "Dodaj logovanje kroz cijelu bazu koda", + "prompt.example.20": "Koje su zavisnosti zastarjele?", + "prompt.example.21": "Pomozi mi da napišem migracijsku skriptu", + "prompt.example.22": "Implementiraj keširanje za ovaj endpoint", + "prompt.example.23": "Dodaj paginaciju u ovu listu", + "prompt.example.24": "Napravi CLI komandu za...", + "prompt.example.25": "Kako ovdje rade varijable okruženja?", + + "prompt.popover.emptyResults": "Nema rezultata", + "prompt.popover.emptyCommands": "Nema komandi", + "prompt.dropzone.label": "Spusti slike ili PDF-ove ovdje", + "prompt.dropzone.file.label": "Spusti za @spominjanje datoteke", + "prompt.slash.badge.custom": "prilagođeno", + "prompt.slash.badge.skill": "skill", + "prompt.slash.badge.mcp": "mcp", + "prompt.context.active": "aktivno", + "prompt.context.includeActiveFile": "Uključi aktivnu datoteku", + "prompt.context.removeActiveFile": "Ukloni aktivnu datoteku iz konteksta", + "prompt.context.removeFile": "Ukloni datoteku iz konteksta", + "prompt.action.attachFile": "Priloži datoteku", + "prompt.attachment.remove": "Ukloni prilog", + "prompt.action.send": "Pošalji", + "prompt.action.stop": "Zaustavi", + + "prompt.toast.pasteUnsupported.title": "Nepodržano lijepljenje", + "prompt.toast.pasteUnsupported.description": "Ovdje se mogu zalijepiti samo slike ili PDF-ovi.", + "prompt.toast.modelAgentRequired.title": "Odaberi agenta i model", + "prompt.toast.modelAgentRequired.description": "Odaberi agenta i model prije slanja upita.", + "prompt.toast.worktreeCreateFailed.title": "Neuspješno kreiranje worktree-a", + "prompt.toast.sessionCreateFailed.title": "Neuspješno kreiranje sesije", + "prompt.toast.shellSendFailed.title": "Neuspješno slanje shell naredbe", + "prompt.toast.commandSendFailed.title": "Neuspješno slanje komande", + "prompt.toast.promptSendFailed.title": "Neuspješno slanje upita", + "prompt.toast.promptSendFailed.description": "Nije moguće dohvatiti sesiju", + + "dialog.mcp.title": "MCP-ovi", + "dialog.mcp.description": "{{enabled}} od {{total}} omogućeno", + "dialog.mcp.empty": "Nema konfigurisnih MCP-ova", + + "dialog.lsp.empty": "LSP-ovi se automatski otkrivaju prema tipu datoteke", + "dialog.plugins.empty": "Plugini su konfigurisani u opencode.json", + + "mcp.status.connected": "povezano", + "mcp.status.failed": "neuspjelo", + "mcp.status.needs_auth": "potrebna autentifikacija", + "mcp.status.disabled": "onemogućeno", + + "dialog.fork.empty": "Nema poruka za fork", + + "dialog.directory.search.placeholder": "Pretraži foldere", + "dialog.directory.empty": "Nema pronađenih foldera", + + "dialog.server.title": "Serveri", + "dialog.server.description": "Promijeni na koji se OpenCode server ova aplikacija povezuje.", + "dialog.server.search.placeholder": "Pretraži servere", + "dialog.server.empty": "Još nema servera", + "dialog.server.add.title": "Dodaj server", + "dialog.server.add.url": "URL servera", + "dialog.server.add.placeholder": "http://localhost:4096", + "dialog.server.add.error": "Nije moguće povezati se na server", + "dialog.server.add.checking": "Provjera...", + "dialog.server.add.button": "Dodaj server", + "dialog.server.default.title": "Podrazumijevani server", + "dialog.server.default.description": + "Poveži se na ovaj server pri pokretanju aplikacije umjesto pokretanja lokalnog servera. Potreban je restart.", + "dialog.server.default.none": "Nije odabran server", + "dialog.server.default.set": "Postavi trenutni server kao podrazumijevani", + "dialog.server.default.clear": "Očisti", + "dialog.server.action.remove": "Ukloni server", + + "dialog.server.menu.edit": "Uredi", + "dialog.server.menu.default": "Postavi kao podrazumijevano", + "dialog.server.menu.defaultRemove": "Ukloni podrazumijevano", + "dialog.server.menu.delete": "Izbriši", + "dialog.server.current": "Trenutni server", + "dialog.server.status.default": "Podrazumijevano", + + "dialog.project.edit.title": "Uredi projekat", + "dialog.project.edit.name": "Naziv", + "dialog.project.edit.icon": "Ikonica", + "dialog.project.edit.icon.alt": "Ikonica projekta", + "dialog.project.edit.icon.hint": "Klikni ili prevuci sliku", + "dialog.project.edit.icon.recommended": "Preporučeno: 128x128px", + "dialog.project.edit.color": "Boja", + "dialog.project.edit.color.select": "Odaberi boju {{color}}", + "dialog.project.edit.worktree.startup": "Skripta za pokretanje radnog prostora", + "dialog.project.edit.worktree.startup.description": "Pokreće se nakon kreiranja novog radnog prostora (worktree).", + "dialog.project.edit.worktree.startup.placeholder": "npr. bun install", + + "context.breakdown.title": "Razlaganje konteksta", + "context.breakdown.note": + 'Približna raspodjela ulaznih tokena. "Ostalo" uključuje definicije alata i dodatni overhead.', + "context.breakdown.system": "Sistem", + "context.breakdown.user": "Korisnik", + "context.breakdown.assistant": "Asistent", + "context.breakdown.tool": "Pozivi alata", + "context.breakdown.other": "Ostalo", + + "context.systemPrompt.title": "Sistemski prompt", + "context.rawMessages.title": "Sirove poruke", + + "context.stats.session": "Sesija", + "context.stats.messages": "Poruke", + "context.stats.provider": "Provajder", + "context.stats.model": "Model", + "context.stats.limit": "Limit konteksta", + "context.stats.totalTokens": "Ukupno tokena", + "context.stats.usage": "Korištenje", + "context.stats.inputTokens": "Ulazni tokeni", + "context.stats.outputTokens": "Izlazni tokeni", + "context.stats.reasoningTokens": "Tokeni za rasuđivanje", + "context.stats.cacheTokens": "Cache tokeni (čitanje/pisanje)", + "context.stats.userMessages": "Korisničke poruke", + "context.stats.assistantMessages": "Poruke asistenta", + "context.stats.totalCost": "Ukupni trošak", + "context.stats.sessionCreated": "Sesija kreirana", + "context.stats.lastActivity": "Posljednja aktivnost", + + "context.usage.tokens": "Tokeni", + "context.usage.usage": "Korištenje", + "context.usage.cost": "Trošak", + "context.usage.clickToView": "Klikni da vidiš kontekst", + "context.usage.view": "Prikaži korištenje konteksta", + + "language.en": "English", + "language.zh": "简体中文", + "language.zht": "繁體中文", + "language.ko": "한국어", + "language.de": "Deutsch", + "language.es": "Español", + "language.fr": "Français", + "language.da": "Dansk", + "language.ja": "日本語", + "language.pl": "Polski", + "language.ru": "Русский", + "language.ar": "العربية", + "language.no": "Norsk", + "language.br": "Português (Brasil)", + "language.bs": "Bosanski", + "language.th": "ไทย", + + "toast.language.title": "Jezik", + "toast.language.description": "Prebačeno na {{language}}", + + "toast.theme.title": "Tema promijenjena", + "toast.scheme.title": "Šema boja", + + "toast.workspace.enabled.title": "Radni prostori omogućeni", + "toast.workspace.enabled.description": "Više worktree-ova se sada prikazuje u bočnoj traci", + "toast.workspace.disabled.title": "Radni prostori onemogućeni", + "toast.workspace.disabled.description": "Samo glavni worktree se prikazuje u bočnoj traci", + + "toast.permissions.autoaccept.on.title": "Automatsko prihvatanje izmjena", + "toast.permissions.autoaccept.on.description": "Dozvole za izmjene i pisanje biće automatski odobrene", + "toast.permissions.autoaccept.off.title": "Zaustavljeno automatsko prihvatanje izmjena", + "toast.permissions.autoaccept.off.description": "Dozvole za izmjene i pisanje zahtijevaće odobrenje", + + "toast.model.none.title": "Nije odabran model", + "toast.model.none.description": "Poveži provajdera da sažmeš ovu sesiju", + + "toast.file.loadFailed.title": "Neuspjelo učitavanje datoteke", + "toast.file.listFailed.title": "Neuspješno listanje datoteka", + + "toast.context.noLineSelection.title": "Nema odabranih linija", + "toast.context.noLineSelection.description": "Prvo odaberi raspon linija u kartici datoteke.", + + "toast.session.share.copyFailed.title": "Neuspjelo kopiranje URL-a u međuspremnik", + "toast.session.share.success.title": "Sesija podijeljena", + "toast.session.share.success.description": "URL za dijeljenje je kopiran u međuspremnik!", + "toast.session.share.failed.title": "Neuspjelo dijeljenje sesije", + "toast.session.share.failed.description": "Došlo je do greške prilikom dijeljenja sesije", + + "toast.session.unshare.success.title": "Dijeljenje sesije ukinuto", + "toast.session.unshare.success.description": "Dijeljenje sesije je uspješno ukinuto!", + "toast.session.unshare.failed.title": "Neuspjelo ukidanje dijeljenja", + "toast.session.unshare.failed.description": "Došlo je do greške prilikom ukidanja dijeljenja", + + "toast.session.listFailed.title": "Neuspjelo učitavanje sesija za {{project}}", + + "toast.update.title": "Dostupno ažuriranje", + "toast.update.description": "Nova verzija OpenCode-a ({{version}}) je dostupna za instalaciju.", + "toast.update.action.installRestart": "Instaliraj i restartuj", + "toast.update.action.notYet": "Ne još", + + "error.page.title": "Nešto je pošlo po zlu", + "error.page.description": "Došlo je do greške prilikom učitavanja aplikacije.", + "error.page.details.label": "Detalji greške", + "error.page.action.restart": "Restartuj", + "error.page.action.checking": "Provjera...", + "error.page.action.checkUpdates": "Provjeri ažuriranja", + "error.page.action.updateTo": "Ažuriraj na {{version}}", + "error.page.report.prefix": "Molimo prijavi ovu grešku OpenCode timu", + "error.page.report.discord": "na Discordu", + "error.page.version": "Verzija: {{version}}", + + "error.dev.rootNotFound": + "Korijenski element nije pronađen. Da li si zaboravio da ga dodaš u index.html? Ili je možda id atribut pogrešno napisan?", + + "error.globalSync.connectFailed": "Nije moguće povezati se na server. Da li server radi na `{{url}}`?", + "directory.error.invalidUrl": "Nevažeći direktorij u URL-u.", + + "error.chain.unknown": "Nepoznata greška", + "error.chain.causedBy": "Uzrok:", + "error.chain.apiError": "API greška", + "error.chain.status": "Status: {{status}}", + "error.chain.retryable": "Može se ponoviti: {{retryable}}", + "error.chain.responseBody": "Tijelo odgovora:\n{{body}}", + "error.chain.didYouMean": "Da li si mislio: {{suggestions}}", + "error.chain.modelNotFound": "Model nije pronađen: {{provider}}/{{model}}", + "error.chain.checkConfig": "Provjeri konfiguraciju (opencode.json) provider/model names", + "error.chain.mcpFailed": 'MCP server "{{name}}" nije uspio. Napomena: OpenCode još ne podržava MCP autentifikaciju.', + "error.chain.providerAuthFailed": "Autentifikacija provajdera nije uspjela ({{provider}}): {{message}}", + "error.chain.providerInitFailed": + 'Neuspjelo inicijalizovanje provajdera "{{provider}}". Provjeri kredencijale i konfiguraciju.', + "error.chain.configJsonInvalid": "Konfiguracijska datoteka na {{path}} nije važeći JSON(C)", + "error.chain.configJsonInvalidWithMessage": "Konfiguracijska datoteka na {{path}} nije važeći JSON(C): {{message}}", + "error.chain.configDirectoryTypo": + 'Direktorij "{{dir}}" u {{path}} nije ispravan. Preimenuj direktorij u "{{suggestion}}" ili ga ukloni. Ovo je česta greška u kucanju.', + "error.chain.configFrontmatterError": "Neuspjelo parsiranje frontmatter-a u {{path}}:\n{{message}}", + "error.chain.configInvalid": "Konfiguracijska datoteka na {{path}} nije ispravna", + "error.chain.configInvalidWithMessage": "Konfiguracijska datoteka na {{path}} nije ispravna: {{message}}", + + "notification.permission.title": "Potrebna dozvola", + "notification.permission.description": "{{sessionTitle}} u {{projectName}} traži dozvolu", + "notification.question.title": "Pitanje", + "notification.question.description": "{{sessionTitle}} u {{projectName}} ima pitanje", + "notification.action.goToSession": "Idi na sesiju", + + "notification.session.responseReady.title": "Odgovor je spreman", + "notification.session.error.title": "Greška sesije", + "notification.session.error.fallbackDescription": "Došlo je do greške", + + "home.recentProjects": "Nedavni projekti", + "home.empty.title": "Nema nedavnih projekata", + "home.empty.description": "Kreni tako što ćeš otvoriti lokalni projekat", + + "session.tab.session": "Sesija", + "session.tab.review": "Pregled", + "session.tab.context": "Kontekst", + "session.panel.reviewAndFiles": "Pregled i datoteke", + "session.review.filesChanged": "Izmijenjeno {{count}} datoteka", + "session.review.change.one": "Izmjena", + "session.review.change.other": "Izmjene", + "session.review.loadingChanges": "Učitavanje izmjena...", + "session.review.empty": "Još nema izmjena u ovoj sesiji", + "session.review.noChanges": "Nema izmjena", + + "session.files.selectToOpen": "Odaberi datoteku za otvaranje", + "session.files.all": "Sve datoteke", + "session.files.binaryContent": "Binarna datoteka (sadržaj se ne može prikazati)", + + "session.messages.renderEarlier": "Prikaži ranije poruke", + "session.messages.loadingEarlier": "Učitavanje ranijih poruka...", + "session.messages.loadEarlier": "Učitaj ranije poruke", + "session.messages.loading": "Učitavanje poruka...", + "session.messages.jumpToLatest": "Idi na najnovije", + + "session.context.addToContext": "Dodaj {{selection}} u kontekst", + + "session.new.worktree.main": "Glavna grana", + "session.new.worktree.mainWithBranch": "Glavna grana ({{branch}})", + "session.new.worktree.create": "Kreiraj novi worktree", + "session.new.lastModified": "Posljednja izmjena", + + "session.header.search.placeholder": "Pretraži {{project}}", + "session.header.searchFiles": "Pretraži datoteke", + "session.header.openIn": "Otvori u", + "session.header.open.action": "Otvori {{app}}", + "session.header.open.ariaLabel": "Otvori u {{app}}", + "session.header.open.menu": "Opcije otvaranja", + "session.header.open.copyPath": "Kopiraj putanju", + + "status.popover.trigger": "Status", + "status.popover.ariaLabel": "Konfiguracije servera", + "status.popover.tab.servers": "Serveri", + "status.popover.tab.mcp": "MCP", + "status.popover.tab.lsp": "LSP", + "status.popover.tab.plugins": "Plugini", + "status.popover.action.manageServers": "Upravljaj serverima", + + "session.share.popover.title": "Objavi na webu", + "session.share.popover.description.shared": "Ova sesija je javna na webu. Dostupna je svima koji imaju link.", + "session.share.popover.description.unshared": "Podijeli sesiju javno na webu. Biće dostupna svima koji imaju link.", + "session.share.action.share": "Podijeli", + "session.share.action.publish": "Objavi", + "session.share.action.publishing": "Objavljivanje...", + "session.share.action.unpublish": "Poništi objavu", + "session.share.action.unpublishing": "Poništavanje objave...", + "session.share.action.view": "Prikaži", + "session.share.copy.copied": "Kopirano", + "session.share.copy.copyLink": "Kopiraj link", + + "lsp.tooltip.none": "Nema LSP servera", + "lsp.label.connected": "{{count}} LSP", + + "prompt.loading": "Učitavanje upita...", + "terminal.loading": "Učitavanje terminala...", + "terminal.title": "Terminal", + "terminal.title.numbered": "Terminal {{number}}", + "terminal.close": "Zatvori terminal", + "terminal.connectionLost.title": "Veza prekinuta", + "terminal.connectionLost.description": + "Veza s terminalom je prekinuta. Ovo se može desiti kada se server restartuje.", + + "common.closeTab": "Zatvori karticu", + "common.dismiss": "Odbaci", + "common.requestFailed": "Zahtjev nije uspio", + "common.moreOptions": "Više opcija", + "common.learnMore": "Saznaj više", + "common.rename": "Preimenuj", + "common.reset": "Resetuj", + "common.archive": "Arhiviraj", + "common.delete": "Izbriši", + "common.close": "Zatvori", + "common.edit": "Uredi", + "common.loadMore": "Učitaj još", + "common.key.esc": "ESC", + + "sidebar.menu.toggle": "Prikaži/sakrij meni", + "sidebar.nav.projectsAndSessions": "Projekti i sesije", + "sidebar.settings": "Postavke", + "sidebar.help": "Pomoć", + "sidebar.workspaces.enable": "Omogući radne prostore", + "sidebar.workspaces.disable": "Onemogući radne prostore", + "sidebar.gettingStarted.title": "Početak", + "sidebar.gettingStarted.line1": "OpenCode uključuje besplatne modele, tako da možeš odmah početi.", + "sidebar.gettingStarted.line2": "Poveži bilo kojeg provajdera da koristiš modele, npr. Claude, GPT, Gemini itd.", + "sidebar.project.recentSessions": "Nedavne sesije", + "sidebar.project.viewAllSessions": "Prikaži sve sesije", + + "app.name.desktop": "OpenCode Desktop", + + "settings.section.desktop": "Desktop", + "settings.section.server": "Server", + "settings.tab.general": "Opšte", + "settings.tab.shortcuts": "Prečice", + "settings.desktop.section.wsl": "WSL", + "settings.desktop.wsl.title": "WSL integracija", + "settings.desktop.wsl.description": "Pokreni OpenCode server unutar WSL-a na Windowsu.", + + "settings.general.section.appearance": "Izgled", + "settings.general.section.notifications": "Sistemske obavijesti", + "settings.general.section.updates": "Ažuriranja", + "settings.general.section.sounds": "Zvučni efekti", + "settings.general.section.display": "Prikaz", + + "settings.general.row.language.title": "Jezik", + "settings.general.row.language.description": "Promijeni jezik prikaza u OpenCode-u", + "settings.general.row.appearance.title": "Izgled", + "settings.general.row.appearance.description": "Prilagodi kako OpenCode izgleda na tvom uređaju", + "settings.general.row.theme.title": "Tema", + "settings.general.row.theme.description": "Prilagodi temu OpenCode-a.", + "settings.general.row.font.title": "Font", + "settings.general.row.font.description": "Prilagodi monospace font koji se koristi u blokovima koda", + + "settings.general.row.wayland.title": "Koristi nativni Wayland", + "settings.general.row.wayland.description": "Onemogući X11 fallback na Waylandu. Zahtijeva restart.", + "settings.general.row.wayland.tooltip": + "Na Linuxu sa monitorima miješanih stopa osvježavanja, nativni Wayland može biti stabilniji.", + + "settings.general.row.releaseNotes.title": "Bilješke o izdanju", + "settings.general.row.releaseNotes.description": 'Prikaži iskačuće prozore "Šta je novo" nakon ažuriranja', + + "settings.updates.row.startup.title": "Provjeri ažuriranja pri pokretanju", + "settings.updates.row.startup.description": "Automatski provjerava ažuriranja kada se OpenCode pokrene", + "settings.updates.row.check.title": "Provjeri ažuriranja", + "settings.updates.row.check.description": "Ručno provjeri ažuriranja i instaliraj ako su dostupna", + "settings.updates.action.checkNow": "Provjeri sada", + "settings.updates.action.checking": "Provjera...", + "settings.updates.toast.latest.title": "Sve je ažurno", + "settings.updates.toast.latest.description": "Koristiš najnoviju verziju OpenCode-a.", + "font.option.ibmPlexMono": "IBM Plex Mono", + "font.option.cascadiaCode": "Cascadia Code", + "font.option.firaCode": "Fira Code", + "font.option.hack": "Hack", + "font.option.inconsolata": "Inconsolata", + "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", + "font.option.jetbrainsMono": "JetBrains Mono", + "font.option.mesloLgs": "Meslo LGS", + "font.option.robotoMono": "Roboto Mono", + "font.option.sourceCodePro": "Source Code Pro", + "font.option.ubuntuMono": "Ubuntu Mono", + "sound.option.alert01": "Upozorenje 01", + "sound.option.alert02": "Upozorenje 02", + "sound.option.alert03": "Upozorenje 03", + "sound.option.alert04": "Upozorenje 04", + "sound.option.alert05": "Upozorenje 05", + "sound.option.alert06": "Upozorenje 06", + "sound.option.alert07": "Upozorenje 07", + "sound.option.alert08": "Upozorenje 08", + "sound.option.alert09": "Upozorenje 09", + "sound.option.alert10": "Upozorenje 10", + "sound.option.bipbop01": "Bip-bop 01", + "sound.option.bipbop02": "Bip-bop 02", + "sound.option.bipbop03": "Bip-bop 03", + "sound.option.bipbop04": "Bip-bop 04", + "sound.option.bipbop05": "Bip-bop 05", + "sound.option.bipbop06": "Bip-bop 06", + "sound.option.bipbop07": "Bip-bop 07", + "sound.option.bipbop08": "Bip-bop 08", + "sound.option.bipbop09": "Bip-bop 09", + "sound.option.bipbop10": "Bip-bop 10", + "sound.option.staplebops01": "Staplebops 01", + "sound.option.staplebops02": "Staplebops 02", + "sound.option.staplebops03": "Staplebops 03", + "sound.option.staplebops04": "Staplebops 04", + "sound.option.staplebops05": "Staplebops 05", + "sound.option.staplebops06": "Staplebops 06", + "sound.option.staplebops07": "Staplebops 07", + "sound.option.nope01": "Ne 01", + "sound.option.nope02": "Ne 02", + "sound.option.nope03": "Ne 03", + "sound.option.nope04": "Ne 04", + "sound.option.nope05": "Ne 05", + "sound.option.nope06": "Ne 06", + "sound.option.nope07": "Ne 07", + "sound.option.nope08": "Ne 08", + "sound.option.nope09": "Ne 09", + "sound.option.nope10": "Ne 10", + "sound.option.nope11": "Ne 11", + "sound.option.nope12": "Ne 12", + "sound.option.yup01": "Da 01", + "sound.option.yup02": "Da 02", + "sound.option.yup03": "Da 03", + "sound.option.yup04": "Da 04", + "sound.option.yup05": "Da 05", + "sound.option.yup06": "Da 06", + + "settings.general.notifications.agent.title": "Agent", + "settings.general.notifications.agent.description": + "Prikaži sistemsku obavijest kada agent završi ili zahtijeva pažnju", + "settings.general.notifications.permissions.title": "Dozvole", + "settings.general.notifications.permissions.description": "Prikaži sistemsku obavijest kada je potrebna dozvola", + "settings.general.notifications.errors.title": "Greške", + "settings.general.notifications.errors.description": "Prikaži sistemsku obavijest kada dođe do greške", + + "settings.general.sounds.agent.title": "Agent", + "settings.general.sounds.agent.description": "Pusti zvuk kada agent završi ili zahtijeva pažnju", + "settings.general.sounds.permissions.title": "Dozvole", + "settings.general.sounds.permissions.description": "Pusti zvuk kada je potrebna dozvola", + "settings.general.sounds.errors.title": "Greške", + "settings.general.sounds.errors.description": "Pusti zvuk kada dođe do greške", + + "settings.shortcuts.title": "Prečice na tastaturi", + "settings.shortcuts.reset.button": "Vrati na podrazumijevano", + "settings.shortcuts.reset.toast.title": "Prečice resetovane", + "settings.shortcuts.reset.toast.description": "Prečice na tastaturi su vraćene na podrazumijevane.", + "settings.shortcuts.conflict.title": "Prečica je već u upotrebi", + "settings.shortcuts.conflict.description": "{{keybind}} je već dodijeljeno za {{titles}}.", + "settings.shortcuts.unassigned": "Nedodijeljeno", + "settings.shortcuts.pressKeys": "Pritisni tastere", + "settings.shortcuts.search.placeholder": "Pretraži prečice", + "settings.shortcuts.search.empty": "Nema pronađenih prečica", + + "settings.shortcuts.group.general": "Opšte", + "settings.shortcuts.group.session": "Sesija", + "settings.shortcuts.group.navigation": "Navigacija", + "settings.shortcuts.group.modelAndAgent": "Model i agent", + "settings.shortcuts.group.terminal": "Terminal", + "settings.shortcuts.group.prompt": "Upit", + + "settings.providers.title": "Provajderi", + "settings.providers.description": "Postavke provajdera će se ovdje moći podešavati.", + "settings.providers.section.connected": "Povezani provajderi", + "settings.providers.connected.empty": "Nema povezanih provajdera", + "settings.providers.section.popular": "Popularni provajderi", + "settings.providers.tag.environment": "Okruženje", + "settings.providers.tag.config": "Konfiguracija", + "settings.providers.tag.custom": "Prilagođeno", + "settings.providers.tag.other": "Ostalo", + "settings.models.title": "Modeli", + "settings.models.description": "Postavke modela će se ovdje moći podešavati.", + "settings.agents.title": "Agenti", + "settings.agents.description": "Postavke agenata će se ovdje moći podešavati.", + "settings.commands.title": "Komande", + "settings.commands.description": "Postavke komandi će se ovdje moći podešavati.", + "settings.mcp.title": "MCP", + "settings.mcp.description": "MCP postavke će se ovdje moći podešavati.", + + "settings.permissions.title": "Dozvole", + "settings.permissions.description": "Kontroliši koje alate server smije koristiti po defaultu.", + "settings.permissions.section.tools": "Alati", + "settings.permissions.toast.updateFailed.title": "Neuspjelo ažuriranje dozvola", + + "settings.permissions.action.allow": "Dozvoli", + "settings.permissions.action.ask": "Pitaj", + "settings.permissions.action.deny": "Zabrani", + + "settings.permissions.tool.read.title": "Čitanje", + "settings.permissions.tool.read.description": "Čitanje datoteke (podudara se s putanjom datoteke)", + "settings.permissions.tool.edit.title": "Uređivanje", + "settings.permissions.tool.edit.description": + "Mijenjanje datoteka, uključujući izmjene, pisanja, patch-eve i multi-izmjene", + "settings.permissions.tool.glob.title": "Glob", + "settings.permissions.tool.glob.description": "Podudaranje datoteka pomoću glob šablona", + "settings.permissions.tool.grep.title": "Grep", + "settings.permissions.tool.grep.description": "Pretraživanje sadržaja datoteka pomoću regularnih izraza", + "settings.permissions.tool.list.title": "Lista", + "settings.permissions.tool.list.description": "Listanje datoteka unutar direktorija", + "settings.permissions.tool.bash.title": "Bash", + "settings.permissions.tool.bash.description": "Pokretanje shell komandi", + "settings.permissions.tool.task.title": "Zadatak", + "settings.permissions.tool.task.description": "Pokretanje pod-agenta", + "settings.permissions.tool.skill.title": "Vještina", + "settings.permissions.tool.skill.description": "Učitaj vještinu po nazivu", + "settings.permissions.tool.lsp.title": "LSP", + "settings.permissions.tool.lsp.description": "Pokreni upite jezičnog servera", + "settings.permissions.tool.todoread.title": "Čitanje liste zadataka", + "settings.permissions.tool.todoread.description": "Čitanje liste zadataka", + "settings.permissions.tool.todowrite.title": "Ažuriranje liste zadataka", + "settings.permissions.tool.todowrite.description": "Ažuriraj listu zadataka", + "settings.permissions.tool.webfetch.title": "Web preuzimanje", + "settings.permissions.tool.webfetch.description": "Preuzmi sadržaj sa URL-a", + "settings.permissions.tool.websearch.title": "Web pretraga", + "settings.permissions.tool.websearch.description": "Pretražuj web", + "settings.permissions.tool.codesearch.title": "Pretraga koda", + "settings.permissions.tool.codesearch.description": "Pretraži kod na webu", + "settings.permissions.tool.external_directory.title": "Vanjski direktorij", + "settings.permissions.tool.external_directory.description": "Pristup datotekama izvan direktorija projekta", + "settings.permissions.tool.doom_loop.title": "Beskonačna petlja", + "settings.permissions.tool.doom_loop.description": "Otkriva ponovljene pozive alata sa identičnim unosom", + + "session.delete.failed.title": "Neuspjelo brisanje sesije", + "session.delete.title": "Izbriši sesiju", + "session.delete.confirm": 'Izbriši sesiju "{{name}}"?', + "session.delete.button": "Izbriši sesiju", + + "workspace.new": "Novi radni prostor", + "workspace.type.local": "lokalno", + "workspace.type.sandbox": "sandbox", + "workspace.create.failed.title": "Neuspješno kreiranje radnog prostora", + "workspace.delete.failed.title": "Neuspješno brisanje radnog prostora", + "workspace.resetting.title": "Resetovanje radnog prostora", + "workspace.resetting.description": "Ovo može potrajati minut.", + "workspace.reset.failed.title": "Neuspješno resetovanje radnog prostora", + "workspace.reset.success.title": "Radni prostor resetovan", + "workspace.reset.success.description": "Radni prostor sada odgovara podrazumijevanoj grani.", + "workspace.error.stillPreparing": "Radni prostor se još priprema", + "workspace.status.checking": "Provjera neobjedinjenih promjena...", + "workspace.status.error": "Nije moguće provjeriti git status.", + "workspace.status.clean": "Nisu pronađene neobjedinjene promjene.", + "workspace.status.dirty": "Pronađene su neobjedinjene promjene u ovom radnom prostoru.", + "workspace.delete.title": "Izbriši radni prostor", + "workspace.delete.confirm": 'Izbriši radni prostor "{{name}}"?', + "workspace.delete.button": "Izbriši radni prostor", + "workspace.reset.title": "Resetuj radni prostor", + "workspace.reset.confirm": 'Resetuj radni prostor "{{name}}"?', + "workspace.reset.button": "Resetuj radni prostor", + "workspace.reset.archived.none": "Nijedna aktivna sesija neće biti arhivirana.", + "workspace.reset.archived.one": "1 sesija će biti arhivirana.", + "workspace.reset.archived.many": "Biće arhivirano {{count}} sesija.", + "workspace.reset.note": "Ovo će resetovati radni prostor da odgovara podrazumijevanoj grani.", +} diff --git a/packages/app/src/i18n/parity.test.ts b/packages/app/src/i18n/parity.test.ts new file mode 100644 index 00000000000..a75dbd3a300 --- /dev/null +++ b/packages/app/src/i18n/parity.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, test } from "bun:test" +import { dict as en } from "./en" +import { dict as ar } from "./ar" +import { dict as br } from "./br" +import { dict as bs } from "./bs" +import { dict as da } from "./da" +import { dict as de } from "./de" +import { dict as es } from "./es" +import { dict as fr } from "./fr" +import { dict as ja } from "./ja" +import { dict as ko } from "./ko" +import { dict as no } from "./no" +import { dict as pl } from "./pl" +import { dict as ru } from "./ru" +import { dict as th } from "./th" +import { dict as zh } from "./zh" +import { dict as zht } from "./zht" + +const locales = [ar, br, bs, da, de, es, fr, ja, ko, no, pl, ru, th, zh, zht] +const keys = ["command.session.previous.unseen", "command.session.next.unseen"] as const + +describe("i18n parity", () => { + test("non-English locales translate targeted unseen session keys", () => { + for (const locale of locales) { + for (const key of keys) { + expect(locale[key]).toBeDefined() + expect(locale[key]).not.toBe(en[key]) + } + } + }) +}) diff --git a/packages/app/src/pages/layout/deep-links.ts b/packages/app/src/pages/layout/deep-links.ts new file mode 100644 index 00000000000..7bdb002a366 --- /dev/null +++ b/packages/app/src/pages/layout/deep-links.ts @@ -0,0 +1,34 @@ +export const deepLinkEvent = "opencode:deep-link" + +export const parseDeepLink = (input: string) => { + if (!input.startsWith("opencode://")) return + if (typeof URL.canParse === "function" && !URL.canParse(input)) return + const url = (() => { + try { + return new URL(input) + } catch { + return undefined + } + })() + if (!url) return + if (url.hostname !== "open-project") return + const directory = url.searchParams.get("directory") + if (!directory) return + return directory +} + +export const collectOpenProjectDeepLinks = (urls: string[]) => + urls.map(parseDeepLink).filter((directory): directory is string => !!directory) + +type OpenCodeWindow = Window & { + __OPENCODE__?: { + deepLinks?: string[] + } +} + +export const drainPendingDeepLinks = (target: OpenCodeWindow) => { + const pending = target.__OPENCODE__?.deepLinks ?? [] + if (pending.length === 0) return [] + if (target.__OPENCODE__) target.__OPENCODE__.deepLinks = [] + return pending +} diff --git a/packages/app/src/pages/layout/helpers.test.ts b/packages/app/src/pages/layout/helpers.test.ts new file mode 100644 index 00000000000..83d8f4748ab --- /dev/null +++ b/packages/app/src/pages/layout/helpers.test.ts @@ -0,0 +1,92 @@ +import { describe, expect, test } from "bun:test" +import { collectOpenProjectDeepLinks, drainPendingDeepLinks, parseDeepLink } from "./deep-links" +import { displayName, errorMessage, getDraggableId, syncWorkspaceOrder, workspaceKey } from "./helpers" + +describe("layout deep links", () => { + test("parses open-project deep links", () => { + expect(parseDeepLink("opencode://open-project?directory=/tmp/demo")).toBe("/tmp/demo") + }) + + test("ignores non-project deep links", () => { + expect(parseDeepLink("opencode://other?directory=/tmp/demo")).toBeUndefined() + expect(parseDeepLink("https://example.com")).toBeUndefined() + }) + + test("ignores malformed deep links safely", () => { + expect(() => parseDeepLink("opencode://open-project/%E0%A4%A%")).not.toThrow() + expect(parseDeepLink("opencode://open-project/%E0%A4%A%")).toBeUndefined() + }) + + test("parses links when URL.canParse is unavailable", () => { + const original = Object.getOwnPropertyDescriptor(URL, "canParse") + Object.defineProperty(URL, "canParse", { configurable: true, value: undefined }) + try { + expect(parseDeepLink("opencode://open-project?directory=/tmp/demo")).toBe("/tmp/demo") + } finally { + if (original) Object.defineProperty(URL, "canParse", original) + if (!original) Reflect.deleteProperty(URL, "canParse") + } + }) + + test("ignores open-project deep links without directory", () => { + expect(parseDeepLink("opencode://open-project")).toBeUndefined() + expect(parseDeepLink("opencode://open-project?directory=")).toBeUndefined() + }) + + test("collects only valid open-project directories", () => { + const result = collectOpenProjectDeepLinks([ + "opencode://open-project?directory=/a", + "opencode://other?directory=/b", + "opencode://open-project?directory=/c", + ]) + expect(result).toEqual(["/a", "/c"]) + }) + + test("drains global deep links once", () => { + const target = { + __OPENCODE__: { + deepLinks: ["opencode://open-project?directory=/a"], + }, + } as unknown as Window & { __OPENCODE__?: { deepLinks?: string[] } } + + expect(drainPendingDeepLinks(target)).toEqual(["opencode://open-project?directory=/a"]) + expect(drainPendingDeepLinks(target)).toEqual([]) + }) +}) + +describe("layout workspace helpers", () => { + test("normalizes trailing slash in workspace key", () => { + expect(workspaceKey("/tmp/demo///")).toBe("/tmp/demo") + expect(workspaceKey("C:\\tmp\\demo\\\\")).toBe("C:\\tmp\\demo") + }) + + test("preserves posix and drive roots in workspace key", () => { + expect(workspaceKey("/")).toBe("/") + expect(workspaceKey("///")).toBe("/") + expect(workspaceKey("C:\\")).toBe("C:\\") + expect(workspaceKey("C:\\\\\\")).toBe("C:\\") + expect(workspaceKey("C:///")).toBe("C:/") + }) + + test("keeps local first while preserving known order", () => { + const result = syncWorkspaceOrder("/root", ["/root", "/b", "/c"], ["/root", "/c", "/a", "/b"]) + expect(result).toEqual(["/root", "/c", "/b"]) + }) + + test("extracts draggable id safely", () => { + expect(getDraggableId({ draggable: { id: "x" } })).toBe("x") + expect(getDraggableId({ draggable: { id: 42 } })).toBeUndefined() + expect(getDraggableId(null)).toBeUndefined() + }) + + test("formats fallback project display name", () => { + expect(displayName({ worktree: "/tmp/app" })).toBe("app") + expect(displayName({ worktree: "/tmp/app", name: "My App" })).toBe("My App") + }) + + test("extracts api error message and fallback", () => { + expect(errorMessage({ data: { message: "boom" } }, "fallback")).toBe("boom") + expect(errorMessage(new Error("broken"), "fallback")).toBe("broken") + expect(errorMessage("unknown", "fallback")).toBe("fallback") + }) +}) diff --git a/packages/app/src/pages/layout/helpers.ts b/packages/app/src/pages/layout/helpers.ts new file mode 100644 index 00000000000..6a1e7c0123d --- /dev/null +++ b/packages/app/src/pages/layout/helpers.ts @@ -0,0 +1,70 @@ +import { getFilename } from "@opencode-ai/util/path" +import { type Session } from "@opencode-ai/sdk/v2/client" + +export const workspaceKey = (directory: string) => { + const drive = directory.match(/^([A-Za-z]:)[\\/]+$/) + if (drive) return `${drive[1]}${directory.includes("\\") ? "\\" : "/"}` + if (/^[\\/]+$/.test(directory)) return directory.includes("\\") ? "\\" : "/" + return directory.replace(/[\\/]+$/, "") +} + +export function sortSessions(now: number) { + const oneMinuteAgo = now - 60 * 1000 + return (a: Session, b: Session) => { + const aUpdated = a.time.updated ?? a.time.created + const bUpdated = b.time.updated ?? b.time.created + const aRecent = aUpdated > oneMinuteAgo + const bRecent = bUpdated > oneMinuteAgo + if (aRecent && bRecent) return a.id < b.id ? -1 : a.id > b.id ? 1 : 0 + if (aRecent && !bRecent) return -1 + if (!aRecent && bRecent) return 1 + return bUpdated - aUpdated + } +} + +export const isRootVisibleSession = (session: Session, directory: string) => + workspaceKey(session.directory) === workspaceKey(directory) && !session.parentID && !session.time?.archived + +export const sortedRootSessions = (store: { session: Session[]; path: { directory: string } }, now: number) => + store.session.filter((session) => isRootVisibleSession(session, store.path.directory)).sort(sortSessions(now)) + +export const childMapByParent = (sessions: Session[]) => { + const map = new Map() + for (const session of sessions) { + if (!session.parentID) continue + const existing = map.get(session.parentID) + if (existing) { + existing.push(session.id) + continue + } + map.set(session.parentID, [session.id]) + } + return map +} + +export function getDraggableId(event: unknown): string | undefined { + if (typeof event !== "object" || event === null) return undefined + if (!("draggable" in event)) return undefined + const draggable = (event as { draggable?: { id?: unknown } }).draggable + if (!draggable) return undefined + return typeof draggable.id === "string" ? draggable.id : undefined +} + +export const displayName = (project: { name?: string; worktree: string }) => + project.name || getFilename(project.worktree) + +export const errorMessage = (err: unknown, fallback: string) => { + if (err && typeof err === "object" && "data" in err) { + const data = (err as { data?: { message?: string } }).data + if (data?.message) return data.message + } + if (err instanceof Error) return err.message + return fallback +} + +export const syncWorkspaceOrder = (local: string, dirs: string[], existing?: string[]) => { + if (!existing) return dirs + const keep = existing.filter((d) => d !== local && dirs.includes(d)) + const missing = dirs.filter((d) => d !== local && !existing.includes(d)) + return [local, ...missing, ...keep] +} diff --git a/packages/app/src/pages/layout/inline-editor.tsx b/packages/app/src/pages/layout/inline-editor.tsx new file mode 100644 index 00000000000..0bbfe244ccb --- /dev/null +++ b/packages/app/src/pages/layout/inline-editor.tsx @@ -0,0 +1,113 @@ +import { createStore } from "solid-js/store" +import { Show, type Accessor } from "solid-js" +import { InlineInput } from "@opencode-ai/ui/inline-input" + +export function createInlineEditorController() { + const [editor, setEditor] = createStore({ + active: "" as string, + value: "", + }) + + const editorOpen = (id: string) => editor.active === id + const editorValue = () => editor.value + const openEditor = (id: string, value: string) => { + if (!id) return + setEditor({ active: id, value }) + } + const closeEditor = () => setEditor({ active: "", value: "" }) + + const saveEditor = (callback: (next: string) => void) => { + const next = editor.value.trim() + if (!next) { + closeEditor() + return + } + closeEditor() + callback(next) + } + + const editorKeyDown = (event: KeyboardEvent, callback: (next: string) => void) => { + if (event.key === "Enter") { + event.preventDefault() + saveEditor(callback) + return + } + if (event.key !== "Escape") return + event.preventDefault() + closeEditor() + } + + const InlineEditor = (props: { + id: string + value: Accessor + onSave: (next: string) => void + class?: string + displayClass?: string + editing?: boolean + stopPropagation?: boolean + openOnDblClick?: boolean + }) => { + const isEditing = () => props.editing ?? editorOpen(props.id) + const stopEvents = () => props.stopPropagation ?? false + const allowDblClick = () => props.openOnDblClick ?? true + const stopPropagation = (event: Event) => { + if (!stopEvents()) return + event.stopPropagation() + } + const handleDblClick = (event: MouseEvent) => { + if (!allowDblClick()) return + stopPropagation(event) + openEditor(props.id, props.value()) + } + + return ( + + {props.value()} + + } + > + { + requestAnimationFrame(() => el.focus()) + }} + value={editorValue()} + class={props.class} + onInput={(event) => setEditor("value", event.currentTarget.value)} + onKeyDown={(event) => { + event.stopPropagation() + editorKeyDown(event, props.onSave) + }} + onBlur={closeEditor} + onPointerDown={stopPropagation} + onClick={stopPropagation} + onDblClick={stopPropagation} + onMouseDown={stopPropagation} + onMouseUp={stopPropagation} + onTouchStart={stopPropagation} + /> + + ) + } + + return { + editor, + editorOpen, + editorValue, + openEditor, + closeEditor, + saveEditor, + editorKeyDown, + setEditor, + InlineEditor, + } +} diff --git a/packages/app/src/pages/layout/sidebar-items.tsx b/packages/app/src/pages/layout/sidebar-items.tsx new file mode 100644 index 00000000000..678bfa0d86d --- /dev/null +++ b/packages/app/src/pages/layout/sidebar-items.tsx @@ -0,0 +1,333 @@ +import { A, useNavigate, useParams } from "@solidjs/router" +import { useGlobalSync } from "@/context/global-sync" +import { useLanguage } from "@/context/language" +import { useLayout, type LocalProject, getAvatarColors } from "@/context/layout" +import { useNotification } from "@/context/notification" +import { base64Encode } from "@opencode-ai/util/encode" +import { Avatar } from "@opencode-ai/ui/avatar" +import { DiffChanges } from "@opencode-ai/ui/diff-changes" +import { HoverCard } from "@opencode-ai/ui/hover-card" +import { Icon } from "@opencode-ai/ui/icon" +import { IconButton } from "@opencode-ai/ui/icon-button" +import { MessageNav } from "@opencode-ai/ui/message-nav" +import { Spinner } from "@opencode-ai/ui/spinner" +import { Tooltip } from "@opencode-ai/ui/tooltip" +import { getFilename } from "@opencode-ai/util/path" +import { type Message, type Session, type TextPart } from "@opencode-ai/sdk/v2/client" +import { For, Match, Show, Switch, createMemo, onCleanup, type Accessor, type JSX } from "solid-js" +import { agentColor } from "@/utils/agent" + +const OPENCODE_PROJECT_ID = "4b0ea68d7af9a6031a7ffda7ad66e0cb83315750" + +export const ProjectIcon = (props: { project: LocalProject; class?: string; notify?: boolean }): JSX.Element => { + const notification = useNotification() + const dirs = createMemo(() => [props.project.worktree, ...(props.project.sandboxes ?? [])]) + const unseenCount = createMemo(() => + dirs().reduce((total, directory) => total + notification.project.unseenCount(directory), 0), + ) + const hasError = createMemo(() => dirs().some((directory) => notification.project.unseenHasError(directory))) + const name = createMemo(() => props.project.name || getFilename(props.project.worktree)) + return ( +
+
+ 0 && props.notify }} + /> +
+ 0 && props.notify}> +
+ +
+ ) +} + +export type SessionItemProps = { + session: Session + slug: string + mobile?: boolean + dense?: boolean + popover?: boolean + children: Map + sidebarExpanded: Accessor + sidebarHovering: Accessor + nav: Accessor + hoverSession: Accessor + setHoverSession: (id: string | undefined) => void + clearHoverProjectSoon: () => void + prefetchSession: (session: Session, priority?: "high" | "low") => void + archiveSession: (session: Session) => Promise +} + +export const SessionItem = (props: SessionItemProps): JSX.Element => { + const params = useParams() + const navigate = useNavigate() + const layout = useLayout() + const language = useLanguage() + const notification = useNotification() + const globalSync = useGlobalSync() + const unseenCount = createMemo(() => notification.session.unseenCount(props.session.id)) + const hasError = createMemo(() => notification.session.unseenHasError(props.session.id)) + const [sessionStore] = globalSync.child(props.session.directory) + const hasPermissions = createMemo(() => { + const permissions = sessionStore.permission?.[props.session.id] ?? [] + if (permissions.length > 0) return true + + for (const id of props.children.get(props.session.id) ?? []) { + const childPermissions = sessionStore.permission?.[id] ?? [] + if (childPermissions.length > 0) return true + } + return false + }) + const isWorking = createMemo(() => { + if (hasPermissions()) return false + const status = sessionStore.session_status[props.session.id] + return status?.type === "busy" || status?.type === "retry" + }) + + const tint = createMemo(() => { + const messages = sessionStore.message[props.session.id] + if (!messages) return undefined + let user: Message | undefined + for (let i = messages.length - 1; i >= 0; i--) { + const message = messages[i] + if (message.role !== "user") continue + user = message + break + } + if (!user?.agent) return undefined + + const agent = sessionStore.agent.find((a) => a.name === user.agent) + return agentColor(user.agent, agent?.color) + }) + + const hoverMessages = createMemo(() => + sessionStore.message[props.session.id]?.filter((message) => message.role === "user"), + ) + const hoverReady = createMemo(() => sessionStore.message[props.session.id] !== undefined) + const hoverAllowed = createMemo(() => !props.mobile && props.sidebarExpanded()) + const hoverEnabled = createMemo(() => (props.popover ?? true) && hoverAllowed()) + const isActive = createMemo(() => props.session.id === params.id) + + const hoverPrefetch = { current: undefined as ReturnType | undefined } + const cancelHoverPrefetch = () => { + if (hoverPrefetch.current === undefined) return + clearTimeout(hoverPrefetch.current) + hoverPrefetch.current = undefined + } + const scheduleHoverPrefetch = () => { + if (hoverPrefetch.current !== undefined) return + hoverPrefetch.current = setTimeout(() => { + hoverPrefetch.current = undefined + props.prefetchSession(props.session) + }, 200) + } + + onCleanup(cancelHoverPrefetch) + + const messageLabel = (message: Message) => { + const parts = sessionStore.part[message.id] ?? [] + const text = parts.find((part): part is TextPart => part?.type === "text" && !part.synthetic && !part.ignored) + return text?.text + } + + const item = ( + props.prefetchSession(props.session, "high")} + onClick={() => { + props.setHoverSession(undefined) + if (layout.sidebar.opened()) return + props.clearHoverProjectSoon() + }} + > +
+
+ }> + + + + +
+ + +
+ + 0}> +
+ + +
+ + {props.session.title} + + + {(summary) => ( +
+ +
+ )} +
+
+
+ ) + + return ( +
+ + {item} + + } + > + props.setHoverSession(open ? props.session.id : undefined)} + > + {language.t("session.messages.loading")}
} + > +
+ { + if (!isActive()) { + layout.pendingMessage.set( + `${base64Encode(props.session.directory)}/${props.session.id}`, + message.id, + ) + navigate(`${props.slug}/session/${props.session.id}`) + return + } + window.history.replaceState(null, "", `#message-${message.id}`) + window.dispatchEvent(new HashChangeEvent("hashchange")) + }} + size="normal" + class="w-60" + /> +
+ + + +
+ + { + event.preventDefault() + event.stopPropagation() + void props.archiveSession(props.session) + }} + /> + +
+
+ ) +} + +export const NewSessionItem = (props: { + slug: string + mobile?: boolean + dense?: boolean + sidebarExpanded: Accessor + clearHoverProjectSoon: () => void + setHoverSession: (id: string | undefined) => void +}): JSX.Element => { + const layout = useLayout() + const language = useLanguage() + const label = language.t("command.session.new") + const tooltip = () => props.mobile || !props.sidebarExpanded() + const item = ( + { + props.setHoverSession(undefined) + if (layout.sidebar.opened()) return + props.clearHoverProjectSoon() + }} + > +
+
+ +
+ + {label} + +
+
+ ) + + return ( +
+ + {item} + + } + > + {item} + +
+ ) +} + +export const SessionSkeleton = (props: { count?: number }): JSX.Element => { + const items = Array.from({ length: props.count ?? 4 }, (_, index) => index) + return ( +
+ + {() =>
} + +
+ ) +} diff --git a/packages/app/src/pages/layout/sidebar-project-helpers.test.ts b/packages/app/src/pages/layout/sidebar-project-helpers.test.ts new file mode 100644 index 00000000000..75958d49e92 --- /dev/null +++ b/packages/app/src/pages/layout/sidebar-project-helpers.test.ts @@ -0,0 +1,63 @@ +import { describe, expect, test } from "bun:test" +import { projectSelected, projectTileActive } from "./sidebar-project-helpers" + +describe("projectSelected", () => { + test("matches direct worktree", () => { + expect(projectSelected("/tmp/root", "/tmp/root")).toBe(true) + }) + + test("matches sandbox worktree", () => { + expect(projectSelected("/tmp/branch", "/tmp/root", ["/tmp/branch"])).toBe(true) + expect(projectSelected("/tmp/other", "/tmp/root", ["/tmp/branch"])).toBe(false) + }) +}) + +describe("projectTileActive", () => { + test("menu state always wins", () => { + expect( + projectTileActive({ + menu: true, + preview: false, + open: false, + overlay: false, + worktree: "/tmp/root", + }), + ).toBe(true) + }) + + test("preview mode uses open state", () => { + expect( + projectTileActive({ + menu: false, + preview: true, + open: true, + overlay: true, + hoverProject: "/tmp/other", + worktree: "/tmp/root", + }), + ).toBe(true) + }) + + test("overlay mode uses hovered project", () => { + expect( + projectTileActive({ + menu: false, + preview: false, + open: false, + overlay: true, + hoverProject: "/tmp/root", + worktree: "/tmp/root", + }), + ).toBe(true) + expect( + projectTileActive({ + menu: false, + preview: false, + open: false, + overlay: true, + hoverProject: "/tmp/other", + worktree: "/tmp/root", + }), + ).toBe(false) + }) +}) diff --git a/packages/app/src/pages/layout/sidebar-project-helpers.ts b/packages/app/src/pages/layout/sidebar-project-helpers.ts new file mode 100644 index 00000000000..06d38a3cd1b --- /dev/null +++ b/packages/app/src/pages/layout/sidebar-project-helpers.ts @@ -0,0 +1,11 @@ +export const projectSelected = (currentDir: string, worktree: string, sandboxes?: string[]) => + worktree === currentDir || sandboxes?.includes(currentDir) === true + +export const projectTileActive = (args: { + menu: boolean + preview: boolean + open: boolean + overlay: boolean + hoverProject?: string + worktree: string +}) => args.menu || (args.preview ? args.open : args.overlay && args.hoverProject === args.worktree) diff --git a/packages/app/src/pages/layout/sidebar-project.tsx b/packages/app/src/pages/layout/sidebar-project.tsx new file mode 100644 index 00000000000..c91dc987d80 --- /dev/null +++ b/packages/app/src/pages/layout/sidebar-project.tsx @@ -0,0 +1,283 @@ +import { createEffect, createMemo, createSignal, For, Show, type Accessor, type JSX } from "solid-js" +import { base64Encode } from "@opencode-ai/util/encode" +import { Button } from "@opencode-ai/ui/button" +import { ContextMenu } from "@opencode-ai/ui/context-menu" +import { HoverCard } from "@opencode-ai/ui/hover-card" +import { Icon } from "@opencode-ai/ui/icon" +import { IconButton } from "@opencode-ai/ui/icon-button" +import { Tooltip } from "@opencode-ai/ui/tooltip" +import { createSortable } from "@thisbeyond/solid-dnd" +import { type LocalProject } from "@/context/layout" +import { useGlobalSync } from "@/context/global-sync" +import { useLanguage } from "@/context/language" +import { ProjectIcon, SessionItem, type SessionItemProps } from "./sidebar-items" +import { childMapByParent, displayName, sortedRootSessions } from "./helpers" +import { projectSelected, projectTileActive } from "./sidebar-project-helpers" + +export type ProjectSidebarContext = { + currentDir: Accessor + sidebarOpened: Accessor + sidebarHovering: Accessor + hoverProject: Accessor + nav: Accessor + onProjectMouseEnter: (worktree: string, event: MouseEvent) => void + onProjectMouseLeave: (worktree: string) => void + onProjectFocus: (worktree: string) => void + navigateToProject: (directory: string) => void + openSidebar: () => void + closeProject: (directory: string) => void + showEditProjectDialog: (project: LocalProject) => void + toggleProjectWorkspaces: (project: LocalProject) => void + workspacesEnabled: (project: LocalProject) => boolean + workspaceIds: (project: LocalProject) => string[] + workspaceLabel: (directory: string, branch?: string, projectId?: string) => string + sessionProps: Omit + setHoverSession: (id: string | undefined) => void +} + +export const ProjectDragOverlay = (props: { + projects: Accessor + activeProject: Accessor +}): JSX.Element => { + const project = createMemo(() => props.projects().find((p) => p.worktree === props.activeProject())) + return ( + + {(p) => ( +
+ +
+ )} +
+ ) +} + +export const SortableProject = (props: { + project: LocalProject + mobile?: boolean + ctx: ProjectSidebarContext +}): JSX.Element => { + const globalSync = useGlobalSync() + const language = useLanguage() + const sortable = createSortable(props.project.worktree) + const selected = createMemo(() => + projectSelected(props.ctx.currentDir(), props.project.worktree, props.project.sandboxes), + ) + const workspaces = createMemo(() => props.ctx.workspaceIds(props.project).slice(0, 2)) + const workspaceEnabled = createMemo(() => props.ctx.workspacesEnabled(props.project)) + const [open, setOpen] = createSignal(false) + const [menu, setMenu] = createSignal(false) + + const preview = createMemo(() => !props.mobile && props.ctx.sidebarOpened()) + const overlay = createMemo(() => !props.mobile && !props.ctx.sidebarOpened()) + const active = createMemo(() => + projectTileActive({ + menu: menu(), + preview: preview(), + open: open(), + overlay: overlay(), + hoverProject: props.ctx.hoverProject(), + worktree: props.project.worktree, + }), + ) + + createEffect(() => { + if (preview()) return + if (!open()) return + setOpen(false) + }) + + const label = (directory: string) => { + const [data] = globalSync.child(directory, { bootstrap: false }) + const kind = + directory === props.project.worktree ? language.t("workspace.type.local") : language.t("workspace.type.sandbox") + const name = props.ctx.workspaceLabel(directory, data.vcs?.branch, props.project.id) + return `${kind} : ${name}` + } + + const projectStore = createMemo(() => globalSync.child(props.project.worktree, { bootstrap: false })[0]) + const projectSessions = createMemo(() => sortedRootSessions(projectStore(), Date.now()).slice(0, 2)) + const projectChildren = createMemo(() => childMapByParent(projectStore().session)) + const workspaceSessions = (directory: string) => { + const [data] = globalSync.child(directory, { bootstrap: false }) + return sortedRootSessions(data, Date.now()).slice(0, 2) + } + const workspaceChildren = (directory: string) => { + const [data] = globalSync.child(directory, { bootstrap: false }) + return childMapByParent(data.session) + } + + const Trigger = () => ( + { + setMenu(value) + if (value) setOpen(false) + }} + > + { + if (!overlay()) return + props.ctx.onProjectMouseEnter(props.project.worktree, event) + }} + onMouseLeave={() => { + if (!overlay()) return + props.ctx.onProjectMouseLeave(props.project.worktree) + }} + onFocus={() => { + if (!overlay()) return + props.ctx.onProjectFocus(props.project.worktree) + }} + onClick={() => props.ctx.navigateToProject(props.project.worktree)} + onBlur={() => setOpen(false)} + > + + + + + props.ctx.showEditProjectDialog(props.project)}> + {language.t("common.edit")} + + props.ctx.toggleProjectWorkspaces(props.project)} + > + + {props.ctx.workspacesEnabled(props.project) + ? language.t("sidebar.workspaces.disable") + : language.t("sidebar.workspaces.enable")} + + + + props.ctx.closeProject(props.project.worktree)} + > + {language.t("common.close")} + + + + + ) + + return ( + // @ts-ignore +
+ }> + } + onOpenChange={(value) => { + if (menu()) return + setOpen(value) + if (value) props.ctx.setHoverSession(undefined) + }} + > +
+
+
{displayName(props.project)}
+ + { + event.stopPropagation() + setOpen(false) + props.ctx.closeProject(props.project.worktree) + }} + /> + +
+
{language.t("sidebar.project.recentSessions")}
+
+ + {(session) => ( + + )} + + } + > + + {(directory) => { + const sessions = createMemo(() => workspaceSessions(directory)) + const children = createMemo(() => workspaceChildren(directory)) + return ( +
+
+
+ +
+ {label(directory)} +
+ + {(session) => ( + + )} + +
+ ) + }} +
+
+
+
+ +
+
+
+
+
+ ) +} diff --git a/packages/app/src/pages/layout/sidebar-shell-helpers.ts b/packages/app/src/pages/layout/sidebar-shell-helpers.ts new file mode 100644 index 00000000000..93c286c1523 --- /dev/null +++ b/packages/app/src/pages/layout/sidebar-shell-helpers.ts @@ -0,0 +1 @@ +export const sidebarExpanded = (mobile: boolean | undefined, opened: boolean) => !!mobile || opened diff --git a/packages/app/src/pages/layout/sidebar-shell.test.ts b/packages/app/src/pages/layout/sidebar-shell.test.ts new file mode 100644 index 00000000000..694025a6532 --- /dev/null +++ b/packages/app/src/pages/layout/sidebar-shell.test.ts @@ -0,0 +1,13 @@ +import { describe, expect, test } from "bun:test" +import { sidebarExpanded } from "./sidebar-shell-helpers" + +describe("sidebarExpanded", () => { + test("expands on mobile regardless of desktop open state", () => { + expect(sidebarExpanded(true, false)).toBe(true) + }) + + test("follows desktop open state when not mobile", () => { + expect(sidebarExpanded(false, true)).toBe(true) + expect(sidebarExpanded(false, false)).toBe(false) + }) +}) diff --git a/packages/app/src/pages/layout/sidebar-shell.tsx b/packages/app/src/pages/layout/sidebar-shell.tsx new file mode 100644 index 00000000000..ce96a09d114 --- /dev/null +++ b/packages/app/src/pages/layout/sidebar-shell.tsx @@ -0,0 +1,109 @@ +import { createMemo, For, Show, type Accessor, type JSX } from "solid-js" +import { + DragDropProvider, + DragDropSensors, + DragOverlay, + SortableProvider, + closestCenter, + type DragEvent, +} from "@thisbeyond/solid-dnd" +import { ConstrainDragXAxis } from "@/utils/solid-dnd" +import { IconButton } from "@opencode-ai/ui/icon-button" +import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip" +import { type LocalProject } from "@/context/layout" +import { sidebarExpanded } from "./sidebar-shell-helpers" + +export const SidebarContent = (props: { + mobile?: boolean + opened: Accessor + aimMove: (event: MouseEvent) => void + projects: Accessor + renderProject: (project: LocalProject) => JSX.Element + handleDragStart: (event: unknown) => void + handleDragEnd: () => void + handleDragOver: (event: DragEvent) => void + openProjectLabel: JSX.Element + openProjectKeybind: Accessor + onOpenProject: () => void + renderProjectOverlay: () => JSX.Element + settingsLabel: Accessor + settingsKeybind: Accessor + onOpenSettings: () => void + helpLabel: Accessor + onOpenHelp: () => void + renderPanel: () => JSX.Element +}): JSX.Element => { + const expanded = createMemo(() => sidebarExpanded(props.mobile, props.opened())) + + return ( +
+
+
+ + + +
+ p.worktree)}> + {(project) => props.renderProject(project)} + + + {props.openProjectLabel} + + {props.openProjectKeybind()} + +
+ } + > + + +
+ {props.renderProjectOverlay()} + +
+
+ + + + + + +
+
+ + {props.renderPanel()} +
+ ) +} diff --git a/packages/app/src/pages/layout/sidebar-workspace-helpers.ts b/packages/app/src/pages/layout/sidebar-workspace-helpers.ts new file mode 100644 index 00000000000..aa7cb480e5e --- /dev/null +++ b/packages/app/src/pages/layout/sidebar-workspace-helpers.ts @@ -0,0 +1,2 @@ +export const workspaceOpenState = (expanded: Record, directory: string, local: boolean) => + expanded[directory] ?? local diff --git a/packages/app/src/pages/layout/sidebar-workspace.test.ts b/packages/app/src/pages/layout/sidebar-workspace.test.ts new file mode 100644 index 00000000000..d71c39fc8bf --- /dev/null +++ b/packages/app/src/pages/layout/sidebar-workspace.test.ts @@ -0,0 +1,13 @@ +import { describe, expect, test } from "bun:test" +import { workspaceOpenState } from "./sidebar-workspace-helpers" + +describe("workspaceOpenState", () => { + test("defaults to local workspace open", () => { + expect(workspaceOpenState({}, "/tmp/root", true)).toBe(true) + }) + + test("uses persisted expansion state when present", () => { + expect(workspaceOpenState({ "/tmp/root": false }, "/tmp/root", true)).toBe(false) + expect(workspaceOpenState({ "/tmp/branch": true }, "/tmp/branch", false)).toBe(true) + }) +}) diff --git a/packages/app/src/pages/layout/sidebar-workspace.tsx b/packages/app/src/pages/layout/sidebar-workspace.tsx new file mode 100644 index 00000000000..13c1e55ef8b --- /dev/null +++ b/packages/app/src/pages/layout/sidebar-workspace.tsx @@ -0,0 +1,420 @@ +import { useNavigate, useParams } from "@solidjs/router" +import { createEffect, createMemo, For, Show, type Accessor, type JSX } from "solid-js" +import { createStore } from "solid-js/store" +import { createSortable } from "@thisbeyond/solid-dnd" +import { createMediaQuery } from "@solid-primitives/media" +import { base64Encode } from "@opencode-ai/util/encode" +import { getFilename } from "@opencode-ai/util/path" +import { Button } from "@opencode-ai/ui/button" +import { Collapsible } from "@opencode-ai/ui/collapsible" +import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu" +import { Icon } from "@opencode-ai/ui/icon" +import { IconButton } from "@opencode-ai/ui/icon-button" +import { Spinner } from "@opencode-ai/ui/spinner" +import { Tooltip } from "@opencode-ai/ui/tooltip" +import { type Session } from "@opencode-ai/sdk/v2/client" +import { type LocalProject } from "@/context/layout" +import { useGlobalSync } from "@/context/global-sync" +import { useLanguage } from "@/context/language" +import { NewSessionItem, SessionItem, SessionSkeleton } from "./sidebar-items" +import { childMapByParent, sortedRootSessions } from "./helpers" + +type InlineEditorComponent = (props: { + id: string + value: Accessor + onSave: (next: string) => void + class?: string + displayClass?: string + editing?: boolean + stopPropagation?: boolean + openOnDblClick?: boolean +}) => JSX.Element + +export type WorkspaceSidebarContext = { + currentDir: Accessor + sidebarExpanded: Accessor + sidebarHovering: Accessor + nav: Accessor + hoverSession: Accessor + setHoverSession: (id: string | undefined) => void + clearHoverProjectSoon: () => void + prefetchSession: (session: Session, priority?: "high" | "low") => void + archiveSession: (session: Session) => Promise + workspaceName: (directory: string, projectId?: string, branch?: string) => string | undefined + renameWorkspace: (directory: string, next: string, projectId?: string, branch?: string) => void + editorOpen: (id: string) => boolean + openEditor: (id: string, value: string) => void + closeEditor: () => void + setEditor: (key: "value", value: string) => void + InlineEditor: InlineEditorComponent + isBusy: (directory: string) => boolean + workspaceExpanded: (directory: string, local: boolean) => boolean + setWorkspaceExpanded: (directory: string, value: boolean) => void + showResetWorkspaceDialog: (root: string, directory: string) => void + showDeleteWorkspaceDialog: (root: string, directory: string) => void + setScrollContainerRef: (el: HTMLDivElement | undefined, mobile?: boolean) => void +} + +export const WorkspaceDragOverlay = (props: { + sidebarProject: Accessor + activeWorkspace: Accessor + workspaceLabel: (directory: string, branch?: string, projectId?: string) => string +}): JSX.Element => { + const globalSync = useGlobalSync() + const language = useLanguage() + const label = createMemo(() => { + const project = props.sidebarProject() + if (!project) return + const directory = props.activeWorkspace() + if (!directory) return + + const [workspaceStore] = globalSync.child(directory, { bootstrap: false }) + const kind = + directory === project.worktree ? language.t("workspace.type.local") : language.t("workspace.type.sandbox") + const name = props.workspaceLabel(directory, workspaceStore.vcs?.branch, project.id) + return `${kind} : ${name}` + }) + + return ( + + {(value) =>
{value()}
} +
+ ) +} + +export const SortableWorkspace = (props: { + ctx: WorkspaceSidebarContext + directory: string + project: LocalProject + mobile?: boolean +}): JSX.Element => { + const navigate = useNavigate() + const params = useParams() + const globalSync = useGlobalSync() + const language = useLanguage() + const sortable = createSortable(props.directory) + const [workspaceStore, setWorkspaceStore] = globalSync.child(props.directory, { bootstrap: false }) + const [menu, setMenu] = createStore({ + open: false, + pendingRename: false, + }) + const slug = createMemo(() => base64Encode(props.directory)) + const sessions = createMemo(() => sortedRootSessions(workspaceStore, Date.now())) + const children = createMemo(() => childMapByParent(workspaceStore.session)) + const local = createMemo(() => props.directory === props.project.worktree) + const active = createMemo(() => props.ctx.currentDir() === props.directory) + const workspaceValue = createMemo(() => { + const branch = workspaceStore.vcs?.branch + const name = branch ?? getFilename(props.directory) + return props.ctx.workspaceName(props.directory, props.project.id, branch) ?? name + }) + const open = createMemo(() => props.ctx.workspaceExpanded(props.directory, local())) + const boot = createMemo(() => open() || active()) + const booted = createMemo((prev) => prev || workspaceStore.status === "complete", false) + const hasMore = createMemo(() => workspaceStore.sessionTotal > sessions().length) + const busy = createMemo(() => props.ctx.isBusy(props.directory)) + const wasBusy = createMemo((prev) => prev || busy(), false) + const loading = createMemo(() => open() && !booted() && sessions().length === 0 && !wasBusy()) + const touch = createMediaQuery("(hover: none)") + const showNew = createMemo(() => !loading() && (touch() || sessions().length === 0 || (active() && !params.id))) + const loadMore = async () => { + setWorkspaceStore("limit", (limit) => (limit ?? 0) + 5) + await globalSync.project.loadSessions(props.directory) + } + + const workspaceEditActive = createMemo(() => props.ctx.editorOpen(`workspace:${props.directory}`)) + + const openWrapper = (value: boolean) => { + props.ctx.setWorkspaceExpanded(props.directory, value) + if (value) return + if (props.ctx.editorOpen(`workspace:${props.directory}`)) props.ctx.closeEditor() + } + + createEffect(() => { + if (!boot()) return + globalSync.child(props.directory, { bootstrap: true }) + }) + + const header = () => ( +
+
+ }> + + +
+ + {local() ? language.t("workspace.type.local") : language.t("workspace.type.sandbox")} : + + + {workspaceStore.vcs?.branch ?? getFilename(props.directory)} + + } + > + { + const trimmed = next.trim() + if (!trimmed) return + props.ctx.renameWorkspace(props.directory, trimmed, props.project.id, workspaceStore.vcs?.branch) + props.ctx.setEditor("value", workspaceValue()) + }} + class="text-14-medium text-text-base min-w-0 truncate" + displayClass="text-14-medium text-text-base min-w-0 truncate" + editing={workspaceEditActive()} + stopPropagation={false} + openOnDblClick={false} + /> + +
+ +
+
+ ) + + return ( +
+ +
+
+
+ + {header()} + + } + > +
+ {header()} +
+
+
+ setMenu("open", open)} + > + + + + + { + if (!menu.pendingRename) return + event.preventDefault() + setMenu("pendingRename", false) + props.ctx.openEditor(`workspace:${props.directory}`, workspaceValue()) + }} + > + { + setMenu("pendingRename", true) + setMenu("open", false) + }} + > + {language.t("common.rename")} + + props.ctx.showResetWorkspaceDialog(props.project.worktree, props.directory)} + > + {language.t("common.reset")} + + props.ctx.showDeleteWorkspaceDialog(props.project.worktree, props.directory)} + > + {language.t("common.delete")} + + + + + + + { + event.preventDefault() + event.stopPropagation() + props.ctx.setHoverSession(undefined) + props.ctx.clearHoverProjectSoon() + navigate(`/${slug()}/session`) + }} + /> + + +
+
+
+
+ + + + +
+
+ ) +} + +export const LocalWorkspace = (props: { + ctx: WorkspaceSidebarContext + project: LocalProject + mobile?: boolean +}): JSX.Element => { + const globalSync = useGlobalSync() + const language = useLanguage() + const workspace = createMemo(() => { + const [store, setStore] = globalSync.child(props.project.worktree) + return { store, setStore } + }) + const slug = createMemo(() => base64Encode(props.project.worktree)) + const sessions = createMemo(() => sortedRootSessions(workspace().store, Date.now())) + const children = createMemo(() => childMapByParent(workspace().store.session)) + const booted = createMemo((prev) => prev || workspace().store.status === "complete", false) + const loading = createMemo(() => !booted() && sessions().length === 0) + const hasMore = createMemo(() => workspace().store.sessionTotal > sessions().length) + const loadMore = async () => { + workspace().setStore("limit", (limit) => (limit ?? 0) + 5) + await globalSync.project.loadSessions(props.project.worktree) + } + + return ( +
props.ctx.setScrollContainerRef(el, props.mobile)} + class="size-full flex flex-col py-2 overflow-y-auto no-scrollbar [overflow-anchor:none]" + > + +
+ ) +} diff --git a/packages/app/src/pages/session/file-tab-scroll.test.ts b/packages/app/src/pages/session/file-tab-scroll.test.ts new file mode 100644 index 00000000000..89e0dcc8fd8 --- /dev/null +++ b/packages/app/src/pages/session/file-tab-scroll.test.ts @@ -0,0 +1,40 @@ +import { describe, expect, test } from "bun:test" +import { nextTabListScrollLeft } from "./file-tab-scroll" + +describe("nextTabListScrollLeft", () => { + test("does not scroll when width shrinks", () => { + const left = nextTabListScrollLeft({ + prevScrollWidth: 500, + scrollWidth: 420, + clientWidth: 300, + prevContextOpen: false, + contextOpen: false, + }) + + expect(left).toBeUndefined() + }) + + test("scrolls to start when context tab opens", () => { + const left = nextTabListScrollLeft({ + prevScrollWidth: 400, + scrollWidth: 500, + clientWidth: 320, + prevContextOpen: false, + contextOpen: true, + }) + + expect(left).toBe(0) + }) + + test("scrolls to right edge for new file tabs", () => { + const left = nextTabListScrollLeft({ + prevScrollWidth: 500, + scrollWidth: 780, + clientWidth: 300, + prevContextOpen: true, + contextOpen: true, + }) + + expect(left).toBe(480) + }) +}) diff --git a/packages/app/src/pages/session/file-tab-scroll.ts b/packages/app/src/pages/session/file-tab-scroll.ts new file mode 100644 index 00000000000..b69188d4051 --- /dev/null +++ b/packages/app/src/pages/session/file-tab-scroll.ts @@ -0,0 +1,67 @@ +type Input = { + prevScrollWidth: number + scrollWidth: number + clientWidth: number + prevContextOpen: boolean + contextOpen: boolean +} + +export const nextTabListScrollLeft = (input: Input) => { + if (input.scrollWidth <= input.prevScrollWidth) return + if (!input.prevContextOpen && input.contextOpen) return 0 + if (input.scrollWidth <= input.clientWidth) return + return input.scrollWidth - input.clientWidth +} + +export const createFileTabListSync = (input: { el: HTMLDivElement; contextOpen: () => boolean }) => { + let frame: number | undefined + let prevScrollWidth = input.el.scrollWidth + let prevContextOpen = input.contextOpen() + + const update = () => { + const scrollWidth = input.el.scrollWidth + const clientWidth = input.el.clientWidth + const contextOpen = input.contextOpen() + const left = nextTabListScrollLeft({ + prevScrollWidth, + scrollWidth, + clientWidth, + prevContextOpen, + contextOpen, + }) + + if (left !== undefined) { + input.el.scrollTo({ + left, + behavior: "smooth", + }) + } + + prevScrollWidth = scrollWidth + prevContextOpen = contextOpen + } + + const schedule = () => { + if (frame !== undefined) cancelAnimationFrame(frame) + frame = requestAnimationFrame(() => { + frame = undefined + update() + }) + } + + const onWheel = (e: WheelEvent) => { + if (Math.abs(e.deltaY) <= Math.abs(e.deltaX)) return + input.el.scrollLeft += e.deltaY > 0 ? 50 : -50 + e.preventDefault() + } + + input.el.addEventListener("wheel", onWheel, { passive: false }) + const observer = new MutationObserver(schedule) + observer.observe(input.el, { childList: true }) + + return () => { + input.el.removeEventListener("wheel", onWheel) + observer.disconnect() + if (frame !== undefined) cancelAnimationFrame(frame) + } +} diff --git a/packages/app/src/pages/session/file-tabs.tsx b/packages/app/src/pages/session/file-tabs.tsx new file mode 100644 index 00000000000..0c8281a66db --- /dev/null +++ b/packages/app/src/pages/session/file-tabs.tsx @@ -0,0 +1,516 @@ +import { type ValidComponent, createEffect, createMemo, For, Match, on, onCleanup, Show, Switch } from "solid-js" +import { createStore } from "solid-js/store" +import { Dynamic } from "solid-js/web" +import { checksum } from "@opencode-ai/util/encode" +import { decode64 } from "@/utils/base64" +import { showToast } from "@opencode-ai/ui/toast" +import { LineComment as LineCommentView, LineCommentEditor } from "@opencode-ai/ui/line-comment" +import { Mark } from "@opencode-ai/ui/logo" +import { Tabs } from "@opencode-ai/ui/tabs" +import { useLayout } from "@/context/layout" +import { useFile, type SelectedLineRange } from "@/context/file" +import { useComments } from "@/context/comments" +import { useLanguage } from "@/context/language" + +export function FileTabContent(props: { + tab: string + activeTab: () => string + tabs: () => ReturnType["tabs"]> + view: () => ReturnType["view"]> + handoffFiles: () => Record | undefined + file: ReturnType + comments: ReturnType + language: ReturnType + codeComponent: NonNullable + addCommentToContext: (input: { + file: string + selection: SelectedLineRange + comment: string + preview?: string + origin?: "review" | "file" + }) => void +}) { + let scroll: HTMLDivElement | undefined + let scrollFrame: number | undefined + let pending: { x: number; y: number } | undefined + let codeScroll: HTMLElement[] = [] + + const path = createMemo(() => props.file.pathFromTab(props.tab)) + const state = createMemo(() => { + const p = path() + if (!p) return + return props.file.get(p) + }) + const contents = createMemo(() => state()?.content?.content ?? "") + const cacheKey = createMemo(() => checksum(contents())) + const isImage = createMemo(() => { + const c = state()?.content + return c?.encoding === "base64" && c?.mimeType?.startsWith("image/") && c?.mimeType !== "image/svg+xml" + }) + const isSvg = createMemo(() => { + const c = state()?.content + return c?.mimeType === "image/svg+xml" + }) + const isBinary = createMemo(() => state()?.content?.type === "binary") + const svgContent = createMemo(() => { + if (!isSvg()) return + const c = state()?.content + if (!c) return + if (c.encoding !== "base64") return c.content + return decode64(c.content) + }) + + const svgDecodeFailed = createMemo(() => { + if (!isSvg()) return false + const c = state()?.content + if (!c) return false + if (c.encoding !== "base64") return false + return svgContent() === undefined + }) + + const svgToast = { shown: false } + createEffect(() => { + if (!svgDecodeFailed()) return + if (svgToast.shown) return + svgToast.shown = true + showToast({ + variant: "error", + title: props.language.t("toast.file.loadFailed.title"), + description: "Invalid base64 content.", + }) + }) + const svgPreviewUrl = createMemo(() => { + if (!isSvg()) return + const c = state()?.content + if (!c) return + if (c.encoding === "base64") return `data:image/svg+xml;base64,${c.content}` + return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(c.content)}` + }) + const imageDataUrl = createMemo(() => { + if (!isImage()) return + const c = state()?.content + return `data:${c?.mimeType};base64,${c?.content}` + }) + const selectedLines = createMemo(() => { + const p = path() + if (!p) return null + if (props.file.ready()) return props.file.selectedLines(p) ?? null + return props.handoffFiles()?.[p] ?? null + }) + + let wrap: HTMLDivElement | undefined + + const fileComments = createMemo(() => { + const p = path() + if (!p) return [] + return props.comments.list(p) + }) + + const commentedLines = createMemo(() => fileComments().map((comment) => comment.selection)) + + const [note, setNote] = createStore({ + openedComment: null as string | null, + commenting: null as SelectedLineRange | null, + draft: "", + positions: {} as Record, + draftTop: undefined as number | undefined, + }) + + const openedComment = () => note.openedComment + const setOpenedComment = ( + value: typeof note.openedComment | ((value: typeof note.openedComment) => typeof note.openedComment), + ) => setNote("openedComment", value) + + const commenting = () => note.commenting + const setCommenting = (value: typeof note.commenting | ((value: typeof note.commenting) => typeof note.commenting)) => + setNote("commenting", value) + + const draft = () => note.draft + const setDraft = (value: typeof note.draft | ((value: typeof note.draft) => typeof note.draft)) => + setNote("draft", value) + + const positions = () => note.positions + const setPositions = (value: typeof note.positions | ((value: typeof note.positions) => typeof note.positions)) => + setNote("positions", value) + + const draftTop = () => note.draftTop + const setDraftTop = (value: typeof note.draftTop | ((value: typeof note.draftTop) => typeof note.draftTop)) => + setNote("draftTop", value) + + const commentLabel = (range: SelectedLineRange) => { + const start = Math.min(range.start, range.end) + const end = Math.max(range.start, range.end) + if (start === end) return `line ${start}` + return `lines ${start}-${end}` + } + + const getRoot = () => { + const el = wrap + if (!el) return + + const host = el.querySelector("diffs-container") + if (!(host instanceof HTMLElement)) return + + const root = host.shadowRoot + if (!root) return + + return root + } + + const findMarker = (root: ShadowRoot, range: SelectedLineRange) => { + const line = Math.max(range.start, range.end) + const node = root.querySelector(`[data-line="${line}"]`) + if (!(node instanceof HTMLElement)) return + return node + } + + const markerTop = (wrapper: HTMLElement, marker: HTMLElement) => { + const wrapperRect = wrapper.getBoundingClientRect() + const rect = marker.getBoundingClientRect() + return rect.top - wrapperRect.top + Math.max(0, (rect.height - 20) / 2) + } + + const updateComments = () => { + const el = wrap + const root = getRoot() + if (!el || !root) { + setPositions({}) + setDraftTop(undefined) + return + } + + const next: Record = {} + for (const comment of fileComments()) { + const marker = findMarker(root, comment.selection) + if (!marker) continue + next[comment.id] = markerTop(el, marker) + } + + setPositions(next) + + const range = commenting() + if (!range) { + setDraftTop(undefined) + return + } + + const marker = findMarker(root, range) + if (!marker) { + setDraftTop(undefined) + return + } + + setDraftTop(markerTop(el, marker)) + } + + const scheduleComments = () => { + requestAnimationFrame(updateComments) + } + + createEffect(() => { + fileComments() + scheduleComments() + }) + + createEffect(() => { + const range = commenting() + scheduleComments() + if (!range) return + setDraft("") + }) + + createEffect(() => { + const focus = props.comments.focus() + const p = path() + if (!focus || !p) return + if (focus.file !== p) return + if (props.activeTab() !== props.tab) return + + const target = fileComments().find((comment) => comment.id === focus.id) + if (!target) return + + setOpenedComment(target.id) + setCommenting(null) + props.file.setSelectedLines(p, target.selection) + requestAnimationFrame(() => props.comments.clearFocus()) + }) + + const getCodeScroll = () => { + const el = scroll + if (!el) return [] + + const host = el.querySelector("diffs-container") + if (!(host instanceof HTMLElement)) return [] + + const root = host.shadowRoot + if (!root) return [] + + return Array.from(root.querySelectorAll("[data-code]")).filter( + (node): node is HTMLElement => node instanceof HTMLElement && node.clientWidth > 0, + ) + } + + const queueScrollUpdate = (next: { x: number; y: number }) => { + pending = next + if (scrollFrame !== undefined) return + + scrollFrame = requestAnimationFrame(() => { + scrollFrame = undefined + + const out = pending + pending = undefined + if (!out) return + + props.view().setScroll(props.tab, out) + }) + } + + const handleCodeScroll = (event: Event) => { + const el = scroll + if (!el) return + + const target = event.currentTarget + if (!(target instanceof HTMLElement)) return + + queueScrollUpdate({ + x: target.scrollLeft, + y: el.scrollTop, + }) + } + + const syncCodeScroll = () => { + const next = getCodeScroll() + if (next.length === codeScroll.length && next.every((el, i) => el === codeScroll[i])) return + + for (const item of codeScroll) { + item.removeEventListener("scroll", handleCodeScroll) + } + + codeScroll = next + + for (const item of codeScroll) { + item.addEventListener("scroll", handleCodeScroll) + } + } + + const restoreScroll = () => { + const el = scroll + if (!el) return + + const s = props.view()?.scroll(props.tab) + if (!s) return + + syncCodeScroll() + + if (codeScroll.length > 0) { + for (const item of codeScroll) { + if (item.scrollLeft !== s.x) item.scrollLeft = s.x + } + } + + if (el.scrollTop !== s.y) el.scrollTop = s.y + if (codeScroll.length > 0) return + if (el.scrollLeft !== s.x) el.scrollLeft = s.x + } + + const handleScroll = (event: Event & { currentTarget: HTMLDivElement }) => { + if (codeScroll.length === 0) syncCodeScroll() + + queueScrollUpdate({ + x: codeScroll[0]?.scrollLeft ?? event.currentTarget.scrollLeft, + y: event.currentTarget.scrollTop, + }) + } + + createEffect( + on( + () => state()?.loaded, + (loaded) => { + if (!loaded) return + requestAnimationFrame(restoreScroll) + }, + { defer: true }, + ), + ) + + createEffect( + on( + () => props.file.ready(), + (ready) => { + if (!ready) return + requestAnimationFrame(restoreScroll) + }, + { defer: true }, + ), + ) + + createEffect( + on( + () => props.tabs().active() === props.tab, + (active) => { + if (!active) return + if (!state()?.loaded) return + requestAnimationFrame(restoreScroll) + }, + ), + ) + + onCleanup(() => { + for (const item of codeScroll) { + item.removeEventListener("scroll", handleCodeScroll) + } + + if (scrollFrame === undefined) return + cancelAnimationFrame(scrollFrame) + }) + + const renderCode = (source: string, wrapperClass: string) => ( +
{ + wrap = el + scheduleComments() + }} + class={`relative overflow-hidden ${wrapperClass}`} + > + { + requestAnimationFrame(restoreScroll) + requestAnimationFrame(scheduleComments) + }} + onLineSelected={(range: SelectedLineRange | null) => { + const p = path() + if (!p) return + props.file.setSelectedLines(p, range) + if (!range) setCommenting(null) + }} + onLineSelectionEnd={(range: SelectedLineRange | null) => { + if (!range) { + setCommenting(null) + return + } + + setOpenedComment(null) + setCommenting(range) + }} + overflow="scroll" + class="select-text" + /> + + {(comment) => ( + { + const p = path() + if (!p) return + props.file.setSelectedLines(p, comment.selection) + }} + onClick={() => { + const p = path() + if (!p) return + setCommenting(null) + setOpenedComment((current) => (current === comment.id ? null : comment.id)) + props.file.setSelectedLines(p, comment.selection) + }} + /> + )} + + + {(range) => ( + + setDraft(value)} + onCancel={() => setCommenting(null)} + onSubmit={(value) => { + const p = path() + if (!p) return + props.addCommentToContext({ + file: p, + selection: range(), + comment: value, + origin: "file", + }) + setCommenting(null) + }} + onPopoverFocusOut={(e: FocusEvent) => { + const current = e.currentTarget as HTMLDivElement + const target = e.relatedTarget + if (target instanceof Node && current.contains(target)) return + + setTimeout(() => { + if (!document.activeElement || !current.contains(document.activeElement)) { + setCommenting(null) + } + }, 0) + }} + /> + + )} + +
+ ) + + return ( + { + scroll = el + restoreScroll() + }} + onScroll={handleScroll} + > + + +
+ {path()} requestAnimationFrame(restoreScroll)} + /> +
+
+ +
+ {renderCode(svgContent() ?? "", "")} + +
+ {path()} +
+
+
+
+ +
+ +
+
{path()?.split("/").pop()}
+
{props.language.t("session.files.binaryContent")}
+
+
+
+ {renderCode(contents(), "pb-40")} + +
{props.language.t("common.loading")}...
+
+ {(err) =>
{err()}
}
+
+
+ ) +} diff --git a/packages/app/src/pages/session/helpers.test.ts b/packages/app/src/pages/session/helpers.test.ts new file mode 100644 index 00000000000..d877d5b2e22 --- /dev/null +++ b/packages/app/src/pages/session/helpers.test.ts @@ -0,0 +1,71 @@ +import { describe, expect, test } from "bun:test" +import { combineCommandSections, createOpenReviewFile, focusTerminalById, getTabReorderIndex } from "./helpers" + +describe("createOpenReviewFile", () => { + test("opens and loads selected review file", () => { + const calls: string[] = [] + const openReviewFile = createOpenReviewFile({ + showAllFiles: () => calls.push("show"), + tabForPath: (path) => { + calls.push(`tab:${path}`) + return `file://${path}` + }, + openTab: (tab) => calls.push(`open:${tab}`), + loadFile: (path) => calls.push(`load:${path}`), + }) + + openReviewFile("src/a.ts") + + expect(calls).toEqual(["show", "tab:src/a.ts", "open:file://src/a.ts", "load:src/a.ts"]) + }) +}) + +describe("focusTerminalById", () => { + test("focuses textarea when present", () => { + document.body.innerHTML = `
` + + const focused = focusTerminalById("one") + + expect(focused).toBe(true) + expect(document.activeElement?.tagName).toBe("TEXTAREA") + }) + + test("falls back to terminal element focus", () => { + document.body.innerHTML = `
` + const terminal = document.querySelector('[data-component="terminal"]') as HTMLElement + let pointerDown = false + terminal.addEventListener("pointerdown", () => { + pointerDown = true + }) + + const focused = focusTerminalById("two") + + expect(focused).toBe(true) + expect(document.activeElement).toBe(terminal) + expect(pointerDown).toBe(true) + }) +}) + +describe("combineCommandSections", () => { + test("keeps section order stable", () => { + const result = combineCommandSections([ + [{ id: "a", title: "A" }], + [ + { id: "b", title: "B" }, + { id: "c", title: "C" }, + ], + ]) + + expect(result.map((item) => item.id)).toEqual(["a", "b", "c"]) + }) +}) + +describe("getTabReorderIndex", () => { + test("returns target index for valid drag reorder", () => { + expect(getTabReorderIndex(["a", "b", "c"], "a", "c")).toBe(2) + }) + + test("returns undefined for unknown droppable id", () => { + expect(getTabReorderIndex(["a", "b", "c"], "a", "missing")).toBeUndefined() + }) +}) diff --git a/packages/app/src/pages/session/helpers.ts b/packages/app/src/pages/session/helpers.ts new file mode 100644 index 00000000000..dcf2c878499 --- /dev/null +++ b/packages/app/src/pages/session/helpers.ts @@ -0,0 +1,45 @@ +import type { CommandOption } from "@/context/command" + +export const focusTerminalById = (id: string) => { + const wrapper = document.getElementById(`terminal-wrapper-${id}`) + const terminal = wrapper?.querySelector('[data-component="terminal"]') + if (!(terminal instanceof HTMLElement)) return false + + const textarea = terminal.querySelector("textarea") + if (textarea instanceof HTMLTextAreaElement) { + textarea.focus() + return true + } + + terminal.focus() + terminal.dispatchEvent( + typeof PointerEvent === "function" + ? new PointerEvent("pointerdown", { bubbles: true, cancelable: true }) + : new MouseEvent("pointerdown", { bubbles: true, cancelable: true }), + ) + return true +} + +export const createOpenReviewFile = (input: { + showAllFiles: () => void + tabForPath: (path: string) => string + openTab: (tab: string) => void + loadFile: (path: string) => void +}) => { + return (path: string) => { + input.showAllFiles() + input.openTab(input.tabForPath(path)) + input.loadFile(path) + } +} + +export const combineCommandSections = (sections: readonly (readonly CommandOption[])[]) => { + return sections.flatMap((section) => section) +} + +export const getTabReorderIndex = (tabs: readonly string[], from: string, to: string) => { + const fromIndex = tabs.indexOf(from) + const toIndex = tabs.indexOf(to) + if (fromIndex === -1 || toIndex === -1 || fromIndex === toIndex) return undefined + return toIndex +} diff --git a/packages/app/src/pages/session/message-gesture.test.ts b/packages/app/src/pages/session/message-gesture.test.ts new file mode 100644 index 00000000000..b2af4bb8342 --- /dev/null +++ b/packages/app/src/pages/session/message-gesture.test.ts @@ -0,0 +1,62 @@ +import { describe, expect, test } from "bun:test" +import { normalizeWheelDelta, shouldMarkBoundaryGesture } from "./message-gesture" + +describe("normalizeWheelDelta", () => { + test("converts line mode to px", () => { + expect(normalizeWheelDelta({ deltaY: 3, deltaMode: 1, rootHeight: 500 })).toBe(120) + }) + + test("converts page mode to container height", () => { + expect(normalizeWheelDelta({ deltaY: -1, deltaMode: 2, rootHeight: 600 })).toBe(-600) + }) + + test("keeps pixel mode unchanged", () => { + expect(normalizeWheelDelta({ deltaY: 16, deltaMode: 0, rootHeight: 600 })).toBe(16) + }) +}) + +describe("shouldMarkBoundaryGesture", () => { + test("marks when nested scroller cannot scroll", () => { + expect( + shouldMarkBoundaryGesture({ + delta: 20, + scrollTop: 0, + scrollHeight: 300, + clientHeight: 300, + }), + ).toBe(true) + }) + + test("marks when scrolling beyond top boundary", () => { + expect( + shouldMarkBoundaryGesture({ + delta: -40, + scrollTop: 10, + scrollHeight: 1000, + clientHeight: 400, + }), + ).toBe(true) + }) + + test("marks when scrolling beyond bottom boundary", () => { + expect( + shouldMarkBoundaryGesture({ + delta: 50, + scrollTop: 580, + scrollHeight: 1000, + clientHeight: 400, + }), + ).toBe(true) + }) + + test("does not mark when nested scroller can consume movement", () => { + expect( + shouldMarkBoundaryGesture({ + delta: 20, + scrollTop: 200, + scrollHeight: 1000, + clientHeight: 400, + }), + ).toBe(false) + }) +}) diff --git a/packages/app/src/pages/session/message-gesture.ts b/packages/app/src/pages/session/message-gesture.ts new file mode 100644 index 00000000000..731cb1bdeb6 --- /dev/null +++ b/packages/app/src/pages/session/message-gesture.ts @@ -0,0 +1,21 @@ +export const normalizeWheelDelta = (input: { deltaY: number; deltaMode: number; rootHeight: number }) => { + if (input.deltaMode === 1) return input.deltaY * 40 + if (input.deltaMode === 2) return input.deltaY * input.rootHeight + return input.deltaY +} + +export const shouldMarkBoundaryGesture = (input: { + delta: number + scrollTop: number + scrollHeight: number + clientHeight: number +}) => { + const max = input.scrollHeight - input.clientHeight + if (max <= 1) return true + if (!input.delta) return false + + if (input.delta < 0) return input.scrollTop + input.delta <= 0 + + const remaining = max - input.scrollTop + return input.delta > remaining +} diff --git a/packages/app/src/pages/session/message-timeline.tsx b/packages/app/src/pages/session/message-timeline.tsx new file mode 100644 index 00000000000..a4ca06dd5b2 --- /dev/null +++ b/packages/app/src/pages/session/message-timeline.tsx @@ -0,0 +1,348 @@ +import { For, onCleanup, onMount, Show, type JSX } from "solid-js" +import { Button } from "@opencode-ai/ui/button" +import { Icon } from "@opencode-ai/ui/icon" +import { IconButton } from "@opencode-ai/ui/icon-button" +import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu" +import { InlineInput } from "@opencode-ai/ui/inline-input" +import { Tooltip } from "@opencode-ai/ui/tooltip" +import { SessionTurn } from "@opencode-ai/ui/session-turn" +import type { UserMessage } from "@opencode-ai/sdk/v2" +import { shouldMarkBoundaryGesture, normalizeWheelDelta } from "@/pages/session/message-gesture" + +export function MessageTimeline(props: { + mobileChanges: boolean + mobileFallback: JSX.Element + scroll: { overflow: boolean; bottom: boolean } + onResumeScroll: () => void + setScrollRef: (el: HTMLDivElement | undefined) => void + onScheduleScrollState: (el: HTMLDivElement) => void + onAutoScrollHandleScroll: () => void + onMarkScrollGesture: (target?: EventTarget | null) => void + hasScrollGesture: () => boolean + isDesktop: boolean + onScrollSpyScroll: () => void + onAutoScrollInteraction: (event: MouseEvent) => void + showHeader: boolean + centered: boolean + title?: string + parentID?: string + openTitleEditor: () => void + closeTitleEditor: () => void + saveTitleEditor: () => void | Promise + titleRef: (el: HTMLInputElement) => void + titleState: { + draft: string + editing: boolean + saving: boolean + menuOpen: boolean + pendingRename: boolean + } + onTitleDraft: (value: string) => void + onTitleMenuOpen: (open: boolean) => void + onTitlePendingRename: (value: boolean) => void + onNavigateParent: () => void + sessionID: string + onArchiveSession: (sessionID: string) => void + onDeleteSession: (sessionID: string) => void + t: (key: string, vars?: Record) => string + setContentRef: (el: HTMLDivElement) => void + turnStart: number + onRenderEarlier: () => void + historyMore: boolean + historyLoading: boolean + onLoadEarlier: () => void + renderedUserMessages: UserMessage[] + anchor: (id: string) => string + onRegisterMessage: (el: HTMLDivElement, id: string) => void + onUnregisterMessage: (id: string) => void + onFirstTurnMount?: () => void + lastUserMessageID?: string + expanded: Record + onToggleExpanded: (id: string) => void +}) { + let touchGesture: number | undefined + + return ( + {props.mobileFallback}
} + > +
+
+ +
+
{ + const root = e.currentTarget + const target = e.target instanceof Element ? e.target : undefined + const nested = target?.closest("[data-scrollable]") + if (!nested || nested === root) { + props.onMarkScrollGesture(root) + return + } + + if (!(nested instanceof HTMLElement)) { + props.onMarkScrollGesture(root) + return + } + + const delta = normalizeWheelDelta({ + deltaY: e.deltaY, + deltaMode: e.deltaMode, + rootHeight: root.clientHeight, + }) + if (!delta) return + + if ( + shouldMarkBoundaryGesture({ + delta, + scrollTop: nested.scrollTop, + scrollHeight: nested.scrollHeight, + clientHeight: nested.clientHeight, + }) + ) { + props.onMarkScrollGesture(root) + } + }} + onTouchStart={(e) => { + touchGesture = e.touches[0]?.clientY + }} + onTouchMove={(e) => { + const next = e.touches[0]?.clientY + const prev = touchGesture + touchGesture = next + if (next === undefined || prev === undefined) return + + const delta = prev - next + if (!delta) return + + const root = e.currentTarget + const target = e.target instanceof Element ? e.target : undefined + const nested = target?.closest("[data-scrollable]") + if (!nested || nested === root) { + props.onMarkScrollGesture(root) + return + } + + if (!(nested instanceof HTMLElement)) { + props.onMarkScrollGesture(root) + return + } + + if ( + shouldMarkBoundaryGesture({ + delta, + scrollTop: nested.scrollTop, + scrollHeight: nested.scrollHeight, + clientHeight: nested.clientHeight, + }) + ) { + props.onMarkScrollGesture(root) + } + }} + onTouchEnd={() => { + touchGesture = undefined + }} + onTouchCancel={() => { + touchGesture = undefined + }} + onPointerDown={(e) => { + if (e.target !== e.currentTarget) return + props.onMarkScrollGesture(e.currentTarget) + }} + onScroll={(e) => { + props.onScheduleScrollState(e.currentTarget) + if (!props.hasScrollGesture()) return + props.onAutoScrollHandleScroll() + props.onMarkScrollGesture(e.currentTarget) + if (props.isDesktop) props.onScrollSpyScroll() + }} + onClick={props.onAutoScrollInteraction} + class="relative min-w-0 w-full h-full overflow-y-auto session-scroller" + style={{ "--session-title-height": props.showHeader ? "40px" : "0px" }} + > + +
+
+
+ + + + + + {props.title} + + } + > + props.onTitleDraft(event.currentTarget.value)} + onKeyDown={(event) => { + event.stopPropagation() + if (event.key === "Enter") { + event.preventDefault() + void props.saveTitleEditor() + return + } + if (event.key === "Escape") { + event.preventDefault() + props.closeTitleEditor() + } + }} + onBlur={props.closeTitleEditor} + /> + + +
+ + {(id) => ( +
+ + + + + + { + if (!props.titleState.pendingRename) return + event.preventDefault() + props.onTitlePendingRename(false) + props.openTitleEditor() + }} + > + { + props.onTitlePendingRename(true) + props.onTitleMenuOpen(false) + }} + > + {props.t("common.rename")} + + props.onArchiveSession(id())}> + {props.t("common.archive")} + + + props.onDeleteSession(id())}> + {props.t("common.delete")} + + + + +
+ )} +
+
+
+
+ +
+ 0}> +
+ +
+
+ +
+ +
+
+ + {(message) => { + if (import.meta.env.DEV && props.onFirstTurnMount) { + onMount(() => props.onFirstTurnMount?.()) + } + + return ( +
{ + props.onRegisterMessage(el, message.id) + onCleanup(() => props.onUnregisterMessage(message.id)) + }} + classList={{ + "min-w-0 w-full max-w-full": true, + "md:max-w-200 2xl:max-w-[1000px]": props.centered, + }} + > + props.onToggleExpanded(message.id)} + classes={{ + root: "min-w-0 w-full relative", + content: "flex flex-col justify-between !overflow-visible", + container: "w-full px-4 md:px-6", + }} + /> +
+ ) + }} +
+
+
+
+ + ) +} diff --git a/packages/app/src/pages/session/review-tab.tsx b/packages/app/src/pages/session/review-tab.tsx new file mode 100644 index 00000000000..a4232dd74e3 --- /dev/null +++ b/packages/app/src/pages/session/review-tab.tsx @@ -0,0 +1,158 @@ +import { createEffect, on, onCleanup, createSignal, type JSX } from "solid-js" +import type { FileDiff } from "@opencode-ai/sdk/v2" +import { SessionReview } from "@opencode-ai/ui/session-review" +import type { SelectedLineRange } from "@/context/file" +import { useSDK } from "@/context/sdk" +import { useLayout } from "@/context/layout" +import type { LineComment } from "@/context/comments" + +export type DiffStyle = "unified" | "split" + +export interface SessionReviewTabProps { + title?: JSX.Element + empty?: JSX.Element + diffs: () => FileDiff[] + view: () => ReturnType["view"]> + diffStyle: DiffStyle + onDiffStyleChange?: (style: DiffStyle) => void + onViewFile?: (file: string) => void + onLineComment?: (comment: { file: string; selection: SelectedLineRange; comment: string; preview?: string }) => void + comments?: LineComment[] + focusedComment?: { file: string; id: string } | null + onFocusedCommentChange?: (focus: { file: string; id: string } | null) => void + focusedFile?: string + onScrollRef?: (el: HTMLDivElement) => void + classes?: { + root?: string + header?: string + container?: string + } +} + +export function StickyAddButton(props: { children: JSX.Element }) { + const [stuck, setStuck] = createSignal(false) + let button: HTMLDivElement | undefined + + createEffect(() => { + const node = button + if (!node) return + + const scroll = node.parentElement + if (!scroll) return + + const handler = () => { + const rect = node.getBoundingClientRect() + const scrollRect = scroll.getBoundingClientRect() + setStuck(rect.right >= scrollRect.right && scroll.scrollWidth > scroll.clientWidth) + } + + scroll.addEventListener("scroll", handler, { passive: true }) + const observer = new ResizeObserver(handler) + observer.observe(scroll) + handler() + onCleanup(() => { + scroll.removeEventListener("scroll", handler) + observer.disconnect() + }) + }) + + return ( +
+ {props.children} +
+ ) +} + +export function SessionReviewTab(props: SessionReviewTabProps) { + let scroll: HTMLDivElement | undefined + let frame: number | undefined + let pending: { x: number; y: number } | undefined + + const sdk = useSDK() + + const readFile = async (path: string) => { + return sdk.client.file + .read({ path }) + .then((x) => x.data) + .catch(() => undefined) + } + + const restoreScroll = () => { + const el = scroll + if (!el) return + + const s = props.view().scroll("review") + if (!s) return + + if (el.scrollTop !== s.y) el.scrollTop = s.y + if (el.scrollLeft !== s.x) el.scrollLeft = s.x + } + + const handleScroll = (event: Event & { currentTarget: HTMLDivElement }) => { + pending = { + x: event.currentTarget.scrollLeft, + y: event.currentTarget.scrollTop, + } + if (frame !== undefined) return + + frame = requestAnimationFrame(() => { + frame = undefined + + const next = pending + pending = undefined + if (!next) return + + props.view().setScroll("review", next) + }) + } + + createEffect( + on( + () => props.diffs().length, + () => { + requestAnimationFrame(restoreScroll) + }, + { defer: true }, + ), + ) + + onCleanup(() => { + if (frame === undefined) return + cancelAnimationFrame(frame) + }) + + return ( + { + scroll = el + props.onScrollRef?.(el) + restoreScroll() + }} + onScroll={handleScroll} + onDiffRendered={() => requestAnimationFrame(restoreScroll)} + open={props.view().review.open()} + onOpenChange={props.view().review.setOpen} + classes={{ + root: props.classes?.root ?? "pb-40", + header: props.classes?.header ?? "px-6", + container: props.classes?.container ?? "px-6", + }} + diffs={props.diffs()} + diffStyle={props.diffStyle} + onDiffStyleChange={props.onDiffStyleChange} + onViewFile={props.onViewFile} + focusedFile={props.focusedFile} + readFile={readFile} + onLineComment={props.onLineComment} + comments={props.comments} + focusedComment={props.focusedComment} + onFocusedCommentChange={props.onFocusedCommentChange} + /> + ) +} diff --git a/packages/app/src/pages/session/scroll-spy.test.ts b/packages/app/src/pages/session/scroll-spy.test.ts new file mode 100644 index 00000000000..f3e6775cb48 --- /dev/null +++ b/packages/app/src/pages/session/scroll-spy.test.ts @@ -0,0 +1,127 @@ +import { describe, expect, test } from "bun:test" +import { createScrollSpy, pickOffsetId, pickVisibleId } from "./scroll-spy" + +const rect = (top: number, height = 80): DOMRect => + ({ + x: 0, + y: top, + top, + left: 0, + right: 800, + bottom: top + height, + width: 800, + height, + toJSON: () => ({}), + }) as DOMRect + +const setRect = (el: Element, top: number, height = 80) => { + Object.defineProperty(el, "getBoundingClientRect", { + configurable: true, + value: () => rect(top, height), + }) +} + +describe("pickVisibleId", () => { + test("prefers higher intersection ratio", () => { + const id = pickVisibleId( + [ + { id: "a", ratio: 0.2, top: 100 }, + { id: "b", ratio: 0.8, top: 300 }, + ], + 120, + ) + + expect(id).toBe("b") + }) + + test("breaks ratio ties by nearest line", () => { + const id = pickVisibleId( + [ + { id: "a", ratio: 0.5, top: 90 }, + { id: "b", ratio: 0.5, top: 140 }, + ], + 130, + ) + + expect(id).toBe("b") + }) +}) + +describe("pickOffsetId", () => { + test("uses binary search cutoff", () => { + const id = pickOffsetId( + [ + { id: "a", top: 0 }, + { id: "b", top: 200 }, + { id: "c", top: 400 }, + ], + 350, + ) + + expect(id).toBe("b") + }) +}) + +describe("createScrollSpy fallback", () => { + test("tracks active id from offsets and dirty refresh", () => { + const active: string[] = [] + const root = document.createElement("div") as HTMLDivElement + const one = document.createElement("div") + const two = document.createElement("div") + const three = document.createElement("div") + + root.append(one, two, three) + document.body.append(root) + + Object.defineProperty(root, "scrollTop", { configurable: true, writable: true, value: 250 }) + setRect(root, 0, 800) + setRect(one, -250) + setRect(two, -50) + setRect(three, 150) + + const queue: FrameRequestCallback[] = [] + const flush = () => { + const run = [...queue] + queue.length = 0 + for (const cb of run) cb(0) + } + + const spy = createScrollSpy({ + onActive: (id) => active.push(id), + raf: (cb) => (queue.push(cb), queue.length), + caf: () => {}, + IntersectionObserver: undefined, + ResizeObserver: undefined, + MutationObserver: undefined, + }) + + spy.setContainer(root) + spy.register(one, "a") + spy.register(two, "b") + spy.register(three, "c") + spy.onScroll() + flush() + + expect(spy.getActiveId()).toBe("b") + expect(active.at(-1)).toBe("b") + + root.scrollTop = 450 + setRect(one, -450) + setRect(two, -250) + setRect(three, -50) + spy.onScroll() + flush() + expect(spy.getActiveId()).toBe("c") + + root.scrollTop = 250 + setRect(one, -250) + setRect(two, 250) + setRect(three, 150) + spy.markDirty() + spy.onScroll() + flush() + expect(spy.getActiveId()).toBe("a") + + spy.destroy() + }) +}) diff --git a/packages/app/src/pages/session/scroll-spy.ts b/packages/app/src/pages/session/scroll-spy.ts new file mode 100644 index 00000000000..6ef4c844c41 --- /dev/null +++ b/packages/app/src/pages/session/scroll-spy.ts @@ -0,0 +1,275 @@ +type Visible = { + id: string + ratio: number + top: number +} + +type Offset = { + id: string + top: number +} + +type Input = { + onActive: (id: string) => void + raf?: (cb: FrameRequestCallback) => number + caf?: (id: number) => void + IntersectionObserver?: typeof globalThis.IntersectionObserver + ResizeObserver?: typeof globalThis.ResizeObserver + MutationObserver?: typeof globalThis.MutationObserver +} + +export const pickVisibleId = (list: Visible[], line: number) => { + if (list.length === 0) return + + const sorted = [...list].sort((a, b) => { + if (b.ratio !== a.ratio) return b.ratio - a.ratio + + const da = Math.abs(a.top - line) + const db = Math.abs(b.top - line) + if (da !== db) return da - db + + return a.top - b.top + }) + + return sorted[0]?.id +} + +export const pickOffsetId = (list: Offset[], cutoff: number) => { + if (list.length === 0) return + + let lo = 0 + let hi = list.length - 1 + let out = 0 + + while (lo <= hi) { + const mid = (lo + hi) >> 1 + const top = list[mid]?.top + if (top === undefined) break + + if (top <= cutoff) { + out = mid + lo = mid + 1 + continue + } + + hi = mid - 1 + } + + return list[out]?.id +} + +export const createScrollSpy = (input: Input) => { + const raf = input.raf ?? requestAnimationFrame + const caf = input.caf ?? cancelAnimationFrame + const CtorIO = input.IntersectionObserver ?? globalThis.IntersectionObserver + const CtorRO = input.ResizeObserver ?? globalThis.ResizeObserver + const CtorMO = input.MutationObserver ?? globalThis.MutationObserver + + let root: HTMLDivElement | undefined + let io: IntersectionObserver | undefined + let ro: ResizeObserver | undefined + let mo: MutationObserver | undefined + let frame: number | undefined + let active: string | undefined + let dirty = true + + const node = new Map() + const id = new WeakMap() + const visible = new Map() + let offset: Offset[] = [] + + const schedule = () => { + if (frame !== undefined) return + frame = raf(() => { + frame = undefined + update() + }) + } + + const refreshOffset = () => { + const el = root + if (!el) { + offset = [] + dirty = false + return + } + + const base = el.getBoundingClientRect().top + offset = [...node].map(([next, item]) => ({ + id: next, + top: item.getBoundingClientRect().top - base + el.scrollTop, + })) + offset.sort((a, b) => a.top - b.top) + dirty = false + } + + const update = () => { + const el = root + if (!el) return + + const line = el.getBoundingClientRect().top + 100 + const next = + pickVisibleId( + [...visible].map(([k, v]) => ({ + id: k, + ratio: v.ratio, + top: v.top, + })), + line, + ) ?? + (() => { + if (dirty) refreshOffset() + return pickOffsetId(offset, el.scrollTop + 100) + })() + + if (!next || next === active) return + active = next + input.onActive(next) + } + + const observe = () => { + const el = root + if (!el) return + + io?.disconnect() + io = undefined + if (CtorIO) { + try { + io = new CtorIO( + (entries) => { + for (const entry of entries) { + const item = entry.target + if (!(item instanceof HTMLElement)) continue + const key = id.get(item) + if (!key) continue + + if (!entry.isIntersecting || entry.intersectionRatio <= 0) { + visible.delete(key) + continue + } + + visible.set(key, { + ratio: entry.intersectionRatio, + top: entry.boundingClientRect.top, + }) + } + + schedule() + }, + { + root: el, + threshold: [0, 0.25, 0.5, 0.75, 1], + }, + ) + } catch { + io = undefined + } + } + + if (io) { + for (const item of node.values()) io.observe(item) + } + + ro?.disconnect() + ro = undefined + if (CtorRO) { + ro = new CtorRO(() => { + dirty = true + schedule() + }) + ro.observe(el) + for (const item of node.values()) ro.observe(item) + } + + mo?.disconnect() + mo = undefined + if (CtorMO) { + mo = new CtorMO(() => { + dirty = true + schedule() + }) + mo.observe(el, { subtree: true, childList: true, characterData: true }) + } + + dirty = true + schedule() + } + + const setContainer = (el?: HTMLDivElement) => { + if (root === el) return + + root = el + visible.clear() + active = undefined + observe() + } + + const register = (el: HTMLElement, key: string) => { + const prev = node.get(key) + if (prev && prev !== el) { + io?.unobserve(prev) + ro?.unobserve(prev) + } + + node.set(key, el) + id.set(el, key) + if (io) io.observe(el) + if (ro) ro.observe(el) + dirty = true + schedule() + } + + const unregister = (key: string) => { + const item = node.get(key) + if (!item) return + + io?.unobserve(item) + ro?.unobserve(item) + node.delete(key) + visible.delete(key) + dirty = true + schedule() + } + + const markDirty = () => { + dirty = true + schedule() + } + + const clear = () => { + for (const item of node.values()) { + io?.unobserve(item) + ro?.unobserve(item) + } + + node.clear() + visible.clear() + offset = [] + active = undefined + dirty = true + } + + const destroy = () => { + if (frame !== undefined) caf(frame) + frame = undefined + clear() + io?.disconnect() + ro?.disconnect() + mo?.disconnect() + io = undefined + ro = undefined + mo = undefined + root = undefined + } + + return { + setContainer, + register, + unregister, + onScroll: schedule, + markDirty, + clear, + destroy, + getActiveId: () => active, + } +} diff --git a/packages/app/src/pages/session/session-command-helpers.ts b/packages/app/src/pages/session/session-command-helpers.ts new file mode 100644 index 00000000000..b71a7b76883 --- /dev/null +++ b/packages/app/src/pages/session/session-command-helpers.ts @@ -0,0 +1,10 @@ +export const canAddSelectionContext = (input: { + active?: string + pathFromTab: (tab: string) => string | undefined + selectedLines: (path: string) => unknown +}) => { + if (!input.active) return false + const path = input.pathFromTab(input.active) + if (!path) return false + return input.selectedLines(path) != null +} diff --git a/packages/app/src/pages/session/session-mobile-tabs.tsx b/packages/app/src/pages/session/session-mobile-tabs.tsx new file mode 100644 index 00000000000..41f05823166 --- /dev/null +++ b/packages/app/src/pages/session/session-mobile-tabs.tsx @@ -0,0 +1,36 @@ +import { Match, Show, Switch } from "solid-js" +import { Tabs } from "@opencode-ai/ui/tabs" + +export function SessionMobileTabs(props: { + open: boolean + hasReview: boolean + reviewCount: number + onSession: () => void + onChanges: () => void + t: (key: string, vars?: Record) => string +}) { + return ( + + + + + {props.t("session.tab.session")} + + + + + {props.t("session.review.filesChanged", { count: props.reviewCount })} + + {props.t("session.review.change.other")} + + + + + + ) +} diff --git a/packages/app/src/pages/session/session-prompt-dock.test.ts b/packages/app/src/pages/session/session-prompt-dock.test.ts new file mode 100644 index 00000000000..b3a9945d66c --- /dev/null +++ b/packages/app/src/pages/session/session-prompt-dock.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, test } from "bun:test" +import { questionSubtitle } from "./session-prompt-helpers" + +describe("questionSubtitle", () => { + const t = (key: string) => { + if (key === "ui.common.question.one") return "question" + if (key === "ui.common.question.other") return "questions" + return key + } + + test("returns empty for zero", () => { + expect(questionSubtitle(0, t)).toBe("") + }) + + test("uses singular label", () => { + expect(questionSubtitle(1, t)).toBe("1 question") + }) + + test("uses plural label", () => { + expect(questionSubtitle(3, t)).toBe("3 questions") + }) +}) diff --git a/packages/app/src/pages/session/session-prompt-dock.tsx b/packages/app/src/pages/session/session-prompt-dock.tsx new file mode 100644 index 00000000000..eaf0564b230 --- /dev/null +++ b/packages/app/src/pages/session/session-prompt-dock.tsx @@ -0,0 +1,137 @@ +import { For, Show, type ComponentProps } from "solid-js" +import { Button } from "@opencode-ai/ui/button" +import { BasicTool } from "@opencode-ai/ui/basic-tool" +import { PromptInput } from "@/components/prompt-input" +import { QuestionDock } from "@/components/question-dock" +import { questionSubtitle } from "@/pages/session/session-prompt-helpers" + +const questionDockRequest = (value: unknown) => value as ComponentProps["request"] + +export function SessionPromptDock(props: { + centered: boolean + questionRequest: () => { questions: unknown[] } | undefined + permissionRequest: () => { patterns: string[]; permission: string } | undefined + blocked: boolean + promptReady: boolean + handoffPrompt?: string + t: (key: string, vars?: Record) => string + responding: boolean + onDecide: (response: "once" | "always" | "reject") => void + inputRef: (el: HTMLDivElement) => void + newSessionWorktree: string + onNewSessionWorktreeReset: () => void + onSubmit: () => void + setPromptDockRef: (el: HTMLDivElement) => void +}) { + return ( +
+
+ + {(req) => { + const subtitle = questionSubtitle(req.questions.length, (key) => props.t(key)) + return ( +
+ + +
+ ) + }} +
+ + + {(perm) => ( +
+ + 0}> +
+ + {(pattern) => {pattern}} + +
+
+ +
+ {props.t("settings.permissions.tool.doom_loop.description")} +
+
+
+
+
+ + + +
+
+
+ )} +
+ + + + {props.handoffPrompt || props.t("prompt.loading")} +
+ } + > + + + +
+
+ ) +} diff --git a/packages/app/src/pages/session/session-prompt-helpers.ts b/packages/app/src/pages/session/session-prompt-helpers.ts new file mode 100644 index 00000000000..ac3234c939a --- /dev/null +++ b/packages/app/src/pages/session/session-prompt-helpers.ts @@ -0,0 +1,4 @@ +export const questionSubtitle = (count: number, t: (key: string) => string) => { + if (count === 0) return "" + return `${count} ${t(count > 1 ? "ui.common.question.other" : "ui.common.question.one")}` +} diff --git a/packages/app/src/pages/session/session-side-panel.tsx b/packages/app/src/pages/session/session-side-panel.tsx new file mode 100644 index 00000000000..d9460cc1a76 --- /dev/null +++ b/packages/app/src/pages/session/session-side-panel.tsx @@ -0,0 +1,319 @@ +import { For, Match, Show, Switch, createMemo, onCleanup, type JSX, type ValidComponent } from "solid-js" +import { Tabs } from "@opencode-ai/ui/tabs" +import { IconButton } from "@opencode-ai/ui/icon-button" +import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip" +import { ResizeHandle } from "@opencode-ai/ui/resize-handle" +import { Mark } from "@opencode-ai/ui/logo" +import FileTree from "@/components/file-tree" +import { SessionContextUsage } from "@/components/session-context-usage" +import { SessionContextTab, SortableTab, FileVisual } from "@/components/session" +import { DialogSelectFile } from "@/components/dialog-select-file" +import { createFileTabListSync } from "@/pages/session/file-tab-scroll" +import { FileTabContent } from "@/pages/session/file-tabs" +import { StickyAddButton } from "@/pages/session/review-tab" +import { DragDropProvider, DragDropSensors, DragOverlay, SortableProvider, closestCenter } from "@thisbeyond/solid-dnd" +import { ConstrainDragYAxis } from "@/utils/solid-dnd" +import type { DragEvent } from "@thisbeyond/solid-dnd" +import { useComments } from "@/context/comments" +import { useCommand } from "@/context/command" +import { useDialog } from "@opencode-ai/ui/context/dialog" +import { useFile, type SelectedLineRange } from "@/context/file" +import { useLanguage } from "@/context/language" +import { useLayout } from "@/context/layout" +import { useSync } from "@/context/sync" + +export function SessionSidePanel(props: { + open: boolean + reviewOpen: boolean + language: ReturnType + layout: ReturnType + command: ReturnType + dialog: ReturnType + file: ReturnType + comments: ReturnType + sync: ReturnType + hasReview: boolean + reviewCount: number + reviewTab: boolean + contextOpen: () => boolean + openedTabs: () => string[] + activeTab: () => string + activeFileTab: () => string | undefined + tabs: () => ReturnType["tabs"]> + openTab: (value: string) => void + showAllFiles: () => void + reviewPanel: () => JSX.Element + messages: () => unknown[] + visibleUserMessages: () => unknown[] + view: () => ReturnType["view"]> + info: () => unknown + handoffFiles: () => Record | undefined + codeComponent: NonNullable + addCommentToContext: (input: { + file: string + selection: SelectedLineRange + comment: string + preview?: string + origin?: "review" | "file" + }) => void + activeDraggable: () => string | undefined + onDragStart: (event: unknown) => void + onDragEnd: () => void + onDragOver: (event: DragEvent) => void + fileTreeTab: () => "changes" | "all" + setFileTreeTabValue: (value: string) => void + diffsReady: boolean + diffFiles: string[] + kinds: Map + activeDiff?: string + focusReviewDiff: (path: string) => void +}) { + return ( + +
+ + + + ) +} diff --git a/packages/app/src/pages/session/terminal-label.ts b/packages/app/src/pages/session/terminal-label.ts new file mode 100644 index 00000000000..6d336769b10 --- /dev/null +++ b/packages/app/src/pages/session/terminal-label.ts @@ -0,0 +1,16 @@ +export const terminalTabLabel = (input: { + title?: string + titleNumber?: number + t: (key: string, vars?: Record) => string +}) => { + const title = input.title ?? "" + const number = input.titleNumber ?? 0 + const match = title.match(/^Terminal (\d+)$/) + const parsed = match ? Number(match[1]) : undefined + const isDefaultTitle = Number.isFinite(number) && number > 0 && Number.isFinite(parsed) && parsed === number + + if (title && !isDefaultTitle) return title + if (number > 0) return input.t("terminal.title.numbered", { number }) + if (title) return title + return input.t("terminal.title") +} diff --git a/packages/app/src/pages/session/terminal-panel.test.ts b/packages/app/src/pages/session/terminal-panel.test.ts new file mode 100644 index 00000000000..43eeec32f21 --- /dev/null +++ b/packages/app/src/pages/session/terminal-panel.test.ts @@ -0,0 +1,25 @@ +import { describe, expect, test } from "bun:test" +import { terminalTabLabel } from "./terminal-label" + +const t = (key: string, vars?: Record) => { + if (key === "terminal.title.numbered") return `Terminal ${vars?.number}` + if (key === "terminal.title") return "Terminal" + return key +} + +describe("terminalTabLabel", () => { + test("returns custom title unchanged", () => { + const label = terminalTabLabel({ title: "server", titleNumber: 3, t }) + expect(label).toBe("server") + }) + + test("normalizes default numbered title", () => { + const label = terminalTabLabel({ title: "Terminal 2", titleNumber: 2, t }) + expect(label).toBe("Terminal 2") + }) + + test("falls back to generic title", () => { + const label = terminalTabLabel({ title: "", titleNumber: 0, t }) + expect(label).toBe("Terminal") + }) +}) diff --git a/packages/app/src/pages/session/terminal-panel.tsx b/packages/app/src/pages/session/terminal-panel.tsx new file mode 100644 index 00000000000..2e65fde0e32 --- /dev/null +++ b/packages/app/src/pages/session/terminal-panel.tsx @@ -0,0 +1,169 @@ +import { createMemo, For, Show } from "solid-js" +import { Tabs } from "@opencode-ai/ui/tabs" +import { ResizeHandle } from "@opencode-ai/ui/resize-handle" +import { IconButton } from "@opencode-ai/ui/icon-button" +import { TooltipKeybind } from "@opencode-ai/ui/tooltip" +import { DragDropProvider, DragDropSensors, DragOverlay, SortableProvider, closestCenter } from "@thisbeyond/solid-dnd" +import type { DragEvent } from "@thisbeyond/solid-dnd" +import { ConstrainDragYAxis } from "@/utils/solid-dnd" +import { SortableTerminalTab } from "@/components/session" +import { Terminal } from "@/components/terminal" +import { useTerminal, type LocalPTY } from "@/context/terminal" +import { useLanguage } from "@/context/language" +import { useCommand } from "@/context/command" +import { terminalTabLabel } from "@/pages/session/terminal-label" + +export function TerminalPanel(props: { + open: boolean + height: number + resize: (value: number) => void + close: () => void + terminal: ReturnType + language: ReturnType + command: ReturnType + handoff: () => string[] + activeTerminalDraggable: () => string | undefined + handleTerminalDragStart: (event: unknown) => void + handleTerminalDragOver: (event: DragEvent) => void + handleTerminalDragEnd: () => void + onCloseTab: () => void +}) { + return ( + +
+ + +
+ + {(title) => ( +
+ {title} +
+ )} +
+
+
+ {props.language.t("common.loading")} + {props.language.t("common.loading.ellipsis")} +
+
+
+ {props.language.t("terminal.loading")} +
+
+ } + > + + + +
+ props.terminal.open(id)} + class="!h-auto !flex-none" + > + + t.id)}> + + {(pty) => ( + { + props.close() + props.onCloseTab() + }} + /> + )} + + +
+ + + +
+
+
+
+ + {(pty) => ( +
+ + props.terminal.clone(pty.id)} + /> + +
+ )} +
+
+
+ + + {(draggedId) => { + const pty = createMemo(() => props.terminal.all().find((t: LocalPTY) => t.id === draggedId())) + return ( + + {(t) => ( +
+ {terminalTabLabel({ + title: t().title, + titleNumber: t().titleNumber, + t: props.language.t as ( + key: string, + vars?: Record, + ) => string, + })} +
+ )} +
+ ) + }} +
+
+
+
+
+
+ ) +} diff --git a/packages/app/src/pages/session/use-session-commands.test.ts b/packages/app/src/pages/session/use-session-commands.test.ts new file mode 100644 index 00000000000..ada1871e1c0 --- /dev/null +++ b/packages/app/src/pages/session/use-session-commands.test.ts @@ -0,0 +1,44 @@ +import { describe, expect, test } from "bun:test" +import { canAddSelectionContext } from "./session-command-helpers" + +describe("canAddSelectionContext", () => { + test("returns false without active tab", () => { + expect( + canAddSelectionContext({ + active: undefined, + pathFromTab: () => "src/a.ts", + selectedLines: () => ({ start: 1, end: 1 }), + }), + ).toBe(false) + }) + + test("returns false when active tab is not a file", () => { + expect( + canAddSelectionContext({ + active: "context", + pathFromTab: () => undefined, + selectedLines: () => ({ start: 1, end: 1 }), + }), + ).toBe(false) + }) + + test("returns false without selected lines", () => { + expect( + canAddSelectionContext({ + active: "file://src/a.ts", + pathFromTab: () => "src/a.ts", + selectedLines: () => null, + }), + ).toBe(false) + }) + + test("returns true when file and selection exist", () => { + expect( + canAddSelectionContext({ + active: "file://src/a.ts", + pathFromTab: () => "src/a.ts", + selectedLines: () => ({ start: 1, end: 2 }), + }), + ).toBe(true) + }) +}) diff --git a/packages/app/src/pages/session/use-session-commands.tsx b/packages/app/src/pages/session/use-session-commands.tsx new file mode 100644 index 00000000000..d52022d73a6 --- /dev/null +++ b/packages/app/src/pages/session/use-session-commands.tsx @@ -0,0 +1,488 @@ +import { createMemo } from "solid-js" +import { useNavigate, useParams } from "@solidjs/router" +import { useCommand } from "@/context/command" +import { useDialog } from "@opencode-ai/ui/context/dialog" +import { useFile, selectionFromLines, type FileSelection } from "@/context/file" +import { useLanguage } from "@/context/language" +import { useLayout } from "@/context/layout" +import { useLocal } from "@/context/local" +import { usePermission } from "@/context/permission" +import { usePrompt } from "@/context/prompt" +import { useSDK } from "@/context/sdk" +import { useSync } from "@/context/sync" +import { useTerminal } from "@/context/terminal" +import { DialogSelectFile } from "@/components/dialog-select-file" +import { DialogSelectModel } from "@/components/dialog-select-model" +import { DialogSelectMcp } from "@/components/dialog-select-mcp" +import { DialogFork } from "@/components/dialog-fork" +import { showToast } from "@opencode-ai/ui/toast" +import { findLast } from "@opencode-ai/util/array" +import { extractPromptFromParts } from "@/utils/prompt" +import { UserMessage } from "@opencode-ai/sdk/v2" +import { combineCommandSections } from "@/pages/session/helpers" +import { canAddSelectionContext } from "@/pages/session/session-command-helpers" + +export const useSessionCommands = (input: { + command: ReturnType + dialog: ReturnType + file: ReturnType + language: ReturnType + local: ReturnType + permission: ReturnType + prompt: ReturnType + sdk: ReturnType + sync: ReturnType + terminal: ReturnType + layout: ReturnType + params: ReturnType + navigate: ReturnType + tabs: () => ReturnType["tabs"]> + view: () => ReturnType["view"]> + info: () => { revert?: { messageID?: string }; share?: { url?: string } } | undefined + status: () => { type: string } + userMessages: () => UserMessage[] + visibleUserMessages: () => UserMessage[] + activeMessage: () => UserMessage | undefined + showAllFiles: () => void + navigateMessageByOffset: (offset: number) => void + setExpanded: (id: string, fn: (open: boolean | undefined) => boolean) => void + setActiveMessage: (message: UserMessage | undefined) => void + addSelectionToContext: (path: string, selection: FileSelection) => void + focusInput: () => void +}) => { + const sessionCommands = createMemo(() => [ + { + id: "session.new", + title: input.language.t("command.session.new"), + category: input.language.t("command.category.session"), + keybind: "mod+shift+s", + slash: "new", + onSelect: () => input.navigate(`/${input.params.dir}/session`), + }, + ]) + + const fileCommands = createMemo(() => [ + { + id: "file.open", + title: input.language.t("command.file.open"), + description: input.language.t("palette.search.placeholder"), + category: input.language.t("command.category.file"), + keybind: "mod+p", + slash: "open", + onSelect: () => input.dialog.show(() => ), + }, + { + id: "tab.close", + title: input.language.t("command.tab.close"), + category: input.language.t("command.category.file"), + keybind: "mod+w", + disabled: !input.tabs().active(), + onSelect: () => { + const active = input.tabs().active() + if (!active) return + input.tabs().close(active) + }, + }, + ]) + + const contextCommands = createMemo(() => [ + { + id: "context.addSelection", + title: input.language.t("command.context.addSelection"), + description: input.language.t("command.context.addSelection.description"), + category: input.language.t("command.category.context"), + keybind: "mod+shift+l", + disabled: !canAddSelectionContext({ + active: input.tabs().active(), + pathFromTab: input.file.pathFromTab, + selectedLines: input.file.selectedLines, + }), + onSelect: () => { + const active = input.tabs().active() + if (!active) return + const path = input.file.pathFromTab(active) + if (!path) return + + const range = input.file.selectedLines(path) + if (!range) { + showToast({ + title: input.language.t("toast.context.noLineSelection.title"), + description: input.language.t("toast.context.noLineSelection.description"), + }) + return + } + + input.addSelectionToContext(path, selectionFromLines(range)) + }, + }, + ]) + + const viewCommands = createMemo(() => [ + { + id: "terminal.toggle", + title: input.language.t("command.terminal.toggle"), + description: "", + category: input.language.t("command.category.view"), + keybind: "ctrl+`", + slash: "terminal", + onSelect: () => input.view().terminal.toggle(), + }, + { + id: "review.toggle", + title: input.language.t("command.review.toggle"), + description: "", + category: input.language.t("command.category.view"), + keybind: "mod+shift+r", + onSelect: () => input.view().reviewPanel.toggle(), + }, + { + id: "fileTree.toggle", + title: input.language.t("command.fileTree.toggle"), + description: "", + category: input.language.t("command.category.view"), + keybind: "mod+\\", + onSelect: () => input.layout.fileTree.toggle(), + }, + { + id: "input.focus", + title: input.language.t("command.input.focus"), + category: input.language.t("command.category.view"), + keybind: "ctrl+l", + onSelect: () => input.focusInput(), + }, + { + id: "terminal.new", + title: input.language.t("command.terminal.new"), + description: input.language.t("command.terminal.new.description"), + category: input.language.t("command.category.terminal"), + keybind: "ctrl+alt+t", + onSelect: () => { + if (input.terminal.all().length > 0) input.terminal.new() + input.view().terminal.open() + }, + }, + { + id: "steps.toggle", + title: input.language.t("command.steps.toggle"), + description: input.language.t("command.steps.toggle.description"), + category: input.language.t("command.category.view"), + keybind: "mod+e", + slash: "steps", + disabled: !input.params.id, + onSelect: () => { + const msg = input.activeMessage() + if (!msg) return + input.setExpanded(msg.id, (open: boolean | undefined) => !open) + }, + }, + ]) + + const messageCommands = createMemo(() => [ + { + id: "message.previous", + title: input.language.t("command.message.previous"), + description: input.language.t("command.message.previous.description"), + category: input.language.t("command.category.session"), + keybind: "mod+arrowup", + disabled: !input.params.id, + onSelect: () => input.navigateMessageByOffset(-1), + }, + { + id: "message.next", + title: input.language.t("command.message.next"), + description: input.language.t("command.message.next.description"), + category: input.language.t("command.category.session"), + keybind: "mod+arrowdown", + disabled: !input.params.id, + onSelect: () => input.navigateMessageByOffset(1), + }, + ]) + + const agentCommands = createMemo(() => [ + { + id: "model.choose", + title: input.language.t("command.model.choose"), + description: input.language.t("command.model.choose.description"), + category: input.language.t("command.category.model"), + keybind: "mod+'", + slash: "model", + onSelect: () => input.dialog.show(() => ), + }, + { + id: "mcp.toggle", + title: input.language.t("command.mcp.toggle"), + description: input.language.t("command.mcp.toggle.description"), + category: input.language.t("command.category.mcp"), + keybind: "mod+;", + slash: "mcp", + onSelect: () => input.dialog.show(() => ), + }, + { + id: "agent.cycle", + title: input.language.t("command.agent.cycle"), + description: input.language.t("command.agent.cycle.description"), + category: input.language.t("command.category.agent"), + keybind: "mod+.", + slash: "agent", + onSelect: () => input.local.agent.move(1), + }, + { + id: "agent.cycle.reverse", + title: input.language.t("command.agent.cycle.reverse"), + description: input.language.t("command.agent.cycle.reverse.description"), + category: input.language.t("command.category.agent"), + keybind: "shift+mod+.", + onSelect: () => input.local.agent.move(-1), + }, + { + id: "model.variant.cycle", + title: input.language.t("command.model.variant.cycle"), + description: input.language.t("command.model.variant.cycle.description"), + category: input.language.t("command.category.model"), + keybind: "shift+mod+d", + onSelect: () => { + input.local.model.variant.cycle() + }, + }, + ]) + + const permissionCommands = createMemo(() => [ + { + id: "permissions.autoaccept", + title: + input.params.id && input.permission.isAutoAccepting(input.params.id, input.sdk.directory) + ? input.language.t("command.permissions.autoaccept.disable") + : input.language.t("command.permissions.autoaccept.enable"), + category: input.language.t("command.category.permissions"), + keybind: "mod+shift+a", + disabled: !input.params.id || !input.permission.permissionsEnabled(), + onSelect: () => { + const sessionID = input.params.id + if (!sessionID) return + input.permission.toggleAutoAccept(sessionID, input.sdk.directory) + showToast({ + title: input.permission.isAutoAccepting(sessionID, input.sdk.directory) + ? input.language.t("toast.permissions.autoaccept.on.title") + : input.language.t("toast.permissions.autoaccept.off.title"), + description: input.permission.isAutoAccepting(sessionID, input.sdk.directory) + ? input.language.t("toast.permissions.autoaccept.on.description") + : input.language.t("toast.permissions.autoaccept.off.description"), + }) + }, + }, + ]) + + const sessionActionCommands = createMemo(() => [ + { + id: "session.undo", + title: input.language.t("command.session.undo"), + description: input.language.t("command.session.undo.description"), + category: input.language.t("command.category.session"), + slash: "undo", + disabled: !input.params.id || input.visibleUserMessages().length === 0, + onSelect: async () => { + const sessionID = input.params.id + if (!sessionID) return + if (input.status()?.type !== "idle") { + await input.sdk.client.session.abort({ sessionID }).catch(() => {}) + } + const revert = input.info()?.revert?.messageID + const message = findLast(input.userMessages(), (x) => !revert || x.id < revert) + if (!message) return + await input.sdk.client.session.revert({ sessionID, messageID: message.id }) + const parts = input.sync.data.part[message.id] + if (parts) { + const restored = extractPromptFromParts(parts, { directory: input.sdk.directory }) + input.prompt.set(restored) + } + const priorMessage = findLast(input.userMessages(), (x) => x.id < message.id) + input.setActiveMessage(priorMessage) + }, + }, + { + id: "session.redo", + title: input.language.t("command.session.redo"), + description: input.language.t("command.session.redo.description"), + category: input.language.t("command.category.session"), + slash: "redo", + disabled: !input.params.id || !input.info()?.revert?.messageID, + onSelect: async () => { + const sessionID = input.params.id + if (!sessionID) return + const revertMessageID = input.info()?.revert?.messageID + if (!revertMessageID) return + const nextMessage = input.userMessages().find((x) => x.id > revertMessageID) + if (!nextMessage) { + await input.sdk.client.session.unrevert({ sessionID }) + input.prompt.reset() + const lastMsg = findLast(input.userMessages(), (x) => x.id >= revertMessageID) + input.setActiveMessage(lastMsg) + return + } + await input.sdk.client.session.revert({ sessionID, messageID: nextMessage.id }) + const priorMsg = findLast(input.userMessages(), (x) => x.id < nextMessage.id) + input.setActiveMessage(priorMsg) + }, + }, + { + id: "session.compact", + title: input.language.t("command.session.compact"), + description: input.language.t("command.session.compact.description"), + category: input.language.t("command.category.session"), + slash: "compact", + disabled: !input.params.id || input.visibleUserMessages().length === 0, + onSelect: async () => { + const sessionID = input.params.id + if (!sessionID) return + const model = input.local.model.current() + if (!model) { + showToast({ + title: input.language.t("toast.model.none.title"), + description: input.language.t("toast.model.none.description"), + }) + return + } + await input.sdk.client.session.summarize({ + sessionID, + modelID: model.id, + providerID: model.provider.id, + }) + }, + }, + { + id: "session.fork", + title: input.language.t("command.session.fork"), + description: input.language.t("command.session.fork.description"), + category: input.language.t("command.category.session"), + slash: "fork", + disabled: !input.params.id || input.visibleUserMessages().length === 0, + onSelect: () => input.dialog.show(() => ), + }, + ]) + + const shareCommands = createMemo(() => { + if (input.sync.data.config.share === "disabled") return [] + return [ + { + id: "session.share", + title: input.info()?.share?.url + ? input.language.t("session.share.copy.copyLink") + : input.language.t("command.session.share"), + description: input.info()?.share?.url + ? input.language.t("toast.session.share.success.description") + : input.language.t("command.session.share.description"), + category: input.language.t("command.category.session"), + slash: "share", + disabled: !input.params.id, + onSelect: async () => { + if (!input.params.id) return + + const write = (value: string) => { + const body = typeof document === "undefined" ? undefined : document.body + if (body) { + const textarea = document.createElement("textarea") + textarea.value = value + textarea.setAttribute("readonly", "") + textarea.style.position = "fixed" + textarea.style.opacity = "0" + textarea.style.pointerEvents = "none" + body.appendChild(textarea) + textarea.select() + const copied = document.execCommand("copy") + body.removeChild(textarea) + if (copied) return Promise.resolve(true) + } + + const clipboard = typeof navigator === "undefined" ? undefined : navigator.clipboard + if (!clipboard?.writeText) return Promise.resolve(false) + return clipboard.writeText(value).then( + () => true, + () => false, + ) + } + + const copy = async (url: string, existing: boolean) => { + const ok = await write(url) + if (!ok) { + showToast({ + title: input.language.t("toast.session.share.copyFailed.title"), + variant: "error", + }) + return + } + + showToast({ + title: existing + ? input.language.t("session.share.copy.copied") + : input.language.t("toast.session.share.success.title"), + description: input.language.t("toast.session.share.success.description"), + variant: "success", + }) + } + + const existing = input.info()?.share?.url + if (existing) { + await copy(existing, true) + return + } + + const url = await input.sdk.client.session + .share({ sessionID: input.params.id }) + .then((res) => res.data?.share?.url) + .catch(() => undefined) + if (!url) { + showToast({ + title: input.language.t("toast.session.share.failed.title"), + description: input.language.t("toast.session.share.failed.description"), + variant: "error", + }) + return + } + + await copy(url, false) + }, + }, + { + id: "session.unshare", + title: input.language.t("command.session.unshare"), + description: input.language.t("command.session.unshare.description"), + category: input.language.t("command.category.session"), + slash: "unshare", + disabled: !input.params.id || !input.info()?.share?.url, + onSelect: async () => { + if (!input.params.id) return + await input.sdk.client.session + .unshare({ sessionID: input.params.id }) + .then(() => + showToast({ + title: input.language.t("toast.session.unshare.success.title"), + description: input.language.t("toast.session.unshare.success.description"), + variant: "success", + }), + ) + .catch(() => + showToast({ + title: input.language.t("toast.session.unshare.failed.title"), + description: input.language.t("toast.session.unshare.failed.description"), + variant: "error", + }), + ) + }, + }, + ] + }) + + input.command.register("session", () => + combineCommandSections([ + sessionCommands(), + fileCommands(), + contextCommands(), + viewCommands(), + messageCommands(), + agentCommands(), + permissionCommands(), + sessionActionCommands(), + shareCommands(), + ]), + ) +} diff --git a/packages/app/src/pages/session/use-session-hash-scroll.test.ts b/packages/app/src/pages/session/use-session-hash-scroll.test.ts new file mode 100644 index 00000000000..844f5451e39 --- /dev/null +++ b/packages/app/src/pages/session/use-session-hash-scroll.test.ts @@ -0,0 +1,16 @@ +import { describe, expect, test } from "bun:test" +import { messageIdFromHash } from "./use-session-hash-scroll" + +describe("messageIdFromHash", () => { + test("parses hash with leading #", () => { + expect(messageIdFromHash("#message-abc123")).toBe("abc123") + }) + + test("parses raw hash fragment", () => { + expect(messageIdFromHash("message-42")).toBe("42") + }) + + test("ignores non-message anchors", () => { + expect(messageIdFromHash("#review-panel")).toBeUndefined() + }) +}) diff --git a/packages/app/src/pages/session/use-session-hash-scroll.ts b/packages/app/src/pages/session/use-session-hash-scroll.ts new file mode 100644 index 00000000000..8952bbd98b6 --- /dev/null +++ b/packages/app/src/pages/session/use-session-hash-scroll.ts @@ -0,0 +1,174 @@ +import { createEffect, on, onCleanup } from "solid-js" +import { UserMessage } from "@opencode-ai/sdk/v2" + +export const messageIdFromHash = (hash: string) => { + const value = hash.startsWith("#") ? hash.slice(1) : hash + const match = value.match(/^message-(.+)$/) + if (!match) return + return match[1] +} + +export const useSessionHashScroll = (input: { + sessionKey: () => string + sessionID: () => string | undefined + messagesReady: () => boolean + visibleUserMessages: () => UserMessage[] + turnStart: () => number + currentMessageId: () => string | undefined + pendingMessage: () => string | undefined + 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 + scheduleScrollState: (el: HTMLDivElement) => void + consumePendingMessage: (key: string) => string | undefined +}) => { + const clearMessageHash = () => { + if (!window.location.hash) return + window.history.replaceState(null, "", window.location.href.replace(/#.*$/, "")) + } + + const updateHash = (id: string) => { + window.history.replaceState(null, "", `#${input.anchor(id)}`) + } + + const scrollToElement = (el: HTMLElement, behavior: ScrollBehavior) => { + const root = input.scroller() + if (!root) return false + + const a = el.getBoundingClientRect() + const b = root.getBoundingClientRect() + const top = a.top - b.top + root.scrollTop + root.scrollTo({ top, behavior }) + return true + } + + const scrollToMessage = (message: UserMessage, behavior: ScrollBehavior = "smooth") => { + input.setActiveMessage(message) + + const msgs = input.visibleUserMessages() + const index = msgs.findIndex((m) => m.id === message.id) + if (index !== -1 && index < input.turnStart()) { + input.setTurnStart(index) + input.scheduleTurnBackfill() + + requestAnimationFrame(() => { + const el = document.getElementById(input.anchor(message.id)) + if (!el) { + requestAnimationFrame(() => { + const next = document.getElementById(input.anchor(message.id)) + if (!next) return + scrollToElement(next, behavior) + }) + return + } + scrollToElement(el, behavior) + }) + + updateHash(message.id) + return + } + + const el = document.getElementById(input.anchor(message.id)) + if (!el) { + updateHash(message.id) + requestAnimationFrame(() => { + const next = document.getElementById(input.anchor(message.id)) + if (!next) return + if (!scrollToElement(next, behavior)) return + }) + return + } + if (scrollToElement(el, behavior)) { + updateHash(message.id) + return + } + + requestAnimationFrame(() => { + const next = document.getElementById(input.anchor(message.id)) + if (!next) return + if (!scrollToElement(next, behavior)) return + }) + updateHash(message.id) + } + + const applyHash = (behavior: ScrollBehavior) => { + const hash = window.location.hash.slice(1) + if (!hash) { + input.autoScroll.forceScrollToBottom() + const el = input.scroller() + if (el) input.scheduleScrollState(el) + return + } + + const messageId = messageIdFromHash(hash) + if (messageId) { + input.autoScroll.pause() + const msg = input.visibleUserMessages().find((m) => m.id === messageId) + if (msg) { + scrollToMessage(msg, behavior) + return + } + return + } + + const target = document.getElementById(hash) + if (target) { + input.autoScroll.pause() + scrollToElement(target, behavior) + return + } + + input.autoScroll.forceScrollToBottom() + const el = input.scroller() + 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")) + }) + + createEffect(() => { + if (!input.sessionID() || !input.messagesReady()) return + + input.visibleUserMessages().length + input.turnStart() + + const targetId = input.pendingMessage() ?? messageIdFromHash(window.location.hash) + if (!targetId) return + if (input.currentMessageId() === targetId) return + + const msg = input.visibleUserMessages().find((m) => m.id === targetId) + if (!msg) return + + if (input.pendingMessage() === targetId) input.setPendingMessage(undefined) + input.autoScroll.pause() + requestAnimationFrame(() => scrollToMessage(msg, "auto")) + }) + + createEffect(() => { + if (!input.sessionID() || !input.messagesReady()) return + const handler = () => requestAnimationFrame(() => applyHash("auto")) + window.addEventListener("hashchange", handler) + onCleanup(() => window.removeEventListener("hashchange", handler)) + }) + + return { + clearMessageHash, + scrollToMessage, + applyHash, + } +} diff --git a/packages/app/src/utils/aim.ts b/packages/app/src/utils/aim.ts new file mode 100644 index 00000000000..23471959e16 --- /dev/null +++ b/packages/app/src/utils/aim.ts @@ -0,0 +1,138 @@ +type Point = { x: number; y: number } + +export function createAim(props: { + enabled: () => boolean + active: () => string | undefined + el: () => HTMLElement | undefined + onActivate: (id: string) => void + delay?: number + max?: number + tolerance?: number + edge?: number +}) { + const state = { + locs: [] as Point[], + timer: undefined as number | undefined, + pending: undefined as string | undefined, + over: undefined as string | undefined, + last: undefined as Point | undefined, + } + + const delay = props.delay ?? 250 + const max = props.max ?? 4 + const tolerance = props.tolerance ?? 80 + const edge = props.edge ?? 18 + + const cancel = () => { + if (state.timer !== undefined) clearTimeout(state.timer) + state.timer = undefined + state.pending = undefined + } + + const reset = () => { + cancel() + state.over = undefined + state.last = undefined + state.locs.length = 0 + } + + const move = (event: MouseEvent) => { + if (!props.enabled()) return + const el = props.el() + if (!el) return + + const rect = el.getBoundingClientRect() + const x = event.clientX + const y = event.clientY + if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom) return + + state.locs.push({ x, y }) + if (state.locs.length > max) state.locs.shift() + } + + const wait = () => { + if (!props.enabled()) return 0 + if (!props.active()) return 0 + + const el = props.el() + if (!el) return 0 + if (state.locs.length < 2) return 0 + + const rect = el.getBoundingClientRect() + const loc = state.locs[state.locs.length - 1] + if (!loc) return 0 + + const prev = state.locs[0] ?? loc + if (prev.x < rect.left || prev.x > rect.right || prev.y < rect.top || prev.y > rect.bottom) return 0 + if (state.last && loc.x === state.last.x && loc.y === state.last.y) return 0 + + if (rect.right - loc.x <= edge) { + state.last = loc + return delay + } + + const upper = { x: rect.right, y: rect.top - tolerance } + const lower = { x: rect.right, y: rect.bottom + tolerance } + const slope = (a: Point, b: Point) => (b.y - a.y) / (b.x - a.x) + + const decreasing = slope(loc, upper) + const increasing = slope(loc, lower) + const prevDecreasing = slope(prev, upper) + const prevIncreasing = slope(prev, lower) + + if (decreasing < prevDecreasing && increasing > prevIncreasing) { + state.last = loc + return delay + } + + state.last = undefined + return 0 + } + + const activate = (id: string) => { + cancel() + props.onActivate(id) + } + + const request = (id: string) => { + if (!id) return + if (props.active() === id) return + + if (!props.active()) { + activate(id) + return + } + + const ms = wait() + if (ms === 0) { + activate(id) + return + } + + cancel() + state.pending = id + state.timer = window.setTimeout(() => { + state.timer = undefined + if (state.pending !== id) return + state.pending = undefined + if (!props.enabled()) return + if (!props.active()) return + if (state.over !== id) return + props.onActivate(id) + }, ms) + } + + const enter = (id: string, event: MouseEvent) => { + if (!props.enabled()) return + state.over = id + move(event) + request(id) + } + + const leave = (id: string) => { + if (state.over === id) state.over = undefined + if (state.pending === id) cancel() + } + + return { move, enter, leave, activate, request, cancel, reset } +} diff --git a/packages/app/src/utils/persist.test.ts b/packages/app/src/utils/persist.test.ts new file mode 100644 index 00000000000..2a2c349b755 --- /dev/null +++ b/packages/app/src/utils/persist.test.ts @@ -0,0 +1,107 @@ +import { beforeAll, beforeEach, describe, expect, mock, test } from "bun:test" + +type PersistTestingType = typeof import("./persist").PersistTesting + +class MemoryStorage implements Storage { + private values = new Map() + readonly events: string[] = [] + readonly calls = { get: 0, set: 0, remove: 0 } + + clear() { + this.values.clear() + } + + get length() { + return this.values.size + } + + key(index: number) { + return Array.from(this.values.keys())[index] ?? null + } + + getItem(key: string) { + this.calls.get += 1 + this.events.push(`get:${key}`) + if (key.startsWith("opencode.throw")) throw new Error("storage get failed") + return this.values.get(key) ?? null + } + + setItem(key: string, value: string) { + this.calls.set += 1 + this.events.push(`set:${key}`) + if (key.startsWith("opencode.quota")) throw new DOMException("quota", "QuotaExceededError") + if (key.startsWith("opencode.throw")) throw new Error("storage set failed") + this.values.set(key, value) + } + + removeItem(key: string) { + this.calls.remove += 1 + this.events.push(`remove:${key}`) + if (key.startsWith("opencode.throw")) throw new Error("storage remove failed") + this.values.delete(key) + } +} + +const storage = new MemoryStorage() + +let persistTesting: PersistTestingType + +beforeAll(async () => { + mock.module("@/context/platform", () => ({ + usePlatform: () => ({ platform: "web" }), + })) + + const mod = await import("./persist") + persistTesting = mod.PersistTesting +}) + +beforeEach(() => { + storage.clear() + storage.events.length = 0 + storage.calls.get = 0 + storage.calls.set = 0 + storage.calls.remove = 0 + Object.defineProperty(globalThis, "localStorage", { + value: storage, + configurable: true, + }) +}) + +describe("persist localStorage resilience", () => { + test("does not cache values as persisted when quota write and eviction fail", () => { + const storageApi = persistTesting.localStorageWithPrefix("opencode.quota.scope") + storageApi.setItem("value", '{"value":1}') + + expect(storage.getItem("opencode.quota.scope:value")).toBeNull() + expect(storageApi.getItem("value")).toBeNull() + }) + + test("disables only the failing scope when storage throws", () => { + const bad = persistTesting.localStorageWithPrefix("opencode.throw.scope") + bad.setItem("value", '{"value":1}') + + const before = storage.calls.set + bad.setItem("value", '{"value":2}') + expect(storage.calls.set).toBe(before) + expect(bad.getItem("value")).toBeNull() + + const healthy = persistTesting.localStorageWithPrefix("opencode.safe.scope") + healthy.setItem("value", '{"value":3}') + expect(storage.getItem("opencode.safe.scope:value")).toBe('{"value":3}') + }) + + test("failing fallback scope does not poison direct storage scope", () => { + const broken = persistTesting.localStorageWithPrefix("opencode.throw.scope2") + broken.setItem("value", '{"value":1}') + + const direct = persistTesting.localStorageDirect() + direct.setItem("direct-value", '{"value":5}') + + expect(storage.getItem("direct-value")).toBe('{"value":5}') + }) + + test("normalizer rejects malformed JSON payloads", () => { + const result = persistTesting.normalize({ value: "ok" }, '{"value":"\\x"}') + expect(result).toBeUndefined() + }) +}) diff --git a/packages/app/src/utils/runtime-adapters.test.ts b/packages/app/src/utils/runtime-adapters.test.ts new file mode 100644 index 00000000000..9f408b8eb7e --- /dev/null +++ b/packages/app/src/utils/runtime-adapters.test.ts @@ -0,0 +1,62 @@ +import { describe, expect, test } from "bun:test" +import { + disposeIfDisposable, + getHoveredLinkText, + getSpeechRecognitionCtor, + hasSetOption, + isDisposable, + setOptionIfSupported, +} from "./runtime-adapters" + +describe("runtime adapters", () => { + test("detects and disposes disposable values", () => { + let count = 0 + const value = { + dispose: () => { + count += 1 + }, + } + expect(isDisposable(value)).toBe(true) + disposeIfDisposable(value) + expect(count).toBe(1) + }) + + test("ignores non-disposable values", () => { + expect(isDisposable({ dispose: "nope" })).toBe(false) + expect(() => disposeIfDisposable({ dispose: "nope" })).not.toThrow() + }) + + test("sets options only when setter exists", () => { + const calls: Array<[string, unknown]> = [] + const value = { + setOption: (key: string, next: unknown) => { + calls.push([key, next]) + }, + } + expect(hasSetOption(value)).toBe(true) + setOptionIfSupported(value, "fontFamily", "Berkeley Mono") + expect(calls).toEqual([["fontFamily", "Berkeley Mono"]]) + expect(() => setOptionIfSupported({}, "fontFamily", "Berkeley Mono")).not.toThrow() + }) + + test("reads hovered link text safely", () => { + expect(getHoveredLinkText({ currentHoveredLink: { text: "https://example.com" } })).toBe("https://example.com") + expect(getHoveredLinkText({ currentHoveredLink: { text: 1 } })).toBeUndefined() + expect(getHoveredLinkText(null)).toBeUndefined() + }) + + test("resolves speech recognition constructor with webkit precedence", () => { + class SpeechCtor {} + class WebkitCtor {} + const ctor = getSpeechRecognitionCtor({ + SpeechRecognition: SpeechCtor, + webkitSpeechRecognition: WebkitCtor, + }) + expect(ctor).toBe(WebkitCtor) + }) + + test("returns undefined when no valid speech constructor exists", () => { + expect(getSpeechRecognitionCtor({ SpeechRecognition: "nope" })).toBeUndefined() + expect(getSpeechRecognitionCtor(undefined)).toBeUndefined() + }) +}) diff --git a/packages/app/src/utils/runtime-adapters.ts b/packages/app/src/utils/runtime-adapters.ts new file mode 100644 index 00000000000..4c74da5dc1d --- /dev/null +++ b/packages/app/src/utils/runtime-adapters.ts @@ -0,0 +1,39 @@ +type RecordValue = Record + +const isRecord = (value: unknown): value is RecordValue => { + return typeof value === "object" && value !== null +} + +export const isDisposable = (value: unknown): value is { dispose: () => void } => { + return isRecord(value) && typeof value.dispose === "function" +} + +export const disposeIfDisposable = (value: unknown) => { + if (!isDisposable(value)) return + value.dispose() +} + +export const hasSetOption = (value: unknown): value is { setOption: (key: string, next: unknown) => void } => { + return isRecord(value) && typeof value.setOption === "function" +} + +export const setOptionIfSupported = (value: unknown, key: string, next: unknown) => { + if (!hasSetOption(value)) return + value.setOption(key, next) +} + +export const getHoveredLinkText = (value: unknown) => { + if (!isRecord(value)) return + const link = value.currentHoveredLink + if (!isRecord(link)) return + if (typeof link.text !== "string") return + return link.text +} + +export const getSpeechRecognitionCtor = (value: unknown): (new () => T) | undefined => { + if (!isRecord(value)) return + const ctor = + typeof value.webkitSpeechRecognition === "function" ? value.webkitSpeechRecognition : value.SpeechRecognition + if (typeof ctor !== "function") return + return ctor as new () => T +} diff --git a/packages/app/src/utils/scoped-cache.test.ts b/packages/app/src/utils/scoped-cache.test.ts new file mode 100644 index 00000000000..0c6189dafe5 --- /dev/null +++ b/packages/app/src/utils/scoped-cache.test.ts @@ -0,0 +1,69 @@ +import { describe, expect, test } from "bun:test" +import { createScopedCache } from "./scoped-cache" + +describe("createScopedCache", () => { + test("evicts least-recently-used entry when max is reached", () => { + const disposed: string[] = [] + const cache = createScopedCache((key) => ({ key }), { + maxEntries: 2, + dispose: (value) => disposed.push(value.key), + }) + + const a = cache.get("a") + const b = cache.get("b") + expect(a.key).toBe("a") + expect(b.key).toBe("b") + + cache.get("a") + const c = cache.get("c") + + expect(c.key).toBe("c") + expect(cache.peek("a")?.key).toBe("a") + expect(cache.peek("b")).toBeUndefined() + expect(cache.peek("c")?.key).toBe("c") + expect(disposed).toEqual(["b"]) + }) + + test("disposes entries on delete and clear", () => { + const disposed: string[] = [] + const cache = createScopedCache((key) => ({ key }), { + dispose: (value) => disposed.push(value.key), + }) + + cache.get("a") + cache.get("b") + + const removed = cache.delete("a") + expect(removed?.key).toBe("a") + expect(cache.peek("a")).toBeUndefined() + + cache.clear() + expect(cache.peek("b")).toBeUndefined() + expect(disposed).toEqual(["a", "b"]) + }) + + test("expires stale entries with ttl and recreates on get", () => { + let clock = 0 + let count = 0 + const disposed: string[] = [] + const cache = createScopedCache((key) => ({ key, count: ++count }), { + ttlMs: 10, + now: () => clock, + dispose: (value) => disposed.push(`${value.key}:${value.count}`), + }) + + const first = cache.get("a") + expect(first.count).toBe(1) + + clock = 9 + expect(cache.peek("a")?.count).toBe(1) + + clock = 11 + expect(cache.peek("a")).toBeUndefined() + expect(disposed).toEqual(["a:1"]) + + const second = cache.get("a") + expect(second.count).toBe(2) + expect(disposed).toEqual(["a:1"]) + }) +}) diff --git a/packages/app/src/utils/scoped-cache.ts b/packages/app/src/utils/scoped-cache.ts new file mode 100644 index 00000000000..224c363c1eb --- /dev/null +++ b/packages/app/src/utils/scoped-cache.ts @@ -0,0 +1,104 @@ +type ScopedCacheOptions = { + maxEntries?: number + ttlMs?: number + dispose?: (value: T, key: string) => void + now?: () => number +} + +type Entry = { + value: T + touchedAt: number +} + +export function createScopedCache(createValue: (key: string) => T, options: ScopedCacheOptions = {}) { + const store = new Map>() + const now = options.now ?? Date.now + + const dispose = (key: string, entry: Entry) => { + options.dispose?.(entry.value, key) + } + + const expired = (entry: Entry) => { + if (options.ttlMs === undefined) return false + return now() - entry.touchedAt >= options.ttlMs + } + + const sweep = () => { + if (options.ttlMs === undefined) return + for (const [key, entry] of store) { + if (!expired(entry)) continue + store.delete(key) + dispose(key, entry) + } + } + + const touch = (key: string, entry: Entry) => { + entry.touchedAt = now() + store.delete(key) + store.set(key, entry) + } + + const prune = () => { + if (options.maxEntries === undefined) return + while (store.size > options.maxEntries) { + const key = store.keys().next().value + if (!key) return + const entry = store.get(key) + store.delete(key) + if (!entry) continue + dispose(key, entry) + } + } + + const remove = (key: string) => { + const entry = store.get(key) + if (!entry) return + store.delete(key) + dispose(key, entry) + return entry.value + } + + const peek = (key: string) => { + sweep() + const entry = store.get(key) + if (!entry) return + if (!expired(entry)) return entry.value + store.delete(key) + dispose(key, entry) + } + + const get = (key: string) => { + sweep() + const entry = store.get(key) + if (entry && !expired(entry)) { + touch(key, entry) + return entry.value + } + if (entry) { + store.delete(key) + dispose(key, entry) + } + + const created = { + value: createValue(key), + touchedAt: now(), + } + store.set(key, created) + prune() + return created.value + } + + const clear = () => { + for (const [key, entry] of store) { + dispose(key, entry) + } + store.clear() + } + + return { + get, + peek, + delete: remove, + clear, + } +} diff --git a/packages/app/src/utils/server-health.test.ts b/packages/app/src/utils/server-health.test.ts new file mode 100644 index 00000000000..26bda070a67 --- /dev/null +++ b/packages/app/src/utils/server-health.test.ts @@ -0,0 +1,114 @@ +import { describe, expect, test } from "bun:test" +import { checkServerHealth } from "./server-health" + +function abortFromInput(input: RequestInfo | URL, init?: RequestInit) { + if (init?.signal) return init.signal + if (input instanceof Request) return input.signal + return undefined +} + +describe("checkServerHealth", () => { + test("returns healthy response with version", async () => { + const fetch = (async () => + new Response(JSON.stringify({ healthy: true, version: "1.2.3" }), { + status: 200, + headers: { "content-type": "application/json" }, + })) as unknown as typeof globalThis.fetch + + const result = await checkServerHealth("http://localhost:4096", fetch) + + expect(result).toEqual({ healthy: true, version: "1.2.3" }) + }) + + test("returns unhealthy when request fails", async () => { + const fetch = (async () => { + throw new Error("network") + }) as unknown as typeof globalThis.fetch + + const result = await checkServerHealth("http://localhost:4096", fetch) + + expect(result).toEqual({ healthy: false }) + }) + + test("uses timeout fallback when AbortSignal.timeout is unavailable", async () => { + const timeout = Object.getOwnPropertyDescriptor(AbortSignal, "timeout") + Object.defineProperty(AbortSignal, "timeout", { + configurable: true, + value: undefined, + }) + + let aborted = false + const fetch = ((input: RequestInfo | URL, init?: RequestInit) => + new Promise((_resolve, reject) => { + const signal = abortFromInput(input, init) + signal?.addEventListener( + "abort", + () => { + aborted = true + reject(new DOMException("Aborted", "AbortError")) + }, + { once: true }, + ) + })) as unknown as typeof globalThis.fetch + + const result = await checkServerHealth("http://localhost:4096", fetch, { timeoutMs: 10 }).finally(() => { + if (timeout) Object.defineProperty(AbortSignal, "timeout", timeout) + if (!timeout) Reflect.deleteProperty(AbortSignal, "timeout") + }) + + expect(aborted).toBe(true) + expect(result).toEqual({ healthy: false }) + }) + + test("uses provided abort signal", async () => { + let signal: AbortSignal | undefined + const fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { + signal = abortFromInput(input, init) + return new Response(JSON.stringify({ healthy: true, version: "1.2.3" }), { + status: 200, + headers: { "content-type": "application/json" }, + }) + }) as unknown as typeof globalThis.fetch + + const abort = new AbortController() + await checkServerHealth("http://localhost:4096", fetch, { signal: abort.signal }) + + expect(signal).toBe(abort.signal) + }) + + test("retries transient failures and eventually succeeds", async () => { + let count = 0 + const fetch = (async () => { + count += 1 + if (count < 3) throw new TypeError("network") + return new Response(JSON.stringify({ healthy: true, version: "1.2.3" }), { + status: 200, + headers: { "content-type": "application/json" }, + }) + }) as unknown as typeof globalThis.fetch + + const result = await checkServerHealth("http://localhost:4096", fetch, { + retryCount: 2, + retryDelayMs: 1, + }) + + expect(count).toBe(3) + expect(result).toEqual({ healthy: true, version: "1.2.3" }) + }) + + test("returns unhealthy when retries are exhausted", async () => { + let count = 0 + const fetch = (async () => { + count += 1 + throw new TypeError("network") + }) as unknown as typeof globalThis.fetch + + const result = await checkServerHealth("http://localhost:4096", fetch, { + retryCount: 2, + retryDelayMs: 1, + }) + + expect(count).toBe(3) + expect(result).toEqual({ healthy: false }) + }) +}) diff --git a/packages/app/src/utils/server-health.ts b/packages/app/src/utils/server-health.ts new file mode 100644 index 00000000000..929826d0dea --- /dev/null +++ b/packages/app/src/utils/server-health.ts @@ -0,0 +1,79 @@ +import { createOpencodeClient } from "@opencode-ai/sdk/v2/client" + +export type ServerHealth = { healthy: boolean; version?: string } + +interface CheckServerHealthOptions { + timeoutMs?: number + signal?: AbortSignal + retryCount?: number + retryDelayMs?: number +} + +const defaultTimeoutMs = 3000 +const defaultRetryCount = 2 +const defaultRetryDelayMs = 100 + +function timeoutSignal(timeoutMs: number) { + const timeout = (AbortSignal as unknown as { timeout?: (ms: number) => AbortSignal }).timeout + if (timeout) { + try { + return { signal: timeout.call(AbortSignal, timeoutMs), clear: undefined as (() => void) | undefined } + } catch {} + } + const controller = new AbortController() + const timer = setTimeout(() => controller.abort(), timeoutMs) + return { signal: controller.signal, clear: () => clearTimeout(timer) } +} + +function wait(ms: number, signal?: AbortSignal) { + return new Promise((resolve, reject) => { + if (signal?.aborted) { + reject(new DOMException("Aborted", "AbortError")) + return + } + const timer = setTimeout(() => { + signal?.removeEventListener("abort", onAbort) + resolve() + }, ms) + const onAbort = () => { + clearTimeout(timer) + reject(new DOMException("Aborted", "AbortError")) + } + signal?.addEventListener("abort", onAbort, { once: true }) + }) +} + +function retryable(error: unknown, signal?: AbortSignal) { + if (signal?.aborted) return false + if (!(error instanceof Error)) return false + if (error.name === "AbortError" || error.name === "TimeoutError") return false + if (error instanceof TypeError) return true + return /network|fetch|econnreset|econnrefused|enotfound|timedout/i.test(error.message) +} + +export async function checkServerHealth( + url: string, + fetch: typeof globalThis.fetch, + opts?: CheckServerHealthOptions, +): Promise { + const timeout = opts?.signal ? undefined : timeoutSignal(opts?.timeoutMs ?? defaultTimeoutMs) + const signal = opts?.signal ?? timeout?.signal + const retryCount = opts?.retryCount ?? defaultRetryCount + const retryDelayMs = opts?.retryDelayMs ?? defaultRetryDelayMs + const next = (count: number, error: unknown) => { + if (count >= retryCount || !retryable(error, signal)) return Promise.resolve({ healthy: false } as const) + return wait(retryDelayMs * (count + 1), signal) + .then(() => attempt(count + 1)) + .catch(() => ({ healthy: false })) + } + const attempt = (count: number): Promise => + createOpencodeClient({ + baseUrl: url, + fetch, + signal, + }) + .global.health() + .then((x) => (x.error ? next(count, x.error) : { healthy: x.data?.healthy === true, version: x.data?.version })) + .catch((error) => next(count, error)) + return attempt(0).finally(() => timeout?.clear?.()) +} diff --git a/packages/app/src/utils/time.ts b/packages/app/src/utils/time.ts new file mode 100644 index 00000000000..ac709d86dd6 --- /dev/null +++ b/packages/app/src/utils/time.ts @@ -0,0 +1,14 @@ +export function getRelativeTime(dateString: string): string { + const date = new Date(dateString) + const now = new Date() + const diffMs = now.getTime() - date.getTime() + const diffSeconds = Math.floor(diffMs / 1000) + const diffMinutes = Math.floor(diffSeconds / 60) + const diffHours = Math.floor(diffMinutes / 60) + const diffDays = Math.floor(diffHours / 24) + + if (diffSeconds < 60) return "Just now" + if (diffMinutes < 60) return `${diffMinutes}m ago` + if (diffHours < 24) return `${diffHours}h ago` + return `${diffDays}d ago` +} diff --git a/packages/app/src/utils/uuid.test.ts b/packages/app/src/utils/uuid.test.ts new file mode 100644 index 00000000000..e6b4e282409 --- /dev/null +++ b/packages/app/src/utils/uuid.test.ts @@ -0,0 +1,78 @@ +import { afterEach, describe, expect, test } from "bun:test" +import { uuid } from "./uuid" + +const cryptoDescriptor = Object.getOwnPropertyDescriptor(globalThis, "crypto") +const secureDescriptor = Object.getOwnPropertyDescriptor(globalThis, "isSecureContext") +const randomDescriptor = Object.getOwnPropertyDescriptor(Math, "random") + +const setCrypto = (value: Partial) => { + Object.defineProperty(globalThis, "crypto", { + configurable: true, + value: value as Crypto, + }) +} + +const setSecure = (value: boolean) => { + Object.defineProperty(globalThis, "isSecureContext", { + configurable: true, + value, + }) +} + +const setRandom = (value: () => number) => { + Object.defineProperty(Math, "random", { + configurable: true, + value, + }) +} + +afterEach(() => { + if (cryptoDescriptor) { + Object.defineProperty(globalThis, "crypto", cryptoDescriptor) + } + + if (secureDescriptor) { + Object.defineProperty(globalThis, "isSecureContext", secureDescriptor) + } + + if (!secureDescriptor) { + delete (globalThis as { isSecureContext?: boolean }).isSecureContext + } + + if (randomDescriptor) { + Object.defineProperty(Math, "random", randomDescriptor) + } +}) + +describe("uuid", () => { + test("uses randomUUID in secure contexts", () => { + setCrypto({ randomUUID: () => "00000000-0000-0000-0000-000000000000" }) + setSecure(true) + expect(uuid()).toBe("00000000-0000-0000-0000-000000000000") + }) + + test("falls back in insecure contexts", () => { + setCrypto({ randomUUID: () => "00000000-0000-0000-0000-000000000000" }) + setSecure(false) + setRandom(() => 0.5) + expect(uuid()).toBe("8") + }) + + test("falls back when randomUUID throws", () => { + setCrypto({ + randomUUID: () => { + throw new DOMException("Failed", "OperationError") + }, + }) + setSecure(true) + setRandom(() => 0.5) + expect(uuid()).toBe("8") + }) + + test("falls back when randomUUID is unavailable", () => { + setCrypto({}) + setSecure(true) + setRandom(() => 0.5) + expect(uuid()).toBe("8") + }) +}) diff --git a/packages/app/src/utils/uuid.ts b/packages/app/src/utils/uuid.ts new file mode 100644 index 00000000000..7b964068c86 --- /dev/null +++ b/packages/app/src/utils/uuid.ts @@ -0,0 +1,12 @@ +const fallback = () => Math.random().toString(16).slice(2) + +export function uuid() { + const c = globalThis.crypto + if (!c || typeof c.randomUUID !== "function") return fallback() + if (typeof globalThis.isSecureContext === "boolean" && !globalThis.isSecureContext) return fallback() + try { + return c.randomUUID() + } catch { + return fallback() + } +} diff --git a/packages/app/src/utils/worktree.test.ts b/packages/app/src/utils/worktree.test.ts new file mode 100644 index 00000000000..8161e7ad836 --- /dev/null +++ b/packages/app/src/utils/worktree.test.ts @@ -0,0 +1,46 @@ +import { describe, expect, test } from "bun:test" +import { Worktree } from "./worktree" + +const dir = (name: string) => `/tmp/opencode-worktree-${name}-${crypto.randomUUID()}` + +describe("Worktree", () => { + test("normalizes trailing slashes", () => { + const key = dir("normalize") + Worktree.ready(`${key}/`) + + expect(Worktree.get(key)).toEqual({ status: "ready" }) + }) + + test("pending does not overwrite a terminal state", () => { + const key = dir("pending") + Worktree.failed(key, "boom") + Worktree.pending(key) + + expect(Worktree.get(key)).toEqual({ status: "failed", message: "boom" }) + }) + + test("wait resolves shared pending waiter when ready", async () => { + const key = dir("wait-ready") + Worktree.pending(key) + + const a = Worktree.wait(key) + const b = Worktree.wait(`${key}/`) + + expect(a).toBe(b) + + Worktree.ready(key) + + expect(await a).toEqual({ status: "ready" }) + expect(await b).toEqual({ status: "ready" }) + }) + + test("wait resolves with failure message", async () => { + const key = dir("wait-failed") + const waiting = Worktree.wait(key) + + Worktree.failed(key, "permission denied") + + expect(await waiting).toEqual({ status: "failed", message: "permission denied" }) + expect(await Worktree.wait(key)).toEqual({ status: "failed", message: "permission denied" }) + }) +}) diff --git a/packages/console/app/src/asset/brand/opencode-logo-dark-square.png b/packages/console/app/src/asset/brand/opencode-logo-dark-square.png new file mode 100644 index 00000000000..673c7e3a20f Binary files /dev/null and b/packages/console/app/src/asset/brand/opencode-logo-dark-square.png differ diff --git a/packages/console/app/src/asset/brand/opencode-logo-dark-square.svg b/packages/console/app/src/asset/brand/opencode-logo-dark-square.svg new file mode 100644 index 00000000000..6a67f62717b --- /dev/null +++ b/packages/console/app/src/asset/brand/opencode-logo-dark-square.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/packages/console/app/src/asset/brand/opencode-logo-light-square.png b/packages/console/app/src/asset/brand/opencode-logo-light-square.png new file mode 100644 index 00000000000..5c710474abc Binary files /dev/null and b/packages/console/app/src/asset/brand/opencode-logo-light-square.png differ diff --git a/packages/console/app/src/asset/brand/opencode-logo-light-square.svg b/packages/console/app/src/asset/brand/opencode-logo-light-square.svg new file mode 100644 index 00000000000..a738ad87dbb --- /dev/null +++ b/packages/console/app/src/asset/brand/opencode-logo-light-square.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/packages/console/app/src/asset/brand/preview-opencode-logo-dark-square.png b/packages/console/app/src/asset/brand/preview-opencode-logo-dark-square.png new file mode 100644 index 00000000000..604ad7aa7a8 Binary files /dev/null and b/packages/console/app/src/asset/brand/preview-opencode-logo-dark-square.png differ diff --git a/packages/console/app/src/asset/brand/preview-opencode-logo-light-square.png b/packages/console/app/src/asset/brand/preview-opencode-logo-light-square.png new file mode 100644 index 00000000000..3964d852844 Binary files /dev/null and b/packages/console/app/src/asset/brand/preview-opencode-logo-light-square.png differ diff --git a/packages/console/app/src/component/language-picker.css b/packages/console/app/src/component/language-picker.css new file mode 100644 index 00000000000..8ef2306d729 --- /dev/null +++ b/packages/console/app/src/component/language-picker.css @@ -0,0 +1,135 @@ +[data-component="language-picker"] { + width: auto; +} + +[data-component="footer"] [data-component="language-picker"] { + width: 100%; +} + +[data-component="footer"] [data-component="language-picker"] [data-component="dropdown"] { + width: 100%; +} + +/* Standard site footer (grid of cells) */ +[data-component="footer"] [data-slot="cell"] [data-component="language-picker"] { + height: 100%; +} + +[data-component="footer"] [data-slot="cell"] [data-component="language-picker"] [data-slot="trigger"] { + width: 100%; + padding: 2rem 0; + border-radius: 0; + justify-content: center; + gap: var(--space-2); + color: inherit; + font: inherit; +} + +[data-component="footer"] [data-slot="cell"] [data-component="language-picker"] [data-slot="trigger"] span { + flex: 0 0 auto; + text-align: center; + font-weight: inherit; +} + +[data-component="footer"] [data-slot="cell"] [data-component="language-picker"] [data-slot="trigger"]:hover { + background: var(--color-background-weak); + text-decoration: underline; + text-underline-offset: var(--space-1); + text-decoration-thickness: 1px; +} + +/* Footer dropdown should open upward */ +[data-component="footer"] [data-component="language-picker"] [data-slot="dropdown"] { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: var(--space-2); + max-height: min(60vh, 420px); + overflow: auto; +} + +[data-component="legal"] { + flex-wrap: wrap; + row-gap: var(--space-2); +} + +[data-component="legal"] [data-component="language-picker"] { + width: auto; +} + +[data-component="legal"] [data-component="language-picker"] [data-slot="trigger"] { + padding: 0; + border-radius: 0; + background: transparent; + font: inherit; + color: var(--color-text-weak); + white-space: nowrap; +} + +[data-component="legal"] [data-component="language-picker"] [data-slot="trigger"] span { + font-weight: inherit; +} + +[data-component="legal"] [data-component="language-picker"] [data-slot="trigger"]:hover { + background: transparent; + color: var(--color-text); + text-decoration: underline; + text-underline-offset: var(--space-1); + text-decoration-thickness: 1px; +} + +[data-component="legal"] [data-component="language-picker"] [data-slot="dropdown"] { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: var(--space-2); + max-height: min(60vh, 420px); + overflow: auto; +} + +/* Black pages footer */ +[data-page="black"] [data-component="language-picker"] { + width: auto; +} + +[data-page="black"] [data-component="language-picker"] [data-component="dropdown"] { + width: auto; +} + +[data-page="black"] [data-component="language-picker"] [data-slot="trigger"] { + padding: 0; + border-radius: 0; + background: transparent; + font: inherit; + color: rgba(255, 255, 255, 0.39); +} + +[data-page="black"] [data-component="language-picker"] [data-slot="trigger"]:hover { + background: transparent; + text-decoration: underline; + text-underline-offset: 4px; +} + +[data-page="black"] [data-component="language-picker"] [data-slot="dropdown"] { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 12px; + background-color: #0e0e10; + border-color: rgba(255, 255, 255, 0.14); + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6); + max-height: min(60vh, 420px); + overflow: auto; +} + +[data-page="black"] [data-component="language-picker"] [data-slot="item"] { + color: rgba(255, 255, 255, 0.86); +} + +[data-page="black"] [data-component="language-picker"] [data-slot="item"]:hover { + background-color: rgba(255, 255, 255, 0.06); +} + +[data-page="black"] [data-component="language-picker"] [data-slot="item"][data-selected="true"] { + background-color: rgba(255, 255, 255, 0.1); +} diff --git a/packages/console/app/src/component/language-picker.tsx b/packages/console/app/src/component/language-picker.tsx new file mode 100644 index 00000000000..f42fd806567 --- /dev/null +++ b/packages/console/app/src/component/language-picker.tsx @@ -0,0 +1,40 @@ +import { For, createSignal } from "solid-js" +import { useLocation, useNavigate } from "@solidjs/router" +import { Dropdown, DropdownItem } from "~/component/dropdown" +import { useLanguage } from "~/context/language" +import { route, strip } from "~/lib/language" +import "./language-picker.css" + +export function LanguagePicker(props: { align?: "left" | "right" } = {}) { + const language = useLanguage() + const navigate = useNavigate() + const location = useLocation() + const [open, setOpen] = createSignal(false) + + return ( +
+ + + {(locale) => ( + { + language.setLocale(locale) + const href = `${route(locale, strip(location.pathname))}${location.search}${location.hash}` + if (href !== `${location.pathname}${location.search}${location.hash}`) navigate(href) + setOpen(false) + }} + > + {language.label(locale)} + + )} + + +
+ ) +} diff --git a/packages/console/app/src/component/locale-links.tsx b/packages/console/app/src/component/locale-links.tsx new file mode 100644 index 00000000000..f773bb885c0 --- /dev/null +++ b/packages/console/app/src/component/locale-links.tsx @@ -0,0 +1,36 @@ +import { Link } from "@solidjs/meta" +import { For } from "solid-js" +import { getRequestEvent } from "solid-js/web" +import { config } from "~/config" +import { useLanguage } from "~/context/language" +import { LOCALES, route, tag } from "~/lib/language" + +function skip(path: string) { + const evt = getRequestEvent() + if (!evt) return false + + const key = "__locale_links_seen" + const locals = evt.locals as Record + const seen = locals[key] instanceof Set ? (locals[key] as Set) : new Set() + locals[key] = seen + if (seen.has(path)) return true + seen.add(path) + return false +} + +export function LocaleLinks(props: { path: string }) { + const language = useLanguage() + if (skip(props.path)) return null + + return ( + <> + + + {(locale) => ( + + )} + + + + ) +} diff --git a/packages/console/app/src/context/i18n.tsx b/packages/console/app/src/context/i18n.tsx new file mode 100644 index 00000000000..5d178c8b8d9 --- /dev/null +++ b/packages/console/app/src/context/i18n.tsx @@ -0,0 +1,27 @@ +import { createMemo } from "solid-js" +import { createSimpleContext } from "@opencode-ai/ui/context" +import { i18n, type Key } from "~/i18n" +import { useLanguage } from "~/context/language" + +function resolve(text: string, params?: Record) { + if (!params) return text + return text.replace(/\{\{(\w+)\}\}/g, (raw, key) => { + const value = params[key] + if (value === undefined || value === null) return raw + return String(value) + }) +} + +export const { use: useI18n, provider: I18nProvider } = createSimpleContext({ + name: "I18n", + init: () => { + const language = useLanguage() + const dict = createMemo(() => i18n(language.locale())) + + return { + t(key: Key, params?: Record) { + return resolve(dict()[key], params) + }, + } + }, +}) diff --git a/packages/console/app/src/context/language.tsx b/packages/console/app/src/context/language.tsx new file mode 100644 index 00000000000..2999242f0ff --- /dev/null +++ b/packages/console/app/src/context/language.tsx @@ -0,0 +1,72 @@ +import { createEffect } from "solid-js" +import { createStore } from "solid-js/store" +import { getRequestEvent } from "solid-js/web" +import { createSimpleContext } from "@opencode-ai/ui/context" +import { + LOCALES, + type Locale, + clearCookie, + cookie, + detectFromLanguages, + dir as localeDir, + label as localeLabel, + localeFromCookieHeader, + localeFromRequest, + parseLocale, + route as localeRoute, + tag as localeTag, +} from "~/lib/language" + +function initial() { + const evt = getRequestEvent() + if (evt) return localeFromRequest(evt.request) + + if (typeof document === "object") { + const fromDom = parseLocale(document.documentElement.dataset.locale) + if (fromDom) return fromDom + + const fromCookie = localeFromCookieHeader(document.cookie) + if (fromCookie) return fromCookie + } + + if (typeof navigator !== "object") return "en" satisfies Locale + + const languages = navigator.languages?.length ? navigator.languages : [navigator.language] + return detectFromLanguages(languages) +} + +export const { use: useLanguage, provider: LanguageProvider } = createSimpleContext({ + name: "Language", + init: () => { + const [store, setStore] = createStore({ + locale: initial(), + }) + + createEffect(() => { + if (typeof document !== "object") return + document.documentElement.lang = localeTag(store.locale) + document.documentElement.dir = localeDir(store.locale) + document.documentElement.dataset.locale = store.locale + }) + + return { + locale: () => store.locale, + locales: LOCALES, + label: localeLabel, + tag: localeTag, + dir: localeDir, + route(pathname: string) { + return localeRoute(store.locale, pathname) + }, + setLocale(next: Locale) { + setStore("locale", next) + if (typeof document !== "object") return + document.cookie = cookie(next) + }, + clear() { + if (typeof document !== "object") return + document.cookie = clearCookie() + }, + } + }, +}) diff --git a/packages/console/app/src/i18n/ar.ts b/packages/console/app/src/i18n/ar.ts new file mode 100644 index 00000000000..bf22ec157fc --- /dev/null +++ b/packages/console/app/src/i18n/ar.ts @@ -0,0 +1,590 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "الوثائق", + "nav.changelog": "سجل التغييرات", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "المؤسسات", + "nav.zen": "Zen", + "nav.login": "تسجيل الدخول", + "nav.free": "مجانا", + "nav.home": "الرئيسية", + "nav.openMenu": "فتح القائمة", + "nav.getStartedFree": "ابدأ مجانا", + + "nav.context.copyLogo": "نسخ الشعار كـ SVG", + "nav.context.copyWordmark": "نسخ اسم العلامة كـ SVG", + "nav.context.brandAssets": "أصول العلامة التجارية", + + "footer.github": "GitHub", + "footer.docs": "الوثائق", + "footer.changelog": "سجل التغييرات", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "العلامة التجارية", + "legal.privacy": "الخصوصية", + "legal.terms": "الشروط", + + "email.title": "كن الأول في المعرفة عند إطلاق منتجات جديدة", + "email.subtitle": "انضم إلى قائمة الانتظار للحصول على وصول مبكر.", + "email.placeholder": "عنوان البريد الإلكتروني", + "email.subscribe": "اشتراك", + "email.success": "تبقّت خطوة واحدة: تحقق من بريدك وأكّد عنوانك", + + "notFound.title": "غير موجود | opencode", + "notFound.heading": "404 - الصفحة غير موجودة", + "notFound.home": "الرئيسية", + "notFound.docs": "الوثائق", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "تسجيل الخروج", + + "workspace.select": "اختر مساحة العمل", + "workspace.createNew": "+ إنشاء مساحة عمل جديدة", + "workspace.modal.title": "إنشاء مساحة عمل جديدة", + "workspace.modal.placeholder": "أدخل اسم مساحة العمل", + + "common.cancel": "إلغاء", + "common.creating": "جارٍ الإنشاء...", + "common.create": "إنشاء", + + "common.videoUnsupported": "متصفحك لا يدعم وسم الفيديو.", + "common.figure": "شكل {{n}}.", + "common.faq": "الأسئلة الشائعة", + "common.learnMore": "اعرف المزيد", + + "error.invalidPlan": "خطة غير صالحة", + "error.workspaceRequired": "معرف مساحة العمل مطلوب", + "error.alreadySubscribed": "مساحة العمل هذه لديها اشتراك بالفعل", + "error.limitRequired": "الحد مطلوب.", + "error.monthlyLimitInvalid": "قم بتعيين حد شهري صالح.", + "error.workspaceNameRequired": "اسم مساحة العمل مطلوب.", + "error.nameTooLong": "يجب أن يكون الاسم 255 حرفًا أو أقل.", + "error.emailRequired": "البريد الإلكتروني مطلوب", + "error.roleRequired": "الدور مطلوب", + "error.idRequired": "المعرف مطلوب", + "error.nameRequired": "الاسم مطلوب", + "error.providerRequired": "المزود مطلوب", + "error.apiKeyRequired": "مفتاح API مطلوب", + "error.modelRequired": "النموذج مطلوب", + "error.reloadAmountMin": "يجب أن يكون مبلغ الشحن ${{amount}} على الأقل", + "error.reloadTriggerMin": "يجب أن يكون حد الرصيد ${{amount}} على الأقل", + + "home.title": "OpenCode | وكيل برمجة بالذكاء الاصطناعي مفتوح المصدر", + + "temp.title": "opencode | وكيل برمجة بالذكاء الاصطناعي مبني للطرفية", + "temp.hero.title": "وكيل البرمجة بالذكاء الاصطناعي المبني للطرفية", + "temp.zen": "opencode zen", + "temp.getStarted": "ابدأ", + "temp.feature.native.title": "واجهة طرفية أصلية", + "temp.feature.native.body": "واجهة مستخدم طرفية سريعة الاستجابة، أصلية، وقابلة للتخصيص", + "temp.feature.zen.beforeLink": "قائمة", + "temp.feature.zen.link": "منسقة من النماذج", + "temp.feature.zen.afterLink": "مقدمة من opencode", + "temp.feature.models.beforeLink": "يدعم أكثر من 75 مزود LLM من خلال", + "temp.feature.models.afterLink": "، بما في ذلك النماذج المحلية", + "temp.screenshot.caption": "واجهة OpenCode الطرفية مع سمة tokyonight", + "temp.screenshot.alt": "واجهة OpenCode الطرفية بسمة tokyonight", + + "home.banner.badge": "جديد", + "home.banner.text": "تطبيق سطح المكتب متاح بنسخة تجريبية", + "home.banner.platforms": "على macOS، Windows، وLinux", + "home.banner.downloadNow": "حمّل الآن", + "home.banner.downloadBetaNow": "حمّل النسخة التجريبية لتطبيق سطح المكتب الآن", + + "home.hero.title": "وكيل برمجة بالذكاء الاصطناعي مفتوح المصدر", + "home.hero.subtitle.a": "نماذج مجانية مضمّنة أو اربط أي نموذج من أي مزوّد،", + "home.hero.subtitle.b": "بما في ذلك Claude، GPT، Gemini وغيرها.", + + "home.install.ariaLabel": "خيارات التثبيت", + + "home.what.title": "ما هو OpenCode؟", + "home.what.body": "OpenCode وكيل مفتوح المصدر يساعدك على كتابة الكود في الطرفية، IDE، أو سطح المكتب.", + "home.what.lsp.title": "دعم LSP", + "home.what.lsp.body": "يحمّل تلقائيًا موافقات LSP المناسبة للـ LLM", + "home.what.multiSession.title": "جلسات متعددة", + "home.what.multiSession.body": "ابدأ عدة وكلاء بالتوازي على نفس المشروع", + "home.what.shareLinks.title": "روابط المشاركة", + "home.what.shareLinks.body": "شارك رابطًا لأي جلسة للرجوع إليها أو لتصحيح الأخطاء", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "سجّل الدخول بـ GitHub لاستخدام حسابك في Copilot", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "سجّل الدخول بـ OpenAI لاستخدام حسابك في ChatGPT Plus أو Pro", + "home.what.anyModel.title": "أي نموذج", + "home.what.anyModel.body": "75+ مزوّد LLM عبر Models.dev، بما في ذلك النماذج المحلية", + "home.what.anyEditor.title": "أي محرر", + "home.what.anyEditor.body": "متاح كواجهة طرفية، وتطبيق سطح مكتب، وامتداد IDE", + "home.what.readDocs": "اقرأ الوثائق", + + "home.growth.title": "وكيل برمجة بالذكاء الاصطناعي مفتوح المصدر", + "home.growth.body": + "مع أكثر من {{stars}} نجمة على GitHub، و{{contributors}} مساهمًا، وأكثر من {{commits}} Commit، يستخدم OpenCode ويثق به أكثر من {{monthlyUsers}} مطوّر كل شهر.", + "home.growth.githubStars": "نجوم GitHub", + "home.growth.contributors": "المساهمون", + "home.growth.monthlyDevs": "مطورون شهريًا", + + "home.privacy.title": "مصمم للخصوصية أولاً", + "home.privacy.body": "لا يخزّن OpenCode أي كود أو بيانات سياق، ليتمكن من العمل في بيئات حساسة للخصوصية.", + "home.privacy.learnMore": "اعرف المزيد عن", + "home.privacy.link": "الخصوصية", + + "home.faq.q1": "ما هو OpenCode؟", + "home.faq.a1": + "OpenCode وكيل مفتوح المصدر يساعدك على كتابة وتشغيل الكود مع أي نموذج ذكاء اصطناعي. متاح كواجهة طرفية، وتطبيق سطح مكتب، أو امتداد IDE.", + "home.faq.q2": "كيف أستخدم OpenCode؟", + "home.faq.a2.before": "أسهل طريقة للبدء هي قراءة", + "home.faq.a2.link": "المقدمة", + "home.faq.q3": "هل أحتاج لاشتراكات ذكاء اصطناعي إضافية لاستخدام OpenCode؟", + "home.faq.a3.p1": + "ليس بالضرورة، فـ OpenCode يأتي مع مجموعة من النماذج المجانية التي تستطيع استخدامها دون إنشاء حساب.", + "home.faq.a3.p2.beforeZen": "وبخلاف ذلك، يمكنك استخدام أي من نماذج البرمجة الشائعة بإنشاء حساب", + "home.faq.a3.p2.afterZen": ".", + "home.faq.a3.p3": + "مع أننا نشجّع المستخدمين على استخدام Zen، فإن OpenCode يعمل أيضًا مع كل المزودين الشائعين مثل OpenAI، Anthropic، xAI إلخ.", + "home.faq.a3.p4.beforeLocal": "ويمكنك أيضًا ربط", + "home.faq.a3.p4.localLink": "النماذج المحلية", + "home.faq.q4": "هل يمكنني استخدام اشتراكاتي الحالية مع OpenCode؟", + "home.faq.a4.p1": + "نعم، يدعم OpenCode خطط الاشتراك من كل المزودين الرئيسيين. يمكنك استخدام اشتراكات Claude Pro/Max، ChatGPT Plus/Pro، أو GitHub Copilot.", + "home.faq.q5": "هل يمكنني استخدام OpenCode في الطرفية فقط؟", + "home.faq.a5.beforeDesktop": "ليس بعد الآن! OpenCode متاح الآن كتطبيق لـ", + "home.faq.a5.desktop": "سطح المكتب", + "home.faq.a5.and": "و", + "home.faq.a5.web": "الويب", + "home.faq.q6": "كم تكلفة OpenCode؟", + "home.faq.a6": + "OpenCode مجاني 100% للاستخدام. كما يأتي مع مجموعة من النماذج المجانية. قد توجد تكاليف إضافية إذا ربطت مزوّدًا آخر.", + "home.faq.q7": "ماذا عن البيانات والخصوصية؟", + "home.faq.a7.p1": "لا يتم تخزين بياناتك ومعلوماتك إلا عندما تستخدم نماذجنا المجانية أو تنشئ روابط قابلة للمشاركة.", + "home.faq.a7.p2.beforeModels": "اعرف المزيد عن", + "home.faq.a7.p2.modelsLink": "نماذجنا", + "home.faq.a7.p2.and": "و", + "home.faq.a7.p2.shareLink": "صفحات المشاركة", + "home.faq.q8": "هل OpenCode مفتوح المصدر؟", + "home.faq.a8.p1": "نعم، OpenCode مفتوح المصدر بالكامل. الكود المصدري متاح علنًا على", + "home.faq.a8.p2": "بموجب", + "home.faq.a8.mitLicense": "رخصة MIT", + "home.faq.a8.p3": + "، مما يعني أن أي شخص يستطيع استخدامه أو تعديله أو المساهمة في تطويره. يمكن لأي شخص من المجتمع فتح قضايا، وتقديم طلبات سحب، وتوسيع الوظائف.", + + "home.zenCta.title": "وصول لنماذج محسنة وموثوقة لوكلاء البرمجة", + "home.zenCta.body": + "يمنحك Zen الوصول إلى مجموعة مختارة بعناية من نماذج الذكاء الاصطناعي التي اختبرها OpenCode وقاس أداءها خصيصًا لوكلاء البرمجة. لا حاجة للقلق بشأن اختلاف الأداء والجودة بين المزودين، استخدم نماذج محققة تعمل بكفاءة.", + "home.zenCta.link": "تعرف على Zen", + + "zen.title": "OpenCode Zen | مجموعة منسقة من النماذج المحسنة والموثوقة لوكلاء البرمجة", + "zen.hero.title": "نماذج محسنة وموثوقة لوكلاء البرمجة", + "zen.hero.body": + "يمنحك Zen الوصول إلى مجموعة منسقة من نماذج الذكاء الاصطناعي التي اختبرها OpenCode وقاس أداءها خصيصًا لوكلاء البرمجة. لا حاجة للقلق بشأن اختلاف الأداء والجودة، استخدم نماذج محققة تعمل بكفاءة.", + + "zen.faq.q1": "ما هو OpenCode Zen؟", + "zen.faq.a1": + "Zen هو مجموعة منسقة من نماذج الذكاء الاصطناعي التي تم اختبارها وقياس أدائها لوكلاء البرمجة، أنشأها الفريق المطور لـ OpenCode.", + "zen.faq.q2": "ما الذي يجعل Zen أكثر دقة؟", + "zen.faq.a2": + "يوفر Zen فقط النماذج التي تم اختبارها وقياس أدائها خصيصًا لوكلاء البرمجة. لن تستخدم سكين زبدة لقطع شريحة لحم، فلا تستخدم نماذج ضعيفة للبرمجة.", + "zen.faq.q3": "هل Zen أرخص؟", + "zen.faq.a3": + "Zen ليس للربح. يمرر Zen التكاليف من مزودي النماذج إليك مباشرة. كلما زاد استخدام Zen، تمكن OpenCode من التفاوض على أسعار أفضل وتمريرها إليك.", + "zen.faq.q4": "كم تكلفة Zen؟", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "يحاسب لكل طلب", + "zen.faq.a4.p1.afterPricing": "بدون أي هوامش ربح، لذا تدفع بالضبط ما يفرضه مزود النموذج.", + "zen.faq.a4.p2.beforeAccount": "تعتمد تكلفتك الإجمالية على الاستخدام، ويمكنك تعيين حدود إنفاق شهرية في", + "zen.faq.a4.p2.accountLink": "حسابك", + "zen.faq.a4.p3": + "لتغطية التكاليف، يضيف OpenCode فقط رسومًا صغيرة لمعالجة الدفع قدرها 1.23 دولار لكل إعادة شحن رصيد بقيمة 20 دولارًا.", + "zen.faq.q5": "ماذا عن البيانات والخصوصية؟", + "zen.faq.a5.beforeExceptions": + "تتم استضافة جميع نماذج Zen في الولايات المتحدة. يتبع المزودون سياسة عدم الاحتفاظ بالبيانات ولا يستخدمون بياناتك لتدريب النماذج، مع", + "zen.faq.a5.exceptionsLink": "الاستثناءات التالية", + "zen.faq.q6": "هل يمكنني تعيين حدود للإنفاق؟", + "zen.faq.a6": "نعم، يمكنك تعيين حدود إنفاق شهرية في حسابك.", + "zen.faq.q7": "هل يمكنني الإلغاء؟", + "zen.faq.a7": "نعم، يمكنك تعطيل الفوترة في أي وقت واستخدام رصيدك المتبقي.", + "zen.faq.q8": "هل يمكنني استخدام Zen مع وكلاء برمجة آخرين؟", + "zen.faq.a8": + "بينما يعمل Zen بشكل رائع مع OpenCode، يمكنك استخدام Zen مع أي وكيل. اتبع تعليمات الإعداد في وكيل البرمجة المفضل لديك.", + + "zen.cta.start": "ابدأ مع Zen", + "zen.pricing.title": "أضف رصيد 20 دولار (دفع حسب الاستخدام)", + "zen.pricing.fee": "(+1.23 دولار رسوم معالجة البطاقة)", + "zen.pricing.body": "استخدمه مع أي وكيل. عيّن حدود الإنفاق الشهري. ألغِ في أي وقت.", + "zen.problem.title": "ما المشكلة التي يحلها Zen؟", + "zen.problem.body": + "هناك العديد من النماذج المتاحة، ولكن القليل منها فقط يعمل بشكل جيد مع وكلاء البرمجة. يقوم معظم مقدمي الخدمة بتكوينها بشكل مختلف مما يعطي نتائج متفاوتة.", + "zen.problem.subtitle": "نحن نعمل على إصلاح هذا للجميع، وليس فقط لمستخدمي OpenCode.", + "zen.problem.item1": "اختبار نماذج مختارة واستشارة فرقها", + "zen.problem.item2": "العمل مع مقدمي الخدمة لضمان تسليمها بشكل صحيح", + "zen.problem.item3": "قياس أداء جميع مجموعات النماذج والمزودين التي نوصي بها", + "zen.how.title": "كيف يعمل Zen", + "zen.how.body": "بينما نقترح عليك استخدام Zen مع OpenCode، يمكنك استخدام Zen مع أي وكيل.", + "zen.how.step1.title": "سجّل وأضف رصيدًا بقيمة 20 دولارًا", + "zen.how.step1.beforeLink": "اتبع", + "zen.how.step1.link": "تعليمات الإعداد", + "zen.how.step2.title": "استخدم Zen بتسعير شفاف", + "zen.how.step2.link": "ادفع لكل طلب", + "zen.how.step2.afterLink": "بدون أي هوامش ربح", + "zen.how.step3.title": "شحن تلقائي", + "zen.how.step3.body": "عندما يصل رصيدك إلى 5 دولارات، سنضيف تلقائيًا 20 دولارًا", + "zen.privacy.title": "خصوصيتك مهمة بالنسبة لنا", + "zen.privacy.beforeExceptions": + "تتم استضافة جميع نماذج Zen في الولايات المتحدة. يتبع المزودون سياسة عدم الاحتفاظ بالبيانات ولا يستخدمون بياناتك لتدريب النماذج، مع", + "zen.privacy.exceptionsLink": "الاستثناءات التالية", + + "black.meta.title": "OpenCode Black | الوصول إلى أفضل نماذج البرمجة في العالم", + "black.meta.description": "احصل على وصول إلى Claude، GPT، Gemini والمزيد مع خطط اشتراك OpenCode Black.", + "black.hero.title": "الوصول إلى أفضل نماذج البرمجة في العالم", + "black.hero.subtitle": "بما في ذلك Claude، GPT، Gemini والمزيد", + "black.title": "OpenCode Black | الأسعار", + "black.plan.icon20": "خطة Black 20", + "black.plan.icon100": "خطة Black 100", + "black.plan.icon200": "خطة Black 200", + "black.plan.multiplier100": "استخدام أكثر بـ 5 أضعاف من Black 20", + "black.plan.multiplier200": "استخدام أكثر بـ 20 ضعفًا من Black 20", + "black.price.perMonth": "شهريًا", + "black.price.perPersonBilledMonthly": "للشخص الواحد، يُفوتر شهريًا", + "black.terms.1": "لن يبدأ اشتراكك على الفور", + "black.terms.2": "ستتم إضافتك إلى قائمة الانتظار وتفعيلك قريبًا", + "black.terms.3": "لن يتم خصم المبلغ من بطاقتك إلا عند تفعيل اشتراكك", + "black.terms.4": "تطبق حدود الاستخدام، وقد يصل الاستخدام المؤتمت بكثافة إلى الحدود بشكل أسرع", + "black.terms.5": "الاشتراكات للأفراد، تواصل مع قسم المؤسسات للفرق", + "black.terms.6": "قد يتم تعديل الحدود وقد يتم إيقاف الخطط في المستقبل", + "black.terms.7": "ألغِ اشتراكك في أي وقت", + "black.action.continue": "متابعة", + "black.finePrint.beforeTerms": "الأسعار المعروضة لا تشمل الضرائب المطبقة", + "black.finePrint.terms": "شروط الخدمة", + "black.workspace.title": "OpenCode Black | اختر مساحة العمل", + "black.workspace.selectPlan": "اختر مساحة عمل لهذه الخطة", + "black.workspace.name": "مساحة العمل {{n}}", + "black.subscribe.title": "اشترك في OpenCode Black", + "black.subscribe.paymentMethod": "طريقة الدفع", + "black.subscribe.loadingPaymentForm": "جارٍ تحميل نموذج الدفع...", + "black.subscribe.selectWorkspaceToContinue": "اختر مساحة عمل للمتابعة", + "black.subscribe.failurePrefix": "أوه لا!", + "black.subscribe.error.generic": "حدث خطأ", + "black.subscribe.error.invalidPlan": "خطة غير صالحة", + "black.subscribe.error.workspaceRequired": "معرف مساحة العمل مطلوب", + "black.subscribe.error.alreadySubscribed": "مساحة العمل هذه لديها اشتراك بالفعل", + "black.subscribe.processing": "جارٍ المعالجة...", + "black.subscribe.submit": "اشترك بمبلغ ${{plan}}", + "black.subscribe.form.chargeNotice": "لن يتم خصم المبلغ إلا عند تفعيل اشتراكك", + "black.subscribe.success.title": "أنت في قائمة انتظار OpenCode Black", + "black.subscribe.success.subscriptionPlan": "خطة الاشتراك", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "المبلغ", + "black.subscribe.success.amountValue": "${{plan}} شهريًا", + "black.subscribe.success.paymentMethod": "طريقة الدفع", + "black.subscribe.success.dateJoined": "تاريخ الانضمام", + "black.subscribe.success.chargeNotice": "سيتم خصم المبلغ من بطاقتك عند تفعيل اشتراكك", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "مفاتيح API", + "workspace.nav.members": "الأعضاء", + "workspace.nav.billing": "الفوترة", + "workspace.nav.settings": "الإعدادات", + + "workspace.home.banner.beforeLink": "نماذج محسنة وموثوقة لوكلاء البرمجة.", + "workspace.home.billing.loading": "جارٍ التحميل...", + "workspace.home.billing.enable": "تمكين الفوترة", + "workspace.home.billing.currentBalance": "الرصيد الحالي", + + "workspace.newUser.feature.tested.title": "نماذج مُختبرة ومحققة", + "workspace.newUser.feature.tested.body": "لقد قمنا بقياس واختبار النماذج خصيصًا لوكلاء البرمجة لضمان أفضل أداء.", + "workspace.newUser.feature.quality.title": "أعلى جودة", + "workspace.newUser.feature.quality.body": + "الوصول إلى النماذج التي تم تكوينها لتحقيق الأداء الأمثل - لا تقليل للجودة أو توجيه إلى موفري خدمة أرخص.", + "workspace.newUser.feature.lockin.title": "لا قيود على المزود", + "workspace.newUser.feature.lockin.body": + "استخدم Zen مع أي وكيل برمجة، واستمر في استخدام موفرين آخرين مع opencode وقتما تشاء.", + "workspace.newUser.copyApiKey": "نسخ مفتاح API", + "workspace.newUser.copyKey": "نسخ المفتاح", + "workspace.newUser.copied": "تم النسخ!", + "workspace.newUser.step.enableBilling": "تمكين الفوترة", + "workspace.newUser.step.login.before": "شغّل", + "workspace.newUser.step.login.after": "واختر opencode", + "workspace.newUser.step.pasteKey": "الصق مفتاح API الخاص بك", + "workspace.newUser.step.models.before": "ابدأ opencode ثم نفّذ", + "workspace.newUser.step.models.after": "لاختيار نموذج", + + "workspace.models.title": "النماذج", + "workspace.models.subtitle.beforeLink": "إدارة النماذج التي يمكن لأعضاء مساحة العمل الوصول إليها.", + "workspace.models.table.model": "النموذج", + "workspace.models.table.enabled": "ممكّن", + + "workspace.providers.title": "أحضر مفتاحك الخاص", + "workspace.providers.subtitle": "قم بتكوين مفاتيح API الخاصة بك من موفري الذكاء الاصطناعي.", + "workspace.providers.placeholder": "أدخل مفتاح API لـ {{provider}} ({{prefix}}...)", + "workspace.providers.configure": "تكوين", + "workspace.providers.edit": "تعديل", + "workspace.providers.delete": "حذف", + "workspace.providers.saving": "جارٍ الحفظ...", + "workspace.providers.save": "حفظ", + "workspace.providers.table.provider": "المزود", + "workspace.providers.table.apiKey": "مفتاح API", + + "workspace.usage.title": "تاريخ الاستخدام", + "workspace.usage.subtitle": "استخدام وتكاليف API الأخيرة.", + "workspace.usage.empty": "قم بإجراء أول استدعاء API للبدء.", + "workspace.usage.table.date": "التاريخ", + "workspace.usage.table.model": "النموذج", + "workspace.usage.table.input": "الدخل", + "workspace.usage.table.output": "الخرج", + "workspace.usage.table.cost": "التكلفة", + "workspace.usage.breakdown.input": "الدخل", + "workspace.usage.breakdown.cacheRead": "قراءة الكاش", + "workspace.usage.breakdown.cacheWrite": "كتابة الكاش", + "workspace.usage.breakdown.output": "الخرج", + "workspace.usage.breakdown.reasoning": "المنطق", + "workspace.usage.subscription": "الاشتراك (${{amount}})", + + "workspace.cost.title": "التكلفة", + "workspace.cost.subtitle": "تكاليف الاستخدام مقسمة حسب النموذج.", + "workspace.cost.allModels": "جميع النماذج", + "workspace.cost.allKeys": "جميع المفاتيح", + "workspace.cost.deletedSuffix": "(محذوف)", + "workspace.cost.empty": "لا توجد بيانات استخدام متاحة للفترة المحددة.", + "workspace.cost.subscriptionShort": "اشتراك", + + "workspace.keys.title": "مفاتيح API", + "workspace.keys.subtitle": "إدارة مفاتيح API الخاصة بك للوصول إلى خدمات opencode.", + "workspace.keys.create": "إنشاء مفتاح API", + "workspace.keys.placeholder": "أدخل اسم المفتاح", + "workspace.keys.empty": "أنشئ مفتاح API لبوابة opencode", + "workspace.keys.table.name": "الاسم", + "workspace.keys.table.key": "المفتاح", + "workspace.keys.table.createdBy": "تم الإنشاء بواسطة", + "workspace.keys.table.lastUsed": "آخر استخدام", + "workspace.keys.copyApiKey": "نسخ مفتاح API", + "workspace.keys.delete": "حذف", + + "workspace.members.title": "الأعضاء", + "workspace.members.subtitle": "إدارة أعضاء مساحة العمل وأذوناتهم.", + "workspace.members.invite": "دعوة عضو", + "workspace.members.inviting": "جارٍ الدعوة...", + "workspace.members.beta.beforeLink": "مساحات العمل مجانية للفرق أثناء الفترة التجريبية.", + "workspace.members.form.invitee": "المدعو", + "workspace.members.form.emailPlaceholder": "أدخل البريد الإلكتروني", + "workspace.members.form.role": "الدور", + "workspace.members.form.monthlyLimit": "حد الإنفاق الشهري", + "workspace.members.noLimit": "لا يوجد حد", + "workspace.members.noLimitLowercase": "لا يوجد حد", + "workspace.members.invited": "تمت دعوته", + "workspace.members.edit": "تعديل", + "workspace.members.delete": "حذف", + "workspace.members.saving": "جارٍ الحفظ...", + "workspace.members.save": "حفظ", + "workspace.members.table.email": "البريد الإلكتروني", + "workspace.members.table.role": "الدور", + "workspace.members.table.monthLimit": "الحد الشهري", + "workspace.members.role.admin": "مسؤول", + "workspace.members.role.adminDescription": "يمكنه إدارة النماذج، والأعضاء، والفوترة", + "workspace.members.role.member": "عضو", + "workspace.members.role.memberDescription": "يمكنه فقط إنشاء مفاتيح API لنفسه", + + "workspace.settings.title": "الإعدادات", + "workspace.settings.subtitle": "حدّث اسم مساحة العمل وتفضيلاتك.", + "workspace.settings.workspaceName": "اسم مساحة العمل", + "workspace.settings.defaultName": "افتراضي", + "workspace.settings.updating": "جارٍ التحديث...", + "workspace.settings.save": "حفظ", + "workspace.settings.edit": "تعديل", + + "workspace.billing.title": "الفوترة", + "workspace.billing.subtitle.beforeLink": "إدارة طرق الدفع.", + "workspace.billing.contactUs": "اتصل بنا", + "workspace.billing.subtitle.afterLink": "إذا كان لديك أي أسئلة.", + "workspace.billing.currentBalance": "الرصيد الحالي", + "workspace.billing.add": "أضف $", + "workspace.billing.enterAmount": "أدخل المبلغ", + "workspace.billing.loading": "جارٍ التحميل...", + "workspace.billing.addAction": "إضافة", + "workspace.billing.addBalance": "إضافة رصيد", + "workspace.billing.linkedToStripe": "مرتبط بـ Stripe", + "workspace.billing.manage": "إدارة", + "workspace.billing.enable": "تمكين الفوترة", + + "workspace.monthlyLimit.title": "الحد الشهري", + "workspace.monthlyLimit.subtitle": "عيّن حد الاستخدام الشهري لحسابك.", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "جارٍ التعيين...", + "workspace.monthlyLimit.set": "تعيين", + "workspace.monthlyLimit.edit": "تعديل الحد", + "workspace.monthlyLimit.noLimit": "لم يتم تعيين حد للاستخدام.", + "workspace.monthlyLimit.currentUsage.beforeMonth": "الاستخدام الحالي لـ", + "workspace.monthlyLimit.currentUsage.beforeAmount": "هو $", + + "workspace.reload.title": "إعادة الشحن التلقائي", + "workspace.reload.disabled.before": "إعادة الشحن التلقائي", + "workspace.reload.disabled.state": "معطّل", + "workspace.reload.disabled.after": "فعّلها لإعادة شحن الرصيد تلقائيًا عندما ينخفض.", + "workspace.reload.enabled.before": "إعادة الشحن التلقائي", + "workspace.reload.enabled.state": "ممكّن", + "workspace.reload.enabled.middle": "سنعيد شحن رصيدك بمبلغ", + "workspace.reload.processingFee": "رسوم معالجة", + "workspace.reload.enabled.after": "عندما يصل الرصيد إلى", + "workspace.reload.edit": "تعديل", + "workspace.reload.enable": "تفعيل", + "workspace.reload.enableAutoReload": "تفعيل إعادة الشحن التلقائي", + "workspace.reload.reloadAmount": "مبلغ الشحن $", + "workspace.reload.whenBalanceReaches": "عندما يصل الرصيد إلى $", + "workspace.reload.saving": "جارٍ الحفظ...", + "workspace.reload.save": "حفظ", + "workspace.reload.failedAt": "فشلت إعادة الشحن في", + "workspace.reload.reason": "السبب:", + "workspace.reload.updatePaymentMethod": "يرجى تحديث طريقة الدفع والمحاولة مرة أخرى.", + "workspace.reload.retrying": "جارٍ إعادة المحاولة...", + "workspace.reload.retry": "أعد المحاولة", + + "workspace.payments.title": "سجل المدفوعات", + "workspace.payments.subtitle": "معاملات الدفع الأخيرة.", + "workspace.payments.table.date": "التاريخ", + "workspace.payments.table.paymentId": "معرف الدفع", + "workspace.payments.table.amount": "المبلغ", + "workspace.payments.table.receipt": "الإيصال", + "workspace.payments.type.credit": "رصيد", + "workspace.payments.type.subscription": "اشتراك", + "workspace.payments.view": "عرض", + + "workspace.black.loading": "جارٍ التحميل...", + "workspace.black.time.day": "يوم", + "workspace.black.time.days": "أيام", + "workspace.black.time.hour": "ساعة", + "workspace.black.time.hours": "ساعات", + "workspace.black.time.minute": "دقيقة", + "workspace.black.time.minutes": "دقائق", + "workspace.black.time.fewSeconds": "بضع ثوان", + "workspace.black.subscription.title": "الاشتراك", + "workspace.black.subscription.message": "أنت مشترك في OpenCode Black مقابل ${{plan}} شهريًا.", + "workspace.black.subscription.manage": "إدارة الاشتراك", + "workspace.black.subscription.rollingUsage": "استخدام لمدة 5 ساعات", + "workspace.black.subscription.weeklyUsage": "الاستخدام الأسبوعي", + "workspace.black.subscription.resetsIn": "إعادة تعيين في", + "workspace.black.subscription.useBalance": "استخدم رصيدك المتوفر بعد الوصول إلى حدود الاستخدام", + "workspace.black.waitlist.title": "قائمة الانتظار", + "workspace.black.waitlist.joined": "أنت في قائمة الانتظار لخطة OpenCode Black بقيمة ${{plan}} شهريًا.", + "workspace.black.waitlist.ready": "نحن مستعدون لتسجيلك في خطة OpenCode Black بقيمة ${{plan}} شهريًا.", + "workspace.black.waitlist.leave": "ترك قائمة الانتظار", + "workspace.black.waitlist.leaving": "جارٍ المغادرة...", + "workspace.black.waitlist.left": "غادر", + "workspace.black.waitlist.enroll": "تسجيل", + "workspace.black.waitlist.enrolling": "جارٍ التسجيل...", + "workspace.black.waitlist.enrolled": "مسجل", + "workspace.black.waitlist.enrollNote": 'عند النقر فوق "تسجيل"، يبدأ اشتراكك على الفور وسيتم خصم الرسوم من بطاقتك.', + + "download.title": "OpenCode | تنزيل", + "download.meta.description": "نزّل OpenCode لـ macOS، Windows، وLinux", + "download.hero.title": "تنزيل OpenCode", + "download.hero.subtitle": "متاح في نسخة تجريبية لـ macOS، Windows، وLinux", + "download.hero.button": "تنزيل لـ {{os}}", + "download.section.terminal": "OpenCode للطرفية", + "download.section.desktop": "OpenCode لسطح المكتب (Beta)", + "download.section.extensions": "امتدادات OpenCode", + "download.section.integrations": "تكاملات OpenCode", + "download.action.download": "تنزيل", + "download.action.install": "تثبيت", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "ليس بالضرورة، ولكن على الأرجح. ستحتاج إلى اشتراك ذكاء اصطناعي إذا كنت تريد ربط OpenCode بمزوّد مدفوع، رغم أنه يمكنك العمل مع", + "download.faq.a3.localLink": "النماذج المحلية", + "download.faq.a3.afterLocal.beforeZen": "مجانًا. بينما نشجع المستخدمين على استخدام", + "download.faq.a3.afterZen": "، فإن OpenCode يعمل مع جميع المزودين الشائعين مثل OpenAI، Anthropic، xAI إلخ.", + + "download.faq.a5.p1": "OpenCode مجاني 100% للاستخدام.", + "download.faq.a5.p2.beforeZen": + "أي تكاليف إضافية ستأتي من اشتراكك لدى مزود النماذج. بينما يعمل OpenCode مع أي مزود نماذج، نوصي باستخدام", + "download.faq.a5.p2.afterZen": ".", + + "download.faq.a6.p1": "يتم حفظ بياناتك ومعلوماتك فقط عند إنشاء روابط قابلة للمشاركة في OpenCode.", + "download.faq.a6.p2.beforeShare": "اعرف المزيد عن", + "download.faq.a6.shareLink": "صفحات المشاركة", + + "enterprise.title": "OpenCode | حلول المؤسسات لمنظمتك", + "enterprise.meta.description": "تواصل مع OpenCode لحلول المؤسسات", + "enterprise.hero.title": "كودك ملكك", + "enterprise.hero.body1": + "يعمل OpenCode بأمان داخل مؤسستك دون تخزين أي بيانات أو سياق، ودون قيود ترخيص أو مطالبات ملكية. ابدأ تجربة مع فريقك، ثم انشره عبر مؤسستك من خلال دمجه مع SSO وبوابة الذكاء الاصطناعي الداخلية لديك.", + "enterprise.hero.body2": "أخبرنا كيف يمكننا المساعدة.", + "enterprise.form.name.label": "الاسم الكامل", + "enterprise.form.name.placeholder": "جيف بيزوس", + "enterprise.form.role.label": "المنصب", + "enterprise.form.role.placeholder": "رئيس مجلس الإدارة التنفيذي", + "enterprise.form.email.label": "البريد الإلكتروني للشركة", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "ما المشكلة التي تحاول حلها؟", + "enterprise.form.message.placeholder": "نحتاج مساعدة في...", + "enterprise.form.send": "إرسال", + "enterprise.form.sending": "جارٍ الإرسال...", + "enterprise.form.success": "تم إرسال الرسالة، سنتواصل معك قريبًا.", + "enterprise.faq.title": "الأسئلة الشائعة", + "enterprise.faq.q1": "ما هو OpenCode Enterprise؟", + "enterprise.faq.a1": + "OpenCode Enterprise مخصص للمؤسسات التي تريد التأكد من أن الكود والبيانات لا تغادر بنيتها التحتية أبدًا. يتحقق ذلك عبر استخدام تكوين مركزي يندمج مع SSO وبوابة الذكاء الاصطناعي الداخلية لديك.", + "enterprise.faq.q2": "كيف أبدأ مع OpenCode Enterprise؟", + "enterprise.faq.a2": + "ابدأ ببساطة بتجربة داخلية مع فريقك. افتراضيًا، لا يقوم OpenCode بتخزين الكود أو بيانات السياق، مما يجعل البدء سهلاً. ثم اتصل بنا لمناقشة الأسعار وخيارات التنفيذ.", + "enterprise.faq.q3": "كيف تعمل تسعيرة المؤسسات؟", + "enterprise.faq.a3": + "نقدم تسعيرًا للمؤسسات حسب المقعد. إذا كان لديك بوابة LLM خاصة بك، فلن نفرض رسومًا على التوكنات المستخدمة. لمزيد من التفاصيل، اتصل بنا للحصول على عرض سعر مخصص بناءً على احتياجات مؤسستك.", + "enterprise.faq.q4": "هل بياناتي آمنة مع OpenCode Enterprise؟", + "enterprise.faq.a4": + "نعم. لا يقوم OpenCode بتخزين الكود أو بيانات السياق. تتم جميع المعالجة محليًا أو عبر استدعاءات API مباشرة إلى مزود الذكاء الاصطناعي لديك. مع التكوين المركزي وتكامل SSO، تظل بياناتك آمنة داخل البنية التحتية لمؤسستك.", + + "brand.title": "OpenCode | العلامة التجارية", + "brand.meta.description": "إرشادات العلامة التجارية لـ OpenCode", + "brand.heading": "إرشادات العلامة التجارية", + "brand.subtitle": "موارد وأصول لمساعدتك في العمل مع العلامة التجارية لـ OpenCode.", + "brand.downloadAll": "تنزيل جميع الأصول", + + "changelog.title": "OpenCode | سجل التغييرات", + "changelog.meta.description": "ملاحظات الإصدار وسجل التغييرات لـ OpenCode", + "changelog.hero.title": "سجل التغييرات", + "changelog.hero.subtitle": "تحديثات وتحسينات جديدة لـ OpenCode", + "changelog.empty": "لم يتم العثور على مدخلات في سجل التغييرات.", + "changelog.viewJson": "عرض JSON", + + "bench.list.title": "المعيار", + "bench.list.heading": "المعايير", + "bench.list.table.agent": "الوكيل", + "bench.list.table.model": "النموذج", + "bench.list.table.score": "الدرجة", + + "bench.detail.title": "المعيار - {{task}}", + "bench.detail.notFound": "المهمة غير موجودة", + "bench.detail.na": "غير متاح", + "bench.detail.labels.agent": "الوكيل", + "bench.detail.labels.model": "النموذج", + "bench.detail.labels.task": "المهمة", + "bench.detail.labels.repo": "المستودع", + "bench.detail.labels.from": "من", + "bench.detail.labels.to": "إلى", + "bench.detail.labels.prompt": "الموجه", + "bench.detail.labels.commit": "Commit", + "bench.detail.labels.averageDuration": "متوسط المدة", + "bench.detail.labels.averageScore": "متوسط الدرجة", + "bench.detail.labels.averageCost": "متوسط التكلفة", + "bench.detail.labels.summary": "الملخص", + "bench.detail.labels.runs": "تشغيلات", + "bench.detail.labels.score": "الدرجة", + "bench.detail.labels.base": "الأساس", + "bench.detail.labels.penalty": "الجزاء", + "bench.detail.labels.weight": "الوزن", + "bench.detail.table.run": "تشغيل", + "bench.detail.table.score": "الدرجة (الأساس - الجزاء)", + "bench.detail.table.cost": "التكلفة", + "bench.detail.table.duration": "المدة", + "bench.detail.run.title": "تشغيل {{n}}", + "bench.detail.rawJson": "JSON خام", +} satisfies Dict diff --git a/packages/console/app/src/i18n/br.ts b/packages/console/app/src/i18n/br.ts new file mode 100644 index 00000000000..0f39484eff4 --- /dev/null +++ b/packages/console/app/src/i18n/br.ts @@ -0,0 +1,598 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "Documentação", + "nav.changelog": "Changelog", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "Enterprise", + "nav.zen": "Zen", + "nav.login": "Entrar", + "nav.free": "Grátis", + "nav.home": "Início", + "nav.openMenu": "Abrir menu", + "nav.getStartedFree": "Começar grátis", + + "nav.context.copyLogo": "Copiar logo como SVG", + "nav.context.copyWordmark": "Copiar marca como SVG", + "nav.context.brandAssets": "Recursos da marca", + + "footer.github": "GitHub", + "footer.docs": "Documentação", + "footer.changelog": "Changelog", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "Marca", + "legal.privacy": "Privacidade", + "legal.terms": "Termos", + + "email.title": "Seja o primeiro a saber quando lançarmos novos produtos", + "email.subtitle": "Entre na lista de espera para acesso antecipado.", + "email.placeholder": "Endereço de e-mail", + "email.subscribe": "Inscrever-se", + "email.success": "Quase lá, verifique sua caixa de entrada e confirme seu e-mail", + + "notFound.title": "Não encontrado | opencode", + "notFound.heading": "404 - Página não encontrada", + "notFound.home": "Início", + "notFound.docs": "Documentação", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "Sair", + + "workspace.select": "Selecionar workspace", + "workspace.createNew": "+ Criar novo workspace", + "workspace.modal.title": "Criar novo workspace", + "workspace.modal.placeholder": "Digite o nome do workspace", + + "common.cancel": "Cancelar", + "common.creating": "Criando...", + "common.create": "Criar", + + "common.videoUnsupported": "Seu navegador não suporta a tag de vídeo.", + "common.figure": "Fig {{n}}.", + "common.faq": "FAQ", + "common.learnMore": "Saiba mais", + + "error.invalidPlan": "Plano inválido", + "error.workspaceRequired": "ID do workspace é obrigatório", + "error.alreadySubscribed": "Este workspace já possui uma assinatura", + "error.limitRequired": "Limite é obrigatório.", + "error.monthlyLimitInvalid": "Defina um limite mensal válido.", + "error.workspaceNameRequired": "Nome do workspace é obrigatório.", + "error.nameTooLong": "O nome deve ter 255 caracteres ou menos.", + "error.emailRequired": "E-mail é obrigatório", + "error.roleRequired": "Função é obrigatória", + "error.idRequired": "ID é obrigatório", + "error.nameRequired": "Nome é obrigatório", + "error.providerRequired": "Provedor é obrigatório", + "error.apiKeyRequired": "Chave de API é obrigatória", + "error.modelRequired": "Modelo é obrigatório", + "error.reloadAmountMin": "O valor de recarga deve ser de pelo menos ${{amount}}", + "error.reloadTriggerMin": "O gatilho de saldo deve ser de pelo menos ${{amount}}", + + "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", + "temp.hero.title": "O agente de codificação com IA feito para o terminal", + "temp.zen": "opencode zen", + "temp.getStarted": "Começar", + "temp.feature.native.title": "TUI Nativa", + "temp.feature.native.body": "Uma interface de terminal responsiva, nativa e personalizável", + "temp.feature.zen.beforeLink": "Uma", + "temp.feature.zen.link": "lista selecionada de modelos", + "temp.feature.zen.afterLink": "fornecida pela opencode", + "temp.feature.models.beforeLink": "Suporta mais de 75 provedores de LLM através do", + "temp.feature.models.afterLink": ", incluindo modelos locais", + "temp.screenshot.caption": "OpenCode TUI com o tema tokyonight", + "temp.screenshot.alt": "OpenCode TUI com tema tokyonight", + + "home.banner.badge": "Novo", + "home.banner.text": "App desktop disponível em beta", + "home.banner.platforms": "no macOS, Windows e Linux", + "home.banner.downloadNow": "Baixar agora", + "home.banner.downloadBetaNow": "Baixe agora o beta do desktop", + + "home.hero.title": "O agente de codificação de código aberto com IA", + "home.hero.subtitle.a": "Modelos grátis incluídos ou conecte qualquer modelo de qualquer provedor,", + "home.hero.subtitle.b": "incluindo Claude, GPT, Gemini e mais.", + + "home.install.ariaLabel": "Opções de instalação", + + "home.what.title": "O que é OpenCode?", + "home.what.body": + "OpenCode é um agente de código aberto que ajuda você a escrever código no seu terminal, IDE ou desktop.", + "home.what.lsp.title": "LSP habilitado", + "home.what.lsp.body": "Carrega automaticamente os LSPs certos para o LLM", + "home.what.multiSession.title": "Multissessão", + "home.what.multiSession.body": "Inicie vários agentes em paralelo no mesmo projeto", + "home.what.shareLinks.title": "Links compartilháveis", + "home.what.shareLinks.body": "Compartilhe um link para qualquer sessão para referência ou depuração", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "Entre com o GitHub para usar sua conta do Copilot", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "Entre com a OpenAI para usar sua conta do ChatGPT Plus ou Pro", + "home.what.anyModel.title": "Qualquer modelo", + "home.what.anyModel.body": "Mais de 75 provedores de LLM via Models.dev, incluindo modelos locais", + "home.what.anyEditor.title": "Qualquer editor", + "home.what.anyEditor.body": "Disponível como interface de terminal, app desktop e extensão de IDE", + "home.what.readDocs": "Ler documentação", + + "home.growth.title": "O agente de codificação de código aberto com IA", + "home.growth.body": + "Com mais de {{stars}} estrelas no GitHub, {{contributors}} colaboradores e mais de {{commits}} commits, OpenCode é usado e confiado por mais de {{monthlyUsers}} desenvolvedores todos os meses.", + "home.growth.githubStars": "Estrelas no GitHub", + "home.growth.contributors": "Colaboradores", + "home.growth.monthlyDevs": "Devs mensais", + + "home.privacy.title": "Feito com privacidade em primeiro lugar", + "home.privacy.body": + "OpenCode não armazena nenhum código seu nem dados de contexto, para que possa operar em ambientes sensíveis à privacidade.", + "home.privacy.learnMore": "Saiba mais sobre", + "home.privacy.link": "privacidade", + + "home.faq.q1": "O que é OpenCode?", + "home.faq.a1": + "OpenCode é um agente de código aberto que ajuda você a escrever e executar código com qualquer modelo de IA. Está disponível como interface de terminal, app desktop ou extensão de IDE.", + "home.faq.q2": "Como eu uso o OpenCode?", + "home.faq.a2.before": "A maneira mais fácil de começar é ler a", + "home.faq.a2.link": "introdução", + "home.faq.q3": "Preciso de assinaturas extras de IA para usar o OpenCode?", + "home.faq.a3.p1": + "Não necessariamente, OpenCode vem com um conjunto de modelos grátis que você pode usar sem criar conta.", + "home.faq.a3.p2.beforeZen": + "Além disso, você pode usar qualquer um dos modelos de codificação populares criando uma conta", + "home.faq.a3.p2.afterZen": ".", + "home.faq.a3.p3": + "Embora incentivemos os usuários a usar o Zen, OpenCode também funciona com todos os provedores populares, como OpenAI, Anthropic, xAI etc.", + "home.faq.a3.p4.beforeLocal": "Você pode até conectar seus", + "home.faq.a3.p4.localLink": "modelos locais", + "home.faq.q4": "Posso usar minhas assinaturas de IA existentes com o OpenCode?", + "home.faq.a4.p1": + "Sim, OpenCode suporta planos de assinatura de todos os principais provedores. Você pode usar suas assinaturas Claude Pro/Max, ChatGPT Plus/Pro ou GitHub Copilot.", + "home.faq.q5": "Posso usar o OpenCode apenas no terminal?", + "home.faq.a5.beforeDesktop": "Não mais! OpenCode agora está disponível como um app para o seu", + "home.faq.a5.desktop": "desktop", + "home.faq.a5.and": "e", + "home.faq.a5.web": "web", + "home.faq.q6": "Quanto custa o OpenCode?", + "home.faq.a6": + "OpenCode é 100% gratuito para usar. Ele também vem com um conjunto de modelos gratuitos. Pode haver custos adicionais se você conectar qualquer outro provedor.", + "home.faq.q7": "E sobre dados e privacidade?", + "home.faq.a7.p1": + "Seus dados e informações só são armazenados quando você usa nossos modelos gratuitos ou cria links compartilháveis.", + "home.faq.a7.p2.beforeModels": "Saiba mais sobre", + "home.faq.a7.p2.modelsLink": "nossos modelos", + "home.faq.a7.p2.and": "e", + "home.faq.a7.p2.shareLink": "páginas de compartilhamento", + "home.faq.q8": "OpenCode é código aberto?", + "home.faq.a8.p1": "Sim, OpenCode é totalmente open source. O código-fonte é público no", + "home.faq.a8.p2": "sob a", + "home.faq.a8.mitLicense": "Licença MIT", + "home.faq.a8.p3": + ", o que significa que qualquer pessoa pode usar, modificar ou contribuir para o seu desenvolvimento. Qualquer pessoa da comunidade pode abrir issues, enviar pull requests e estender a funcionalidade.", + + "home.zenCta.title": "Acesse modelos confiáveis e otimizados para agentes de codificação", + "home.zenCta.body": + "O Zen dá acesso a um conjunto selecionado de modelos de IA que a OpenCode testou e avaliou especificamente para agentes de codificação. Não precisa se preocupar com desempenho e qualidade inconsistentes entre provedores, use modelos validados que funcionam.", + "home.zenCta.link": "Saiba mais sobre o Zen", + + "zen.title": "OpenCode Zen | Um conjunto selecionado de modelos confiáveis e otimizados para agentes de codificação", + "zen.hero.title": "Modelos confiáveis e otimizados para agentes de codificação", + "zen.hero.body": + "O Zen dá acesso a um conjunto selecionado de modelos de IA que a OpenCode testou e avaliou especificamente para agentes de codificação. Não precisa se preocupar com desempenho e qualidade inconsistentes, use modelos validados que funcionam.", + + "zen.faq.q1": "O que é OpenCode Zen?", + "zen.faq.a1": + "Zen é um conjunto selecionado de modelos de IA testados e avaliados para agentes de codificação, criado pela equipe por trás do OpenCode.", + "zen.faq.q2": "O que torna o Zen mais preciso?", + "zen.faq.a2": + "O Zen fornece apenas modelos que foram especificamente testados e avaliados para agentes de codificação. Você não usaria uma faca de manteiga para cortar um bife, não use modelos ruins para programar.", + "zen.faq.q3": "O Zen é mais barato?", + "zen.faq.a3": + "O Zen não tem fins lucrativos. O Zen repassa os custos dos provedores de modelos para você. Quanto maior o uso do Zen, mais a OpenCode pode negociar melhores taxas e repassá-las para você.", + "zen.faq.q4": "Quanto custa o Zen?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "cobra por requisição", + "zen.faq.a4.p1.afterPricing": "sem margens de lucro, então você paga exatamente o que o provedor do modelo cobra.", + "zen.faq.a4.p2.beforeAccount": "Seu custo total depende do uso, e você pode definir limites de gastos mensais em sua", + "zen.faq.a4.p2.accountLink": "conta", + "zen.faq.a4.p3": + "Para cobrir custos, a OpenCode adiciona apenas uma pequena taxa de processamento de pagamento de $1,23 por recarga de $20.", + "zen.faq.q5": "E sobre dados e privacidade?", + "zen.faq.a5.beforeExceptions": + "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 modelos, com as", + "zen.faq.a5.exceptionsLink": "seguintes exceções", + "zen.faq.q6": "Posso definir limites de gastos?", + "zen.faq.a6": "Sim, você pode definir limites de gastos mensais em sua conta.", + "zen.faq.q7": "Posso cancelar?", + "zen.faq.a7": "Sim, você pode desativar o faturamento a qualquer momento e usar seu saldo restante.", + "zen.faq.q8": "Posso usar o Zen com outros agentes de codificação?", + "zen.faq.a8": + "Embora o Zen funcione muito bem com o OpenCode, você pode usar o Zen com qualquer agente. Siga as instruções de configuração no seu agente de codificação preferido.", + + "zen.cta.start": "Comece com o Zen", + "zen.pricing.title": "Adicionar $20 de saldo pré-pago", + "zen.pricing.fee": "(+$1,23 taxa de processamento do cartão)", + "zen.pricing.body": "Use com qualquer agente. Defina limites de gastos mensais. Cancele a qualquer momento.", + "zen.problem.title": "Que problema o Zen resolve?", + "zen.problem.body": + "Existem muitos modelos disponíveis, mas apenas alguns funcionam bem com agentes de codificação. A maioria dos provedores os configura de maneira diferente, com resultados variados.", + "zen.problem.subtitle": "Estamos corrigindo isso para todos, não apenas para os usuários do OpenCode.", + "zen.problem.item1": "Testando modelos selecionados e consultando suas equipes", + "zen.problem.item2": "Trabalhando com provedores para garantir que sejam entregues corretamente", + "zen.problem.item3": "Avaliando todas as combinações de modelo-provedor que recomendamos", + "zen.how.title": "Como o Zen funciona", + "zen.how.body": "Embora sugerimos que você use o Zen com o OpenCode, você pode usá-lo com qualquer agente.", + "zen.how.step1.title": "Cadastre-se e adicione $20 de saldo", + "zen.how.step1.beforeLink": "siga as", + "zen.how.step1.link": "instruções de configuração", + "zen.how.step2.title": "Use o Zen com preços transparentes", + "zen.how.step2.link": "pague por requisição", + "zen.how.step2.afterLink": "sem margens de lucro", + "zen.how.step3.title": "Recarga automática", + "zen.how.step3.body": "quando seu saldo atingir $5, adicionaremos automaticamente $20", + "zen.privacy.title": "Sua privacidade é importante para nós", + "zen.privacy.beforeExceptions": + "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", + + "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", + "black.hero.subtitle": "Incluindo Claude, GPT, Gemini e mais", + "black.title": "OpenCode Black | Preços", + "black.plan.icon20": "Plano Black 20", + "black.plan.icon100": "Plano Black 100", + "black.plan.icon200": "Plano Black 200", + "black.plan.multiplier100": "5x mais uso que o Black 20", + "black.plan.multiplier200": "20x mais uso que o Black 20", + "black.price.perMonth": "por mês", + "black.price.perPersonBilledMonthly": "por pessoa faturado mensalmente", + "black.terms.1": "Sua assinatura não começará imediatamente", + "black.terms.2": "Você será adicionado à lista de espera e ativado em breve", + "black.terms.3": "Seu cartão só será cobrado quando sua assinatura for ativada", + "black.terms.4": "Limites de uso se aplicam; uso fortemente automatizado pode atingir os limites mais cedo", + "black.terms.5": "Assinaturas são para indivíduos, contate Enterprise para equipes", + "black.terms.6": "Limites podem ser ajustados e planos podem ser descontinuados no futuro", + "black.terms.7": "Cancele sua assinatura a qualquer momento", + "black.action.continue": "Continuar", + "black.finePrint.beforeTerms": "Os preços mostrados não incluem impostos aplicáveis", + "black.finePrint.terms": "Termos de Serviço", + "black.workspace.title": "OpenCode Black | Selecionar Workspace", + "black.workspace.selectPlan": "Selecione um workspace para este plano", + "black.workspace.name": "Workspace {{n}}", + "black.subscribe.title": "Assinar OpenCode Black", + "black.subscribe.paymentMethod": "Forma de pagamento", + "black.subscribe.loadingPaymentForm": "Carregando formulário de pagamento...", + "black.subscribe.selectWorkspaceToContinue": "Selecione um workspace para continuar", + "black.subscribe.failurePrefix": "Ops!", + "black.subscribe.error.generic": "Ocorreu um erro", + "black.subscribe.error.invalidPlan": "Plano inválido", + "black.subscribe.error.workspaceRequired": "ID do workspace é obrigatório", + "black.subscribe.error.alreadySubscribed": "Este workspace já possui uma assinatura", + "black.subscribe.processing": "Processando...", + "black.subscribe.submit": "Assinar ${{plan}}", + "black.subscribe.form.chargeNotice": "Você só será cobrado quando sua assinatura for ativada", + "black.subscribe.success.title": "Você está na lista de espera do OpenCode Black", + "black.subscribe.success.subscriptionPlan": "Plano de assinatura", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "Valor", + "black.subscribe.success.amountValue": "${{plan}} por mês", + "black.subscribe.success.paymentMethod": "Forma de pagamento", + "black.subscribe.success.dateJoined": "Data de entrada", + "black.subscribe.success.chargeNotice": "Seu cartão será cobrado quando sua assinatura for ativada", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "Chaves de API", + "workspace.nav.members": "Membros", + "workspace.nav.billing": "Faturamento", + "workspace.nav.settings": "Configurações", + + "workspace.home.banner.beforeLink": "Modelos otimizados e confiáveis para agentes de codificação.", + "workspace.home.billing.loading": "Carregando...", + "workspace.home.billing.enable": "Ativar faturamento", + "workspace.home.billing.currentBalance": "Saldo atual", + + "workspace.newUser.feature.tested.title": "Modelos Testados e Verificados", + "workspace.newUser.feature.tested.body": + "Avaliamos e testamos modelos especificamente para agentes de codificação para garantir o melhor desempenho.", + "workspace.newUser.feature.quality.title": "Qualidade Máxima", + "workspace.newUser.feature.quality.body": + "Acesse modelos configurados para desempenho ideal - sem downgrades ou roteamento para provedores mais baratos.", + "workspace.newUser.feature.lockin.title": "Sem Fidelidade", + "workspace.newUser.feature.lockin.body": + "Use o Zen com qualquer agente de codificação e continue usando outros provedores com opencode sempre que quiser.", + "workspace.newUser.copyApiKey": "Copiar chave de API", + "workspace.newUser.copyKey": "Copiar Chave", + "workspace.newUser.copied": "Copiado!", + "workspace.newUser.step.enableBilling": "Ativar faturamento", + "workspace.newUser.step.login.before": "Execute", + "workspace.newUser.step.login.after": "e selecione opencode", + "workspace.newUser.step.pasteKey": "Cole sua chave de API", + "workspace.newUser.step.models.before": "Inicie o opencode e execute", + "workspace.newUser.step.models.after": "para selecionar um modelo", + + "workspace.models.title": "Modelos", + "workspace.models.subtitle.beforeLink": "Gerencie quais modelos os membros do workspace podem acessar.", + "workspace.models.table.model": "Modelo", + "workspace.models.table.enabled": "Habilitado", + + "workspace.providers.title": "Traga Sua Própria Chave", + "workspace.providers.subtitle": "Configure suas próprias chaves de API de provedores de IA.", + "workspace.providers.placeholder": "Insira a chave de API {{provider}} ({{prefix}}...)", + "workspace.providers.configure": "Configurar", + "workspace.providers.edit": "Editar", + "workspace.providers.delete": "Excluir", + "workspace.providers.saving": "Salvando...", + "workspace.providers.save": "Salvar", + "workspace.providers.table.provider": "Provedor", + "workspace.providers.table.apiKey": "Chave de API", + + "workspace.usage.title": "Histórico de Uso", + "workspace.usage.subtitle": "Uso recente da API e custos.", + "workspace.usage.empty": "Faça sua primeira chamada de API para começar.", + "workspace.usage.table.date": "Data", + "workspace.usage.table.model": "Modelo", + "workspace.usage.table.input": "Entrada", + "workspace.usage.table.output": "Saída", + "workspace.usage.table.cost": "Custo", + "workspace.usage.breakdown.input": "Entrada", + "workspace.usage.breakdown.cacheRead": "Leitura de Cache", + "workspace.usage.breakdown.cacheWrite": "Escrita em Cache", + "workspace.usage.breakdown.output": "Saída", + "workspace.usage.breakdown.reasoning": "Raciocínio", + "workspace.usage.subscription": "assinatura (${{amount}})", + + "workspace.cost.title": "Custo", + "workspace.cost.subtitle": "Custos de uso discriminados por modelo.", + "workspace.cost.allModels": "Todos os Modelos", + "workspace.cost.allKeys": "Todas as Chaves", + "workspace.cost.deletedSuffix": "(excluído)", + "workspace.cost.empty": "Nenhum dado de uso disponível para o período selecionado.", + "workspace.cost.subscriptionShort": "ass", + + "workspace.keys.title": "Chaves de API", + "workspace.keys.subtitle": "Gerencie suas chaves de API para acessar os serviços opencode.", + "workspace.keys.create": "Criar Chave de API", + "workspace.keys.placeholder": "Digite o nome da chave", + "workspace.keys.empty": "Crie uma chave de API do opencode Gateway", + "workspace.keys.table.name": "Nome", + "workspace.keys.table.key": "Chave", + "workspace.keys.table.createdBy": "Criado Por", + "workspace.keys.table.lastUsed": "Último Uso", + "workspace.keys.copyApiKey": "Copiar chave de API", + "workspace.keys.delete": "Excluir", + + "workspace.members.title": "Membros", + "workspace.members.subtitle": "Gerencie os membros do workspace e suas permissões.", + "workspace.members.invite": "Convidar Membro", + "workspace.members.inviting": "Convidando...", + "workspace.members.beta.beforeLink": "Workspaces são gratuitos para equipes durante o beta.", + "workspace.members.form.invitee": "Convidado", + "workspace.members.form.emailPlaceholder": "Digite o e-mail", + "workspace.members.form.role": "Função", + "workspace.members.form.monthlyLimit": "Limite de gastos mensais", + "workspace.members.noLimit": "Sem limite", + "workspace.members.noLimitLowercase": "sem limite", + "workspace.members.invited": "convidado", + "workspace.members.edit": "Editar", + "workspace.members.delete": "Excluir", + "workspace.members.saving": "Salvando...", + "workspace.members.save": "Salvar", + "workspace.members.table.email": "E-mail", + "workspace.members.table.role": "Função", + "workspace.members.table.monthLimit": "Limite mensal", + "workspace.members.role.admin": "Admin", + "workspace.members.role.adminDescription": "Pode gerenciar modelos, membros e faturamento", + "workspace.members.role.member": "Membro", + "workspace.members.role.memberDescription": "Só pode gerar chaves de API para si mesmo", + + "workspace.settings.title": "Configurações", + "workspace.settings.subtitle": "Atualize o nome e as preferências do seu workspace.", + "workspace.settings.workspaceName": "Nome do workspace", + "workspace.settings.defaultName": "Padrão", + "workspace.settings.updating": "Atualizando...", + "workspace.settings.save": "Salvar", + "workspace.settings.edit": "Editar", + + "workspace.billing.title": "Faturamento", + "workspace.billing.subtitle.beforeLink": "Gerenciar formas de pagamento.", + "workspace.billing.contactUs": "Contate-nos", + "workspace.billing.subtitle.afterLink": "se você tiver alguma dúvida.", + "workspace.billing.currentBalance": "Saldo Atual", + "workspace.billing.add": "Adicionar $", + "workspace.billing.enterAmount": "Digite o valor", + "workspace.billing.loading": "Carregando...", + "workspace.billing.addAction": "Adicionar", + "workspace.billing.addBalance": "Adicionar Saldo", + "workspace.billing.linkedToStripe": "Vinculado ao Stripe", + "workspace.billing.manage": "Gerenciar", + "workspace.billing.enable": "Ativar Faturamento", + + "workspace.monthlyLimit.title": "Limite Mensal", + "workspace.monthlyLimit.subtitle": "Defina um limite de uso mensal para sua conta.", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "Definindo...", + "workspace.monthlyLimit.set": "Definir", + "workspace.monthlyLimit.edit": "Editar Limite", + "workspace.monthlyLimit.noLimit": "Nenhum limite de uso definido.", + "workspace.monthlyLimit.currentUsage.beforeMonth": "Uso atual para", + "workspace.monthlyLimit.currentUsage.beforeAmount": "é $", + + "workspace.reload.title": "Recarga Automática", + "workspace.reload.disabled.before": "A recarga automática está", + "workspace.reload.disabled.state": "desativada", + "workspace.reload.disabled.after": "Ative para recarregar automaticamente quando o saldo estiver baixo.", + "workspace.reload.enabled.before": "A recarga automática está", + "workspace.reload.enabled.state": "ativada", + "workspace.reload.enabled.middle": "Recarregaremos", + "workspace.reload.processingFee": "taxa de processamento", + "workspace.reload.enabled.after": "quando o saldo atingir", + "workspace.reload.edit": "Editar", + "workspace.reload.enable": "Ativar", + "workspace.reload.enableAutoReload": "Ativar Recarga Automática", + "workspace.reload.reloadAmount": "Recarregar $", + "workspace.reload.whenBalanceReaches": "Quando o saldo atingir $", + "workspace.reload.saving": "Salvando...", + "workspace.reload.save": "Salvar", + "workspace.reload.failedAt": "Recarga falhou em", + "workspace.reload.reason": "Motivo:", + "workspace.reload.updatePaymentMethod": "Por favor, atualize sua forma de pagamento e tente novamente.", + "workspace.reload.retrying": "Tentando novamente...", + "workspace.reload.retry": "Tentar novamente", + + "workspace.payments.title": "Histórico de Pagamentos", + "workspace.payments.subtitle": "Transações de pagamento recentes.", + "workspace.payments.table.date": "Data", + "workspace.payments.table.paymentId": "ID do Pagamento", + "workspace.payments.table.amount": "Valor", + "workspace.payments.table.receipt": "Recibo", + "workspace.payments.type.credit": "crédito", + "workspace.payments.type.subscription": "assinatura", + "workspace.payments.view": "Ver", + + "workspace.black.loading": "Carregando...", + "workspace.black.time.day": "dia", + "workspace.black.time.days": "dias", + "workspace.black.time.hour": "hora", + "workspace.black.time.hours": "horas", + "workspace.black.time.minute": "minuto", + "workspace.black.time.minutes": "minutos", + "workspace.black.time.fewSeconds": "alguns segundos", + "workspace.black.subscription.title": "Assinatura", + "workspace.black.subscription.message": "Você assina o OpenCode Black por ${{plan}} por mês.", + "workspace.black.subscription.manage": "Gerenciar Assinatura", + "workspace.black.subscription.rollingUsage": "Uso de 5 horas", + "workspace.black.subscription.weeklyUsage": "Uso Semanal", + "workspace.black.subscription.resetsIn": "Reinicia em", + "workspace.black.subscription.useBalance": "Use seu saldo disponível após atingir os limites de uso", + "workspace.black.waitlist.title": "Lista de Espera", + "workspace.black.waitlist.joined": "Você está na lista de espera para o plano OpenCode Black de ${{plan}} por mês.", + "workspace.black.waitlist.ready": "Estamos prontos para inscrever você no plano OpenCode Black de ${{plan}} por mês.", + "workspace.black.waitlist.leave": "Sair da Lista de Espera", + "workspace.black.waitlist.leaving": "Saindo...", + "workspace.black.waitlist.left": "Saiu", + "workspace.black.waitlist.enroll": "Inscrever-se", + "workspace.black.waitlist.enrolling": "Inscrevendo-se...", + "workspace.black.waitlist.enrolled": "Inscrito", + "workspace.black.waitlist.enrollNote": + "Ao clicar em Inscrever-se, sua assinatura começará imediatamente e seu cartão será cobrado.", + + "download.title": "OpenCode | Baixar", + "download.meta.description": "Baixe o OpenCode para macOS, Windows e Linux", + "download.hero.title": "Baixar OpenCode", + "download.hero.subtitle": "Disponível em Beta para macOS, Windows e Linux", + "download.hero.button": "Baixar para {{os}}", + "download.section.terminal": "OpenCode Terminal", + "download.section.desktop": "OpenCode Desktop (Beta)", + "download.section.extensions": "Extensões OpenCode", + "download.section.integrations": "Integrações OpenCode", + "download.action.download": "Baixar", + "download.action.install": "Instalar", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "Não necessariamente, mas provavelmente. Você precisará de uma assinatura de IA se quiser conectar o OpenCode a um provedor pago, embora você possa trabalhar com", + "download.faq.a3.localLink": "modelos locais", + "download.faq.a3.afterLocal.beforeZen": "de graça. Embora incentivemos os usuários a usar o", + "download.faq.a3.afterZen": + ", o OpenCode funciona com todos os provedores populares, como OpenAI, Anthropic, xAI etc.", + + "download.faq.a5.p1": "O OpenCode é 100% gratuito para usar.", + "download.faq.a5.p2.beforeZen": + "Quaisquer custos adicionais virão da sua assinatura de um provedor de modelo. Embora o OpenCode funcione com qualquer provedor de modelo, recomendamos o uso do", + "download.faq.a5.p2.afterZen": ".", + + "download.faq.a6.p1": + "Seus dados e informações só são armazenados quando você cria links compartilháveis no OpenCode.", + "download.faq.a6.p2.beforeShare": "Saiba mais sobre", + "download.faq.a6.shareLink": "páginas de compartilhamento", + + "enterprise.title": "OpenCode | Soluções empresariais para sua organização", + "enterprise.meta.description": "Contate a OpenCode para soluções empresariais", + "enterprise.hero.title": "Seu código é seu", + "enterprise.hero.body1": + "O OpenCode opera com segurança dentro da sua organização, sem dados ou contexto armazenados e sem restrições de licenciamento ou reivindicações de propriedade. Inicie um teste com sua equipe e, em seguida, implante em toda a organização integrando-o ao seu SSO e gateway de IA interno.", + "enterprise.hero.body2": "Deixe-nos saber como podemos ajudar.", + "enterprise.form.name.label": "Nome completo", + "enterprise.form.name.placeholder": "Jeff Bezos", + "enterprise.form.role.label": "Cargo", + "enterprise.form.role.placeholder": "Presidente Executivo", + "enterprise.form.email.label": "E-mail corporativo", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "Qual problema você está tentando resolver?", + "enterprise.form.message.placeholder": "Precisamos de ajuda com...", + "enterprise.form.send": "Enviar", + "enterprise.form.sending": "Enviando...", + "enterprise.form.success": "Mensagem enviada, entraremos em contato em breve.", + "enterprise.faq.title": "FAQ", + "enterprise.faq.q1": "O que é OpenCode Enterprise?", + "enterprise.faq.a1": + "OpenCode Enterprise é para organizações que desejam garantir que seu código e dados nunca saiam de sua infraestrutura. Isso pode ser feito usando uma configuração centralizada que se integra ao seu SSO e gateway de IA interno.", + "enterprise.faq.q2": "Como faço para começar com o OpenCode Enterprise?", + "enterprise.faq.a2": + "Basta começar com um teste interno com sua equipe. O OpenCode por padrão não armazena seu código ou dados de contexto, facilitando o início. Em seguida, entre em contato conosco para discutir opções de preços e implementação.", + "enterprise.faq.q3": "Como funciona o preço empresarial?", + "enterprise.faq.a3": + "Oferecemos preços empresariais por assento. Se você tiver seu próprio gateway de LLM, não cobramos pelos tokens usados. Para mais detalhes, entre em contato conosco para um orçamento personalizado com base nas necessidades da sua organização.", + "enterprise.faq.q4": "Meus dados estão seguros com o OpenCode Enterprise?", + "enterprise.faq.a4": + "Sim. O OpenCode não armazena seu código ou dados de contexto. Todo o processamento acontece localmente ou por meio de chamadas de API diretas para seu provedor de IA. Com configuração centralizada e integração de SSO, seus dados permanecem seguros dentro da infraestrutura de sua organização.", + + "brand.title": "OpenCode | Marca", + "brand.meta.description": "Diretrizes da marca OpenCode", + "brand.heading": "Diretrizes da marca", + "brand.subtitle": "Recursos e ativos para ajudá-lo a trabalhar com a marca OpenCode.", + "brand.downloadAll": "Baixar todos os recursos", + + "changelog.title": "OpenCode | Changelog", + "changelog.meta.description": "Notas de versão e changelog do OpenCode", + "changelog.hero.title": "Changelog", + "changelog.hero.subtitle": "Novas atualizações e melhorias no OpenCode", + "changelog.empty": "Nenhuma entrada de changelog encontrada.", + "changelog.viewJson": "Ver JSON", + + "bench.list.title": "Benchmark", + "bench.list.heading": "Benchmarks", + "bench.list.table.agent": "Agente", + "bench.list.table.model": "Modelo", + "bench.list.table.score": "Pontuação", + + "bench.detail.title": "Benchmark - {{task}}", + "bench.detail.notFound": "Tarefa não encontrada", + "bench.detail.na": "N/A", + "bench.detail.labels.agent": "Agente", + "bench.detail.labels.model": "Modelo", + "bench.detail.labels.task": "Tarefa", + "bench.detail.labels.repo": "Repositório", + "bench.detail.labels.from": "De", + "bench.detail.labels.to": "Para", + "bench.detail.labels.prompt": "Prompt", + "bench.detail.labels.commit": "Commit", + "bench.detail.labels.averageDuration": "Duração Média", + "bench.detail.labels.averageScore": "Pontuação Média", + "bench.detail.labels.averageCost": "Custo Médio", + "bench.detail.labels.summary": "Resumo", + "bench.detail.labels.runs": "Execuções", + "bench.detail.labels.score": "Pontuação", + "bench.detail.labels.base": "Base", + "bench.detail.labels.penalty": "Penalidade", + "bench.detail.labels.weight": "peso", + "bench.detail.table.run": "Execução", + "bench.detail.table.score": "Pontuação (Base - Penalidade)", + "bench.detail.table.cost": "Custo", + "bench.detail.table.duration": "Duração", + "bench.detail.run.title": "Execução {{n}}", + "bench.detail.rawJson": "JSON Bruto", +} satisfies Dict diff --git a/packages/console/app/src/i18n/da.ts b/packages/console/app/src/i18n/da.ts new file mode 100644 index 00000000000..39f8cfb5252 --- /dev/null +++ b/packages/console/app/src/i18n/da.ts @@ -0,0 +1,594 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "Dokumentation", + "nav.changelog": "Changelog", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "Enterprise", + "nav.zen": "Zen", + "nav.login": "Log ind", + "nav.free": "Gratis", + "nav.home": "Hjem", + "nav.openMenu": "Åbn menu", + "nav.getStartedFree": "Kom i gang gratis", + + "nav.context.copyLogo": "Kopier logo som SVG", + "nav.context.copyWordmark": "Kopier wordmark som SVG", + "nav.context.brandAssets": "Brand-assets", + + "footer.github": "GitHub", + "footer.docs": "Dokumentation", + "footer.changelog": "Changelog", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "Brand", + "legal.privacy": "Privatliv", + "legal.terms": "Vilkår", + + "email.title": "Få besked først, når vi lancerer nye produkter", + "email.subtitle": "Tilmeld dig ventelisten for tidlig adgang.", + "email.placeholder": "E-mailadresse", + "email.subscribe": "Tilmeld", + "email.success": "Næsten færdig - tjek din indbakke og bekræft din e-mailadresse", + + "notFound.title": "Ikke fundet | opencode", + "notFound.heading": "404 - Siden blev ikke fundet", + "notFound.home": "Hjem", + "notFound.docs": "Dokumentation", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "Log ud", + + "workspace.select": "Vælg workspace", + "workspace.createNew": "+ Opret nyt workspace", + "workspace.modal.title": "Opret nyt workspace", + "workspace.modal.placeholder": "Indtast workspace-navn", + + "common.cancel": "Annuller", + "common.creating": "Opretter...", + "common.create": "Opret", + + "common.videoUnsupported": "Din browser understøtter ikke video-tagget.", + "common.figure": "Fig {{n}}.", + "common.faq": "FAQ", + "common.learnMore": "Læs mere", + + "error.invalidPlan": "Ugyldig plan", + "error.workspaceRequired": "Workspace-ID er påkrævet", + "error.alreadySubscribed": "Dette workspace har allerede et abonnement", + "error.limitRequired": "Grænse er påkrævet.", + "error.monthlyLimitInvalid": "Angiv en gyldig månedlig grænse.", + "error.workspaceNameRequired": "Workspace-navn er påkrævet.", + "error.nameTooLong": "Navnet må højst være på 255 tegn.", + "error.emailRequired": "E-mail er påkrævet", + "error.roleRequired": "Rolle er påkrævet", + "error.idRequired": "ID er påkrævet", + "error.nameRequired": "Navn er påkrævet", + "error.providerRequired": "Udbyder er påkrævet", + "error.apiKeyRequired": "API-nøgle er påkrævet", + "error.modelRequired": "Model er påkrævet", + "error.reloadAmountMin": "Genopfyldningsbeløb skal være mindst ${{amount}}", + "error.reloadTriggerMin": "Saldogrænse skal være mindst ${{amount}}", + + "home.title": "OpenCode | Den open source AI-kodningsagent", + + "temp.title": "opencode | AI-kodningsagent bygget til terminalen", + "temp.hero.title": "AI-kodningsagenten bygget til terminalen", + "temp.zen": "opencode zen", + "temp.getStarted": "Kom i gang", + "temp.feature.native.title": "Native TUI", + "temp.feature.native.body": "En responsiv, native, tema-bar terminal-UI", + "temp.feature.zen.beforeLink": "En", + "temp.feature.zen.link": "kurateret liste over modeller", + "temp.feature.zen.afterLink": "leveret af opencode", + "temp.feature.models.beforeLink": "Understøtter 75+ LLM-udbydere gennem", + "temp.feature.models.afterLink": ", inklusive lokale modeller", + "temp.screenshot.caption": "opencode TUI med tokyonight-temaet", + "temp.screenshot.alt": "opencode TUI med tokyonight-temaet", + + "home.banner.badge": "Ny", + "home.banner.text": "Desktop-app tilgængelig i beta", + "home.banner.platforms": "på macOS, Windows og Linux", + "home.banner.downloadNow": "Download nu", + "home.banner.downloadBetaNow": "Download desktop-betaen nu", + + "home.hero.title": "Den open source AI-kodningsagent", + "home.hero.subtitle.a": "Gratis modeller inkluderet, eller forbind enhver model fra enhver udbyder,", + "home.hero.subtitle.b": "inklusive Claude, GPT, Gemini og mere.", + + "home.install.ariaLabel": "Installationsmuligheder", + + "home.what.title": "Hvad er OpenCode?", + "home.what.body": + "OpenCode er en open source agent, der hjælper dig med at skrive kode i din terminal, IDE eller desktop.", + "home.what.lsp.title": "LSP aktiveret", + "home.what.lsp.body": "Indlæser automatisk de rigtige LSP'er til LLM'en", + "home.what.multiSession.title": "Multi-session", + "home.what.multiSession.body": "Start flere agenter parallelt på det samme projekt", + "home.what.shareLinks.title": "Del links", + "home.what.shareLinks.body": "Del et link til enhver session til reference eller debugging", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "Log ind med GitHub for at bruge din Copilot-konto", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "Log ind med OpenAI for at bruge din ChatGPT Plus- eller Pro-konto", + "home.what.anyModel.title": "Enhver model", + "home.what.anyModel.body": "75+ LLM-udbydere via Models.dev, inklusive lokale modeller", + "home.what.anyEditor.title": "Enhver editor", + "home.what.anyEditor.body": "Tilgængelig som terminal-interface, desktop-app og IDE-udvidelse", + "home.what.readDocs": "Læs docs", + + "home.growth.title": "Den open source AI-kodningsagent", + "home.growth.body": + "Med over {{stars}} GitHub-stjerner, {{contributors}} bidragsydere og over {{commits}} commits bruges OpenCode af over {{monthlyUsers}} udviklere hver måned.", + "home.growth.githubStars": "GitHub-stjerner", + "home.growth.contributors": "Bidragsydere", + "home.growth.monthlyDevs": "Månedlige udviklere", + + "home.privacy.title": "Bygget med privatliv først", + "home.privacy.body": + "OpenCode gemmer ikke din kode eller kontekstdata, så den kan bruges i privatlivsfølsomme miljøer.", + "home.privacy.learnMore": "Læs mere om", + "home.privacy.link": "privatliv", + + "home.faq.q1": "Hvad er OpenCode?", + "home.faq.a1": + "OpenCode er en open source agent, der hjælper dig med at skrive og køre kode med enhver AI-model. Den er tilgængelig som terminal-interface, desktop-app eller IDE-udvidelse.", + "home.faq.q2": "Hvordan bruger jeg OpenCode?", + "home.faq.a2.before": "Den nemmeste måde at komme i gang på er at læse", + "home.faq.a2.link": "introen", + "home.faq.q3": "Skal jeg have ekstra AI-abonnementer for at bruge OpenCode?", + "home.faq.a3.p1": + "Ikke nødvendigvis. OpenCode kommer med gratis modeller, som du kan bruge uden at oprette en konto.", + "home.faq.a3.p2.beforeZen": "Derudover kan du bruge populære kodningsmodeller ved at oprette en", + "home.faq.a3.p2.afterZen": " konto.", + "home.faq.a3.p3": + "Vi opfordrer til at bruge Zen, men OpenCode virker også med populære udbydere som OpenAI, Anthropic, xAI osv.", + "home.faq.a3.p4.beforeLocal": "Du kan endda forbinde dine", + "home.faq.a3.p4.localLink": "lokale modeller", + "home.faq.q4": "Kan jeg bruge mine eksisterende AI-abonnementer med OpenCode?", + "home.faq.a4.p1": + "Ja. OpenCode understøtter abonnementer fra alle store udbydere. Du kan bruge Claude Pro/Max, ChatGPT Plus/Pro eller GitHub Copilot.", + "home.faq.q5": "Kan jeg kun bruge OpenCode i terminalen?", + "home.faq.a5.beforeDesktop": "Ikke længere! OpenCode er nu tilgængelig som en app til", + "home.faq.a5.desktop": "desktop", + "home.faq.a5.and": "og", + "home.faq.a5.web": "web", + "home.faq.q6": "Hvad koster OpenCode?", + "home.faq.a6": + "OpenCode er 100% gratis at bruge. Det kommer også med et sæt gratis modeller. Der kan være ekstra omkostninger, hvis du forbinder en anden udbyder.", + "home.faq.q7": "Hvad med data og privatliv?", + "home.faq.a7.p1": "Dine data gemmes kun, når du bruger vores gratis modeller eller opretter delbare links.", + "home.faq.a7.p2.beforeModels": "Læs mere om", + "home.faq.a7.p2.modelsLink": "vores modeller", + "home.faq.a7.p2.and": "og", + "home.faq.a7.p2.shareLink": "delingssider", + "home.faq.q8": "Er OpenCode open source?", + "home.faq.a8.p1": "Ja, OpenCode er fuldt open source. Kildekoden er offentlig på", + "home.faq.a8.p2": "under", + "home.faq.a8.mitLicense": "MIT-licensen", + "home.faq.a8.p3": + ", hvilket betyder at alle kan bruge, ændre eller bidrage til udviklingen. Alle i communityet kan oprette issues, indsende pull requests og udvide funktionalitet.", + + "home.zenCta.title": "Få adgang til pålidelige, optimerede modeller til kodningsagenter", + "home.zenCta.body": + "Zen giver dig adgang til et håndplukket sæt AI-modeller, som OpenCode har testet og benchmarked specifikt til kodningsagenter. Du behøver ikke bekymre dig om svingende performance og kvalitet på tværs af udbydere: brug validerede modeller, der virker.", + "home.zenCta.link": "Læs om Zen", + + "zen.title": "OpenCode Zen | Et kurateret sæt af pålidelige, optimerede modeller til kodningsagenter", + "zen.hero.title": "Pålidelige optimerede modeller til kodningsagenter", + "zen.hero.body": + "Zen giver dig adgang til et kurateret sæt AI-modeller, som OpenCode har testet og benchmarked specifikt til kodningsagenter. Du behøver ikke bekymre dig om svingende performance og kvalitet: brug validerede modeller, der virker.", + + "zen.faq.q1": "Hvad er OpenCode Zen?", + "zen.faq.a1": + "Zen er et kurateret sæt AI-modeller testet og benchmarked til kodningsagenter, skabt af teamet bag OpenCode.", + "zen.faq.q2": "Hvad gør Zen mere præcis?", + "zen.faq.a2": + "Zen tilbyder kun modeller, der er testet og benchmarked specifikt til kodningsagenter. Du ville ikke bruge en smørkniv til at skære steak; brug ikke dårlige modeller til kodning.", + "zen.faq.q3": "Er Zen billigere?", + "zen.faq.a3": + "Zen er ikke for profit. Zen videregiver omkostningerne fra modeludbyderne til dig. Jo mere Zen bruges, desto mere kan OpenCode forhandle bedre priser og give dem videre til dig.", + "zen.faq.q4": "Hvad koster Zen?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "opkræver per request", + "zen.faq.a4.p1.afterPricing": "uden markups, så du betaler præcis det, som modeludbyderen opkræver.", + "zen.faq.a4.p2.beforeAccount": "Din samlede pris afhænger af brug, og du kan sætte månedlige udgiftsgrænser i din", + "zen.faq.a4.p2.accountLink": "konto", + "zen.faq.a4.p3": + "For at dække omkostninger tilføjer OpenCode kun et lille betalingsgebyr på $1.23 per $20 saldo-opfyldning.", + "zen.faq.q5": "Hvad med data og privatliv?", + "zen.faq.a5.beforeExceptions": + "Alle Zen-modeller hostes i USA. Udbydere følger en zero-retention-policy og bruger ikke dine data til modeltræning, med de", + "zen.faq.a5.exceptionsLink": "følgende undtagelser", + "zen.faq.q6": "Kan jeg sætte udgiftsgrænser?", + "zen.faq.a6": "Ja, du kan sætte månedlige udgiftsgrænser i din konto.", + "zen.faq.q7": "Kan jeg afmelde?", + "zen.faq.a7": "Ja, du kan deaktivere betaling når som helst og bruge din resterende saldo.", + "zen.faq.q8": "Kan jeg bruge Zen med andre kodningsagenter?", + "zen.faq.a8": + "Selvom Zen fungerer godt med OpenCode, kan du bruge Zen med enhver agent. Følg opsætningsinstruktionerne i din foretrukne kodningsagent.", + + "zen.cta.start": "Kom godt i gang med Zen", + "zen.pricing.title": "Tilføj $20 Pay as you go-saldo", + "zen.pricing.fee": "(+$1.23 kortbehandlingsgebyr)", + "zen.pricing.body": "Brug med enhver agent. Indstil månedlige forbrugsgrænser. Annuller til enhver tid.", + "zen.problem.title": "Hvilket problem løser Zen?", + "zen.problem.body": + "Der er så mange modeller tilgængelige, men kun få fungerer godt med kodningsagenter. De fleste udbydere konfigurerer dem anderledes med forskellige resultater.", + "zen.problem.subtitle": "Vi løser dette for alle, ikke kun OpenCode-brugere.", + "zen.problem.item1": "Test af udvalgte modeller og høring af deres teams", + "zen.problem.item2": "Samarbejde med udbydere for at sikre, at de bliver leveret korrekt", + "zen.problem.item3": "Benchmarking af alle model-udbyder kombinationer, vi anbefaler", + "zen.how.title": "Hvordan Zen virker", + "zen.how.body": "Selvom vi foreslår, at du bruger Zen med OpenCode, kan du bruge Zen med enhver agent.", + "zen.how.step1.title": "Tilmeld dig og tilføj saldo på $20", + "zen.how.step1.beforeLink": "følg", + "zen.how.step1.link": "opsætningsinstruktioner", + "zen.how.step2.title": "Brug Zen med gennemsigtige priser", + "zen.how.step2.link": "betal per request", + "zen.how.step2.afterLink": "med nul markups", + "zen.how.step3.title": "Auto-top op", + "zen.how.step3.body": "når din saldo når $5, tilføjer vi automatisk $20", + "zen.privacy.title": "Dit privatliv er vigtigt for os", + "zen.privacy.beforeExceptions": + "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", + + "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", + "black.hero.subtitle": "Inklusive Claude, GPT, Gemini og mere", + "black.title": "OpenCode Black | Priser", + "black.plan.icon20": "Black 20-plan", + "black.plan.icon100": "Black 100-plan", + "black.plan.icon200": "Black 200-plan", + "black.plan.multiplier100": "5x mere brug end Black 20", + "black.plan.multiplier200": "20x mere brug end Black 20", + "black.price.perMonth": "pr. måned", + "black.price.perPersonBilledMonthly": "pr. person faktureret månedligt", + "black.terms.1": "Dit abonnement starter ikke med det samme", + "black.terms.2": "Du bliver sat på ventelisten og aktiveret snart", + "black.terms.3": "Dit kort debiteres først, når dit abonnement er aktiveret", + "black.terms.4": "Forbrugsgrænser gælder, tung automatiseret brug kan nå grænserne hurtigere", + "black.terms.5": "Abonnementer er for enkeltpersoner, kontakt Enterprise for teams", + "black.terms.6": "Grænser kan justeres, og planer kan blive udfaset i fremtiden", + "black.terms.7": "Opsig dit abonnement når som helst", + "black.action.continue": "Fortsæt", + "black.finePrint.beforeTerms": "Viste priser inkluderer ikke gældende skat", + "black.finePrint.terms": "Servicevilkår", + "black.workspace.title": "OpenCode Black | Vælg workspace", + "black.workspace.selectPlan": "Vælg et workspace til denne plan", + "black.workspace.name": "Workspace {{n}}", + "black.subscribe.title": "Abonner på OpenCode Black", + "black.subscribe.paymentMethod": "Betalingsmetode", + "black.subscribe.loadingPaymentForm": "Indlæser betalingsformular...", + "black.subscribe.selectWorkspaceToContinue": "Vælg et workspace for at fortsætte", + "black.subscribe.failurePrefix": "Åh nej!", + "black.subscribe.error.generic": "Der opstod en fejl", + "black.subscribe.error.invalidPlan": "Ugyldig plan", + "black.subscribe.error.workspaceRequired": "Workspace-ID er påkrævet", + "black.subscribe.error.alreadySubscribed": "Dette workspace har allerede et abonnement", + "black.subscribe.processing": "Behandler...", + "black.subscribe.submit": "Abonner ${{plan}}", + "black.subscribe.form.chargeNotice": "Du bliver først debiteret, når dit abonnement er aktiveret", + "black.subscribe.success.title": "Du er på OpenCode Black-ventelisten", + "black.subscribe.success.subscriptionPlan": "Abonnementsplan", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "Beløb", + "black.subscribe.success.amountValue": "${{plan}} pr. måned", + "black.subscribe.success.paymentMethod": "Betalingsmetode", + "black.subscribe.success.dateJoined": "Dato tilmeldt", + "black.subscribe.success.chargeNotice": "Dit kort vil blive debiteret, når dit abonnement er aktiveret", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "API-nøgler", + "workspace.nav.members": "Medlemmer", + "workspace.nav.billing": "Fakturering", + "workspace.nav.settings": "Indstillinger", + + "workspace.home.banner.beforeLink": "Pålidelige optimerede modeller til kodningsagenter.", + "workspace.home.billing.loading": "Indlæser...", + "workspace.home.billing.enable": "Aktiver fakturering", + "workspace.home.billing.currentBalance": "Nuværende saldo", + + "workspace.newUser.feature.tested.title": "Testede og verificerede modeller", + "workspace.newUser.feature.tested.body": + "Vi har benchmarket og testet modeller specifikt til kodningsagenter for at sikre den bedste ydeevne.", + "workspace.newUser.feature.quality.title": "Højeste kvalitet", + "workspace.newUser.feature.quality.body": + "Få adgang til modeller konfigureret til optimal ydeevne - ingen nedgraderinger eller routing til billigere udbydere.", + "workspace.newUser.feature.lockin.title": "Ingen indlåsning", + "workspace.newUser.feature.lockin.body": + "Brug Zen med en hvilken som helst kodningsagent, og fortsæt med at bruge andre udbydere med opencode, når du vil.", + "workspace.newUser.copyApiKey": "Kopiér API-nøgle", + "workspace.newUser.copyKey": "Kopier nøgle", + "workspace.newUser.copied": "Kopieret!", + "workspace.newUser.step.enableBilling": "Aktiver fakturering", + "workspace.newUser.step.login.before": "Kør", + "workspace.newUser.step.login.after": "og vælg opencode", + "workspace.newUser.step.pasteKey": "Indsæt din API-nøgle", + "workspace.newUser.step.models.before": "Start opencode og kør", + "workspace.newUser.step.models.after": "for at vælge en model", + + "workspace.models.title": "Modeller", + "workspace.models.subtitle.beforeLink": "Administrer, hvilke modeller workspace-medlemmer kan få adgang til.", + "workspace.models.table.model": "Model", + "workspace.models.table.enabled": "Aktiveret", + + "workspace.providers.title": "Medbring din egen nøgle", + "workspace.providers.subtitle": "Konfigurer dine egne API-nøgler fra AI-udbydere.", + "workspace.providers.placeholder": "Indtast {{provider}} API-nøgle ({{prefix}}...)", + "workspace.providers.configure": "Konfigurer", + "workspace.providers.edit": "Rediger", + "workspace.providers.delete": "Slet", + "workspace.providers.saving": "Gemmer...", + "workspace.providers.save": "Gem", + "workspace.providers.table.provider": "Udbyder", + "workspace.providers.table.apiKey": "API-nøgle", + + "workspace.usage.title": "Brugshistorik", + "workspace.usage.subtitle": "Seneste API-brug og omkostninger.", + "workspace.usage.empty": "Foretag dit første API-opkald for at komme i gang.", + "workspace.usage.table.date": "Dato", + "workspace.usage.table.model": "Model", + "workspace.usage.table.input": "Input", + "workspace.usage.table.output": "Output", + "workspace.usage.table.cost": "Omkostning", + "workspace.usage.breakdown.input": "Input", + "workspace.usage.breakdown.cacheRead": "Cache læst", + "workspace.usage.breakdown.cacheWrite": "Cache skriv", + "workspace.usage.breakdown.output": "Output", + "workspace.usage.breakdown.reasoning": "Ræsonnement", + "workspace.usage.subscription": "abonnement (${{amount}})", + + "workspace.cost.title": "Omkostninger", + "workspace.cost.subtitle": "Brugsomkostninger opdelt efter model.", + "workspace.cost.allModels": "Alle modeller", + "workspace.cost.allKeys": "Alle nøgler", + "workspace.cost.deletedSuffix": "(slettet)", + "workspace.cost.empty": "Ingen brugsdata tilgængelige for den valgte periode.", + "workspace.cost.subscriptionShort": "sub", + + "workspace.keys.title": "API-nøgler", + "workspace.keys.subtitle": "Administrer dine API-nøgler for at få adgang til opencode-tjenester.", + "workspace.keys.create": "Opret API-nøgle", + "workspace.keys.placeholder": "Indtast nøglenavn", + "workspace.keys.empty": "Opret en opencode Gateway API-nøgle", + "workspace.keys.table.name": "Navn", + "workspace.keys.table.key": "Nøgle", + "workspace.keys.table.createdBy": "Oprettet af", + "workspace.keys.table.lastUsed": "Sidst brugt", + "workspace.keys.copyApiKey": "Kopiér API-nøgle", + "workspace.keys.delete": "Slet", + + "workspace.members.title": "Medlemmer", + "workspace.members.subtitle": "Administrer workspace-medlemmer og deres tilladelser.", + "workspace.members.invite": "Inviter medlem", + "workspace.members.inviting": "Inviterer...", + "workspace.members.beta.beforeLink": "Workspaces er gratis for teams under betaversionen.", + "workspace.members.form.invitee": "Inviteret", + "workspace.members.form.emailPlaceholder": "Indtast e-mail", + "workspace.members.form.role": "Rolle", + "workspace.members.form.monthlyLimit": "Månedlig forbrugsgrænse", + "workspace.members.noLimit": "Ingen grænse", + "workspace.members.noLimitLowercase": "ingen grænse", + "workspace.members.invited": "inviteret", + "workspace.members.edit": "Rediger", + "workspace.members.delete": "Slet", + "workspace.members.saving": "Gemmer...", + "workspace.members.save": "Gem", + "workspace.members.table.email": "E-mail", + "workspace.members.table.role": "Rolle", + "workspace.members.table.monthLimit": "Månedsgrænse", + "workspace.members.role.admin": "Admin", + "workspace.members.role.adminDescription": "Kan administrere modeller, medlemmer og fakturering", + "workspace.members.role.member": "Medlem", + "workspace.members.role.memberDescription": "Kan kun generere API-nøgler til sig selv", + + "workspace.settings.title": "Indstillinger", + "workspace.settings.subtitle": "Opdater dit workspace-navn og præferencer.", + "workspace.settings.workspaceName": "Workspace-navn", + "workspace.settings.defaultName": "Standard", + "workspace.settings.updating": "Opdaterer...", + "workspace.settings.save": "Gem", + "workspace.settings.edit": "Rediger", + + "workspace.billing.title": "Fakturering", + "workspace.billing.subtitle.beforeLink": "Administrer betalingsmetoder.", + "workspace.billing.contactUs": "Kontakt os", + "workspace.billing.subtitle.afterLink": "hvis du har spørgsmål.", + "workspace.billing.currentBalance": "Nuværende saldo", + "workspace.billing.add": "Tilføj $", + "workspace.billing.enterAmount": "Indtast beløb", + "workspace.billing.loading": "Indlæser...", + "workspace.billing.addAction": "Tilføj", + "workspace.billing.addBalance": "Tilføj saldo", + "workspace.billing.linkedToStripe": "Forbundet til Stripe", + "workspace.billing.manage": "Administrer", + "workspace.billing.enable": "Aktiver fakturering", + + "workspace.monthlyLimit.title": "Månedlig grænse", + "workspace.monthlyLimit.subtitle": "Indstil en månedlig forbrugsgrænse for din konto.", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "Indstiller...", + "workspace.monthlyLimit.set": "Sæt", + "workspace.monthlyLimit.edit": "Rediger grænse", + "workspace.monthlyLimit.noLimit": "Ingen forbrugsgrænse angivet.", + "workspace.monthlyLimit.currentUsage.beforeMonth": "Nuværende brug for", + "workspace.monthlyLimit.currentUsage.beforeAmount": "er $", + + "workspace.reload.title": "Automatisk genopfyldning", + "workspace.reload.disabled.before": "Automatisk genopfyldning er", + "workspace.reload.disabled.state": "deaktiveret", + "workspace.reload.disabled.after": "Aktiver for automatisk at genopfylde, når saldoen er lav.", + "workspace.reload.enabled.before": "Automatisk genopfyldning er", + "workspace.reload.enabled.state": "aktiveret", + "workspace.reload.enabled.middle": "Vi genopfylder", + "workspace.reload.processingFee": "ekspeditionsgebyr", + "workspace.reload.enabled.after": "når saldoen når", + "workspace.reload.edit": "Rediger", + "workspace.reload.enable": "Aktiver", + "workspace.reload.enableAutoReload": "Aktiver automatisk genopfyldning", + "workspace.reload.reloadAmount": "Genopfyld $", + "workspace.reload.whenBalanceReaches": "Når saldoen når $", + "workspace.reload.saving": "Gemmer...", + "workspace.reload.save": "Gem", + "workspace.reload.failedAt": "Genopfyldning mislykkedes kl", + "workspace.reload.reason": "Årsag:", + "workspace.reload.updatePaymentMethod": "Opdater din betalingsmetode, og prøv igen.", + "workspace.reload.retrying": "Prøver igen...", + "workspace.reload.retry": "Prøv igen", + + "workspace.payments.title": "Betalingshistorik", + "workspace.payments.subtitle": "Seneste betalingstransaktioner.", + "workspace.payments.table.date": "Dato", + "workspace.payments.table.paymentId": "Betalings-ID", + "workspace.payments.table.amount": "Beløb", + "workspace.payments.table.receipt": "Kvittering", + "workspace.payments.type.credit": "kredit", + "workspace.payments.type.subscription": "abonnement", + "workspace.payments.view": "Vis", + + "workspace.black.loading": "Indlæser...", + "workspace.black.time.day": "dag", + "workspace.black.time.days": "dage", + "workspace.black.time.hour": "time", + "workspace.black.time.hours": "timer", + "workspace.black.time.minute": "minut", + "workspace.black.time.minutes": "minutter", + "workspace.black.time.fewSeconds": "et par sekunder", + "workspace.black.subscription.title": "Abonnement", + "workspace.black.subscription.message": "Du abonnerer på OpenCode Black for ${{plan}} om måneden.", + "workspace.black.subscription.manage": "Administrer abonnement", + "workspace.black.subscription.rollingUsage": "5-timers brug", + "workspace.black.subscription.weeklyUsage": "Ugentlig brug", + "workspace.black.subscription.resetsIn": "Nulstiller i", + "workspace.black.subscription.useBalance": "Brug din tilgængelige saldo, når du har nået forbrugsgrænserne", + "workspace.black.waitlist.title": "Venteliste", + "workspace.black.waitlist.joined": "Du er på ventelisten for ${{plan}} per måned OpenCode Black plan.", + "workspace.black.waitlist.ready": "Vi er klar til at tilmelde dig ${{plan}} per måned OpenCode Black plan.", + "workspace.black.waitlist.leave": "Forlad venteliste", + "workspace.black.waitlist.leaving": "Forlader...", + "workspace.black.waitlist.left": "Forladt", + "workspace.black.waitlist.enroll": "Tilmeld", + "workspace.black.waitlist.enrolling": "Tilmelder...", + "workspace.black.waitlist.enrolled": "Tilmeldt", + "workspace.black.waitlist.enrollNote": + "Når du klikker på Tilmeld, starter dit abonnement med det samme, og dit kort vil blive debiteret.", + + "download.title": "OpenCode | Download", + "download.meta.description": "Download OpenCode til macOS, Windows og Linux", + "download.hero.title": "Download OpenCode", + "download.hero.subtitle": "Tilgængelig i beta til macOS, Windows og Linux", + "download.hero.button": "Download til {{os}}", + "download.section.terminal": "OpenCode Terminal", + "download.section.desktop": "OpenCode Desktop (Beta)", + "download.section.extensions": "OpenCode Extensions", + "download.section.integrations": "OpenCode Integrations", + "download.action.download": "Download", + "download.action.install": "Installer", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "Ikke nødvendigvis, men sandsynligvis. Du skal bruge et AI-abonnement hvis du vil forbinde OpenCode til en betalt udbyder, men du kan arbejde med", + "download.faq.a3.localLink": "lokale modeller", + "download.faq.a3.afterLocal.beforeZen": "gratis. Selvom vi opfordrer brugere til at bruge", + "download.faq.a3.afterZen": ", fungerer OpenCode med alle populære udbydere som OpenAI, Anthropic, xAI osv.", + + "download.faq.a5.p1": "OpenCode er 100% gratis at bruge.", + "download.faq.a5.p2.beforeZen": + "Eventuelle ekstra omkostninger kommer fra dit abonnement hos en modeludbyder. Selvom OpenCode fungerer med enhver modeludbyder, anbefaler vi at bruge", + "download.faq.a5.p2.afterZen": ".", + + "download.faq.a6.p1": "Dine data og oplysninger gemmes kun når du opretter delbare links i OpenCode.", + "download.faq.a6.p2.beforeShare": "Læs mere om", + "download.faq.a6.shareLink": "delingssider", + + "enterprise.title": "OpenCode | Enterprise-løsninger til din organisation", + "enterprise.meta.description": "Kontakt OpenCode for enterprise-løsninger", + "enterprise.hero.title": "Din kode er din egen", + "enterprise.hero.body1": + "OpenCode fungerer sikkert inde i din organisation uden at lagre data eller kontekst og uden licensbegrænsninger eller ejerskabskrav. Start en prøveperiode med dit team, og udrul det derefter i hele din organisation ved at integrere det med dit SSO og din interne AI-gateway.", + "enterprise.hero.body2": "Fortæl os, hvordan vi kan hjælpe.", + "enterprise.form.name.label": "Fulde navn", + "enterprise.form.name.placeholder": "Jeff Bezos", + "enterprise.form.role.label": "Rolle", + "enterprise.form.role.placeholder": "Bestyrelsesformand", + "enterprise.form.email.label": "Firma-e-mail", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "Hvilket problem prøver du at løse?", + "enterprise.form.message.placeholder": "Vi har brug for hjælp med...", + "enterprise.form.send": "Send", + "enterprise.form.sending": "Sender...", + "enterprise.form.success": "Besked sendt, vi vender tilbage snart.", + "enterprise.faq.title": "FAQ", + "enterprise.faq.q1": "Hvad er OpenCode Enterprise?", + "enterprise.faq.a1": + "OpenCode Enterprise er til organisationer, der vil sikre, at deres kode og data aldrig forlader deres infrastruktur. Det kan gøres med en central konfiguration, der integrerer med dit SSO og din interne AI-gateway.", + "enterprise.faq.q2": "Hvordan kommer jeg i gang med OpenCode Enterprise?", + "enterprise.faq.a2": + "Start blot med en intern prøveperiode med dit team. OpenCode gemmer som standard ikke din kode eller kontekstdata, hvilket gør det nemt at komme i gang. Kontakt os derefter for at tale om priser og implementeringsmuligheder.", + "enterprise.faq.q3": "Hvordan fungerer enterprise-priser?", + "enterprise.faq.a3": + "Vi tilbyder enterprise-priser pr. bruger. Hvis du har din egen LLM-gateway, opkræver vi ikke for brugte tokens. Kontakt os for flere detaljer og et tilbud tilpasset din organisations behov.", + "enterprise.faq.q4": "Er mine data sikre med OpenCode Enterprise?", + "enterprise.faq.a4": + "Ja. OpenCode gemmer ikke din kode eller kontekstdata. Al behandling sker lokalt eller via direkte API-kald til din AI-udbyder. Med central konfiguration og SSO-integration forbliver dine data sikre inden for din organisations infrastruktur.", + + "brand.title": "OpenCode | Brand", + "brand.meta.description": "OpenCode brandretningslinjer", + "brand.heading": "Brandretningslinjer", + "brand.subtitle": "Ressourcer og assets, der hjælper dig med at arbejde med OpenCode-brandet.", + "brand.downloadAll": "Download alle assets", + + "changelog.title": "OpenCode | Changelog", + "changelog.meta.description": "OpenCode versionsnoter og changelog", + "changelog.hero.title": "Changelog", + "changelog.hero.subtitle": "Nye opdateringer og forbedringer til OpenCode", + "changelog.empty": "Ingen changelog-indlæg fundet.", + "changelog.viewJson": "Se JSON", + + "bench.list.title": "Benchmark", + "bench.list.heading": "Benchmarks", + "bench.list.table.agent": "Agent", + "bench.list.table.model": "Model", + "bench.list.table.score": "Score", + + "bench.detail.title": "Benchmark - {{task}}", + "bench.detail.notFound": "Opgave ikke fundet", + "bench.detail.na": "Ikke tilgængelig", + "bench.detail.labels.agent": "Agent", + "bench.detail.labels.model": "Model", + "bench.detail.labels.task": "Opgave", + "bench.detail.labels.repo": "Repo", + "bench.detail.labels.from": "Fra", + "bench.detail.labels.to": "Til", + "bench.detail.labels.prompt": "Prompt", + "bench.detail.labels.commit": "Commit", + "bench.detail.labels.averageDuration": "Gennemsnitlig varighed", + "bench.detail.labels.averageScore": "Gennemsnitlig score", + "bench.detail.labels.averageCost": "Gennemsnitlig omkostning", + "bench.detail.labels.summary": "Resumé", + "bench.detail.labels.runs": "Kørsler", + "bench.detail.labels.score": "Score", + "bench.detail.labels.base": "Basis", + "bench.detail.labels.penalty": "Straf", + "bench.detail.labels.weight": "vægt", + "bench.detail.table.run": "Kørsel", + "bench.detail.table.score": "Score (Basis - Straf)", + "bench.detail.table.cost": "Omkostning", + "bench.detail.table.duration": "Varighed", + "bench.detail.run.title": "Kørsel {{n}}", + "bench.detail.rawJson": "Rå JSON", +} satisfies Dict diff --git a/packages/console/app/src/i18n/de.ts b/packages/console/app/src/i18n/de.ts new file mode 100644 index 00000000000..733f38ca5fc --- /dev/null +++ b/packages/console/app/src/i18n/de.ts @@ -0,0 +1,598 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "Dokumentation", + "nav.changelog": "Changelog", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "Enterprise", + "nav.zen": "Zen", + "nav.login": "Anmelden", + "nav.free": "Kostenlos", + "nav.home": "Startseite", + "nav.openMenu": "Menü öffnen", + "nav.getStartedFree": "Kostenlos starten", + + "nav.context.copyLogo": "Logo als SVG kopieren", + "nav.context.copyWordmark": "Wortmarke als SVG kopieren", + "nav.context.brandAssets": "Marken-Assets", + + "footer.github": "GitHub", + "footer.docs": "Dokumentation", + "footer.changelog": "Changelog", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "Marke", + "legal.privacy": "Datenschutz", + "legal.terms": "AGB", + + "email.title": "Erfahre als Erste:r, wenn wir neue Produkte veröffentlichen", + "email.subtitle": "Trage dich in die Warteliste für frühen Zugang ein.", + "email.placeholder": "E-Mail-Adresse", + "email.subscribe": "Anmelden", + "email.success": "Fast geschafft, überprüfe deinen Posteingang und bestätige deine E-Mail-Adresse", + + "notFound.title": "Nicht gefunden | OpenCode", + "notFound.heading": "404 - Seite nicht gefunden", + "notFound.home": "Startseite", + "notFound.docs": "Dokumentation", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "Abmelden", + + "workspace.select": "Workspace auswählen", + "workspace.createNew": "+ Neuen Workspace erstellen", + "workspace.modal.title": "Neuen Workspace erstellen", + "workspace.modal.placeholder": "Workspace-Namen eingeben", + + "common.cancel": "Abbrechen", + "common.creating": "Erstelle...", + "common.create": "Erstellen", + + "common.videoUnsupported": "Dein Browser unterstützt das Video-Tag nicht.", + "common.figure": "Abb. {{n}}.", + "common.faq": "FAQ", + "common.learnMore": "Mehr erfahren", + + "error.invalidPlan": "Ungültiger Plan", + "error.workspaceRequired": "Workspace-ID ist erforderlich", + "error.alreadySubscribed": "Dieser Workspace hat bereits ein Abonnement", + "error.limitRequired": "Limit ist erforderlich.", + "error.monthlyLimitInvalid": "Bitte gib ein gültiges monatliches Limit ein.", + "error.workspaceNameRequired": "Workspace-Name ist erforderlich.", + "error.nameTooLong": "Der Name darf höchstens 255 Zeichen lang sein.", + "error.emailRequired": "E-Mail ist erforderlich", + "error.roleRequired": "Rolle ist erforderlich", + "error.idRequired": "ID ist erforderlich", + "error.nameRequired": "Name ist erforderlich", + "error.providerRequired": "Anbieter ist erforderlich", + "error.apiKeyRequired": "API-Key ist erforderlich", + "error.modelRequired": "Modell ist erforderlich", + "error.reloadAmountMin": "Aufladebetrag muss mindestens ${{amount}} betragen", + "error.reloadTriggerMin": "Guthaben-Auslöser muss mindestens ${{amount}} betragen", + + "home.title": "OpenCode | Der Open-Source AI-Coding-Agent", + + "temp.title": "OpenCode | Für das Terminal gebauter AI-Coding-Agent", + "temp.hero.title": "Der für das Terminal gebaute AI-Coding-Agent", + "temp.zen": "OpenCode Zen", + "temp.getStarted": "Loslegen", + "temp.feature.native.title": "Native TUI", + "temp.feature.native.body": "Eine reaktionsschnelle, native, thematisierbare Terminal-UI", + "temp.feature.zen.beforeLink": "Eine", + "temp.feature.zen.link": "kuratierte Liste von Modellen", + "temp.feature.zen.afterLink": "bereitgestellt von OpenCode", + "temp.feature.models.beforeLink": "Unterstützt 75+ LLM-Anbieter durch", + "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", + + "home.banner.badge": "Neu", + "home.banner.text": "Desktop-App in der Beta verfügbar", + "home.banner.platforms": "auf macOS, Windows und Linux", + "home.banner.downloadNow": "Jetzt herunterladen", + "home.banner.downloadBetaNow": "Desktop-Beta jetzt herunterladen", + + "home.hero.title": "Der Open-Source AI-Coding-Agent", + "home.hero.subtitle.a": "Kostenlose Modelle inklusive oder verbinde jedes Modell eines beliebigen Anbieters,", + "home.hero.subtitle.b": "einschließlich Claude, GPT, Gemini und mehr.", + + "home.install.ariaLabel": "Installationsoptionen", + + "home.what.title": "Was ist OpenCode?", + "home.what.body": + "OpenCode ist ein Open-Source-Agent, der dir hilft, Code in deinem Terminal, deiner IDE oder auf dem Desktop zu schreiben.", + "home.what.lsp.title": "LSP-fähig", + "home.what.lsp.body": "Lädt automatisch die richtigen LSPs für das LLM", + "home.what.multiSession.title": "Multi-Session", + "home.what.multiSession.body": "Starte mehrere Agenten parallel im selben Projekt", + "home.what.shareLinks.title": "Links teilen", + "home.what.shareLinks.body": "Teile einen Link zu jeder Sitzung als Referenz oder zum Debuggen", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "Melde dich mit GitHub an, um deinen Copilot-Account zu nutzen", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "Melde dich mit OpenAI an, um deinen ChatGPT Plus- oder Pro-Account zu nutzen", + "home.what.anyModel.title": "Jedes Modell", + "home.what.anyModel.body": "75+ LLM-Anbieter durch Models.dev, einschließlich lokaler Modelle", + "home.what.anyEditor.title": "Jeder Editor", + "home.what.anyEditor.body": "Verfügbar als Terminal-Interface, Desktop-App und IDE-Extension", + "home.what.readDocs": "Doku lesen", + + "home.growth.title": "Der Open-Source AI-Coding-Agent", + "home.growth.body": + "Mit über {{stars}} GitHub-Stars, {{contributors}} Contributors und über {{commits}} Commits wird OpenCode von über {{monthlyUsers}} Entwickler:innen jeden Monat genutzt und geschätzt.", + "home.growth.githubStars": "GitHub Stars", + "home.growth.contributors": "Contributors", + "home.growth.monthlyDevs": "Monatliche Devs", + + "home.privacy.title": "Built for privacy first", + "home.privacy.body": + "OpenCode speichert keinen deiner Codes oder Kontextdaten, sodass es in datenschutzsensiblen Umgebungen arbeiten kann.", + "home.privacy.learnMore": "Erfahre mehr über", + "home.privacy.link": "Datenschutz", + + "home.faq.q1": "Was ist OpenCode?", + "home.faq.a1": + "OpenCode ist ein Open-Source-Agent, der dir hilft, Code mit jedem KI-Modell zu schreiben und auszuführen. Er ist als Terminal-Interface, Desktop-App oder IDE-Erweiterung verfügbar.", + "home.faq.q2": "Wie nutze ich OpenCode?", + "home.faq.a2.before": "Der einfachste Weg zu starten ist, die", + "home.faq.a2.link": "Einführung zu lesen", + "home.faq.q3": "Brauche ich zusätzliche AI-Abos, um OpenCode zu nutzen?", + "home.faq.a3.p1": + "Nicht unbedingt, OpenCode kommt mit einer Reihe kostenloser Modelle, die du ohne Account nutzen kannst.", + "home.faq.a3.p2.beforeZen": "Abgesehen davon kannst du jedes beliebige Coding-Modell nutzen, indem du einen", + "home.faq.a3.p2.afterZen": " Account erstellst.", + "home.faq.a3.p3": + "Während wir dazu raten, Zen zu nutzen, funktioniert OpenCode auch mit allen beliebten Anbietern wie OpenAI, Anthropic, xAI etc.", + "home.faq.a3.p4.beforeLocal": "Du kannst sogar deine", + "home.faq.a3.p4.localLink": "lokalen Modelle verbinden", + "home.faq.q4": "Kann ich meine bestehenden AI-Abos mit OpenCode nutzen?", + "home.faq.a4.p1": + "Ja, OpenCode unterstützt Abos von allen großen Anbietern. Du kannst deine Claude Pro/Max, ChatGPT Plus/Pro oder GitHub Copilot Abos nutzen.", + "home.faq.q5": "Kann ich OpenCode nur im Terminal nutzen?", + "home.faq.a5.beforeDesktop": "Nicht mehr! OpenCode ist jetzt als App für", + "home.faq.a5.desktop": "Desktop", + "home.faq.a5.and": "und", + "home.faq.a5.web": "Web verfügbar", + "home.faq.q6": "Wie viel kostet OpenCode?", + "home.faq.a6": + "OpenCode ist zu 100% kostenlos. Es enthält auch eine Reihe kostenloser Modelle. Zusätzliche Kosten können entstehen, wenn du andere Anbieter verbindest.", + "home.faq.q7": "Was ist mit Daten und Privatsphäre?", + "home.faq.a7.p1": + "Deine Daten und Informationen werden nur gespeichert, wenn du unsere kostenlosen Modelle nutzt oder teilbare Links erstellst.", + "home.faq.a7.p2.beforeModels": "Erfahre mehr über", + "home.faq.a7.p2.modelsLink": "unsere Modelle", + "home.faq.a7.p2.and": "und", + "home.faq.a7.p2.shareLink": "Share-Pages", + "home.faq.q8": "Ist OpenCode Open Source?", + "home.faq.a8.p1": "Ja, OpenCode ist vollständig Open Source. Der Quellcode ist öffentlich auf", + "home.faq.a8.p2": "unter der", + "home.faq.a8.mitLicense": "MIT Lizenz", + "home.faq.a8.p3": + ", was bedeutet, dass jeder ihn nutzen, modifizieren oder zu seiner Entwicklung beitragen kann. Jeder aus der Community kann Issues melden, Pull Requests einreichen und die Funktionalität erweitern.", + + "home.zenCta.title": "Zugriff auf zuverlässige, optimierte Modelle für Coding-Agents", + "home.zenCta.body": + "Zen gibt dir Zugriff auf ein handverlesenes Set an AI-Modellen, die OpenCode speziell für Coding-Agents getestet und bewertet hat. Keine Sorge wegen inkonsistenter Leistung und Qualität bei verschiedenen Anbietern – nutze validierte Modelle, die funktionieren.", + "home.zenCta.link": "Erfahre mehr über Zen", + + "zen.title": "OpenCode Zen | Ein kuratiertes Set zuverlässiger, optimierter Modelle für Coding-Agents", + "zen.hero.title": "Zuverlässige, optimierte Modelle für Coding-Agents", + "zen.hero.body": + "Zen gibt dir Zugriff auf ein kuratiertes Set an AI-Modellen, die OpenCode speziell für Coding-Agents getestet und bewertet hat. Keine Sorge wegen inkonsistenter Leistung und Qualität – nutze validierte Modelle, die funktionieren.", + + "zen.faq.q1": "Was ist OpenCode Zen?", + "zen.faq.a1": + "Zen ist ein kuratiertes Set an AI-Modellen, getestet und bewertet für Coding-Agents, erstellt vom Team hinter OpenCode.", + "zen.faq.q2": "Was macht Zen genauer?", + "zen.faq.a2": + "Zen bietet nur Modelle, die speziell für Coding-Agents getestet und bewertet wurden. Du würdest kein Buttermesser nehmen, um ein Steak zu schneiden – nutze keine schlechten Modelle zum Coden.", + "zen.faq.q3": "Ist Zen günstiger?", + "zen.faq.a3": + "Zen ist nicht gewinnorientiert. Zen gibt die Kosten der Modellanbieter an dich weiter. Je höher die Nutzung von Zen, desto besser kann OpenCode Preise verhandeln und diese an dich weitergeben.", + "zen.faq.q4": "Wie viel kostet Zen?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "berechnet pro Anfrage", + "zen.faq.a4.p1.afterPricing": "ohne Aufschläge, also zahlst du genau das, was der Modellanbieter berechnet.", + "zen.faq.a4.p2.beforeAccount": + "Deine Gesamtkosten hängen von der Nutzung ab, und du kannst monatliche Ausgabenlimits in deinem", + "zen.faq.a4.p2.accountLink": "Account festlegen", + "zen.faq.a4.p3": + "Um die Kosten zu decken, fügt OpenCode nur eine kleine Bearbeitungsgebühr von $1.23 pro $20 Guthabenaufladung hinzu.", + "zen.faq.q5": "Was ist mit Daten und Privatsphäre?", + "zen.faq.a5.beforeExceptions": + "Alle Zen-Modelle werden in den USA gehostet. Anbieter folgen einer Zero-Retention-Policy und nutzen deine Daten nicht zum Trainieren von Modellen, mit den", + "zen.faq.a5.exceptionsLink": "folgenden Ausnahmen", + "zen.faq.q6": "Kann ich Ausgabenlimits setzen?", + "zen.faq.a6": "Ja, du kannst monatliche Ausgabenlimits in deinem Account setzen.", + "zen.faq.q7": "Kann ich kündigen?", + "zen.faq.a7": "Ja, du kannst die Abrechnung jederzeit deaktivieren und dein verbleibendes Guthaben nutzen.", + "zen.faq.q8": "Kann ich Zen mit anderen Coding-Agents nutzen?", + "zen.faq.a8": + "Während Zen großartig mit OpenCode funktioniert, kannst du Zen mit jedem Agent nutzen. Folge den Einrichtungsanweisungen in deinem bevorzugten Coding-Agent.", + + "zen.cta.start": "Starte mit Zen", + "zen.pricing.title": "Füge $20 Pay-as-you-go Guthaben hinzu", + "zen.pricing.fee": "(+$1.23 Bearbeitungsgebühr)", + "zen.pricing.body": "Nutze es mit jedem Agent. Setze monatliche Ausgabenlimits. Jederzeit kündbar.", + "zen.problem.title": "Welches Problem löst Zen?", + "zen.problem.body": + "Es gibt so viele Modelle, aber nur wenige funktionieren gut mit Coding-Agents. Die meisten Anbieter konfigurieren sie unterschiedlich, was zu variierenden Ergebnissen führt.", + "zen.problem.subtitle": "Wir beheben das für alle, nicht nur für OpenCode-Nutzer.", + "zen.problem.item1": "Testen ausgewählter Modelle und Beratung mit deren Teams", + "zen.problem.item2": "Zusammenarbeit mit Anbietern, um korrekte Bereitstellung zu sichern", + "zen.problem.item3": "Benchmarking aller Modell-Anbieter-Kombinationen, die wir empfehlen", + "zen.how.title": "Wie Zen funktioniert", + "zen.how.body": "Während wir dir raten, Zen mit OpenCode zu nutzen, kannst du Zen mit jedem Agent nutzen.", + "zen.how.step1.title": "Melde dich an und füge $20 Guthaben hinzu", + "zen.how.step1.beforeLink": "folge den", + "zen.how.step1.link": "Einrichtungsanweisungen", + "zen.how.step2.title": "Nutze Zen mit transparenter Preisgestaltung", + "zen.how.step2.link": "zahle pro Anfrage", + "zen.how.step2.afterLink": "ohne Aufschläge", + "zen.how.step3.title": "Auto-Top-up", + "zen.how.step3.body": "wenn dein Guthaben $5 erreicht, fügen wir automatisch $20 hinzu", + "zen.privacy.title": "Deine Privatsphäre ist uns wichtig", + "zen.privacy.beforeExceptions": + "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", + + "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", + "black.hero.subtitle": "Einschließlich Claude, GPT, Gemini und mehr", + "black.title": "OpenCode Black | Preise", + "black.plan.icon20": "Black 20 Plan", + "black.plan.icon100": "Black 100 Plan", + "black.plan.icon200": "Black 200 Plan", + "black.plan.multiplier100": "5x mehr Nutzung als Black 20", + "black.plan.multiplier200": "20x mehr Nutzung als Black 20", + "black.price.perMonth": "pro Monat", + "black.price.perPersonBilledMonthly": "pro Person, monatlich abgerechnet", + "black.terms.1": "Dein Abonnement startet nicht sofort", + "black.terms.2": "Du wirst auf die Warteliste gesetzt und bald freigeschaltet", + "black.terms.3": "Deine Karte wird erst belastet, wenn dein Abonnement aktiviert ist", + "black.terms.4": "Nutzungslimits gelten, stark automatisierte Nutzung kann Limits schneller erreichen", + "black.terms.5": "Abonnements sind für Einzelpersonen, kontaktiere Enterprise für Teams", + "black.terms.6": "Limits können angepasst werden und Pläne können in Zukunft eingestellt werden", + "black.terms.7": "Kündige dein Abonnement jederzeit", + "black.action.continue": "Weiter", + "black.finePrint.beforeTerms": "Angezeigte Preise enthalten keine anfallenden Steuern", + "black.finePrint.terms": "Nutzungsbedingungen", + "black.workspace.title": "OpenCode Black | Workspace wählen", + "black.workspace.selectPlan": "Wähle einen Workspace für diesen Plan", + "black.workspace.name": "Workspace {{n}}", + "black.subscribe.title": "OpenCode Black abonnieren", + "black.subscribe.paymentMethod": "Zahlungsmethode", + "black.subscribe.loadingPaymentForm": "Lade Zahlungsformular...", + "black.subscribe.selectWorkspaceToContinue": "Wähle einen Workspace um fortzufahren", + "black.subscribe.failurePrefix": "Oh nein!", + "black.subscribe.error.generic": "Ein Fehler ist aufgetreten", + "black.subscribe.error.invalidPlan": "Ungültiger Plan", + "black.subscribe.error.workspaceRequired": "Workspace-ID ist erforderlich", + "black.subscribe.error.alreadySubscribed": "Dieser Workspace hat bereits ein Abonnement", + "black.subscribe.processing": "Verarbeitung...", + "black.subscribe.submit": "Abonnieren ${{plan}}", + "black.subscribe.form.chargeNotice": "Du wirst erst belastet, wenn dein Abonnement aktiviert ist", + "black.subscribe.success.title": "Du bist auf der OpenCode Black Warteliste", + "black.subscribe.success.subscriptionPlan": "Abo-Plan", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "Betrag", + "black.subscribe.success.amountValue": "${{plan}} pro Monat", + "black.subscribe.success.paymentMethod": "Zahlungsmethode", + "black.subscribe.success.dateJoined": "Beitrittsdatum", + "black.subscribe.success.chargeNotice": "Deine Karte wird belastet, sobald dein Abonnement aktiviert ist", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "API Keys", + "workspace.nav.members": "Mitglieder", + "workspace.nav.billing": "Abrechnung", + "workspace.nav.settings": "Einstellungen", + + "workspace.home.banner.beforeLink": "Zuverlässige, optimierte Modelle für Coding-Agents.", + "workspace.home.billing.loading": "Laden...", + "workspace.home.billing.enable": "Abrechnung aktivieren", + "workspace.home.billing.currentBalance": "Aktuelles Guthaben", + + "workspace.newUser.feature.tested.title": "Getestete & Verifizierte Modelle", + "workspace.newUser.feature.tested.body": + "Wir haben Modelle speziell für Coding-Agents getestet und bewertet, um beste Leistung zu garantieren.", + "workspace.newUser.feature.quality.title": "Höchste Qualität", + "workspace.newUser.feature.quality.body": + "Zugriff auf Modelle, die für optimale Leistung konfiguriert sind – keine Downgrades oder Routing zu billigeren Anbietern.", + "workspace.newUser.feature.lockin.title": "Kein Lock-in", + "workspace.newUser.feature.lockin.body": + "Nutze Zen mit jedem Coding-Agent und nutze weiterhin andere Anbieter mit OpenCode, wann immer du willst.", + "workspace.newUser.copyApiKey": "API Key kopieren", + "workspace.newUser.copyKey": "Key kopieren", + "workspace.newUser.copied": "Kopiert!", + "workspace.newUser.step.enableBilling": "Abrechnung aktivieren", + "workspace.newUser.step.login.before": "Führe", + "workspace.newUser.step.login.after": "aus und wähle OpenCode", + "workspace.newUser.step.pasteKey": "Füge deinen API Key ein", + "workspace.newUser.step.models.before": "Starte OpenCode und führe", + "workspace.newUser.step.models.after": "aus, um ein Modell zu wählen", + + "workspace.models.title": "Modelle", + "workspace.models.subtitle.beforeLink": "Verwalte, auf welche Modelle Workspace-Mitglieder zugreifen können.", + "workspace.models.table.model": "Modell", + "workspace.models.table.enabled": "Aktiviert", + + "workspace.providers.title": "Bring Your Own Key", + "workspace.providers.subtitle": "Konfiguriere deine eigenen API Keys von AI-Anbietern.", + "workspace.providers.placeholder": "Gib {{provider}} API Key ein ({{prefix}}...)", + "workspace.providers.configure": "Konfigurieren", + "workspace.providers.edit": "Bearbeiten", + "workspace.providers.delete": "Löschen", + "workspace.providers.saving": "Speichere...", + "workspace.providers.save": "Speichern", + "workspace.providers.table.provider": "Anbieter", + "workspace.providers.table.apiKey": "API Key", + + "workspace.usage.title": "Nutzungsverlauf", + "workspace.usage.subtitle": "Kürzliche API-Nutzung und Kosten.", + "workspace.usage.empty": "Mache deinen ersten API-Aufruf, um loszulegen.", + "workspace.usage.table.date": "Datum", + "workspace.usage.table.model": "Modell", + "workspace.usage.table.input": "Input", + "workspace.usage.table.output": "Output", + "workspace.usage.table.cost": "Kosten", + "workspace.usage.breakdown.input": "Input", + "workspace.usage.breakdown.cacheRead": "Cache Read", + "workspace.usage.breakdown.cacheWrite": "Cache Write", + "workspace.usage.breakdown.output": "Output", + "workspace.usage.breakdown.reasoning": "Reasoning", + "workspace.usage.subscription": "Abonnement (${{amount}})", + + "workspace.cost.title": "Kosten", + "workspace.cost.subtitle": "Nutzungskosten aufgeschlüsselt nach Modell.", + "workspace.cost.allModels": "Alle Modelle", + "workspace.cost.allKeys": "Alle Keys", + "workspace.cost.deletedSuffix": "(gelöscht)", + "workspace.cost.empty": "Keine Nutzungsdaten für den gewählten Zeitraum verfügbar.", + "workspace.cost.subscriptionShort": "Abo", + + "workspace.keys.title": "API Keys", + "workspace.keys.subtitle": "Verwalte deine API Keys für den Zugriff auf OpenCode-Dienste.", + "workspace.keys.create": "API Key erstellen", + "workspace.keys.placeholder": "Key-Namen eingeben", + "workspace.keys.empty": "Erstelle einen OpenCode Gateway API Key", + "workspace.keys.table.name": "Name", + "workspace.keys.table.key": "Key", + "workspace.keys.table.createdBy": "Erstellt von", + "workspace.keys.table.lastUsed": "Zuletzt genutzt", + "workspace.keys.copyApiKey": "API Key kopieren", + "workspace.keys.delete": "Löschen", + + "workspace.members.title": "Mitglieder", + "workspace.members.subtitle": "Verwalte Workspace-Mitglieder und deren Berechtigungen.", + "workspace.members.invite": "Mitglied einladen", + "workspace.members.inviting": "Lade ein...", + "workspace.members.beta.beforeLink": "Workspaces sind für Teams während der Beta kostenlos.", + "workspace.members.form.invitee": "Eingeladene Person", + "workspace.members.form.emailPlaceholder": "E-Mail eingeben", + "workspace.members.form.role": "Rolle", + "workspace.members.form.monthlyLimit": "Monatliches Ausgabenlimit", + "workspace.members.noLimit": "Kein Limit", + "workspace.members.noLimitLowercase": "kein Limit", + "workspace.members.invited": "eingeladen", + "workspace.members.edit": "Bearbeiten", + "workspace.members.delete": "Löschen", + "workspace.members.saving": "Speichere...", + "workspace.members.save": "Speichern", + "workspace.members.table.email": "E-Mail", + "workspace.members.table.role": "Rolle", + "workspace.members.table.monthLimit": "Monatslimit", + "workspace.members.role.admin": "Admin", + "workspace.members.role.adminDescription": "Kann Modelle, Mitglieder und Abrechnung verwalten", + "workspace.members.role.member": "Mitglied", + "workspace.members.role.memberDescription": "Kann nur API Keys für sich selbst generieren", + + "workspace.settings.title": "Einstellungen", + "workspace.settings.subtitle": "Aktualisiere deinen Workspace-Namen und Präferenzen.", + "workspace.settings.workspaceName": "Workspace-Name", + "workspace.settings.defaultName": "Standard", + "workspace.settings.updating": "Aktualisiere...", + "workspace.settings.save": "Speichern", + "workspace.settings.edit": "Bearbeiten", + + "workspace.billing.title": "Abrechnung", + "workspace.billing.subtitle.beforeLink": "Zahlungsmethoden verwalten.", + "workspace.billing.contactUs": "Kontaktiere uns", + "workspace.billing.subtitle.afterLink": "wenn du Fragen hast.", + "workspace.billing.currentBalance": "Aktuelles Guthaben", + "workspace.billing.add": "$ hinzufügen", + "workspace.billing.enterAmount": "Betrag eingeben", + "workspace.billing.loading": "Lade...", + "workspace.billing.addAction": "Hinzufügen", + "workspace.billing.addBalance": "Guthaben aufladen", + "workspace.billing.linkedToStripe": "Mit Stripe verbunden", + "workspace.billing.manage": "Verwalten", + "workspace.billing.enable": "Abrechnung aktivieren", + + "workspace.monthlyLimit.title": "Monatliches Limit", + "workspace.monthlyLimit.subtitle": "Setze ein monatliches Nutzungslimit für deinen Account.", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "Setze...", + "workspace.monthlyLimit.set": "Setzen", + "workspace.monthlyLimit.edit": "Limit bearbeiten", + "workspace.monthlyLimit.noLimit": "Kein Nutzungslimit gesetzt.", + "workspace.monthlyLimit.currentUsage.beforeMonth": "Aktuelle Nutzung für", + "workspace.monthlyLimit.currentUsage.beforeAmount": "ist $", + + "workspace.reload.title": "Auto-Reload", + "workspace.reload.disabled.before": "Auto-Reload ist", + "workspace.reload.disabled.state": "deaktiviert", + "workspace.reload.disabled.after": "Aktivieren, um automatisch aufzuladen, wenn das Guthaben niedrig ist.", + "workspace.reload.enabled.before": "Auto-Reload ist", + "workspace.reload.enabled.state": "aktiviert", + "workspace.reload.enabled.middle": "Wir laden auf", + "workspace.reload.processingFee": "Bearbeitungsgebühr", + "workspace.reload.enabled.after": "wenn das Guthaben erreicht:", + "workspace.reload.edit": "Bearbeiten", + "workspace.reload.enable": "Aktivieren", + "workspace.reload.enableAutoReload": "Auto-Reload aktivieren", + "workspace.reload.reloadAmount": "Aufladebetrag $", + "workspace.reload.whenBalanceReaches": "Wenn Guthaben $ erreicht", + "workspace.reload.saving": "Speichere...", + "workspace.reload.save": "Speichern", + "workspace.reload.failedAt": "Aufladung fehlgeschlagen am", + "workspace.reload.reason": "Grund:", + "workspace.reload.updatePaymentMethod": "Bitte aktualisiere deine Zahlungsmethode und versuche es erneut.", + "workspace.reload.retrying": "Versuche erneut...", + "workspace.reload.retry": "Erneut versuchen", + + "workspace.payments.title": "Zahlungshistorie", + "workspace.payments.subtitle": "Kürzliche Zahlungstransaktionen.", + "workspace.payments.table.date": "Datum", + "workspace.payments.table.paymentId": "Zahlungs-ID", + "workspace.payments.table.amount": "Betrag", + "workspace.payments.table.receipt": "Beleg", + "workspace.payments.type.credit": "Guthaben", + "workspace.payments.type.subscription": "Abonnement", + "workspace.payments.view": "Ansehen", + + "workspace.black.loading": "Lade...", + "workspace.black.time.day": "Tag", + "workspace.black.time.days": "Tage", + "workspace.black.time.hour": "Stunde", + "workspace.black.time.hours": "Stunden", + "workspace.black.time.minute": "Minute", + "workspace.black.time.minutes": "Minuten", + "workspace.black.time.fewSeconds": "einige Sekunden", + "workspace.black.subscription.title": "Abonnement", + "workspace.black.subscription.message": "Du hast OpenCode Black für ${{plan}} pro Monat abonniert.", + "workspace.black.subscription.manage": "Abo verwalten", + "workspace.black.subscription.rollingUsage": "5-Stunden-Nutzung", + "workspace.black.subscription.weeklyUsage": "Wöchentliche Nutzung", + "workspace.black.subscription.resetsIn": "Setzt zurück in", + "workspace.black.subscription.useBalance": "Nutze dein verfügbares Guthaben, nachdem die Limits erreicht sind", + "workspace.black.waitlist.title": "Warteliste", + "workspace.black.waitlist.joined": "Du bist auf der Warteliste für den ${{plan}} pro Monat OpenCode Black Plan.", + "workspace.black.waitlist.ready": "Wir sind bereit, dich in den ${{plan}} pro Monat OpenCode Black Plan aufzunehmen.", + "workspace.black.waitlist.leave": "Warteliste verlassen", + "workspace.black.waitlist.leaving": "Verlasse...", + "workspace.black.waitlist.left": "Verlassen", + "workspace.black.waitlist.enroll": "Einschreiben", + "workspace.black.waitlist.enrolling": "Schreibe ein...", + "workspace.black.waitlist.enrolled": "Eingeschrieben", + "workspace.black.waitlist.enrollNote": + "Wenn du auf Einschreiben klickst, startet dein Abo sofort und deine Karte wird belastet.", + + "download.title": "OpenCode | Download", + "download.meta.description": "Lade OpenCode für macOS, Windows und Linux herunter", + "download.hero.title": "OpenCode herunterladen", + "download.hero.subtitle": "In Beta verfügbar für macOS, Windows und Linux", + "download.hero.button": "Download für {{os}}", + "download.section.terminal": "OpenCode Terminal", + "download.section.desktop": "OpenCode Desktop (Beta)", + "download.section.extensions": "OpenCode Extensions", + "download.section.integrations": "OpenCode Integrationen", + "download.action.download": "Download", + "download.action.install": "Installieren", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "Nicht unbedingt, aber wahrscheinlich. Du brauchst ein AI-Abo, wenn du OpenCode mit einem bezahlten Anbieter verbinden willst, obwohl du mit", + "download.faq.a3.localLink": "lokalen Modellen", + "download.faq.a3.afterLocal.beforeZen": "kostenlos arbeiten kannst. Während wir Nutzern raten,", + "download.faq.a3.afterZen": + " zu nutzen, funktioniert OpenCode mit allen populären Anbietern wie OpenAI, Anthropic, xAI etc.", + + "download.faq.a5.p1": "OpenCode ist 100% kostenlos.", + "download.faq.a5.p2.beforeZen": + "Zusätzliche Kosten entstehen durch dein Abo bei einem Modellanbieter. Während OpenCode mit jedem Modellanbieter funktioniert, empfehlen wir", + "download.faq.a5.p2.afterZen": " zu nutzen.", + + "download.faq.a6.p1": + "Deine Daten und Informationen werden nur gespeichert, wenn du teilbare Links in OpenCode erstellst.", + "download.faq.a6.p2.beforeShare": "Erfahre mehr über", + "download.faq.a6.shareLink": "Share-Pages", + + "enterprise.title": "OpenCode | Enterprise-Lösungen für Ihre Organisation", + "enterprise.meta.description": "Kontaktieren Sie OpenCode für Enterprise-Lösungen", + "enterprise.hero.title": "Ihr Code gehört Ihnen", + "enterprise.hero.body1": + "OpenCode arbeitet sicher innerhalb Ihrer Organisation, ohne dass Daten oder Kontext gespeichert werden und ohne Lizenzbeschränkungen oder Eigentumsansprüche. Starten Sie einen Testlauf mit Ihrem Team, dann rollen Sie es in Ihrer Organisation aus, indem Sie es in Ihr SSO und internes AI-Gateway integrieren.", + "enterprise.hero.body2": "Lassen Sie uns wissen, wie wir helfen können.", + "enterprise.form.name.label": "Vollständiger Name", + "enterprise.form.name.placeholder": "Jeff Bezos", + "enterprise.form.role.label": "Rolle", + "enterprise.form.role.placeholder": "Executive Chairman", + "enterprise.form.email.label": "Firmen-E-Mail", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "Welches Problem versuchen Sie zu lösen?", + "enterprise.form.message.placeholder": "Wir brauchen Hilfe bei...", + "enterprise.form.send": "Senden", + "enterprise.form.sending": "Sende...", + "enterprise.form.success": "Nachricht gesendet, wir melden uns bald.", + "enterprise.faq.title": "FAQ", + "enterprise.faq.q1": "Was ist OpenCode Enterprise?", + "enterprise.faq.a1": + "OpenCode Enterprise ist für Organisationen, die sicherstellen wollen, dass Code und Daten niemals ihre Infrastruktur verlassen. Dies geschieht durch eine zentrale Konfiguration, die in Ihr SSO und internes AI-Gateway integriert wird.", + "enterprise.faq.q2": "Wie starte ich mit OpenCode Enterprise?", + "enterprise.faq.a2": + "Starten Sie einfach mit einem internen Testlauf mit Ihrem Team. OpenCode speichert standardmäßig weder Code noch Kontextdaten, was den Einstieg erleichtert. Kontaktieren Sie uns dann, um Preise und Implementierungsoptionen zu besprechen.", + "enterprise.faq.q3": "Wie funktioniert das Enterprise-Pricing?", + "enterprise.faq.a3": + "Wir bieten eine Preisgestaltung pro Arbeitsplatz (Seat) an. Wenn Sie Ihr eigenes LLM-Gateway haben, berechnen wir keine Gebühren für genutzte Token. Für weitere Details kontaktieren Sie uns für ein individuelles Angebot basierend auf den Anforderungen Ihrer Organisation.", + "enterprise.faq.q4": "Sind meine Daten mit OpenCode Enterprise sicher?", + "enterprise.faq.a4": + "Ja. OpenCode speichert weder Ihren Code noch Kontextdaten. Alle Verarbeitungen finden lokal oder über direkte API-Aufrufe an Ihren AI-Anbieter statt. Mit zentraler Konfiguration und SSO-Integration bleiben Ihre Daten sicher innerhalb der Infrastruktur Ihrer Organisation.", + + "brand.title": "OpenCode | Marke", + "brand.meta.description": "OpenCode Markenrichtlinien", + "brand.heading": "Markenrichtlinien", + "brand.subtitle": "Ressourcen und Assets, die dir helfen, mit der OpenCode-Marke zu arbeiten.", + "brand.downloadAll": "Alle Assets herunterladen", + + "changelog.title": "OpenCode | Changelog", + "changelog.meta.description": "OpenCode Release Notes und Changelog", + "changelog.hero.title": "Changelog", + "changelog.hero.subtitle": "Neue Updates und Verbesserungen für OpenCode", + "changelog.empty": "Keine Changelog-Einträge gefunden.", + "changelog.viewJson": "JSON ansehen", + + "bench.list.title": "Benchmark", + "bench.list.heading": "Benchmarks", + "bench.list.table.agent": "Agent", + "bench.list.table.model": "Modell", + "bench.list.table.score": "Score", + + "bench.detail.title": "Benchmark - {{task}}", + "bench.detail.notFound": "Task nicht gefunden", + "bench.detail.na": "N/A", + "bench.detail.labels.agent": "Agent", + "bench.detail.labels.model": "Modell", + "bench.detail.labels.task": "Task", + "bench.detail.labels.repo": "Repo", + "bench.detail.labels.from": "Von", + "bench.detail.labels.to": "Bis", + "bench.detail.labels.prompt": "Prompt", + "bench.detail.labels.commit": "Commit", + "bench.detail.labels.averageDuration": "Durchschnittliche Dauer", + "bench.detail.labels.averageScore": "Durchschnittlicher Score", + "bench.detail.labels.averageCost": "Durchschnittliche Kosten", + "bench.detail.labels.summary": "Zusammenfassung", + "bench.detail.labels.runs": "Durchläufe", + "bench.detail.labels.score": "Score", + "bench.detail.labels.base": "Basis", + "bench.detail.labels.penalty": "Strafe", + "bench.detail.labels.weight": "Gewichtung", + "bench.detail.table.run": "Durchlauf", + "bench.detail.table.score": "Score (Basis - Strafe)", + "bench.detail.table.cost": "Kosten", + "bench.detail.table.duration": "Dauer", + "bench.detail.run.title": "Durchlauf {{n}}", + "bench.detail.rawJson": "Raw JSON", +} satisfies Dict diff --git a/packages/console/app/src/i18n/en.ts b/packages/console/app/src/i18n/en.ts new file mode 100644 index 00000000000..08c716aba3b --- /dev/null +++ b/packages/console/app/src/i18n/en.ts @@ -0,0 +1,591 @@ +export const dict = { + "nav.github": "GitHub", + "nav.docs": "Docs", + "nav.changelog": "Changelog", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "Enterprise", + "nav.zen": "Zen", + "nav.login": "Login", + "nav.free": "Free", + "nav.home": "Home", + "nav.openMenu": "Open menu", + "nav.getStartedFree": "Get started for free", + + "nav.context.copyLogo": "Copy logo as SVG", + "nav.context.copyWordmark": "Copy wordmark as SVG", + "nav.context.brandAssets": "Brand assets", + + "footer.github": "GitHub", + "footer.docs": "Docs", + "footer.changelog": "Changelog", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "Brand", + "legal.privacy": "Privacy", + "legal.terms": "Terms", + + "email.title": "Be the first to know when we release new products", + "email.subtitle": "Join the waitlist for early access.", + "email.placeholder": "Email address", + "email.subscribe": "Subscribe", + "email.success": "Almost done, check your inbox and confirm your email address", + + "notFound.title": "Not Found | opencode", + "notFound.heading": "404 - Page Not Found", + "notFound.home": "Home", + "notFound.docs": "Docs", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "Logout", + + "workspace.select": "Select workspace", + "workspace.createNew": "+ Create New Workspace", + "workspace.modal.title": "Create New Workspace", + "workspace.modal.placeholder": "Enter workspace name", + + "common.cancel": "Cancel", + "common.creating": "Creating...", + "common.create": "Create", + + "common.videoUnsupported": "Your browser does not support the video tag.", + "common.figure": "Fig {{n}}.", + "common.faq": "FAQ", + "common.learnMore": "Learn more", + + "error.invalidPlan": "Invalid plan", + "error.workspaceRequired": "Workspace ID is required", + "error.alreadySubscribed": "This workspace already has a subscription", + "error.limitRequired": "Limit is required.", + "error.monthlyLimitInvalid": "Set a valid monthly limit.", + "error.workspaceNameRequired": "Workspace name is required.", + "error.nameTooLong": "Name must be 255 characters or less.", + "error.emailRequired": "Email is required", + "error.roleRequired": "Role is required", + "error.idRequired": "ID is required", + "error.nameRequired": "Name is required", + "error.providerRequired": "Provider is required", + "error.apiKeyRequired": "API key is required", + "error.modelRequired": "Model is required", + "error.reloadAmountMin": "Reload amount must be at least ${{amount}}", + "error.reloadTriggerMin": "Balance trigger must be at least ${{amount}}", + + "home.title": "OpenCode | The open source AI coding agent", + + "temp.title": "opencode | AI coding agent built for the terminal", + "temp.hero.title": "The AI coding agent built for the terminal", + "temp.zen": "opencode zen", + "temp.getStarted": "Get Started", + "temp.feature.native.title": "Native TUI", + "temp.feature.native.body": "A responsive, native, themeable terminal UI", + "temp.feature.zen.beforeLink": "A", + "temp.feature.zen.link": "curated list of models", + "temp.feature.zen.afterLink": "provided by opencode", + "temp.feature.models.beforeLink": "Supports 75+ LLM providers through", + "temp.feature.models.afterLink": ", including local models", + "temp.screenshot.caption": "opencode TUI with the tokyonight theme", + "temp.screenshot.alt": "opencode TUI with tokyonight theme", + + "home.banner.badge": "New", + "home.banner.text": "Desktop app available in beta", + "home.banner.platforms": "on macOS, Windows, and Linux", + "home.banner.downloadNow": "Download now", + "home.banner.downloadBetaNow": "Download the desktop beta now", + + "home.hero.title": "The open source AI coding agent", + "home.hero.subtitle.a": "Free models included or connect any model from any provider,", + "home.hero.subtitle.b": "including Claude, GPT, Gemini and more.", + + "home.install.ariaLabel": "Install options", + + "home.what.title": "What is OpenCode?", + "home.what.body": "OpenCode is an open source agent that helps you write code in your terminal, IDE, or desktop.", + "home.what.lsp.title": "LSP enabled", + "home.what.lsp.body": "Automatically loads the right LSPs for the LLM", + "home.what.multiSession.title": "Multi-session", + "home.what.multiSession.body": "Start multiple agents in parallel on the same project", + "home.what.shareLinks.title": "Share links", + "home.what.shareLinks.body": "Share a link to any session for reference or to debug", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "Log in with GitHub to use your Copilot account", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "Log in with OpenAI to use your ChatGPT Plus or Pro account", + "home.what.anyModel.title": "Any model", + "home.what.anyModel.body": "75+ LLM providers through Models.dev, including local models", + "home.what.anyEditor.title": "Any editor", + "home.what.anyEditor.body": "Available as a terminal interface, desktop app, and IDE extension", + "home.what.readDocs": "Read docs", + + "home.growth.title": "The open source AI coding agent", + "home.growth.body": + "With over {{stars}} GitHub stars, {{contributors}} contributors, and over {{commits}} commits, OpenCode is used and trusted by over {{monthlyUsers}} developers every month.", + "home.growth.githubStars": "GitHub Stars", + "home.growth.contributors": "Contributors", + "home.growth.monthlyDevs": "Monthly Devs", + + "home.privacy.title": "Built for privacy first", + "home.privacy.body": + "OpenCode does not store any of your code or context data, so that it can operate in privacy sensitive environments.", + "home.privacy.learnMore": "Learn more about", + "home.privacy.link": "privacy", + + "home.faq.q1": "What is OpenCode?", + "home.faq.a1": + "OpenCode is an open source agent that helps you write and run code with any AI model. It's available as a terminal-based interface, desktop app, or IDE extension.", + "home.faq.q2": "How do I use OpenCode?", + "home.faq.a2.before": "The easiest way to get started is to read the", + "home.faq.a2.link": "intro", + "home.faq.q3": "Do I need extra AI subscriptions to use OpenCode?", + "home.faq.a3.p1": + "Not necessarily, OpenCode comes with a set of free models that you can use without creating an account.", + "home.faq.a3.p2.beforeZen": "Aside from these, you can use any of the popular coding models by creating a", + "home.faq.a3.p2.afterZen": " account.", + "home.faq.a3.p3": + "While we encourage users to use Zen, OpenCode also works with all popular providers such as OpenAI, Anthropic, xAI etc.", + "home.faq.a3.p4.beforeLocal": "You can even connect your", + "home.faq.a3.p4.localLink": "local models", + "home.faq.q4": "Can I use my existing AI subscriptions with OpenCode?", + "home.faq.a4.p1": + "Yes, OpenCode supports subscription plans from all major providers. You can use your Claude Pro/Max, ChatGPT Plus/Pro, or GitHub Copilot subscriptions.", + "home.faq.q5": "Can I only use OpenCode in the terminal?", + "home.faq.a5.beforeDesktop": "Not anymore! OpenCode is now available as an app for your", + "home.faq.a5.desktop": "desktop", + "home.faq.a5.and": "and", + "home.faq.a5.web": "web", + "home.faq.q6": "How much does OpenCode cost?", + "home.faq.a6": + "OpenCode is 100% free to use. It also comes with a set of free models. There might be additional costs if you connect any other provider.", + "home.faq.q7": "What about data and privacy?", + "home.faq.a7.p1": "Your data and information is only stored when you use our free models or create sharable links.", + "home.faq.a7.p2.beforeModels": "Learn more about", + "home.faq.a7.p2.modelsLink": "our models", + "home.faq.a7.p2.and": "and", + "home.faq.a7.p2.shareLink": "share pages", + "home.faq.q8": "Is OpenCode open source?", + "home.faq.a8.p1": "Yes, OpenCode is fully open source. The source code is public on", + "home.faq.a8.p2": "under the", + "home.faq.a8.mitLicense": "MIT License", + "home.faq.a8.p3": + ", meaning anyone can use, modify, or contribute to its development. Anyone from the community can file issues, submit pull requests, and extend functionality.", + + "home.zenCta.title": "Access reliable optimized models for coding agents", + "home.zenCta.body": + "Zen gives you access to a handpicked set of AI models that OpenCode has tested and benchmarked specifically for coding agents. No need to worry about inconsistent performance and quality across providers, use validated models that work.", + "home.zenCta.link": "Learn about Zen", + + "zen.title": "OpenCode Zen | A curated set of reliable optimized models for coding agents", + "zen.hero.title": "Reliable optimized models for coding agents", + "zen.hero.body": + "Zen gives you access to a curated set of AI models that OpenCode has tested and benchmarked specifically for coding agents. No need to worry about inconsistent performance and quality, use validated models that work.", + + "zen.faq.q1": "What is OpenCode Zen?", + "zen.faq.a1": + "Zen is a curated set of AI models tested and benchmarked for coding agents created by the team behind OpenCode.", + "zen.faq.q2": "What makes Zen more accurate?", + "zen.faq.a2": + "Zen only provides models that have been specifically tested and benchmarked for coding agents. You wouldn't use a butter knife to cut steak, don't use poor models for coding.", + "zen.faq.q3": "Is Zen cheaper?", + "zen.faq.a3": + "Zen is not for profit. Zen passes through the costs from the model providers to you. The higher Zen's usage the more OpenCode can negotiate better rates and pass those to you.", + "zen.faq.q4": "How much does Zen cost?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "charges per request", + "zen.faq.a4.p1.afterPricing": "with zero markups, so you pay exactly what the model provider charges.", + "zen.faq.a4.p2.beforeAccount": "Your total cost depends on usage, and you can set monthly spend limits in your", + "zen.faq.a4.p2.accountLink": "account", + "zen.faq.a4.p3": "To cover costs, OpenCode adds only a small payment processing fee of $1.23 per $20 balance top-up.", + "zen.faq.q5": "What about data and privacy?", + "zen.faq.a5.beforeExceptions": + "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.faq.a5.exceptionsLink": "following exceptions", + "zen.faq.q6": "Can I set spend limits?", + "zen.faq.a6": "Yes, you can set monthly spending limits in your account.", + "zen.faq.q7": "Can I cancel?", + "zen.faq.a7": "Yes, you can disable billing at any time and use your remaining balance.", + "zen.faq.q8": "Can I use Zen with other coding agents?", + "zen.faq.a8": + "While Zen works great with OpenCode, you can use Zen with any agent. Follow the setup instructions in your preferred coding agent.", + + "zen.cta.start": "Get started with Zen", + "zen.pricing.title": "Add $20 Pay as you go balance", + "zen.pricing.fee": "(+$1.23 card processing fee)", + "zen.pricing.body": "Use with any agent. Set monthly spend limits. Cancel any time.", + "zen.problem.title": "What problem is Zen solving?", + "zen.problem.body": + "There are so many models available, but only a few work well with coding agents. Most providers configure them differently with varying results.", + "zen.problem.subtitle": "We're fixing this for everyone, not just OpenCode users.", + "zen.problem.item1": "Testing select models and consulting their teams", + "zen.problem.item2": "Working with providers to ensure they're delivered properly", + "zen.problem.item3": "Benchmarking all model-provider combinations we recommend", + "zen.how.title": "How Zen works", + "zen.how.body": "While we suggest you use Zen with OpenCode, you can use Zen with any agent.", + "zen.how.step1.title": "Sign up and add $20 balance", + "zen.how.step1.beforeLink": "follow the", + "zen.how.step1.link": "setup instructions", + "zen.how.step2.title": "Use Zen with transparent pricing", + "zen.how.step2.link": "pay per request", + "zen.how.step2.afterLink": "with zero markups", + "zen.how.step3.title": "Auto-top up", + "zen.how.step3.body": "when your balance reaches $5 we'll automatically add $20", + "zen.privacy.title": "Your privacy is important to us", + "zen.privacy.beforeExceptions": + "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", + + "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", + "black.hero.subtitle": "Including Claude, GPT, Gemini and more", + "black.title": "OpenCode Black | Pricing", + "black.plan.icon20": "Black 20 plan", + "black.plan.icon100": "Black 100 plan", + "black.plan.icon200": "Black 200 plan", + "black.plan.multiplier100": "5x more usage than Black 20", + "black.plan.multiplier200": "20x more usage than Black 20", + "black.price.perMonth": "per month", + "black.price.perPersonBilledMonthly": "per person billed monthly", + "black.terms.1": "Your subscription will not start immediately", + "black.terms.2": "You will be added to the waitlist and activated soon", + "black.terms.3": "Your card will only be charged when your subscription is activated", + "black.terms.4": "Usage limits apply, heavily automated use may reach limits sooner", + "black.terms.5": "Subscriptions are for individuals, contact Enterprise for teams", + "black.terms.6": "Limits may be adjusted and plans may be discontinued in the future", + "black.terms.7": "Cancel your subscription at any time", + "black.action.continue": "Continue", + "black.finePrint.beforeTerms": "Prices shown don't include applicable tax", + "black.finePrint.terms": "Terms of Service", + "black.workspace.title": "OpenCode Black | Select Workspace", + "black.workspace.selectPlan": "Select a workspace for this plan", + "black.workspace.name": "Workspace {{n}}", + "black.subscribe.title": "Subscribe to OpenCode Black", + "black.subscribe.paymentMethod": "Payment method", + "black.subscribe.loadingPaymentForm": "Loading payment form...", + "black.subscribe.selectWorkspaceToContinue": "Select a workspace to continue", + "black.subscribe.failurePrefix": "Uh oh!", + "black.subscribe.error.generic": "An error occurred", + "black.subscribe.error.invalidPlan": "Invalid plan", + "black.subscribe.error.workspaceRequired": "Workspace ID is required", + "black.subscribe.error.alreadySubscribed": "This workspace already has a subscription", + "black.subscribe.processing": "Processing...", + "black.subscribe.submit": "Subscribe ${{plan}}", + "black.subscribe.form.chargeNotice": "You will only be charged when your subscription is activated", + "black.subscribe.success.title": "You're on the OpenCode Black waitlist", + "black.subscribe.success.subscriptionPlan": "Subscription plan", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "Amount", + "black.subscribe.success.amountValue": "${{plan}} per month", + "black.subscribe.success.paymentMethod": "Payment method", + "black.subscribe.success.dateJoined": "Date joined", + "black.subscribe.success.chargeNotice": "Your card will be charged when your subscription is activated", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "API Keys", + "workspace.nav.members": "Members", + "workspace.nav.billing": "Billing", + "workspace.nav.settings": "Settings", + + "workspace.home.banner.beforeLink": "Reliable optimized models for coding agents.", + "workspace.home.billing.loading": "Loading...", + "workspace.home.billing.enable": "Enable billing", + "workspace.home.billing.currentBalance": "Current balance", + + "workspace.newUser.feature.tested.title": "Tested & Verified Models", + "workspace.newUser.feature.tested.body": + "We've benchmarked and tested models specifically for coding agents to ensure the best performance.", + "workspace.newUser.feature.quality.title": "Highest Quality", + "workspace.newUser.feature.quality.body": + "Access models configured for optimal performance - no downgrades or routing to cheaper providers.", + "workspace.newUser.feature.lockin.title": "No Lock-in", + "workspace.newUser.feature.lockin.body": + "Use Zen with any coding agent, and continue using other providers with opencode whenever you want.", + "workspace.newUser.copyApiKey": "Copy API key", + "workspace.newUser.copyKey": "Copy Key", + "workspace.newUser.copied": "Copied!", + "workspace.newUser.step.enableBilling": "Enable billing", + "workspace.newUser.step.login.before": "Run", + "workspace.newUser.step.login.after": "and select opencode", + "workspace.newUser.step.pasteKey": "Paste your API key", + "workspace.newUser.step.models.before": "Start opencode and run", + "workspace.newUser.step.models.after": "to select a model", + + "workspace.models.title": "Models", + "workspace.models.subtitle.beforeLink": "Manage which models workspace members can access.", + "workspace.models.table.model": "Model", + "workspace.models.table.enabled": "Enabled", + + "workspace.providers.title": "Bring Your Own Key", + "workspace.providers.subtitle": "Configure your own API keys from AI providers.", + "workspace.providers.placeholder": "Enter {{provider}} API key ({{prefix}}...)", + "workspace.providers.configure": "Configure", + "workspace.providers.edit": "Edit", + "workspace.providers.delete": "Delete", + "workspace.providers.saving": "Saving...", + "workspace.providers.save": "Save", + "workspace.providers.table.provider": "Provider", + "workspace.providers.table.apiKey": "API Key", + + "workspace.usage.title": "Usage History", + "workspace.usage.subtitle": "Recent API usage and costs.", + "workspace.usage.empty": "Make your first API call to get started.", + "workspace.usage.table.date": "Date", + "workspace.usage.table.model": "Model", + "workspace.usage.table.input": "Input", + "workspace.usage.table.output": "Output", + "workspace.usage.table.cost": "Cost", + "workspace.usage.breakdown.input": "Input", + "workspace.usage.breakdown.cacheRead": "Cache Read", + "workspace.usage.breakdown.cacheWrite": "Cache Write", + "workspace.usage.breakdown.output": "Output", + "workspace.usage.breakdown.reasoning": "Reasoning", + "workspace.usage.subscription": "subscription (${{amount}})", + + "workspace.cost.title": "Cost", + "workspace.cost.subtitle": "Usage costs broken down by model.", + "workspace.cost.allModels": "All Models", + "workspace.cost.allKeys": "All Keys", + "workspace.cost.deletedSuffix": "(deleted)", + "workspace.cost.empty": "No usage data available for the selected period.", + "workspace.cost.subscriptionShort": "sub", + + "workspace.keys.title": "API Keys", + "workspace.keys.subtitle": "Manage your API keys for accessing opencode services.", + "workspace.keys.create": "Create API Key", + "workspace.keys.placeholder": "Enter key name", + "workspace.keys.empty": "Create an opencode Gateway API key", + "workspace.keys.table.name": "Name", + "workspace.keys.table.key": "Key", + "workspace.keys.table.createdBy": "Created By", + "workspace.keys.table.lastUsed": "Last Used", + "workspace.keys.copyApiKey": "Copy API key", + "workspace.keys.delete": "Delete", + + "workspace.members.title": "Members", + "workspace.members.subtitle": "Manage workspace members and their permissions.", + "workspace.members.invite": "Invite Member", + "workspace.members.inviting": "Inviting...", + "workspace.members.beta.beforeLink": "Workspaces are free for teams during the beta.", + "workspace.members.form.invitee": "Invitee", + "workspace.members.form.emailPlaceholder": "Enter email", + "workspace.members.form.role": "Role", + "workspace.members.form.monthlyLimit": "Monthly spending limit", + "workspace.members.noLimit": "No limit", + "workspace.members.noLimitLowercase": "no limit", + "workspace.members.invited": "invited", + "workspace.members.edit": "Edit", + "workspace.members.delete": "Delete", + "workspace.members.saving": "Saving...", + "workspace.members.save": "Save", + "workspace.members.table.email": "Email", + "workspace.members.table.role": "Role", + "workspace.members.table.monthLimit": "Month limit", + "workspace.members.role.admin": "Admin", + "workspace.members.role.adminDescription": "Can manage models, members, and billing", + "workspace.members.role.member": "Member", + "workspace.members.role.memberDescription": "Can only generate API keys for themselves", + + "workspace.settings.title": "Settings", + "workspace.settings.subtitle": "Update your workspace name and preferences.", + "workspace.settings.workspaceName": "Workspace name", + "workspace.settings.defaultName": "Default", + "workspace.settings.updating": "Updating...", + "workspace.settings.save": "Save", + "workspace.settings.edit": "Edit", + + "workspace.billing.title": "Billing", + "workspace.billing.subtitle.beforeLink": "Manage payment methods.", + "workspace.billing.contactUs": "Contact us", + "workspace.billing.subtitle.afterLink": "if you have any questions.", + "workspace.billing.currentBalance": "Current Balance", + "workspace.billing.add": "Add $", + "workspace.billing.enterAmount": "Enter amount", + "workspace.billing.loading": "Loading...", + "workspace.billing.addAction": "Add", + "workspace.billing.addBalance": "Add Balance", + "workspace.billing.linkedToStripe": "Linked to Stripe", + "workspace.billing.manage": "Manage", + "workspace.billing.enable": "Enable Billing", + + "workspace.monthlyLimit.title": "Monthly Limit", + "workspace.monthlyLimit.subtitle": "Set a monthly usage limit for your account.", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "Setting...", + "workspace.monthlyLimit.set": "Set", + "workspace.monthlyLimit.edit": "Edit Limit", + "workspace.monthlyLimit.noLimit": "No usage limit set.", + "workspace.monthlyLimit.currentUsage.beforeMonth": "Current usage for", + "workspace.monthlyLimit.currentUsage.beforeAmount": "is $", + + "workspace.reload.title": "Auto Reload", + "workspace.reload.disabled.before": "Auto reload is", + "workspace.reload.disabled.state": "disabled", + "workspace.reload.disabled.after": "Enable to automatically reload when balance is low.", + "workspace.reload.enabled.before": "Auto reload is", + "workspace.reload.enabled.state": "enabled", + "workspace.reload.enabled.middle": "We'll reload", + "workspace.reload.processingFee": "processing fee", + "workspace.reload.enabled.after": "when balance reaches", + "workspace.reload.edit": "Edit", + "workspace.reload.enable": "Enable", + "workspace.reload.enableAutoReload": "Enable Auto Reload", + "workspace.reload.reloadAmount": "Reload $", + "workspace.reload.whenBalanceReaches": "When balance reaches $", + "workspace.reload.saving": "Saving...", + "workspace.reload.save": "Save", + "workspace.reload.failedAt": "Reload failed at", + "workspace.reload.reason": "Reason:", + "workspace.reload.updatePaymentMethod": "Please update your payment method and try again.", + "workspace.reload.retrying": "Retrying...", + "workspace.reload.retry": "Retry", + + "workspace.payments.title": "Payments History", + "workspace.payments.subtitle": "Recent payment transactions.", + "workspace.payments.table.date": "Date", + "workspace.payments.table.paymentId": "Payment ID", + "workspace.payments.table.amount": "Amount", + "workspace.payments.table.receipt": "Receipt", + "workspace.payments.type.credit": "credit", + "workspace.payments.type.subscription": "subscription", + "workspace.payments.view": "View", + + "workspace.black.loading": "Loading...", + "workspace.black.time.day": "day", + "workspace.black.time.days": "days", + "workspace.black.time.hour": "hour", + "workspace.black.time.hours": "hours", + "workspace.black.time.minute": "minute", + "workspace.black.time.minutes": "minutes", + "workspace.black.time.fewSeconds": "a few seconds", + "workspace.black.subscription.title": "Subscription", + "workspace.black.subscription.message": "You are subscribed to OpenCode Black for ${{plan}} per month.", + "workspace.black.subscription.manage": "Manage Subscription", + "workspace.black.subscription.rollingUsage": "5-hour Usage", + "workspace.black.subscription.weeklyUsage": "Weekly Usage", + "workspace.black.subscription.resetsIn": "Resets in", + "workspace.black.subscription.useBalance": "Use your available balance after reaching the usage limits", + "workspace.black.waitlist.title": "Waitlist", + "workspace.black.waitlist.joined": "You are on the waitlist for the ${{plan}} per month OpenCode Black plan.", + "workspace.black.waitlist.ready": "We're ready to enroll you into the ${{plan}} per month OpenCode Black plan.", + "workspace.black.waitlist.leave": "Leave Waitlist", + "workspace.black.waitlist.leaving": "Leaving...", + "workspace.black.waitlist.left": "Left", + "workspace.black.waitlist.enroll": "Enroll", + "workspace.black.waitlist.enrolling": "Enrolling...", + "workspace.black.waitlist.enrolled": "Enrolled", + "workspace.black.waitlist.enrollNote": + "When you click Enroll, your subscription starts immediately and your card will be charged.", + + "download.title": "OpenCode | Download", + "download.meta.description": "Download OpenCode for macOS, Windows, and Linux", + "download.hero.title": "Download OpenCode", + "download.hero.subtitle": "Available in Beta for macOS, Windows, and Linux", + "download.hero.button": "Download for {{os}}", + "download.section.terminal": "OpenCode Terminal", + "download.section.desktop": "OpenCode Desktop (Beta)", + "download.section.extensions": "OpenCode Extensions", + "download.section.integrations": "OpenCode Integrations", + "download.action.download": "Download", + "download.action.install": "Install", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "Not necessarily, but probably. You'll need an AI subscription if you want to connect OpenCode to a paid provider, although you can work with", + "download.faq.a3.localLink": "local models", + "download.faq.a3.afterLocal.beforeZen": "for free. While we encourage users to use", + "download.faq.a3.afterZen": ", OpenCode works with all popular providers such as OpenAI, Anthropic, xAI etc.", + + "download.faq.a5.p1": "OpenCode is 100% free to use.", + "download.faq.a5.p2.beforeZen": + "Any additional costs will come from your subscription to a model provider. While OpenCode works with any model provider, we recommend using", + "download.faq.a5.p2.afterZen": ".", + + "download.faq.a6.p1": "Your data and information is only stored when you create sharable links in OpenCode.", + "download.faq.a6.p2.beforeShare": "Learn more about", + "download.faq.a6.shareLink": "share pages", + + "enterprise.title": "OpenCode | Enterprise solutions for your organisation", + "enterprise.meta.description": "Contact OpenCode for enterprise solutions", + "enterprise.hero.title": "Your code is yours", + "enterprise.hero.body1": + "OpenCode operates securely inside your organization with no data or context stored and no licensing restrictions or ownership claims. Start a trial with your team, then deploy it across your organization by integrating it with your SSO and internal AI gateway.", + "enterprise.hero.body2": "Let us know how we can help.", + "enterprise.form.name.label": "Full name", + "enterprise.form.name.placeholder": "Jeff Bezos", + "enterprise.form.role.label": "Role", + "enterprise.form.role.placeholder": "Executive Chairman", + "enterprise.form.email.label": "Company email", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "What problem are you trying to solve?", + "enterprise.form.message.placeholder": "We need help with...", + "enterprise.form.send": "Send", + "enterprise.form.sending": "Sending...", + "enterprise.form.success": "Message sent, we'll be in touch soon.", + "enterprise.faq.title": "FAQ", + "enterprise.faq.q1": "What is OpenCode Enterprise?", + "enterprise.faq.a1": + "OpenCode Enterprise is for organizations that want to ensure that their code and data never leaves their infrastructure. It can do this by using a centralized config that integrates with your SSO and internal AI gateway.", + "enterprise.faq.q2": "How do I get started with OpenCode Enterprise?", + "enterprise.faq.a2": + "Simply start with an internal trial with your team. OpenCode by default does not store your code or context data, making it easy to get started. Then contact us to discuss pricing and implementation options.", + "enterprise.faq.q3": "How does enterprise pricing work?", + "enterprise.faq.a3": + "We offer per-seat enterprise pricing. If you have your own LLM gateway, we do not charge for tokens used. For further details, contact us for a custom quote based on your organization's needs.", + "enterprise.faq.q4": "Is my data secure with OpenCode Enterprise?", + "enterprise.faq.a4": + "Yes. OpenCode does not store your code or context data. All processing happens locally or through direct API calls to your AI provider. With central config and SSO integration, your data remains secure within your organization's infrastructure.", + + "brand.title": "OpenCode | Brand", + "brand.meta.description": "OpenCode brand guidelines", + "brand.heading": "Brand guidelines", + "brand.subtitle": "Resources and assets to help you work with the OpenCode brand.", + "brand.downloadAll": "Download all assets", + + "changelog.title": "OpenCode | Changelog", + "changelog.meta.description": "OpenCode release notes and changelog", + "changelog.hero.title": "Changelog", + "changelog.hero.subtitle": "New updates and improvements to OpenCode", + "changelog.empty": "No changelog entries found.", + "changelog.viewJson": "View JSON", + + "bench.list.title": "Benchmark", + "bench.list.heading": "Benchmarks", + "bench.list.table.agent": "Agent", + "bench.list.table.model": "Model", + "bench.list.table.score": "Score", + + "bench.detail.title": "Benchmark - {{task}}", + "bench.detail.notFound": "Task not found", + "bench.detail.na": "N/A", + "bench.detail.labels.agent": "Agent", + "bench.detail.labels.model": "Model", + "bench.detail.labels.task": "Task", + "bench.detail.labels.repo": "Repo", + "bench.detail.labels.from": "From", + "bench.detail.labels.to": "To", + "bench.detail.labels.prompt": "Prompt", + "bench.detail.labels.commit": "Commit", + "bench.detail.labels.averageDuration": "Average Duration", + "bench.detail.labels.averageScore": "Average Score", + "bench.detail.labels.averageCost": "Average Cost", + "bench.detail.labels.summary": "Summary", + "bench.detail.labels.runs": "Runs", + "bench.detail.labels.score": "Score", + "bench.detail.labels.base": "Base", + "bench.detail.labels.penalty": "Penalty", + "bench.detail.labels.weight": "weight", + "bench.detail.table.run": "Run", + "bench.detail.table.score": "Score (Base - Penalty)", + "bench.detail.table.cost": "Cost", + "bench.detail.table.duration": "Duration", + "bench.detail.run.title": "Run {{n}}", + "bench.detail.rawJson": "Raw JSON", +} as const + +export type Key = keyof typeof dict +export type Dict = Record diff --git a/packages/console/app/src/i18n/es.ts b/packages/console/app/src/i18n/es.ts new file mode 100644 index 00000000000..1a18a872ebf --- /dev/null +++ b/packages/console/app/src/i18n/es.ts @@ -0,0 +1,598 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "Documentación", + "nav.changelog": "Registro de cambios", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "Enterprise", + "nav.zen": "Zen", + "nav.login": "Iniciar sesión", + "nav.free": "Gratis", + "nav.home": "Inicio", + "nav.openMenu": "Abrir menú", + "nav.getStartedFree": "Empezar gratis", + + "nav.context.copyLogo": "Copiar logo como SVG", + "nav.context.copyWordmark": "Copiar marca como SVG", + "nav.context.brandAssets": "Activos de marca", + + "footer.github": "GitHub", + "footer.docs": "Documentación", + "footer.changelog": "Registro de cambios", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "Marca", + "legal.privacy": "Privacidad", + "legal.terms": "Términos", + + "email.title": "Sé el primero en enterarte cuando lancemos nuevos productos", + "email.subtitle": "Únete a la lista de espera para acceso anticipado.", + "email.placeholder": "Dirección de correo", + "email.subscribe": "Suscribirse", + "email.success": "Casi listo, revisa tu bandeja de entrada y confirma tu correo", + + "notFound.title": "No encontrado | opencode", + "notFound.heading": "404 - Página no encontrada", + "notFound.home": "Inicio", + "notFound.docs": "Documentación", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "Cerrar sesión", + + "workspace.select": "Seleccionar espacio de trabajo", + "workspace.createNew": "+ Crear nuevo espacio de trabajo", + "workspace.modal.title": "Crear nuevo espacio de trabajo", + "workspace.modal.placeholder": "Introduce nombre del espacio de trabajo", + + "common.cancel": "Cancelar", + "common.creating": "Creando...", + "common.create": "Crear", + + "common.videoUnsupported": "Tu navegador no soporta la etiqueta de video.", + "common.figure": "Fig {{n}}.", + "common.faq": "FAQ", + "common.learnMore": "Más información", + + "error.invalidPlan": "Plan inválido", + "error.workspaceRequired": "Se requiere ID del espacio de trabajo", + "error.alreadySubscribed": "Este espacio de trabajo ya tiene una suscripción", + "error.limitRequired": "El límite es obligatorio.", + "error.monthlyLimitInvalid": "Establece un límite mensual válido.", + "error.workspaceNameRequired": "El nombre del espacio de trabajo es obligatorio.", + "error.nameTooLong": "El nombre debe tener 255 caracteres o menos.", + "error.emailRequired": "El correo es obligatorio", + "error.roleRequired": "El rol es obligatorio", + "error.idRequired": "El ID es obligatorio", + "error.nameRequired": "El nombre es obligatorio", + "error.providerRequired": "El proveedor es obligatorio", + "error.apiKeyRequired": "La clave de API es obligatoria", + "error.modelRequired": "El modelo es obligatorio", + "error.reloadAmountMin": "La cantidad de recarga debe ser al menos ${{amount}}", + "error.reloadTriggerMin": "El disparador de saldo debe ser al menos ${{amount}}", + + "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", + "temp.hero.title": "El agente de codificación IA creado para la terminal", + "temp.zen": "opencode zen", + "temp.getStarted": "Empezar", + "temp.feature.native.title": "TUI Nativa", + "temp.feature.native.body": "Una interfaz de terminal responsiva, nativa y personalizable", + "temp.feature.zen.beforeLink": "Una lista", + "temp.feature.zen.link": "seleccionada de modelos", + "temp.feature.zen.afterLink": "proporcionada por opencode", + "temp.feature.models.beforeLink": "Soporta más de 75 proveedores de LLM a través de", + "temp.feature.models.afterLink": ", incluyendo modelos locales", + "temp.screenshot.caption": "opencode TUI con el tema tokyonight", + "temp.screenshot.alt": "opencode TUI con tema tokyonight", + + "home.banner.badge": "Nuevo", + "home.banner.text": "Aplicación de escritorio disponible en beta", + "home.banner.platforms": "en macOS, Windows y Linux", + "home.banner.downloadNow": "Descargar ahora", + "home.banner.downloadBetaNow": "Descargar la beta de escritorio ahora", + + "home.hero.title": "El agente de codificación IA de código abierto", + "home.hero.subtitle.a": "Modelos gratuitos incluidos o conecta cualquier modelo de cualquier proveedor,", + "home.hero.subtitle.b": "incluyendo Claude, GPT, Gemini y más.", + + "home.install.ariaLabel": "Opciones de instalación", + + "home.what.title": "¿Qué es OpenCode?", + "home.what.body": + "OpenCode es un agente de código abierto que te ayuda a escribir código en tu terminal, IDE o escritorio.", + "home.what.lsp.title": "LSP habilitado", + "home.what.lsp.body": "Carga automáticamente los LSPs correctos para el LLM", + "home.what.multiSession.title": "Multi-sesión", + "home.what.multiSession.body": "Inicia múltiples agentes en paralelo en el mismo proyecto", + "home.what.shareLinks.title": "Compartir enlaces", + "home.what.shareLinks.body": "Comparte un enlace a cualquier sesión para referencia o depuración", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "Inicia sesión con GitHub para usar tu cuenta de Copilot", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "Inicia sesión con OpenAI para usar tu cuenta de ChatGPT Plus o Pro", + "home.what.anyModel.title": "Cualquier modelo", + "home.what.anyModel.body": "Más de 75 proveedores de LLM a través de Models.dev, incluyendo modelos locales", + "home.what.anyEditor.title": "Cualquier editor", + "home.what.anyEditor.body": "Disponible como interfaz de terminal, aplicación de escritorio y extensión de IDE", + "home.what.readDocs": "Leer documentación", + + "home.growth.title": "El agente de codificación IA de código abierto", + "home.growth.body": + "Con más de {{stars}} estrellas en GitHub, {{contributors}} colaboradores y más de {{commits}} commits, OpenCode es usado y confiado por más de {{monthlyUsers}} desarrolladores cada mes.", + "home.growth.githubStars": "Estrellas en GitHub", + "home.growth.contributors": "Colaboradores", + "home.growth.monthlyDevs": "Desarrolladores Mensuales", + + "home.privacy.title": "Creado pensando en la privacidad", + "home.privacy.body": + "OpenCode no almacena tu código ni datos de contexto, para que pueda operar en entornos sensibles a la privacidad.", + "home.privacy.learnMore": "Más información sobre", + "home.privacy.link": "privacidad", + + "home.faq.q1": "¿Qué es OpenCode?", + "home.faq.a1": + "OpenCode es un agente de código abierto que te ayuda a escribir y ejecutar código con cualquier modelo de IA. Está disponible como interfaz de terminal, aplicación de escritorio o extensión de IDE.", + "home.faq.q2": "¿Cómo uso OpenCode?", + "home.faq.a2.before": "La forma más fácil de empezar es leer la", + "home.faq.a2.link": "introducción", + "home.faq.q3": "¿Necesito suscripciones extra de IA para usar OpenCode?", + "home.faq.a3.p1": + "No necesariamente, OpenCode viene con un conjunto de modelos gratuitos que puedes usar sin crear una cuenta.", + "home.faq.a3.p2.beforeZen": + "Aparte de estos, puedes usar cualquiera de los modelos de codificación populares creando una cuenta de", + "home.faq.a3.p2.afterZen": ".", + "home.faq.a3.p3": + "Aunque animamos a los usuarios a usar Zen, OpenCode también funciona con todos los proveedores populares como OpenAI, Anthropic, xAI, etc.", + "home.faq.a3.p4.beforeLocal": "Incluso puedes conectar tus", + "home.faq.a3.p4.localLink": "modelos locales", + "home.faq.q4": "¿Puedo usar mis suscripciones de IA existentes con OpenCode?", + "home.faq.a4.p1": + "Sí, OpenCode soporta planes de suscripción de los principales proveedores. Puedes usar tus suscripciones de Claude Pro/Max, ChatGPT Plus/Pro o GitHub Copilot.", + "home.faq.q5": "¿Solo puedo usar OpenCode en la terminal?", + "home.faq.a5.beforeDesktop": "¡Ya no! OpenCode ahora está disponible como una aplicación para tu", + "home.faq.a5.desktop": "escritorio", + "home.faq.a5.and": "y", + "home.faq.a5.web": "web", + "home.faq.q6": "¿Cuánto cuesta OpenCode?", + "home.faq.a6": + "OpenCode es 100% gratuito de usar. También viene con un conjunto de modelos gratuitos. Puede haber costos adicionales si conectas cualquier otro proveedor.", + "home.faq.q7": "¿Qué hay sobre datos y privacidad?", + "home.faq.a7.p1": + "Tus datos e información solo se almacenan cuando usas nuestros modelos gratuitos o creas enlaces compartibles.", + "home.faq.a7.p2.beforeModels": "Más información sobre", + "home.faq.a7.p2.modelsLink": "nuestros modelos", + "home.faq.a7.p2.and": "y", + "home.faq.a7.p2.shareLink": "páginas compartidas", + "home.faq.q8": "¿Es OpenCode de código abierto?", + "home.faq.a8.p1": "Sí, OpenCode es totalmente de código abierto. El código fuente es público en", + "home.faq.a8.p2": "bajo la", + "home.faq.a8.mitLicense": "Licencia MIT", + "home.faq.a8.p3": + ", lo que significa que cualquiera puede usar, modificar o contribuir a su desarrollo. Cualquiera de la comunidad puede abrir problemas, enviar solicitudes de extracción y extender la funcionalidad.", + + "home.zenCta.title": "Accede a modelos optimizados y confiables para agentes de codificación", + "home.zenCta.body": + "Zen te da acceso a un conjunto seleccionado de modelos de IA que OpenCode ha probado y evaluado específicamente para agentes de codificación. No necesitas preocuparte por el rendimiento y la calidad inconsistentes entre proveedores, usa modelos validados que funcionan.", + "home.zenCta.link": "Aprende sobre Zen", + + "zen.title": + "OpenCode Zen | Un conjunto seleccionado de modelos optimizados y confiables para agentes de codificación", + "zen.hero.title": "Modelos optimizados y confiables para agentes de codificación", + "zen.hero.body": + "Zen te da acceso a un conjunto seleccionado de modelos de IA que OpenCode ha probado y evaluado específicamente para agentes de codificación. No necesitas preocuparte por el rendimiento y la calidad inconsistentes, usa modelos validados que funcionan.", + + "zen.faq.q1": "¿Qué es OpenCode Zen?", + "zen.faq.a1": + "Zen es un conjunto seleccionado de modelos de IA probados y evaluados para agentes de codificación, creado por el equipo detrás de OpenCode.", + "zen.faq.q2": "¿Qué hace a Zen más preciso?", + "zen.faq.a2": + "Zen solo proporciona modelos que han sido específicamente probados y evaluados para agentes de codificación. No usarías un cuchillo de mantequilla para cortar carne, no uses modelos pobres para codificar.", + "zen.faq.q3": "¿Es Zen más barato?", + "zen.faq.a3": + "Zen no tiene fines de lucro. Zen te transfiere los costos de los proveedores de modelos. Cuanto mayor sea el uso de Zen, más podrá OpenCode negociar mejores tarifas y transferírtelas.", + "zen.faq.q4": "¿Cuánto cuesta Zen?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "cobra por solicitud", + "zen.faq.a4.p1.afterPricing": "sin recargos, así que pagas exactamente lo que cobra el proveedor del modelo.", + "zen.faq.a4.p2.beforeAccount": "Tu costo total depende del uso, y puedes establecer límites de gasto mensuales en tu", + "zen.faq.a4.p2.accountLink": "cuenta", + "zen.faq.a4.p3": + "Para cubrir costos, OpenCode añade solo una pequeña tarifa de procesamiento de pagos de $1.23 por cada recarga de saldo de $20.", + "zen.faq.q5": "¿Qué hay sobre datos y privacidad?", + "zen.faq.a5.beforeExceptions": + "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.faq.a5.exceptionsLink": "siguientes excepciones", + "zen.faq.q6": "¿Puedo establecer límites de gasto?", + "zen.faq.a6": "Sí, puedes establecer límites de gasto mensuales en tu cuenta.", + "zen.faq.q7": "¿Puedo cancelar?", + "zen.faq.a7": "Sí, puedes deshabilitar la facturación en cualquier momento y usar tu saldo restante.", + "zen.faq.q8": "¿Puedo usar Zen con otros agentes de codificación?", + "zen.faq.a8": + "Aunque Zen funciona genial con OpenCode, puedes usar Zen con cualquier agente. Sigue las instrucciones de configuración en tu agente de codificación preferido.", + + "zen.cta.start": "Empieza con Zen", + "zen.pricing.title": "Añade $20 de saldo prepago", + "zen.pricing.fee": "(+$1.23 tarifa de procesamiento de tarjeta)", + "zen.pricing.body": "Úsalo con cualquier agente. Establece límites de gasto mensual. Cancela en cualquier momento.", + "zen.problem.title": "¿Qué problema está resolviendo Zen?", + "zen.problem.body": + "Hay muchos modelos disponibles, pero solo unos pocos funcionan bien con agentes de codificación. La mayoría de los proveedores los configuran de manera diferente con resultados variables.", + "zen.problem.subtitle": "Estamos arreglando esto para todos, no solo para usuarios de OpenCode.", + "zen.problem.item1": "Probando modelos seleccionados y consultando a sus equipos", + "zen.problem.item2": "Trabajando con proveedores para asegurar que se entreguen correctamente", + "zen.problem.item3": "Evaluando todas las combinaciones modelo-proveedor que recomendamos", + "zen.how.title": "Cómo funciona Zen", + "zen.how.body": "Aunque sugerimos usar Zen con OpenCode, puedes usar Zen con cualquier agente.", + "zen.how.step1.title": "Regístrate y añade $20 de saldo", + "zen.how.step1.beforeLink": "sigue las", + "zen.how.step1.link": "instrucciones de configuración", + "zen.how.step2.title": "Usa Zen con precios transparentes", + "zen.how.step2.link": "paga por solicitud", + "zen.how.step2.afterLink": "con cero recargos", + "zen.how.step3.title": "Auto-recarga", + "zen.how.step3.body": "cuando tu saldo alcance $5 añadiremos automáticamente $20", + "zen.privacy.title": "Tu privacidad es importante para nosotros", + "zen.privacy.beforeExceptions": + "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", + + "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", + "black.hero.subtitle": "Incluyendo Claude, GPT, Gemini y más", + "black.title": "OpenCode Black | Precios", + "black.plan.icon20": "Plan Black 20", + "black.plan.icon100": "Plan Black 100", + "black.plan.icon200": "Plan Black 200", + "black.plan.multiplier100": "5x más uso que Black 20", + "black.plan.multiplier200": "20x más uso que Black 20", + "black.price.perMonth": "al mes", + "black.price.perPersonBilledMonthly": "por persona facturado mensualmente", + "black.terms.1": "Tu suscripción no comenzará inmediatamente", + "black.terms.2": "Serás añadido a la lista de espera y activado pronto", + "black.terms.3": "Tu tarjeta solo se cargará cuando tu suscripción se active", + "black.terms.4": "Aplican límites de uso, el uso fuertemente automatizado puede alcanzar los límites antes", + "black.terms.5": "Las suscripciones son para individuos, contacta a Enterprise para equipos", + "black.terms.6": "Los límites pueden ajustarse y los planes pueden discontinuarse en el futuro", + "black.terms.7": "Cancela tu suscripción en cualquier momento", + "black.action.continue": "Continuar", + "black.finePrint.beforeTerms": "Los precios mostrados no incluyen impuestos aplicables", + "black.finePrint.terms": "Términos de Servicio", + "black.workspace.title": "OpenCode Black | Seleccionar Espacio de Trabajo", + "black.workspace.selectPlan": "Selecciona un espacio de trabajo para este plan", + "black.workspace.name": "Espacio de trabajo {{n}}", + "black.subscribe.title": "Suscribirse a OpenCode Black", + "black.subscribe.paymentMethod": "Método de pago", + "black.subscribe.loadingPaymentForm": "Cargando formulario de pago...", + "black.subscribe.selectWorkspaceToContinue": "Selecciona un espacio de trabajo para continuar", + "black.subscribe.failurePrefix": "¡Oh no!", + "black.subscribe.error.generic": "Ocurrió un error", + "black.subscribe.error.invalidPlan": "Plan inválido", + "black.subscribe.error.workspaceRequired": "Se requiere ID del espacio de trabajo", + "black.subscribe.error.alreadySubscribed": "Este espacio de trabajo ya tiene una suscripción", + "black.subscribe.processing": "Procesando...", + "black.subscribe.submit": "Suscribirse ${{plan}}", + "black.subscribe.form.chargeNotice": "Solo se te cobrará cuando tu suscripción se active", + "black.subscribe.success.title": "Estás en la lista de espera de OpenCode Black", + "black.subscribe.success.subscriptionPlan": "Plan de suscripción", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "Cantidad", + "black.subscribe.success.amountValue": "${{plan}} al mes", + "black.subscribe.success.paymentMethod": "Método de pago", + "black.subscribe.success.dateJoined": "Fecha de unión", + "black.subscribe.success.chargeNotice": "Tu tarjeta se cargará cuando tu suscripción se active", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "Claves API", + "workspace.nav.members": "Miembros", + "workspace.nav.billing": "Facturación", + "workspace.nav.settings": "Configuración", + + "workspace.home.banner.beforeLink": "Modelos optimizados y confiables para agentes de codificación.", + "workspace.home.billing.loading": "Cargando...", + "workspace.home.billing.enable": "Habilitar facturación", + "workspace.home.billing.currentBalance": "Saldo actual", + + "workspace.newUser.feature.tested.title": "Modelos Probados y Verificados", + "workspace.newUser.feature.tested.body": + "Hemos evaluado y probado modelos específicamente para agentes de codificación para asegurar el mejor rendimiento.", + "workspace.newUser.feature.quality.title": "Máxima Calidad", + "workspace.newUser.feature.quality.body": + "Accede a modelos configurados para un rendimiento óptimo - sin degradaciones ni enrutamiento a proveedores más baratos.", + "workspace.newUser.feature.lockin.title": "Sin Bloqueo", + "workspace.newUser.feature.lockin.body": + "Usa Zen con cualquier agente de codificación, y continúa usando otros proveedores con opencode cuando quieras.", + "workspace.newUser.copyApiKey": "Copiar clave API", + "workspace.newUser.copyKey": "Copiar Clave", + "workspace.newUser.copied": "¡Copiada!", + "workspace.newUser.step.enableBilling": "Habilitar facturación", + "workspace.newUser.step.login.before": "Ejecuta", + "workspace.newUser.step.login.after": "y selecciona opencode", + "workspace.newUser.step.pasteKey": "Pega tu clave API", + "workspace.newUser.step.models.before": "Inicia opencode y ejecuta", + "workspace.newUser.step.models.after": "para seleccionar un modelo", + + "workspace.models.title": "Modelos", + "workspace.models.subtitle.beforeLink": "Gestiona qué modelos pueden acceder los miembros del espacio de trabajo.", + "workspace.models.table.model": "Modelo", + "workspace.models.table.enabled": "Habilitado", + + "workspace.providers.title": "Trae Tu Propia Clave", + "workspace.providers.subtitle": "Configura tus propias claves API de proveedores de IA.", + "workspace.providers.placeholder": "Introduce clave API de {{provider}} ({{prefix}}...)", + "workspace.providers.configure": "Configurar", + "workspace.providers.edit": "Editar", + "workspace.providers.delete": "Eliminar", + "workspace.providers.saving": "Guardando...", + "workspace.providers.save": "Guardar", + "workspace.providers.table.provider": "Proveedor", + "workspace.providers.table.apiKey": "Clave API", + + "workspace.usage.title": "Historial de Uso", + "workspace.usage.subtitle": "Uso reciente de API y costos.", + "workspace.usage.empty": "Haz tu primera llamada a la API para empezar.", + "workspace.usage.table.date": "Fecha", + "workspace.usage.table.model": "Modelo", + "workspace.usage.table.input": "Entrada", + "workspace.usage.table.output": "Salida", + "workspace.usage.table.cost": "Costo", + "workspace.usage.breakdown.input": "Entrada", + "workspace.usage.breakdown.cacheRead": "Lectura de Caché", + "workspace.usage.breakdown.cacheWrite": "Escritura de Caché", + "workspace.usage.breakdown.output": "Salida", + "workspace.usage.breakdown.reasoning": "Razonamiento", + "workspace.usage.subscription": "suscripción (${{amount}})", + + "workspace.cost.title": "Costo", + "workspace.cost.subtitle": "Costos de uso desglosados por modelo.", + "workspace.cost.allModels": "Todos los Modelos", + "workspace.cost.allKeys": "Todas las Claves", + "workspace.cost.deletedSuffix": "(eliminado)", + "workspace.cost.empty": "No hay datos de uso disponibles para el periodo seleccionado.", + "workspace.cost.subscriptionShort": "sub", + + "workspace.keys.title": "Claves API", + "workspace.keys.subtitle": "Gestiona tus claves API para acceder a los servicios de opencode.", + "workspace.keys.create": "Crear Clave API", + "workspace.keys.placeholder": "Introduce nombre de la clave", + "workspace.keys.empty": "Crea una clave API de opencode Gateway", + "workspace.keys.table.name": "Nombre", + "workspace.keys.table.key": "Clave", + "workspace.keys.table.createdBy": "Creado Por", + "workspace.keys.table.lastUsed": "Último Uso", + "workspace.keys.copyApiKey": "Copiar clave API", + "workspace.keys.delete": "Eliminar", + + "workspace.members.title": "Miembros", + "workspace.members.subtitle": "Gestiona miembros del espacio de trabajo y sus permisos.", + "workspace.members.invite": "Invitar Miembro", + "workspace.members.inviting": "Invitando...", + "workspace.members.beta.beforeLink": "Los espacios de trabajo son gratuitos para equipos durante la beta.", + "workspace.members.form.invitee": "Invitado", + "workspace.members.form.emailPlaceholder": "Introduce correo", + "workspace.members.form.role": "Rol", + "workspace.members.form.monthlyLimit": "Límite de gasto mensual", + "workspace.members.noLimit": "Sin límite", + "workspace.members.noLimitLowercase": "sin límite", + "workspace.members.invited": "invitado", + "workspace.members.edit": "Editar", + "workspace.members.delete": "Eliminar", + "workspace.members.saving": "Guardando...", + "workspace.members.save": "Guardar", + "workspace.members.table.email": "Correo", + "workspace.members.table.role": "Rol", + "workspace.members.table.monthLimit": "Límite mensual", + "workspace.members.role.admin": "Administrador", + "workspace.members.role.adminDescription": "Puede gestionar modelos, miembros y facturación", + "workspace.members.role.member": "Miembro", + "workspace.members.role.memberDescription": "Solo puede generar claves API para sí mismo", + + "workspace.settings.title": "Configuración", + "workspace.settings.subtitle": "Actualiza el nombre de tu espacio de trabajo y preferencias.", + "workspace.settings.workspaceName": "Nombre del espacio de trabajo", + "workspace.settings.defaultName": "Por defecto", + "workspace.settings.updating": "Actualizando...", + "workspace.settings.save": "Guardar", + "workspace.settings.edit": "Editar", + + "workspace.billing.title": "Facturación", + "workspace.billing.subtitle.beforeLink": "Gestionar métodos de pago.", + "workspace.billing.contactUs": "Contáctanos", + "workspace.billing.subtitle.afterLink": "si tienes alguna pregunta.", + "workspace.billing.currentBalance": "Saldo Actual", + "workspace.billing.add": "Añadir $", + "workspace.billing.enterAmount": "Introduce cantidad", + "workspace.billing.loading": "Cargando...", + "workspace.billing.addAction": "Añadir", + "workspace.billing.addBalance": "Añadir Saldo", + "workspace.billing.linkedToStripe": "Vinculado con Stripe", + "workspace.billing.manage": "Gestionar", + "workspace.billing.enable": "Habilitar Facturación", + + "workspace.monthlyLimit.title": "Límite Mensual", + "workspace.monthlyLimit.subtitle": "Establece un límite de uso mensual para tu cuenta.", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "Estableciendo...", + "workspace.monthlyLimit.set": "Establecer", + "workspace.monthlyLimit.edit": "Editar Límite", + "workspace.monthlyLimit.noLimit": "Sin límite de uso establecido.", + "workspace.monthlyLimit.currentUsage.beforeMonth": "Uso actual para", + "workspace.monthlyLimit.currentUsage.beforeAmount": "es $", + + "workspace.reload.title": "Auto Recarga", + "workspace.reload.disabled.before": "La auto recarga está", + "workspace.reload.disabled.state": "deshabilitada", + "workspace.reload.disabled.after": "Habilita para recargar automáticamente cuando el saldo sea bajo.", + "workspace.reload.enabled.before": "La auto recarga está", + "workspace.reload.enabled.state": "habilitada", + "workspace.reload.enabled.middle": "Recargaremos", + "workspace.reload.processingFee": "tarifa de procesamiento", + "workspace.reload.enabled.after": "cuando el saldo alcance", + "workspace.reload.edit": "Editar", + "workspace.reload.enable": "Habilitar", + "workspace.reload.enableAutoReload": "Habilitar Auto Recarga", + "workspace.reload.reloadAmount": "Recargar $", + "workspace.reload.whenBalanceReaches": "Cuando el saldo alcance $", + "workspace.reload.saving": "Guardando...", + "workspace.reload.save": "Guardar", + "workspace.reload.failedAt": "La recarga falló en", + "workspace.reload.reason": "Razón:", + "workspace.reload.updatePaymentMethod": "Por favor actualiza tu método de pago e intenta de nuevo.", + "workspace.reload.retrying": "Reintentando...", + "workspace.reload.retry": "Reintentar", + + "workspace.payments.title": "Historial de Pagos", + "workspace.payments.subtitle": "Transacciones de pago recientes.", + "workspace.payments.table.date": "Fecha", + "workspace.payments.table.paymentId": "ID de Pago", + "workspace.payments.table.amount": "Cantidad", + "workspace.payments.table.receipt": "Recibo", + "workspace.payments.type.credit": "crédito", + "workspace.payments.type.subscription": "suscripción", + "workspace.payments.view": "Ver", + + "workspace.black.loading": "Cargando...", + "workspace.black.time.day": "día", + "workspace.black.time.days": "días", + "workspace.black.time.hour": "hora", + "workspace.black.time.hours": "horas", + "workspace.black.time.minute": "minuto", + "workspace.black.time.minutes": "minutos", + "workspace.black.time.fewSeconds": "unos pocos segundos", + "workspace.black.subscription.title": "Suscripción", + "workspace.black.subscription.message": "Estás suscrito a OpenCode Black por ${{plan}} al mes.", + "workspace.black.subscription.manage": "Gestionar Suscripción", + "workspace.black.subscription.rollingUsage": "Uso de 5 horas", + "workspace.black.subscription.weeklyUsage": "Uso Semanal", + "workspace.black.subscription.resetsIn": "Se reinicia en", + "workspace.black.subscription.useBalance": "Usa tu saldo disponible después de alcanzar los límites de uso", + "workspace.black.waitlist.title": "Lista de Espera", + "workspace.black.waitlist.joined": "Estás en la lista de espera para el plan OpenCode Black de ${{plan}} al mes.", + "workspace.black.waitlist.ready": "Estamos listos para inscribirte en el plan OpenCode Black de ${{plan}} al mes.", + "workspace.black.waitlist.leave": "Abandonar Lista de Espera", + "workspace.black.waitlist.leaving": "Abandonando...", + "workspace.black.waitlist.left": "Abandonada", + "workspace.black.waitlist.enroll": "Inscribirse", + "workspace.black.waitlist.enrolling": "Inscribiéndose...", + "workspace.black.waitlist.enrolled": "Inscrito", + "workspace.black.waitlist.enrollNote": + "Cuando haces clic en Inscribirse, tu suscripción comienza inmediatamente y se cargará a tu tarjeta.", + + "download.title": "OpenCode | Descargar", + "download.meta.description": "Descarga OpenCode para macOS, Windows y Linux", + "download.hero.title": "Descargar OpenCode", + "download.hero.subtitle": "Disponible en Beta para macOS, Windows y Linux", + "download.hero.button": "Descargar para {{os}}", + "download.section.terminal": "OpenCode Terminal", + "download.section.desktop": "OpenCode Desktop (Beta)", + "download.section.extensions": "Extensiones OpenCode", + "download.section.integrations": "Integraciones OpenCode", + "download.action.download": "Descargar", + "download.action.install": "Instalar", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "No necesariamente, pero probablemente. Necesitarás una suscripción de IA si quieres conectar OpenCode a un proveedor de pago, aunque puedes trabajar con", + "download.faq.a3.localLink": "modelos locales", + "download.faq.a3.afterLocal.beforeZen": "gratis. Aunque animamos a los usuarios a usar", + "download.faq.a3.afterZen": + ", OpenCode funciona con todos los proveedores populares como OpenAI, Anthropic, xAI, etc.", + + "download.faq.a5.p1": "OpenCode es 100% gratuito de usar.", + "download.faq.a5.p2.beforeZen": + "Cualquier costo adicional vendrá de tu suscripción a un proveedor de modelos. Aunque OpenCode funciona con cualquier proveedor de modelos, recomendamos usar", + "download.faq.a5.p2.afterZen": ".", + + "download.faq.a6.p1": "Tus datos e información solo se almacenan cuando creas enlaces compartibles en OpenCode.", + "download.faq.a6.p2.beforeShare": "Más información sobre", + "download.faq.a6.shareLink": "páginas compartidas", + + "enterprise.title": "OpenCode | Soluciones empresariales para tu organización", + "enterprise.meta.description": "Contacta a OpenCode para soluciones empresariales", + "enterprise.hero.title": "Tu código es tuyo", + "enterprise.hero.body1": + "OpenCode opera de forma segura dentro de tu organización sin almacenar datos ni contexto, y sin restricciones de licencia ni reclamaciones de propiedad. Inicia una prueba con tu equipo, luego despliégalo en toda tu organización integrándolo con tu SSO y pasarela de IA interna.", + "enterprise.hero.body2": "Déjanos saber cómo podemos ayudar.", + "enterprise.form.name.label": "Nombre completo", + "enterprise.form.name.placeholder": "Jeff Bezos", + "enterprise.form.role.label": "Rol", + "enterprise.form.role.placeholder": "Presidente Ejecutivo", + "enterprise.form.email.label": "Correo de empresa", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "¿Qué problema estás intentando resolver?", + "enterprise.form.message.placeholder": "Necesitamos ayuda con...", + "enterprise.form.send": "Enviar", + "enterprise.form.sending": "Enviando...", + "enterprise.form.success": "Mensaje enviado, estaremos en contacto pronto.", + "enterprise.faq.title": "FAQ", + "enterprise.faq.q1": "¿Qué es OpenCode Enterprise?", + "enterprise.faq.a1": + "OpenCode Enterprise es para organizaciones que quieren asegurar que su código y datos nunca salgan de su infraestructura. Puede hacer esto usando una configuración centralizada que se integra con tu SSO y pasarela de IA interna.", + "enterprise.faq.q2": "¿Cómo empiezo con OpenCode Enterprise?", + "enterprise.faq.a2": + "Simplemente empieza con una prueba interna con tu equipo. OpenCode por defecto no almacena tu código ni datos de contexto, haciendo fácil empezar. Luego contáctanos para discutir precios y opciones de implementación.", + "enterprise.faq.q3": "¿Cómo funciona el precio para empresas?", + "enterprise.faq.a3": + "Ofrecemos precios empresariales por asiento. Si tienes tu propia pasarela de LLM, no cobramos por los tokens usados. Para más detalles, contáctanos para una cotización personalizada basada en las necesidades de tu organización.", + "enterprise.faq.q4": "¿Están mis datos seguros con OpenCode Enterprise?", + "enterprise.faq.a4": + "Sí. OpenCode no almacena tu código ni datos de contexto. Todo el procesamiento ocurre localmente o a través de llamadas directas a la API de tu proveedor de IA. Con configuración central y integración SSO, tus datos permanecen seguros dentro de la infraestructura de tu organización.", + + "brand.title": "OpenCode | Marca", + "brand.meta.description": "Guías de marca de OpenCode", + "brand.heading": "Guías de marca", + "brand.subtitle": "Recursos y activos para ayudarte a trabajar con la marca OpenCode.", + "brand.downloadAll": "Descargar todos los activos", + + "changelog.title": "OpenCode | Registro de cambios", + "changelog.meta.description": "Notas de versión y registro de cambios de OpenCode", + "changelog.hero.title": "Registro de cambios", + "changelog.hero.subtitle": "Nuevas actualizaciones y mejoras para OpenCode", + "changelog.empty": "No se encontraron entradas en el registro de cambios.", + "changelog.viewJson": "Ver JSON", + + "bench.list.title": "Benchmark", + "bench.list.heading": "Benchmarks", + "bench.list.table.agent": "Agente", + "bench.list.table.model": "Modelo", + "bench.list.table.score": "Puntuación", + + "bench.detail.title": "Benchmark - {{task}}", + "bench.detail.notFound": "Tarea no encontrada", + "bench.detail.na": "N/A", + "bench.detail.labels.agent": "Agente", + "bench.detail.labels.model": "Modelo", + "bench.detail.labels.task": "Tarea", + "bench.detail.labels.repo": "Repo", + "bench.detail.labels.from": "De", + "bench.detail.labels.to": "A", + "bench.detail.labels.prompt": "Prompt", + "bench.detail.labels.commit": "Commit", + "bench.detail.labels.averageDuration": "Duración Promedio", + "bench.detail.labels.averageScore": "Puntuación Promedio", + "bench.detail.labels.averageCost": "Costo Promedio", + "bench.detail.labels.summary": "Resumen", + "bench.detail.labels.runs": "Ejecuciones", + "bench.detail.labels.score": "Puntuación", + "bench.detail.labels.base": "Base", + "bench.detail.labels.penalty": "Penalización", + "bench.detail.labels.weight": "peso", + "bench.detail.table.run": "Ejecución", + "bench.detail.table.score": "Puntuación (Base - Penalización)", + "bench.detail.table.cost": "Costo", + "bench.detail.table.duration": "Duración", + "bench.detail.run.title": "Ejecución {{n}}", + "bench.detail.rawJson": "JSON Crudo", +} as const satisfies Dict diff --git a/packages/console/app/src/i18n/fr.ts b/packages/console/app/src/i18n/fr.ts new file mode 100644 index 00000000000..8974927a967 --- /dev/null +++ b/packages/console/app/src/i18n/fr.ts @@ -0,0 +1,607 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "Documentation", + "nav.changelog": "Changelog", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "Entreprise", + "nav.zen": "Zen", + "nav.login": "Se connecter", + "nav.free": "Gratuit", + "nav.home": "Accueil", + "nav.openMenu": "Ouvrir le menu", + "nav.getStartedFree": "Commencer gratuitement", + + "nav.context.copyLogo": "Copier le logo en SVG", + "nav.context.copyWordmark": "Copier le logotype en SVG", + "nav.context.brandAssets": "Ressources de marque", + + "footer.github": "GitHub", + "footer.docs": "Documentation", + "footer.changelog": "Changelog", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "Marque", + "legal.privacy": "Confidentialité", + "legal.terms": "Conditions", + + "email.title": "Soyez le premier à être informé de nos nouveaux produits", + "email.subtitle": "Inscrivez-vous à la liste d'attente pour un accès anticipé.", + "email.placeholder": "Adresse e-mail", + "email.subscribe": "S'abonner", + "email.success": "Presque terminé - vérifiez votre boîte de réception et confirmez votre adresse e-mail", + + "notFound.title": "Introuvable | OpenCode", + "notFound.heading": "404 - Page introuvable", + "notFound.home": "Accueil", + "notFound.docs": "Documentation", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "Se déconnecter", + + "workspace.select": "Sélectionner un espace de travail", + "workspace.createNew": "+ Créer un nouvel espace", + "workspace.modal.title": "Créer un nouvel espace", + "workspace.modal.placeholder": "Saisir le nom de l'espace", + + "common.cancel": "Annuler", + "common.creating": "Création...", + "common.create": "Créer", + + "common.videoUnsupported": "Votre navigateur ne prend pas en charge la balise vidéo.", + "common.figure": "Fig {{n}}.", + "common.faq": "FAQ", + "common.learnMore": "En savoir plus", + + "error.invalidPlan": "Forfait invalide", + "error.workspaceRequired": "L'ID de l'espace de travail est requis", + "error.alreadySubscribed": "Cet espace de travail a déjà un abonnement", + "error.limitRequired": "La limite est requise.", + "error.monthlyLimitInvalid": "Définissez une limite mensuelle valide.", + "error.workspaceNameRequired": "Le nom de l'espace de travail est requis.", + "error.nameTooLong": "Le nom doit comporter 255 caractères ou moins.", + "error.emailRequired": "L'e-mail est requis", + "error.roleRequired": "Le rôle est requis", + "error.idRequired": "L'ID est requis", + "error.nameRequired": "Le nom est requis", + "error.providerRequired": "Le fournisseur est requis", + "error.apiKeyRequired": "La clé API est requise", + "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}} $", + + "home.title": "OpenCode | L'agent de code IA open source", + + "temp.title": "OpenCode | Agent de code IA conçu pour le terminal", + "temp.hero.title": "L'agent de code IA conçu pour le terminal", + "temp.zen": "OpenCode Zen", + "temp.getStarted": "Commencer", + "temp.feature.native.title": "TUI Native", + "temp.feature.native.body": "Une interface terminal native, réactive et thémable", + "temp.feature.zen.beforeLink": "Une", + "temp.feature.zen.link": "liste organisée de modèles", + "temp.feature.zen.afterLink": "fournie par OpenCode", + "temp.feature.models.beforeLink": "Prend en charge plus de 75 fournisseurs LLM via", + "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", + + "home.banner.badge": "Nouveau", + "home.banner.text": "Application desktop disponible en bêta", + "home.banner.platforms": "sur macOS, Windows et Linux", + "home.banner.downloadNow": "Télécharger maintenant", + "home.banner.downloadBetaNow": "Télécharger la bêta desktop maintenant", + + "home.hero.title": "L'agent de code IA open source", + "home.hero.subtitle.a": + "Modèles gratuits inclus ou connectez n'importe quel modèle depuis n'importe quel fournisseur,", + "home.hero.subtitle.b": "dont Claude, GPT, Gemini et plus.", + + "home.install.ariaLabel": "Options d'installation", + + "home.what.title": "Qu'est-ce que OpenCode ?", + "home.what.body": + "OpenCode est un agent open source qui vous aide à écrire du code dans votre terminal, IDE ou desktop.", + "home.what.lsp.title": "LSP activé", + "home.what.lsp.body": "Charge automatiquement les bons LSP pour le LLM", + "home.what.multiSession.title": "Multi-session", + "home.what.multiSession.body": "Lancez plusieurs agents en parallèle sur le même projet", + "home.what.shareLinks.title": "Liens de partage", + "home.what.shareLinks.body": "Partagez un lien vers n'importe quelle session pour référence ou debug", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "Connectez-vous avec GitHub pour utiliser votre compte Copilot", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "Connectez-vous avec OpenAI pour utiliser votre compte ChatGPT Plus ou Pro", + "home.what.anyModel.title": "N'importe quel modèle", + "home.what.anyModel.body": "75+ fournisseurs de LLM via Models.dev, y compris des modèles locaux", + "home.what.anyEditor.title": "N'importe quel éditeur", + "home.what.anyEditor.body": "Disponible en interface terminal, application desktop et extension IDE", + "home.what.readDocs": "Lire la doc", + + "home.growth.title": "L'agent de code IA open source", + "home.growth.body": + "Avec plus de {{stars}} étoiles sur GitHub, {{contributors}} contributeurs et plus de {{commits}} commits, OpenCode est utilisé et approuvé par plus de {{monthlyUsers}} développeurs chaque mois.", + "home.growth.githubStars": "Étoiles GitHub", + "home.growth.contributors": "Contributeurs", + "home.growth.monthlyDevs": "Devs mensuels", + + "home.privacy.title": "Conçu pour la confidentialité", + "home.privacy.body": + "OpenCode ne stocke ni votre code ni vos données de contexte, afin de pouvoir fonctionner dans des environnements sensibles à la confidentialité.", + "home.privacy.learnMore": "En savoir plus sur", + "home.privacy.link": "la confidentialité", + + "home.faq.q1": "Qu'est-ce que OpenCode ?", + "home.faq.a1": + "OpenCode est un agent open source qui vous aide à écrire et exécuter du code avec n'importe quel modèle d'IA. Il est disponible en interface terminal, application desktop ou extension IDE.", + "home.faq.q2": "Comment utiliser OpenCode ?", + "home.faq.a2.before": "Le moyen le plus simple de commencer est de lire l'", + "home.faq.a2.link": "intro", + "home.faq.q3": "Ai-je besoin d'abonnements IA supplémentaires pour utiliser OpenCode ?", + "home.faq.a3.p1": + "Pas forcément : OpenCode propose des modèles gratuits que vous pouvez utiliser sans créer de compte.", + "home.faq.a3.p2.beforeZen": "En plus, vous pouvez utiliser des modèles populaires pour le code en créant un compte", + "home.faq.a3.p2.afterZen": ".", + "home.faq.a3.p3": + "Nous encourageons l'utilisation de Zen, mais OpenCode fonctionne aussi avec les fournisseurs populaires comme OpenAI, Anthropic, xAI, etc.", + "home.faq.a3.p4.beforeLocal": "Vous pouvez même connecter vos", + "home.faq.a3.p4.localLink": "modèles locaux", + "home.faq.q4": "Puis-je utiliser mes abonnements IA existants avec OpenCode ?", + "home.faq.a4.p1": + "Oui, OpenCode prend en charge les abonnements des principaux fournisseurs. Vous pouvez utiliser Claude Pro/Max, ChatGPT Plus/Pro ou GitHub Copilot.", + "home.faq.q5": "Puis-je utiliser OpenCode uniquement dans le terminal ?", + "home.faq.a5.beforeDesktop": "Plus maintenant ! OpenCode est désormais disponible en application pour", + "home.faq.a5.desktop": "desktop", + "home.faq.a5.and": "et", + "home.faq.a5.web": "web", + "home.faq.q6": "Combien coûte OpenCode ?", + "home.faq.a6": + "OpenCode est 100% gratuit. Il inclut aussi des modèles gratuits. Des coûts supplémentaires peuvent s'appliquer si vous connectez un autre fournisseur.", + "home.faq.q7": "Qu'en est-il des données et de la confidentialité ?", + "home.faq.a7.p1": + "Vos données ne sont stockées que lorsque vous utilisez nos modèles gratuits ou créez des liens partageables.", + "home.faq.a7.p2.beforeModels": "En savoir plus sur", + "home.faq.a7.p2.modelsLink": "nos modèles", + "home.faq.a7.p2.and": "et", + "home.faq.a7.p2.shareLink": "les pages de partage", + "home.faq.q8": "OpenCode est-il open source ?", + "home.faq.a8.p1": "Oui, OpenCode est entièrement open source. Le code source est public sur", + "home.faq.a8.p2": "sous la", + "home.faq.a8.mitLicense": "Licence MIT", + "home.faq.a8.p3": + ", ce qui signifie que tout le monde peut l'utiliser, le modifier ou contribuer à son développement. Toute personne de la communauté peut ouvrir des tickets, soumettre des pull requests et étendre les fonctionnalités.", + + "home.zenCta.title": "Accédez à des modèles fiables et optimisés pour les agents de code", + "home.zenCta.body": + "Zen vous donne accès à un ensemble sélectionné de modèles d'IA que OpenCode a testés et benchmarkés spécifiquement pour les agents de code. Plus besoin de vous soucier des variations de performance et de qualité selon les fournisseurs : utilisez des modèles validés qui fonctionnent.", + "home.zenCta.link": "En savoir plus sur Zen", + + "zen.title": "OpenCode Zen | Un ensemble sélectionné de modèles fiables et optimisés pour les agents de code", + "zen.hero.title": "Modèles fiables et optimisés pour les agents de code", + "zen.hero.body": + "Zen vous donne accès à un ensemble sélectionné de modèles d'IA que OpenCode a testés et benchmarkés spécifiquement pour les agents de code. Plus besoin de vous soucier des variations de performance et de qualité selon les fournisseurs : utilisez des modèles validés qui fonctionnent.", + + "zen.faq.q1": "Qu'est-ce que OpenCode Zen ?", + "zen.faq.a1": + "Zen est un ensemble sélectionné de modèles d'IA testés et benchmarkés pour les agents de code, créé par l'équipe derrière OpenCode.", + "zen.faq.q2": "Qu'est-ce qui rend Zen plus précis ?", + "zen.faq.a2": + "Zen ne propose que des modèles testés et benchmarkés spécifiquement pour les agents de code. Vous n'utiliseriez pas un couteau à beurre pour couper un steak ; n'utilisez pas de mauvais modèles pour coder.", + "zen.faq.q3": "Zen est-il moins cher ?", + "zen.faq.a3": + "Zen n'est pas à but lucratif. Zen vous facture au prix coûtant des fournisseurs de modèles. Plus Zen est utilisé, plus OpenCode peut négocier de meilleurs tarifs et vous les répercuter.", + "zen.faq.q4": "Combien coûte Zen ?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "facture par requête", + "zen.faq.a4.p1.afterPricing": "sans marge, vous payez donc exactement ce que facture le fournisseur du modèle.", + "zen.faq.a4.p2.beforeAccount": + "Votre coût total dépend de l'usage, et vous pouvez définir des limites de dépense mensuelles dans votre", + "zen.faq.a4.p2.accountLink": "compte", + "zen.faq.a4.p3": + "Pour couvrir les coûts, OpenCode ajoute uniquement de petits frais de traitement de paiement de 1,23 $ par recharge de 20 $.", + "zen.faq.q5": "Et pour les données et la confidentialité ?", + "zen.faq.a5.beforeExceptions": + "Tous les modèles Zen sont hébergés aux États-Unis. Les fournisseurs appliquent une politique de rétention zéro et n'utilisent pas vos données pour l'entraînement des modèles, avec les", + "zen.faq.a5.exceptionsLink": "exceptions suivantes", + "zen.faq.q6": "Puis-je définir des limites de dépense ?", + "zen.faq.a6": "Oui, vous pouvez définir des limites de dépense mensuelles dans votre compte.", + "zen.faq.q7": "Puis-je annuler ?", + "zen.faq.a7": "Oui, vous pouvez désactiver la facturation à tout moment et utiliser votre solde restant.", + "zen.faq.q8": "Puis-je utiliser Zen avec d'autres agents de code ?", + "zen.faq.a8": + "Zen fonctionne très bien avec OpenCode, mais vous pouvez utiliser Zen avec n'importe quel agent. Suivez les instructions de configuration dans votre agent préféré.", + + "zen.cta.start": "Commencez avec Zen", + "zen.pricing.title": "Ajoutez 20 $ de solde Pay as you go", + "zen.pricing.fee": "(+1,23 $ de frais de traitement de carte)", + "zen.pricing.body": + "Utilisez avec n'importe quel agent. Fixez des limites de dépenses mensuelles. Annulez à tout moment.", + "zen.problem.title": "Quel problème Zen résout-il ?", + "zen.problem.body": + "Il existe de nombreux modèles disponibles, mais seuls quelques-uns fonctionnent bien avec les agents de code. La plupart des fournisseurs les configurent différemment avec des résultats variables.", + "zen.problem.subtitle": + "Nous résolvons ce problème pour tout le monde, pas seulement pour les utilisateurs de OpenCode.", + "zen.problem.item1": "Test des modèles sélectionnés et consultation de leurs équipes", + "zen.problem.item2": "Collaboration avec les fournisseurs pour garantir une livraison correcte", + "zen.problem.item3": "Benchmark de toutes les combinaisons modèle-fournisseur que nous recommandons", + "zen.how.title": "Comment fonctionne Zen", + "zen.how.body": + "Bien que nous vous suggérions d'utiliser Zen avec OpenCode, vous pouvez utiliser Zen avec n'importe quel agent.", + "zen.how.step1.title": "Inscrivez-vous et ajoutez un solde de 20 $", + "zen.how.step1.beforeLink": "suivez les", + "zen.how.step1.link": "instructions de configuration", + "zen.how.step2.title": "Utilisez Zen avec une tarification transparente", + "zen.how.step2.link": "payez par requête", + "zen.how.step2.afterLink": "sans marge", + "zen.how.step3.title": "Recharge automatique", + "zen.how.step3.body": "lorsque votre solde atteint 5 $, nous ajouterons automatiquement 20 $", + "zen.privacy.title": "Votre vie privée est importante pour nous", + "zen.privacy.beforeExceptions": + "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", + + "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", + "black.hero.subtitle": "Y compris Claude, GPT, Gemini et plus", + "black.title": "OpenCode Black | Tarification", + "black.plan.icon20": "Forfait Black 20", + "black.plan.icon100": "Forfait Black 100", + "black.plan.icon200": "Forfait Black 200", + "black.plan.multiplier100": "5x plus d'utilisation que Black 20", + "black.plan.multiplier200": "20x plus d'utilisation que Black 20", + "black.price.perMonth": "par mois", + "black.price.perPersonBilledMonthly": "par personne facturé mensuellement", + "black.terms.1": "Votre abonnement ne commencera pas immédiatement", + "black.terms.2": "Vous serez ajouté à la liste d'attente et activé bientôt", + "black.terms.3": "Votre carte ne sera débitée que lorsque votre abonnement sera activé", + "black.terms.4": + "Des limites d'utilisation s'appliquent, une utilisation fortement automatisée peut atteindre les limites plus tôt", + "black.terms.5": "Les abonnements sont pour les individus, contactez Enterprise pour les équipes", + "black.terms.6": "Les limites peuvent être ajustées et les forfaits peuvent être interrompus à l'avenir", + "black.terms.7": "Annulez votre abonnement à tout moment", + "black.action.continue": "Continuer", + "black.finePrint.beforeTerms": "Les prix affichés n'incluent pas les taxes applicables", + "black.finePrint.terms": "Conditions d'utilisation", + "black.workspace.title": "OpenCode Black | Sélectionner un espace de travail", + "black.workspace.selectPlan": "Sélectionnez un espace de travail pour ce forfait", + "black.workspace.name": "Espace de travail {{n}}", + "black.subscribe.title": "S'abonner à OpenCode Black", + "black.subscribe.paymentMethod": "Méthode de paiement", + "black.subscribe.loadingPaymentForm": "Chargement du formulaire de paiement...", + "black.subscribe.selectWorkspaceToContinue": "Sélectionnez un espace de travail pour continuer", + "black.subscribe.failurePrefix": "Oh oh !", + "black.subscribe.error.generic": "Une erreur est survenue", + "black.subscribe.error.invalidPlan": "Forfait invalide", + "black.subscribe.error.workspaceRequired": "L'ID de l'espace de travail est requis", + "black.subscribe.error.alreadySubscribed": "Cet espace de travail a déjà un abonnement", + "black.subscribe.processing": "Traitement...", + "black.subscribe.submit": "S'abonner ${{plan}}", + "black.subscribe.form.chargeNotice": "Vous ne serez débité que lorsque votre abonnement sera activé", + "black.subscribe.success.title": "Vous êtes sur la liste d'attente OpenCode Black", + "black.subscribe.success.subscriptionPlan": "Forfait d'abonnement", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "Montant", + "black.subscribe.success.amountValue": "{{plan}} $ par mois", + "black.subscribe.success.paymentMethod": "Méthode de paiement", + "black.subscribe.success.dateJoined": "Date d'inscription", + "black.subscribe.success.chargeNotice": "Votre carte sera débitée lorsque votre abonnement sera activé", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "Clés API", + "workspace.nav.members": "Membres", + "workspace.nav.billing": "Facturation", + "workspace.nav.settings": "Paramètres", + + "workspace.home.banner.beforeLink": "Modèles optimisés fiables pour les agents de code.", + "workspace.home.billing.loading": "Chargement...", + "workspace.home.billing.enable": "Activer la facturation", + "workspace.home.billing.currentBalance": "Solde actuel", + + "workspace.newUser.feature.tested.title": "Modèles testés et vérifiés", + "workspace.newUser.feature.tested.body": + "Nous avons benchmarké et testé des modèles spécifiquement pour les agents de code afin de garantir les meilleures performances.", + "workspace.newUser.feature.quality.title": "La plus haute qualité", + "workspace.newUser.feature.quality.body": + "Accédez à des modèles configurés pour des performances optimales - pas de rétrogradation ni de routage vers des fournisseurs moins chers.", + "workspace.newUser.feature.lockin.title": "Pas de verrouillage", + "workspace.newUser.feature.lockin.body": + "Utilisez Zen avec n'importe quel agent de code et continuez à utiliser d'autres fournisseurs avec OpenCode quand vous le souhaitez.", + "workspace.newUser.copyApiKey": "Copier la clé API", + "workspace.newUser.copyKey": "Copier la clé", + "workspace.newUser.copied": "Copié !", + "workspace.newUser.step.enableBilling": "Activer la facturation", + "workspace.newUser.step.login.before": "Exécuter", + "workspace.newUser.step.login.after": "et sélectionnez OpenCode", + "workspace.newUser.step.pasteKey": "Collez votre clé API", + "workspace.newUser.step.models.before": "Démarrez OpenCode et exécutez", + "workspace.newUser.step.models.after": "pour sélectionner un modèle", + + "workspace.models.title": "Modèles", + "workspace.models.subtitle.beforeLink": + "Gérez les modèles auxquels les membres de l'espace de travail peuvent accéder.", + "workspace.models.table.model": "Modèle", + "workspace.models.table.enabled": "Activé", + + "workspace.providers.title": "Apportez votre propre clé", + "workspace.providers.subtitle": "Configurez vos propres clés API auprès des fournisseurs d'IA.", + "workspace.providers.placeholder": "Entrez la clé API {{provider}} ({{prefix}}...)", + "workspace.providers.configure": "Configurer", + "workspace.providers.edit": "Modifier", + "workspace.providers.delete": "Supprimer", + "workspace.providers.saving": "Enregistrement...", + "workspace.providers.save": "Enregistrer", + "workspace.providers.table.provider": "Fournisseur", + "workspace.providers.table.apiKey": "Clé API", + + "workspace.usage.title": "Historique d'utilisation", + "workspace.usage.subtitle": "Utilisation récente de l'API et coûts.", + "workspace.usage.empty": "Faites votre premier appel API pour commencer.", + "workspace.usage.table.date": "Date", + "workspace.usage.table.model": "Modèle", + "workspace.usage.table.input": "Entrée", + "workspace.usage.table.output": "Sortie", + "workspace.usage.table.cost": "Coût", + "workspace.usage.breakdown.input": "Entrée", + "workspace.usage.breakdown.cacheRead": "Lecture cache", + "workspace.usage.breakdown.cacheWrite": "Écriture cache", + "workspace.usage.breakdown.output": "Sortie", + "workspace.usage.breakdown.reasoning": "Raisonnement", + "workspace.usage.subscription": "abonnement ({{amount}} $)", + + "workspace.cost.title": "Coût", + "workspace.cost.subtitle": "Coûts d'utilisation répartis par modèle.", + "workspace.cost.allModels": "Tous les modèles", + "workspace.cost.allKeys": "Toutes les clés", + "workspace.cost.deletedSuffix": "(supprimé)", + "workspace.cost.empty": "Aucune donnée d'utilisation disponible pour la période sélectionnée.", + "workspace.cost.subscriptionShort": "abo", + + "workspace.keys.title": "Clés API", + "workspace.keys.subtitle": "Gérez vos clés API pour accéder aux services OpenCode.", + "workspace.keys.create": "Créer une clé API", + "workspace.keys.placeholder": "Entrez le nom de la clé", + "workspace.keys.empty": "Créer une clé API OpenCode Gateway", + "workspace.keys.table.name": "Nom", + "workspace.keys.table.key": "Clé", + "workspace.keys.table.createdBy": "Créé par", + "workspace.keys.table.lastUsed": "Dernière utilisation", + "workspace.keys.copyApiKey": "Copier la clé API", + "workspace.keys.delete": "Supprimer", + + "workspace.members.title": "Membres", + "workspace.members.subtitle": "Gérez les membres de l'espace de travail et leurs autorisations.", + "workspace.members.invite": "Inviter un membre", + "workspace.members.inviting": "Invitation en cours...", + "workspace.members.beta.beforeLink": "Les espaces de travail sont gratuits pour les équipes pendant la version bêta.", + "workspace.members.form.invitee": "Invité", + "workspace.members.form.emailPlaceholder": "Entrez l'e-mail", + "workspace.members.form.role": "Rôle", + "workspace.members.form.monthlyLimit": "Limite de dépense mensuelle", + "workspace.members.noLimit": "Aucune limite", + "workspace.members.noLimitLowercase": "pas de limite", + "workspace.members.invited": "invité", + "workspace.members.edit": "Modifier", + "workspace.members.delete": "Supprimer", + "workspace.members.saving": "Enregistrement...", + "workspace.members.save": "Enregistrer", + "workspace.members.table.email": "E-mail", + "workspace.members.table.role": "Rôle", + "workspace.members.table.monthLimit": "Limite mensuelle", + "workspace.members.role.admin": "Administrateur", + "workspace.members.role.adminDescription": "Peut gérer les modèles, les membres et la facturation", + "workspace.members.role.member": "Membre", + "workspace.members.role.memberDescription": "Ne peut générer que des clés API pour lui-même", + + "workspace.settings.title": "Paramètres", + "workspace.settings.subtitle": "Mettez à jour le nom et les préférences de votre espace de travail.", + "workspace.settings.workspaceName": "Nom de l'espace de travail", + "workspace.settings.defaultName": "Défaut", + "workspace.settings.updating": "Mise à jour...", + "workspace.settings.save": "Enregistrer", + "workspace.settings.edit": "Modifier", + + "workspace.billing.title": "Facturation", + "workspace.billing.subtitle.beforeLink": "Gérer les méthodes de paiement.", + "workspace.billing.contactUs": "Contactez-nous", + "workspace.billing.subtitle.afterLink": "si vous avez des questions.", + "workspace.billing.currentBalance": "Solde actuel", + "workspace.billing.add": "Ajouter $", + "workspace.billing.enterAmount": "Saisir le montant", + "workspace.billing.loading": "Chargement...", + "workspace.billing.addAction": "Ajouter", + "workspace.billing.addBalance": "Ajouter un solde", + "workspace.billing.linkedToStripe": "Lié à Stripe", + "workspace.billing.manage": "Gérer", + "workspace.billing.enable": "Activer la facturation", + + "workspace.monthlyLimit.title": "Limite mensuelle", + "workspace.monthlyLimit.subtitle": "Définissez une limite d'utilisation mensuelle pour votre compte.", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "Définition...", + "workspace.monthlyLimit.set": "Défini", + "workspace.monthlyLimit.edit": "Modifier la limite", + "workspace.monthlyLimit.noLimit": "Aucune limite d'utilisation définie.", + "workspace.monthlyLimit.currentUsage.beforeMonth": "L'utilisation actuelle pour", + "workspace.monthlyLimit.currentUsage.beforeAmount": "est de", + + "workspace.reload.title": "Rechargement automatique", + "workspace.reload.disabled.before": "Le rechargement automatique est", + "workspace.reload.disabled.state": "désactivé", + "workspace.reload.disabled.after": "Activer le rechargement automatique lorsque le solde est faible.", + "workspace.reload.enabled.before": "Le rechargement automatique est", + "workspace.reload.enabled.state": "activé", + "workspace.reload.enabled.middle": "Nous rechargerons", + "workspace.reload.processingFee": "frais de traitement", + "workspace.reload.enabled.after": "quand le solde atteint", + "workspace.reload.edit": "Modifier", + "workspace.reload.enable": "Activer", + "workspace.reload.enableAutoReload": "Activer le rechargement automatique", + "workspace.reload.reloadAmount": "Recharger $", + "workspace.reload.whenBalanceReaches": "Lorsque le solde atteint $", + "workspace.reload.saving": "Enregistrement...", + "workspace.reload.save": "Enregistrer", + "workspace.reload.failedAt": "Le rechargement a échoué à", + "workspace.reload.reason": "Raison :", + "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.payments.title": "Historique des paiements", + "workspace.payments.subtitle": "Transactions de paiement récentes.", + "workspace.payments.table.date": "Date", + "workspace.payments.table.paymentId": "ID de paiement", + "workspace.payments.table.amount": "Montant", + "workspace.payments.table.receipt": "Reçu", + "workspace.payments.type.credit": "crédit", + "workspace.payments.type.subscription": "abonnement", + "workspace.payments.view": "Voir", + + "workspace.black.loading": "Chargement...", + "workspace.black.time.day": "jour", + "workspace.black.time.days": "jours", + "workspace.black.time.hour": "heure", + "workspace.black.time.hours": "heures", + "workspace.black.time.minute": "minute", + "workspace.black.time.minutes": "minutes", + "workspace.black.time.fewSeconds": "quelques secondes", + "workspace.black.subscription.title": "Abonnement", + "workspace.black.subscription.message": "Vous êtes abonné à OpenCode Black pour {{plan}} $ par mois.", + "workspace.black.subscription.manage": "Gérer l'abonnement", + "workspace.black.subscription.rollingUsage": "Utilisation 5 heures", + "workspace.black.subscription.weeklyUsage": "Utilisation hebdomadaire", + "workspace.black.subscription.resetsIn": "Réinitialisation dans", + "workspace.black.subscription.useBalance": + "Utilisez votre solde disponible après avoir atteint les limites d'utilisation", + "workspace.black.waitlist.title": "Liste d'attente", + "workspace.black.waitlist.joined": + "Vous êtes sur la liste d'attente pour le forfait OpenCode Black à {{plan}} $ par mois.", + "workspace.black.waitlist.ready": + "Nous sommes prêts à vous inscrire au forfait OpenCode Black à {{plan}} $ par mois.", + "workspace.black.waitlist.leave": "Quitter la liste d'attente", + "workspace.black.waitlist.leaving": "Sortie...", + "workspace.black.waitlist.left": "Quitté", + "workspace.black.waitlist.enroll": "S'inscrire", + "workspace.black.waitlist.enrolling": "Inscription...", + "workspace.black.waitlist.enrolled": "Inscrit", + "workspace.black.waitlist.enrollNote": + "Lorsque vous cliquez sur S'inscrire, votre abonnement démarre immédiatement et votre carte sera débitée.", + + "download.title": "OpenCode | Téléchargement", + "download.meta.description": "Téléchargez OpenCode pour macOS, Windows et Linux", + "download.hero.title": "Télécharger OpenCode", + "download.hero.subtitle": "Disponible en bêta pour macOS, Windows et Linux", + "download.hero.button": "Télécharger pour {{os}}", + "download.section.terminal": "OpenCode Terminal", + "download.section.desktop": "OpenCode Desktop (Bêta)", + "download.section.extensions": "Extensions OpenCode", + "download.section.integrations": "Intégrations OpenCode", + "download.action.download": "Télécharger", + "download.action.install": "Installer", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "Pas forcément, mais probablement. Vous aurez besoin d'un abonnement IA si vous voulez connecter OpenCode à un fournisseur payant, mais vous pouvez travailler avec des", + "download.faq.a3.localLink": "modèles locaux", + "download.faq.a3.afterLocal.beforeZen": "gratuitement. Même si nous encourageons les utilisateurs à utiliser", + "download.faq.a3.afterZen": + ", OpenCode fonctionne avec tous les fournisseurs populaires comme OpenAI, Anthropic, xAI, etc.", + + "download.faq.a5.p1": "OpenCode est 100% gratuit à utiliser.", + "download.faq.a5.p2.beforeZen": + "Les coûts supplémentaires viendront de votre abonnement à un fournisseur de modèle. Même si OpenCode fonctionne avec n'importe quel fournisseur, nous recommandons d'utiliser", + "download.faq.a5.p2.afterZen": ".", + + "download.faq.a6.p1": + "Vos données et informations ne sont stockées que lorsque vous créez des liens partageables dans OpenCode.", + "download.faq.a6.p2.beforeShare": "En savoir plus sur", + "download.faq.a6.shareLink": "les pages de partage", + + "enterprise.title": "OpenCode | Solutions entreprise pour votre organisation", + "enterprise.meta.description": "Contactez OpenCode pour des solutions entreprise", + "enterprise.hero.title": "Votre code vous appartient", + "enterprise.hero.body1": + "OpenCode fonctionne de manière sécurisée au sein de votre organisation, sans stocker de données ni de contexte, et sans restrictions de licence ni revendications de propriété. Démarrez un essai avec votre équipe, puis déployez-le dans votre organisation en l'intégrant à votre SSO et à votre passerelle IA interne.", + "enterprise.hero.body2": "Dites-nous comment nous pouvons vous aider.", + "enterprise.form.name.label": "Nom complet", + "enterprise.form.name.placeholder": "Jeff Bezos", + "enterprise.form.role.label": "Poste", + "enterprise.form.role.placeholder": "Président exécutif", + "enterprise.form.email.label": "E-mail professionnel", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "Quel problème essayez-vous de résoudre ?", + "enterprise.form.message.placeholder": "Nous avons besoin d'aide pour...", + "enterprise.form.send": "Envoyer", + "enterprise.form.sending": "Envoi...", + "enterprise.form.success": "Message envoyé, nous vous contacterons bientôt.", + "enterprise.faq.title": "FAQ", + "enterprise.faq.q1": "Qu'est-ce que OpenCode Enterprise ?", + "enterprise.faq.a1": + "OpenCode Enterprise s'adresse aux organisations qui veulent s'assurer que leur code et leurs données ne quittent jamais leur infrastructure. Cela est possible grâce à une configuration centralisée qui s'intègre à votre SSO et à votre passerelle IA interne.", + "enterprise.faq.q2": "Comment démarrer avec OpenCode Enterprise ?", + "enterprise.faq.a2": + "Commencez simplement par un essai interne avec votre équipe. Par défaut, OpenCode ne stocke pas votre code ni vos données de contexte, ce qui facilite la prise en main. Ensuite, contactez-nous pour discuter des tarifs et des options de mise en œuvre.", + "enterprise.faq.q3": "Comment fonctionne la tarification entreprise ?", + "enterprise.faq.a3": + "Nous proposons une tarification entreprise par siège. Si vous avez votre propre passerelle LLM, nous ne facturons pas les tokens utilisés. Pour plus de détails, contactez-nous pour un devis sur mesure en fonction des besoins de votre organisation.", + "enterprise.faq.q4": "Mes données sont-elles sécurisées avec OpenCode Enterprise ?", + "enterprise.faq.a4": + "Oui. OpenCode ne stocke pas votre code ni vos données de contexte. Tout le traitement se fait localement ou via des appels API directs vers votre fournisseur d'IA. Avec une configuration centralisée et une intégration SSO, vos données restent sécurisées au sein de l'infrastructure de votre organisation.", + + "brand.title": "OpenCode | Marque", + "brand.meta.description": "Guide de marque OpenCode", + "brand.heading": "Guide de marque", + "brand.subtitle": "Ressources et éléments pour vous aider à travailler avec la marque OpenCode.", + "brand.downloadAll": "Télécharger tous les assets", + + "changelog.title": "OpenCode | Changelog", + "changelog.meta.description": "Notes de version et changelog d'OpenCode", + "changelog.hero.title": "Changelog", + "changelog.hero.subtitle": "Nouvelles mises à jour et améliorations pour OpenCode", + "changelog.empty": "Aucune entrée de changelog trouvée.", + "changelog.viewJson": "Voir le JSON", + + "bench.list.title": "Benchmark", + "bench.list.heading": "Benchmarks", + "bench.list.table.agent": "Agent", + "bench.list.table.model": "Modèle", + "bench.list.table.score": "Score", + + "bench.detail.title": "Benchmark - {{task}}", + "bench.detail.notFound": "Tâche introuvable", + "bench.detail.na": "N/A", + "bench.detail.labels.agent": "Agent", + "bench.detail.labels.model": "Modèle", + "bench.detail.labels.task": "Tâche", + "bench.detail.labels.repo": "Dépôt", + "bench.detail.labels.from": "De", + "bench.detail.labels.to": "À", + "bench.detail.labels.prompt": "Prompt", + "bench.detail.labels.commit": "Commit", + "bench.detail.labels.averageDuration": "Durée moyenne", + "bench.detail.labels.averageScore": "Score moyen", + "bench.detail.labels.averageCost": "Coût moyen", + "bench.detail.labels.summary": "Résumé", + "bench.detail.labels.runs": "Exécutions", + "bench.detail.labels.score": "Score", + "bench.detail.labels.base": "Base", + "bench.detail.labels.penalty": "Pénalité", + "bench.detail.labels.weight": "poids", + "bench.detail.table.run": "Exécution", + "bench.detail.table.score": "Score (Base - Pénalité)", + "bench.detail.table.cost": "Coût", + "bench.detail.table.duration": "Durée", + "bench.detail.run.title": "Exécution {{n}}", + "bench.detail.rawJson": "JSON brut", +} satisfies Dict diff --git a/packages/console/app/src/i18n/index.ts b/packages/console/app/src/i18n/index.ts new file mode 100644 index 00000000000..a49fbe37588 --- /dev/null +++ b/packages/console/app/src/i18n/index.ts @@ -0,0 +1,43 @@ +import type { Locale } from "~/lib/language" +import { dict as en } from "~/i18n/en" +import { dict as zh } from "~/i18n/zh" +import { dict as zht } from "~/i18n/zht" +import { dict as ko } from "~/i18n/ko" +import { dict as de } from "~/i18n/de" +import { dict as es } from "~/i18n/es" +import { dict as fr } from "~/i18n/fr" +import { dict as it } from "~/i18n/it" +import { dict as da } from "~/i18n/da" +import { dict as ja } from "~/i18n/ja" +import { dict as pl } from "~/i18n/pl" +import { dict as ru } from "~/i18n/ru" +import { dict as ar } from "~/i18n/ar" +import { dict as no } from "~/i18n/no" +import { dict as br } from "~/i18n/br" +import { dict as th } from "~/i18n/th" +import { dict as tr } from "~/i18n/tr" + +export type Key = keyof typeof en +export type Dict = Record + +const base = en satisfies Dict + +export function i18n(locale: Locale): Dict { + if (locale === "en") return base + if (locale === "zh") return { ...base, ...zh } + if (locale === "zht") return { ...base, ...zht } + if (locale === "ko") return { ...base, ...ko } + if (locale === "de") return { ...base, ...de } + if (locale === "es") return { ...base, ...es } + if (locale === "fr") return { ...base, ...fr } + if (locale === "it") return { ...base, ...it } + if (locale === "da") return { ...base, ...da } + if (locale === "ja") return { ...base, ...ja } + if (locale === "pl") return { ...base, ...pl } + if (locale === "ru") return { ...base, ...ru } + if (locale === "ar") return { ...base, ...ar } + if (locale === "no") return { ...base, ...no } + if (locale === "br") return { ...base, ...br } + if (locale === "th") return { ...base, ...th } + return { ...base, ...tr } +} diff --git a/packages/console/app/src/i18n/it.ts b/packages/console/app/src/i18n/it.ts new file mode 100644 index 00000000000..ce464f0009a --- /dev/null +++ b/packages/console/app/src/i18n/it.ts @@ -0,0 +1,596 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "Documentazione", + "nav.changelog": "Changelog", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "Enterprise", + "nav.zen": "Zen", + "nav.login": "Accedi", + "nav.free": "Gratis", + "nav.home": "Home", + "nav.openMenu": "Apri menu", + "nav.getStartedFree": "Inizia gratis", + + "nav.context.copyLogo": "Copia il logo come SVG", + "nav.context.copyWordmark": "Copia il wordmark come SVG", + "nav.context.brandAssets": "Asset del brand", + + "footer.github": "GitHub", + "footer.docs": "Documentazione", + "footer.changelog": "Changelog", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "Brand", + "legal.privacy": "Privacy", + "legal.terms": "Termini", + + "email.title": "Sii il primo a sapere quando rilasciamo nuovi prodotti", + "email.subtitle": "Iscriviti alla waitlist per l'accesso anticipato.", + "email.placeholder": "Indirizzo email", + "email.subscribe": "Iscriviti", + "email.success": "Quasi fatto, controlla la posta in arrivo e conferma il tuo indirizzo email", + + "notFound.title": "Non trovato | opencode", + "notFound.heading": "404 - Pagina non trovata", + "notFound.home": "Home", + "notFound.docs": "Documentazione", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "Esci", + + "workspace.select": "Seleziona workspace", + "workspace.createNew": "+ Crea nuovo workspace", + "workspace.modal.title": "Crea nuovo workspace", + "workspace.modal.placeholder": "Inserisci il nome del workspace", + + "common.cancel": "Annulla", + "common.creating": "Creazione...", + "common.create": "Crea", + + "common.videoUnsupported": "Il tuo browser non supporta il tag video.", + "common.figure": "Fig {{n}}.", + "common.faq": "FAQ", + "common.learnMore": "Scopri di più", + + "error.invalidPlan": "Piano non valido", + "error.workspaceRequired": "ID Workspace richiesto", + "error.alreadySubscribed": "Questo workspace ha già un abbonamento", + "error.limitRequired": "Il limite è richiesto.", + "error.monthlyLimitInvalid": "Imposta un limite mensile valido.", + "error.workspaceNameRequired": "Il nome del workspace è richiesto.", + "error.nameTooLong": "Il nome deve essere di 255 caratteri o meno.", + "error.emailRequired": "L'email è richiesta", + "error.roleRequired": "Il ruolo è richiesto", + "error.idRequired": "L'ID è richiesto", + "error.nameRequired": "Il nome è richiesto", + "error.providerRequired": "Il provider è richiesto", + "error.apiKeyRequired": "La chiave API è richiesta", + "error.modelRequired": "Il modello è richiesto", + "error.reloadAmountMin": "L'importo della ricarica deve essere almeno ${{amount}}", + "error.reloadTriggerMin": "La soglia del saldo deve essere almeno ${{amount}}", + + "home.title": "OpenCode | L'agente di coding IA open source", + + "temp.title": "opencode | Agente di coding IA costruito per il terminale", + "temp.hero.title": "L'agente di coding IA costruito per il terminale", + "temp.zen": "opencode zen", + "temp.getStarted": "Inizia", + "temp.feature.native.title": "TUI Nativa", + "temp.feature.native.body": "Un'interfaccia terminale reattiva, nativa e personalizzabile", + "temp.feature.zen.beforeLink": "Una", + "temp.feature.zen.link": "lista curata di modelli", + "temp.feature.zen.afterLink": "fornita da opencode", + "temp.feature.models.beforeLink": "Supporta 75+ provider LLM tramite", + "temp.feature.models.afterLink": ", inclusi modelli locali", + "temp.screenshot.caption": "OpenCode TUI con il tema tokyonight", + "temp.screenshot.alt": "OpenCode TUI con tema tokyonight", + + "home.banner.badge": "Nuovo", + "home.banner.text": "App desktop disponibile in beta", + "home.banner.platforms": "su macOS, Windows e Linux", + "home.banner.downloadNow": "Scarica ora", + "home.banner.downloadBetaNow": "Scarica ora la beta desktop", + + "home.hero.title": "L'agente di coding IA open source", + "home.hero.subtitle.a": "Modelli gratuiti inclusi o collega qualsiasi modello da qualsiasi provider,", + "home.hero.subtitle.b": "inclusi Claude, GPT, Gemini e altri.", + + "home.install.ariaLabel": "Opzioni di installazione", + + "home.what.title": "Che cos'è OpenCode?", + "home.what.body": "OpenCode è un agente open source che ti aiuta a scrivere codice nel terminale, IDE o desktop.", + "home.what.lsp.title": "LSP abilitato", + "home.what.lsp.body": "Carica automaticamente gli LSP giusti per il LLM", + "home.what.multiSession.title": "Multi-session", + "home.what.multiSession.body": "Avvia più agenti in parallelo sullo stesso progetto", + "home.what.shareLinks.title": "Link condivisi", + "home.what.shareLinks.body": "Condividi un link a qualsiasi sessione per riferimento o debug", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "Accedi con GitHub per usare il tuo account Copilot", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "Accedi con OpenAI per usare il tuo account ChatGPT Plus o Pro", + "home.what.anyModel.title": "Qualsiasi modello", + "home.what.anyModel.body": "75+ provider LLM tramite Models.dev, inclusi modelli locali", + "home.what.anyEditor.title": "Qualsiasi editor", + "home.what.anyEditor.body": "Disponibile come interfaccia terminale, app desktop ed estensione IDE", + "home.what.readDocs": "Leggi la doc", + + "home.growth.title": "L'agente di coding IA open source", + "home.growth.body": + "Con oltre {{stars}} stelle su GitHub, {{contributors}} contributori e oltre {{commits}} commit, OpenCode è usato e apprezzato da oltre {{monthlyUsers}} sviluppatori ogni mese.", + "home.growth.githubStars": "Stelle GitHub", + "home.growth.contributors": "Contributori", + "home.growth.monthlyDevs": "Devs mensili", + + "home.privacy.title": "Progettato per la privacy", + "home.privacy.body": + "OpenCode non archivia il tuo codice né i dati di contesto, così può operare in ambienti sensibili alla privacy.", + "home.privacy.learnMore": "Scopri di più su", + "home.privacy.link": "privacy", + + "home.faq.q1": "Che cos'è OpenCode?", + "home.faq.a1": + "OpenCode è un agente open source che ti aiuta a scrivere ed eseguire codice con qualsiasi modello di IA. È disponibile come interfaccia terminale, app desktop o estensione IDE.", + "home.faq.q2": "Come uso OpenCode?", + "home.faq.a2.before": "Il modo più semplice per iniziare è leggere l'", + "home.faq.a2.link": "introduzione", + "home.faq.q3": "Mi servono abbonamenti IA extra per usare OpenCode?", + "home.faq.a3.p1": + "Non necessariamente: OpenCode include un set di modelli gratuiti che puoi usare senza creare un account.", + "home.faq.a3.p2.beforeZen": "Inoltre, puoi usare modelli popolari per il coding creando un account", + "home.faq.a3.p2.afterZen": ".", + "home.faq.a3.p3": + "Anche se incoraggiamo gli utenti a usare Zen, OpenCode funziona anche con i provider più diffusi come OpenAI, Anthropic, xAI, ecc.", + "home.faq.a3.p4.beforeLocal": "Puoi anche collegare i tuoi", + "home.faq.a3.p4.localLink": "modelli locali", + "home.faq.q4": "Posso usare i miei abbonamenti IA esistenti con OpenCode?", + "home.faq.a4.p1": + "Sì, OpenCode supporta gli abbonamenti dei principali provider. Puoi usare Claude Pro/Max, ChatGPT Plus/Pro o GitHub Copilot.", + "home.faq.q5": "Posso usare OpenCode solo nel terminale?", + "home.faq.a5.beforeDesktop": "Non più! OpenCode ora è disponibile come app per", + "home.faq.a5.desktop": "desktop", + "home.faq.a5.and": "e", + "home.faq.a5.web": "web", + "home.faq.q6": "Quanto costa OpenCode?", + "home.faq.a6": + "OpenCode è gratuito al 100%. Include anche un set di modelli gratuiti. Potrebbero esserci costi aggiuntivi se colleghi altri provider.", + "home.faq.q7": "E per quanto riguarda dati e privacy?", + "home.faq.a7.p1": + "I tuoi dati vengono archiviati solo quando usi i nostri modelli gratuiti o crei link condivisibili.", + "home.faq.a7.p2.beforeModels": "Scopri di più su", + "home.faq.a7.p2.modelsLink": "i nostri modelli", + "home.faq.a7.p2.and": "e", + "home.faq.a7.p2.shareLink": "le pagine di condivisione", + "home.faq.q8": "OpenCode è open source?", + "home.faq.a8.p1": "Sì, OpenCode è completamente open source. Il codice sorgente è pubblico su", + "home.faq.a8.p2": "sotto la", + "home.faq.a8.mitLicense": "Licenza MIT", + "home.faq.a8.p3": + ", il che significa che chiunque può usarlo, modificarlo o contribuire al suo sviluppo. Chiunque nella comunità può aprire issue, inviare pull request ed estendere le funzionalità.", + + "home.zenCta.title": "Accedi a modelli affidabili e ottimizzati per agenti di coding", + "home.zenCta.body": + "Zen ti dà accesso a una selezione di modelli di IA che OpenCode ha testato e benchmarkato specificamente per agenti di coding. Niente più preoccupazioni per prestazioni e qualità incoerenti tra provider: usa modelli validati che funzionano.", + "home.zenCta.link": "Scopri Zen", + + "zen.title": "OpenCode Zen | Una selezione curata di modelli affidabili e ottimizzati per agenti di coding", + "zen.hero.title": "Accedi a modelli affidabili e ottimizzati per agenti di coding", + "zen.hero.body": + "Zen ti dà accesso a una selezione di modelli di IA che OpenCode ha testato e benchmarkato specificamente per agenti di coding. Niente più preoccupazioni per prestazioni e qualità incoerenti tra provider: usa modelli validati che funzionano.", + + "zen.faq.q1": "Cos'è OpenCode Zen?", + "zen.faq.a1": + "Zen è un set curato di modelli di IA testati e benchmarkati per agenti di coding, creato dal team dietro OpenCode.", + "zen.faq.q2": "Cosa rende Zen più accurato?", + "zen.faq.a2": + "Zen offre solo modelli testati e benchmarkati specificamente per agenti di coding. Non useresti un coltello da burro per tagliare una bistecca; non usare modelli scarsi per programmare.", + "zen.faq.q3": "Zen è più economico?", + "zen.faq.a3": + "Zen non è a scopo di lucro. Zen ribalta i costi dei provider di modelli direttamente su di te. Più Zen viene usato, più OpenCode può negoziare tariffe migliori e passarle a te.", + "zen.faq.q4": "Quanto costa Zen?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "addebita per richiesta", + "zen.faq.a4.p1.afterPricing": "senza ricarichi, quindi paghi esattamente ciò che addebita il provider del modello.", + "zen.faq.a4.p2.beforeAccount": "Il costo totale dipende dall'uso e puoi impostare limiti di spesa mensili nel tuo", + "zen.faq.a4.p2.accountLink": "account", + "zen.faq.a4.p3": + "Per coprire i costi, OpenCode aggiunge solo una piccola commissione di elaborazione del pagamento di $1.23 per ogni ricarica di saldo da $20.", + "zen.faq.q5": "E per quanto riguarda dati e privacy?", + "zen.faq.a5.beforeExceptions": + "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.faq.a5.exceptionsLink": "seguenti eccezioni", + "zen.faq.q6": "Posso impostare limiti di spesa?", + "zen.faq.a6": "Sì, puoi impostare limiti di spesa mensuali nel tuo account.", + "zen.faq.q7": "Posso annullare?", + "zen.faq.a7": "Sì, puoi disattivare la fatturazione in qualsiasi momento e usare il saldo rimanente.", + "zen.faq.q8": "Posso usare Zen con altri agenti di coding?", + "zen.faq.a8": + "Anche se Zen funziona alla grande con OpenCode, puoi usare Zen con qualsiasi agente. Segui le istruzioni di configurazione nel tuo agente di coding preferito.", + + "zen.cta.start": "Inizia con Zen", + "zen.pricing.title": "Aggiungi $20 di saldo a consumo", + "zen.pricing.fee": "(+$1.23 commissione di elaborazione carta)", + "zen.pricing.body": "Usa con qualsiasi agente. Imposta limiti di spesa mensili. Annulla in qualsiasi momento.", + "zen.problem.title": "Quale problema risolve Zen?", + "zen.problem.body": + "Sono disponibili numerosi modelli, ma solo pochi funzionano bene con gli agenti di coding. La maggior parte dei provider li configura in modo diverso con risultati variabili.", + "zen.problem.subtitle": "Stiamo risolvendo questo problema per tutti, non solo per gli utenti OpenCode.", + "zen.problem.item1": "Testare modelli selezionati e consultare i loro team", + "zen.problem.item2": "Collaborare con i provider per garantire che vengano consegnati correttamente", + "zen.problem.item3": "Benchmark di tutte le combinazioni modello-provider che raccomandiamo", + "zen.how.title": "Come funziona Zen", + "zen.how.body": "Anche se ti consigliamo di utilizzare Zen con OpenCode, puoi utilizzare Zen con qualsiasi agente.", + "zen.how.step1.title": "Iscriviti e aggiungi un saldo di $20", + "zen.how.step1.beforeLink": "segui le", + "zen.how.step1.link": "istruzioni di configurazione", + "zen.how.step2.title": "Usa Zen con prezzi trasparenti", + "zen.how.step2.link": "paga per richiesta", + "zen.how.step2.afterLink": "senza ricarichi", + "zen.how.step3.title": "Ricarica automatica", + "zen.how.step3.body": "quando il tuo saldo raggiunge $5, aggiungeremo automaticamente $20", + "zen.privacy.title": "La tua privacy è importante per noi", + "zen.privacy.beforeExceptions": + "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", + + "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.", + "black.hero.title": "Accedi ai migliori modelli di coding al mondo", + "black.hero.subtitle": "Inclusi Claude, GPT, Gemini e altri", + "black.title": "OpenCode Black | Prezzi", + "black.plan.icon20": "Piano Black 20", + "black.plan.icon100": "Piano Black 100", + "black.plan.icon200": "Piano Black 200", + "black.plan.multiplier100": "5x più utilizzo rispetto a Black 20", + "black.plan.multiplier200": "20x più utilizzo rispetto a Black 20", + "black.price.perMonth": "al mese", + "black.price.perPersonBilledMonthly": "per persona fatturato mensilmente", + "black.terms.1": "Il tuo abbonamento non inizierà immediatamente", + "black.terms.2": "Verrai aggiunto alla lista d'attesa e attivato presto", + "black.terms.3": "La tua carta verrà addebitata solo quando il tuo abbonamento sarà attivato", + "black.terms.4": + "Si applicano limiti di utilizzo, un uso fortemente automatizzato potrebbe raggiungere i limiti prima", + "black.terms.5": "Gli abbonamenti sono per individui, contatta Enterprise per i team", + "black.terms.6": "I limiti potrebbero essere modificati e i piani potrebbero essere interrotti in futuro", + "black.terms.7": "Annulla il tuo abbonamento in qualsiasi momento", + "black.action.continue": "Continua", + "black.finePrint.beforeTerms": "I prezzi mostrati non includono le tasse applicabili", + "black.finePrint.terms": "Termini di servizio", + "black.workspace.title": "OpenCode Black | Seleziona Workspace", + "black.workspace.selectPlan": "Seleziona un workspace per questo piano", + "black.workspace.name": "Workspace {{n}}", + "black.subscribe.title": "Abbonati a OpenCode Black", + "black.subscribe.paymentMethod": "Metodo di pagamento", + "black.subscribe.loadingPaymentForm": "Caricamento modulo di pagamento...", + "black.subscribe.selectWorkspaceToContinue": "Seleziona un workspace per continuare", + "black.subscribe.failurePrefix": "Oh no!", + "black.subscribe.error.generic": "Si è verificato un errore", + "black.subscribe.error.invalidPlan": "Piano non valido", + "black.subscribe.error.workspaceRequired": "ID Workspace richiesto", + "black.subscribe.error.alreadySubscribed": "Questo workspace ha già un abbonamento", + "black.subscribe.processing": "Elaborazione...", + "black.subscribe.submit": "Abbonati ${{plan}}", + "black.subscribe.form.chargeNotice": "Ti verrà addebitato solo quando il tuo abbonamento sarà attivato", + "black.subscribe.success.title": "Sei nella lista d'attesa di OpenCode Black", + "black.subscribe.success.subscriptionPlan": "Piano di abbonamento", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "Importo", + "black.subscribe.success.amountValue": "${{plan}} al mese", + "black.subscribe.success.paymentMethod": "Metodo di pagamento", + "black.subscribe.success.dateJoined": "Data di adesione", + "black.subscribe.success.chargeNotice": "La tua carta verrà addebitata quando il tuo abbonamento sarà attivato", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "Chiavi API", + "workspace.nav.members": "Membri", + "workspace.nav.billing": "Fatturazione", + "workspace.nav.settings": "Impostazioni", + + "workspace.home.banner.beforeLink": "Modelli ottimizzati e affidabili per agenti di coding.", + "workspace.home.billing.loading": "Caricamento...", + "workspace.home.billing.enable": "Abilita fatturazione", + "workspace.home.billing.currentBalance": "Saldo attuale", + + "workspace.newUser.feature.tested.title": "Modelli testati e verificati", + "workspace.newUser.feature.tested.body": + "Abbiamo benchmarkato e testato modelli specificamente per agenti di coding per garantire le migliori prestazioni.", + "workspace.newUser.feature.quality.title": "Massima qualità", + "workspace.newUser.feature.quality.body": + "Accedi a modelli configurati per prestazioni ottimali - nessun downgrade o instradamento verso provider più economici.", + "workspace.newUser.feature.lockin.title": "Nessun lock-in", + "workspace.newUser.feature.lockin.body": + "Usa Zen con qualsiasi agente di coding, e continua a usare altri provider con opencode quando vuoi.", + "workspace.newUser.copyApiKey": "Copia chiave API", + "workspace.newUser.copyKey": "Copia Chiave", + "workspace.newUser.copied": "Copiato!", + "workspace.newUser.step.enableBilling": "Abilita fatturazione", + "workspace.newUser.step.login.before": "Esegui", + "workspace.newUser.step.login.after": "e seleziona opencode", + "workspace.newUser.step.pasteKey": "Incolla la tua chiave API", + "workspace.newUser.step.models.before": "Avvia opencode ed esegui", + "workspace.newUser.step.models.after": "per selezionare un modello", + + "workspace.models.title": "Modelli", + "workspace.models.subtitle.beforeLink": "Gestisci i modelli a cui possono accedere i membri del workspace.", + "workspace.models.table.model": "Modello", + "workspace.models.table.enabled": "Abilitato", + + "workspace.providers.title": "Bring Your Own Key", + "workspace.providers.subtitle": "Configura le tue chiavi API dai provider di IA.", + "workspace.providers.placeholder": "Inserisci chiave API {{provider}} ({{prefix}}...)", + "workspace.providers.configure": "Configura", + "workspace.providers.edit": "Modifica", + "workspace.providers.delete": "Elimina", + "workspace.providers.saving": "Salvataggio...", + "workspace.providers.save": "Salva", + "workspace.providers.table.provider": "Provider", + "workspace.providers.table.apiKey": "Chiave API", + + "workspace.usage.title": "Cronologia Utilizzo", + "workspace.usage.subtitle": "Utilizzo API recente e costi.", + "workspace.usage.empty": "Effettua la tua prima chiamata API per iniziare.", + "workspace.usage.table.date": "Data", + "workspace.usage.table.model": "Modello", + "workspace.usage.table.input": "Input", + "workspace.usage.table.output": "Output", + "workspace.usage.table.cost": "Costo", + "workspace.usage.breakdown.input": "Input", + "workspace.usage.breakdown.cacheRead": "Lettura Cache", + "workspace.usage.breakdown.cacheWrite": "Scrittura Cache", + "workspace.usage.breakdown.output": "Output", + "workspace.usage.breakdown.reasoning": "Reasoning", + "workspace.usage.subscription": "abbonamento (${{amount}})", + + "workspace.cost.title": "Costo", + "workspace.cost.subtitle": "Costi di utilizzo suddivisi per modello.", + "workspace.cost.allModels": "Tutti i Modelli", + "workspace.cost.allKeys": "Tutte le Chiavi", + "workspace.cost.deletedSuffix": "(eliminato)", + "workspace.cost.empty": "Nessun dato di utilizzo disponibile per il periodo selezionato.", + "workspace.cost.subscriptionShort": "sub", + + "workspace.keys.title": "Chiavi API", + "workspace.keys.subtitle": "Gestisci le tue chiavi API per accedere ai servizi opencode.", + "workspace.keys.create": "Crea Chiave API", + "workspace.keys.placeholder": "Inserisci nome chiave", + "workspace.keys.empty": "Crea una chiave API opencode Gateway", + "workspace.keys.table.name": "Nome", + "workspace.keys.table.key": "Chiave", + "workspace.keys.table.createdBy": "Creato da", + "workspace.keys.table.lastUsed": "Ultimo Utilizzo", + "workspace.keys.copyApiKey": "Copia chiave API", + "workspace.keys.delete": "Elimina", + + "workspace.members.title": "Membri", + "workspace.members.subtitle": "Gestisci i membri del workspace e le loro autorizzazioni.", + "workspace.members.invite": "Invita Membro", + "workspace.members.inviting": "Invito in corso...", + "workspace.members.beta.beforeLink": "I workspace sono gratuiti per i team durante la beta.", + "workspace.members.form.invitee": "Invitato", + "workspace.members.form.emailPlaceholder": "Inserisci email", + "workspace.members.form.role": "Ruolo", + "workspace.members.form.monthlyLimit": "Limite di spesa mensile", + "workspace.members.noLimit": "Nessun limite", + "workspace.members.noLimitLowercase": "nessun limite", + "workspace.members.invited": "invitato", + "workspace.members.edit": "Modifica", + "workspace.members.delete": "Elimina", + "workspace.members.saving": "Salvataggio...", + "workspace.members.save": "Salva", + "workspace.members.table.email": "Email", + "workspace.members.table.role": "Ruolo", + "workspace.members.table.monthLimit": "Limite mensile", + "workspace.members.role.admin": "Admin", + "workspace.members.role.adminDescription": "Può gestire modelli, membri e fatturazione", + "workspace.members.role.member": "Membro", + "workspace.members.role.memberDescription": "Può generare chiavi API solo per sé", + + "workspace.settings.title": "Impostazioni", + "workspace.settings.subtitle": "Aggiorna il nome e le preferenze del workspace.", + "workspace.settings.workspaceName": "Nome Workspace", + "workspace.settings.defaultName": "Predefinito", + "workspace.settings.updating": "Aggiornamento...", + "workspace.settings.save": "Salva", + "workspace.settings.edit": "Modifica", + + "workspace.billing.title": "Fatturazione", + "workspace.billing.subtitle.beforeLink": "Gestisci i metodi di pagamento.", + "workspace.billing.contactUs": "Contattaci", + "workspace.billing.subtitle.afterLink": "se hai domande.", + "workspace.billing.currentBalance": "Saldo Attuale", + "workspace.billing.add": "Aggiungi $", + "workspace.billing.enterAmount": "Inserisci importo", + "workspace.billing.loading": "Caricamento...", + "workspace.billing.addAction": "Aggiungi", + "workspace.billing.addBalance": "Aggiungi Saldo", + "workspace.billing.linkedToStripe": "Collegato a Stripe", + "workspace.billing.manage": "Gestisci", + "workspace.billing.enable": "Abilita Fatturazione", + + "workspace.monthlyLimit.title": "Limite Mensile", + "workspace.monthlyLimit.subtitle": "Imposta un limite di utilizzo mensile per il tuo account.", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "Impostazione...", + "workspace.monthlyLimit.set": "Impostato", + "workspace.monthlyLimit.edit": "Modifica Limite", + "workspace.monthlyLimit.noLimit": "Nessun limite di utilizzo impostato.", + "workspace.monthlyLimit.currentUsage.beforeMonth": "Utilizzo attuale per", + "workspace.monthlyLimit.currentUsage.beforeAmount": "è $", + + "workspace.reload.title": "Ricarica Auto", + "workspace.reload.disabled.before": "La ricarica auto è", + "workspace.reload.disabled.state": "disabilitata", + "workspace.reload.disabled.after": "Abilita per ricaricare automaticamente quando il saldo è basso.", + "workspace.reload.enabled.before": "La ricarica auto è", + "workspace.reload.enabled.state": "abilitata", + "workspace.reload.enabled.middle": "Ricaricheremo", + "workspace.reload.processingFee": "commissione", + "workspace.reload.enabled.after": "quando il saldo raggiunge", + "workspace.reload.edit": "Modifica", + "workspace.reload.enable": "Abilita", + "workspace.reload.enableAutoReload": "Abilita Ricarica Auto", + "workspace.reload.reloadAmount": "Ricarica $", + "workspace.reload.whenBalanceReaches": "Quando il saldo raggiunge $", + "workspace.reload.saving": "Salvataggio...", + "workspace.reload.save": "Salva", + "workspace.reload.failedAt": "Ricarica fallita il", + "workspace.reload.reason": "Motivo:", + "workspace.reload.updatePaymentMethod": "Aggiorna il tuo metodo di pagamento e riprova.", + "workspace.reload.retrying": "Riprovo...", + "workspace.reload.retry": "Riprova", + + "workspace.payments.title": "Cronologia Pagamenti", + "workspace.payments.subtitle": "Transazioni di pagamento recenti.", + "workspace.payments.table.date": "Data", + "workspace.payments.table.paymentId": "ID Pagamento", + "workspace.payments.table.amount": "Importo", + "workspace.payments.table.receipt": "Ricevuta", + "workspace.payments.type.credit": "credito", + "workspace.payments.type.subscription": "abbonamento", + "workspace.payments.view": "Visualizza", + + "workspace.black.loading": "Caricamento...", + "workspace.black.time.day": "giorno", + "workspace.black.time.days": "giorni", + "workspace.black.time.hour": "ora", + "workspace.black.time.hours": "ore", + "workspace.black.time.minute": "minuto", + "workspace.black.time.minutes": "minuti", + "workspace.black.time.fewSeconds": "pochi secondi", + "workspace.black.subscription.title": "Abbonamento", + "workspace.black.subscription.message": "Sei abbonato a OpenCode Black per ${{plan}} al mese.", + "workspace.black.subscription.manage": "Gestisci Abbonamento", + "workspace.black.subscription.rollingUsage": "Utilizzo 5-ore", + "workspace.black.subscription.weeklyUsage": "Utilizzo Settimanale", + "workspace.black.subscription.resetsIn": "Si resetta tra", + "workspace.black.subscription.useBalance": "Usa il tuo saldo disponibile dopo aver raggiunto i limiti di utilizzo", + "workspace.black.waitlist.title": "Waitlist", + "workspace.black.waitlist.joined": "Sei nella waitlist per il piano OpenCode Black da ${{plan}} al mese.", + "workspace.black.waitlist.ready": "Siamo pronti per iscriverti al piano OpenCode Black da ${{plan}} al mese.", + "workspace.black.waitlist.leave": "Lascia Waitlist", + "workspace.black.waitlist.leaving": "Uscita...", + "workspace.black.waitlist.left": "Uscito", + "workspace.black.waitlist.enroll": "Iscriviti", + "workspace.black.waitlist.enrolling": "Iscrizione...", + "workspace.black.waitlist.enrolled": "Iscritto", + "workspace.black.waitlist.enrollNote": + "Quando clicchi su Iscriviti, il tuo abbonamento inizia immediatamente e la tua carta verrà addebitata.", + + "download.title": "OpenCode | Download", + "download.meta.description": "Scarica OpenCode per macOS, Windows e Linux", + "download.hero.title": "Scarica OpenCode", + "download.hero.subtitle": "Disponibile in Beta per macOS, Windows e Linux", + "download.hero.button": "Scarica per {{os}}", + "download.section.terminal": "OpenCode Terminal", + "download.section.desktop": "OpenCode Desktop (Beta)", + "download.section.extensions": "OpenCode Extensions", + "download.section.integrations": "OpenCode Integrations", + "download.action.download": "Scarica", + "download.action.install": "Installa", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "Non necessariamente, ma probabilmente. Avrai bisogno di un abbonamento IA se vuoi collegare OpenCode a un provider a pagamento, sebbene tu possa lavorare con", + "download.faq.a3.localLink": "modelli locali", + "download.faq.a3.afterLocal.beforeZen": "gratuitamente. Mentre incoraggiamo gli utenti a usare", + "download.faq.a3.afterZen": ", OpenCode funziona con tutti i provider popolari come OpenAI, Anthropic, xAI ecc.", + + "download.faq.a5.p1": "OpenCode è gratuito al 100%.", + "download.faq.a5.p2.beforeZen": + "Eventuali costi aggiuntivi proverranno dal tuo abbonamento a un provider di modelli. Mentre OpenCode funziona con qualsiasi provider di modelli, raccomandiamo di usare", + "download.faq.a5.p2.afterZen": ".", + + "download.faq.a6.p1": "I tuoi dati e informazioni sono archiviati solo quando crei link condivisibili in OpenCode.", + "download.faq.a6.p2.beforeShare": "Scopri di più sulle", + "download.faq.a6.shareLink": "pagine condivise", + + "enterprise.title": "OpenCode | Soluzioni Enterprise per la tua organizzazione", + "enterprise.meta.description": "Contatta OpenCode per soluzioni enterprise", + "enterprise.hero.title": "Il tuo codice è tuo", + "enterprise.hero.body1": + "OpenCode opera in modo sicuro all'interno della tua organizzazione senza dati o contesto archiviati e senza restrizioni di licenza o rivendicazioni di proprietà. Inizia una prova con il tuo team, poi distribuisci attraverso la tua organizzazione integrandolo con il tuo SSO e gateway IA interno.", + "enterprise.hero.body2": "Facci sapere come possiamo aiutare.", + "enterprise.form.name.label": "Nome completo", + "enterprise.form.name.placeholder": "Jeff Bezos", + "enterprise.form.role.label": "Ruolo", + "enterprise.form.role.placeholder": "Presidente Esecutivo", + "enterprise.form.email.label": "Email aziendale", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "Quale problema stai cercando di risolvere?", + "enterprise.form.message.placeholder": "Abbiamo bisogno di aiuto con...", + "enterprise.form.send": "Invia", + "enterprise.form.sending": "Invio...", + "enterprise.form.success": "Messaggio inviato, ti contatteremo presto.", + "enterprise.faq.title": "FAQ", + "enterprise.faq.q1": "Cos'è OpenCode Enterprise?", + "enterprise.faq.a1": + "OpenCode Enterprise è per le organizzazioni che vogliono garantire che il loro codice e dati non lascino mai la loro infrastruttura. Può farlo usando una configurazione centralizzata che si integra con il tuo SSO e gateway IA interno.", + "enterprise.faq.q2": "Come inizio con OpenCode Enterprise?", + "enterprise.faq.a2": + "Inizia semplicemente con una prova interna con il tuo team. OpenCode per impostazione predefinita non archivia il tuo codice o dati di contesto, rendendo facile iniziare. Poi contattaci per discutere prezzi e opzioni di implementazione.", + "enterprise.faq.q3": "Come funziona il prezzo enterprise?", + "enterprise.faq.a3": + "Offriamo prezzi enterprise per postazione. Se hai il tuo gateway LLM, non addebitiamo per i token usati. Per ulteriori dettagli, contattaci per un preventivo personalizzato basato sulle esigenze della tua organizzazione.", + "enterprise.faq.q4": "I miei dati sono sicuri con OpenCode Enterprise?", + "enterprise.faq.a4": + "Sì. OpenCode non archivia il tuo codice o dati di contesto. Tutto il trattamento avviene localmente o attraverso chiamate API dirette al tuo provider IA. Con configurazione centrale e integrazione SSO, i tuoi dati rimangono sicuri all'interno dell'infrastruttura della tua organizzazione.", + + "brand.title": "OpenCode | Brand", + "brand.meta.description": "Linee guida del brand OpenCode", + "brand.heading": "Linee guida del brand", + "brand.subtitle": "Risorse e asset per aiutarti a lavorare con il brand OpenCode.", + "brand.downloadAll": "Scarica tutti gli asset", + + "changelog.title": "OpenCode | Changelog", + "changelog.meta.description": "Note di rilascio e changelog OpenCode", + "changelog.hero.title": "Changelog", + "changelog.hero.subtitle": "Nuovi aggiornamenti e miglioramenti a OpenCode", + "changelog.empty": "Nessuna voce del changelog trovata.", + "changelog.viewJson": "Vedi JSON", + + "bench.list.title": "Benchmark", + "bench.list.heading": "Benchmark", + "bench.list.table.agent": "Agente", + "bench.list.table.model": "Modello", + "bench.list.table.score": "Punteggio", + + "bench.detail.title": "Benchmark - {{task}}", + "bench.detail.notFound": "Task non trovato", + "bench.detail.na": "N/D", + "bench.detail.labels.agent": "Agente", + "bench.detail.labels.model": "Modello", + "bench.detail.labels.task": "Task", + "bench.detail.labels.repo": "Repo", + "bench.detail.labels.from": "Da", + "bench.detail.labels.to": "A", + "bench.detail.labels.prompt": "Prompt", + "bench.detail.labels.commit": "Commit", + "bench.detail.labels.averageDuration": "Durata Media", + "bench.detail.labels.averageScore": "Punteggio Medio", + "bench.detail.labels.averageCost": "Costo Medio", + "bench.detail.labels.summary": "Riepilogo", + "bench.detail.labels.runs": "Esecuzioni", + "bench.detail.labels.score": "Punteggio", + "bench.detail.labels.base": "Base", + "bench.detail.labels.penalty": "Penalità", + "bench.detail.labels.weight": "peso", + "bench.detail.table.run": "Esecuzione", + "bench.detail.table.score": "Punteggio (Base - Penalità)", + "bench.detail.table.cost": "Costo", + "bench.detail.table.duration": "Durata", + "bench.detail.run.title": "Esecuzione {{n}}", + "bench.detail.rawJson": "Raw JSON", +} satisfies Dict diff --git a/packages/console/app/src/i18n/ja.ts b/packages/console/app/src/i18n/ja.ts new file mode 100644 index 00000000000..4dea6ccf4fe --- /dev/null +++ b/packages/console/app/src/i18n/ja.ts @@ -0,0 +1,595 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "ドキュメント", + "nav.changelog": "変更履歴", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "エンタープライズ", + "nav.zen": "Zen", + "nav.login": "ログイン", + "nav.free": "無料", + "nav.home": "ホーム", + "nav.openMenu": "メニューを開く", + "nav.getStartedFree": "無料ではじめる", + + "nav.context.copyLogo": "ロゴをSVGでコピー", + "nav.context.copyWordmark": "ワードマークをSVGでコピー", + "nav.context.brandAssets": "ブランド素材", + + "footer.github": "GitHub", + "footer.docs": "ドキュメント", + "footer.changelog": "変更履歴", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "ブランド", + "legal.privacy": "プライバシー", + "legal.terms": "利用規約", + + "email.title": "新製品リリースの情報をいち早く受け取る", + "email.subtitle": "早期アクセスのためにウェイトリストに登録してください。", + "email.placeholder": "メールアドレス", + "email.subscribe": "登録", + "email.success": "ほぼ完了です。受信トレイを確認してメールアドレスを認証してください", + + "notFound.title": "見つかりません | OpenCode", + "notFound.heading": "404 - ページが見つかりません", + "notFound.home": "ホーム", + "notFound.docs": "ドキュメント", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "ログアウト", + + "workspace.select": "ワークスペースを選択", + "workspace.createNew": "+ 新しいワークスペースを作成", + "workspace.modal.title": "新しいワークスペースを作成", + "workspace.modal.placeholder": "ワークスペース名を入力", + + "common.cancel": "キャンセル", + "common.creating": "作成中...", + "common.create": "作成", + + "common.videoUnsupported": "お使いのブラウザは video タグをサポートしていません。", + "common.figure": "図 {{n}}.", + "common.faq": "FAQ", + "common.learnMore": "詳しく見る", + + "error.invalidPlan": "無効なプラン", + "error.workspaceRequired": "ワークスペースIDが必要です", + "error.alreadySubscribed": "このワークスペースは既にサブスクリプションを持っています", + "error.limitRequired": "制限値が必要です。", + "error.monthlyLimitInvalid": "有効な月間制限を設定してください。", + "error.workspaceNameRequired": "ワークスペース名が必要です。", + "error.nameTooLong": "名前は255文字以下である必要があります。", + "error.emailRequired": "メールアドレスが必要です", + "error.roleRequired": "ロールが必要です", + "error.idRequired": "IDが必要です", + "error.nameRequired": "名前が必要です", + "error.providerRequired": "プロバイダーが必要です", + "error.apiKeyRequired": "APIキーが必要です", + "error.modelRequired": "モデルが必要です", + "error.reloadAmountMin": "リロード額は少なくとも ${{amount}} である必要があります", + "error.reloadTriggerMin": "残高トリガーは少なくとも ${{amount}} である必要があります", + + "home.title": "OpenCode | オープンソースのAIコーディングエージェント", + + "temp.title": "OpenCode | ターミナル向けに構築されたAIコーディングエージェント", + "temp.hero.title": "ターミナル向けに構築されたAIコーディングエージェント", + "temp.zen": "OpenCode Zen", + "temp.getStarted": "はじめる", + "temp.feature.native.title": "ネイティブ TUI", + "temp.feature.native.body": "レスポンシブでネイティブ、テーマ変更可能なターミナルUI", + "temp.feature.zen.beforeLink": "OpenCodeが提供する", + "temp.feature.zen.link": "厳選されたモデルリスト", + "temp.feature.zen.afterLink": "", + "temp.feature.models.beforeLink": "ローカルモデルを含む、", + "temp.feature.models.afterLink": "を通じて75以上のLLMプロバイダーをサポート", + "temp.screenshot.caption": "tokyonight テーマを使用した OpenCode TUI", + "temp.screenshot.alt": "tokyonight テーマの OpenCode TUI", + + "home.banner.badge": "新着", + "home.banner.text": "デスクトップアプリのベータ版が利用可能", + "home.banner.platforms": "macOS、Windows、Linux で", + "home.banner.downloadNow": "今すぐダウンロード", + "home.banner.downloadBetaNow": "デスクトップベータ版を今すぐダウンロード", + + "home.hero.title": "オープンソースのAIコーディングエージェント", + "home.hero.subtitle.a": "無料モデルが含まれています。また、任意のプロバイダーの任意のモデルに接続でき、", + "home.hero.subtitle.b": "Claude、GPT、Gemini などにも対応します。", + + "home.install.ariaLabel": "インストールオプション", + + "home.what.title": "OpenCodeとは?", + "home.what.body": + "OpenCodeは、ターミナル、IDE、またはデスクトップでのコード作成を支援するオープンソースのエージェントです。", + "home.what.lsp.title": "LSP対応", + "home.what.lsp.body": "LLMに適したLSPを自動的に読み込みます", + "home.what.multiSession.title": "マルチセッション", + "home.what.multiSession.body": "同じプロジェクトで複数のエージェントを並行実行できます", + "home.what.shareLinks.title": "共有リンク", + "home.what.shareLinks.body": "参照やデバッグのために、任意のセッションへのリンクを共有できます", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "GitHubでログインしてCopilotアカウントを利用できます", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "OpenAIでログインしてChatGPT PlusまたはProアカウントを利用できます", + "home.what.anyModel.title": "あらゆるモデル", + "home.what.anyModel.body": "Models.dev経由で75以上のLLMプロバイダーに対応(ローカルモデル含む)", + "home.what.anyEditor.title": "あらゆるエディタ", + "home.what.anyEditor.body": "ターミナルインターフェース、デスクトップアプリ、IDE拡張機能として利用できます", + "home.what.readDocs": "ドキュメントを読む", + + "home.growth.title": "オープンソースのAIコーディングエージェント", + "home.growth.body": + "GitHubスター{{stars}}以上、コントリビューター{{contributors}}人、コミット{{commits}}件以上。毎月{{monthlyUsers}}人以上の開発者に利用・信頼されています。", + "home.growth.githubStars": "GitHubスター", + "home.growth.contributors": "コントリビューター", + "home.growth.monthlyDevs": "月間開発者数", + + "home.privacy.title": "プライバシーを最優先に設計", + "home.privacy.body": + "OpenCodeはコードやコンテキストデータを一切保存しないため、プライバシーが重視される環境でも利用できます。", + "home.privacy.learnMore": "詳しくは", + "home.privacy.link": "プライバシー", + + "home.faq.q1": "OpenCodeとは?", + "home.faq.a1": + "OpenCodeは、任意のAIモデルでコードの作成・実行を支援するオープンソースのエージェントです。ターミナルベースのインターフェース、デスクトップアプリ、IDE拡張として利用できます。", + "home.faq.q2": "OpenCodeの使い方は?", + "home.faq.a2.before": "最も簡単な始め方は", + "home.faq.a2.link": "イントロを読む", + "home.faq.q3": "OpenCodeには追加のAIサブスクリプションが必要ですか?", + "home.faq.a3.p1": "必ずしも必要ではありません。OpenCodeには、アカウント不要で使える無料モデルが含まれています。", + "home.faq.a3.p2.beforeZen": "これらに加えて、", + "home.faq.a3.p2.afterZen": " アカウントを作成することで、人気のコーディングモデルを利用できます。", + "home.faq.a3.p3": + "Zenの利用を推奨していますが、OpenCodeはOpenAI、Anthropic、xAIなどの主要プロバイダーにも対応しています。", + "home.faq.a3.p4.beforeLocal": "さらに、", + "home.faq.a3.p4.localLink": "ローカルモデル", + "home.faq.q4": "既存のAIサブスクリプションをOpenCodeで使えますか?", + "home.faq.a4.p1": + "はい、OpenCodeは主要プロバイダーのサブスクリプションプランに対応しています。Claude Pro/Max、ChatGPT Plus/Pro、GitHub Copilotのサブスクリプションを利用できます。", + "home.faq.q5": "ターミナルだけで使えますか?", + "home.faq.a5.beforeDesktop": "もう違います!OpenCodeは今は", + "home.faq.a5.desktop": "デスクトップ", + "home.faq.a5.and": "と", + "home.faq.a5.web": "ウェブ", + "home.faq.q6": "OpenCodeの価格は?", + "home.faq.a6": + "OpenCodeは100%無料で使えます。無料モデルも含まれています。他のプロバイダーに接続する場合は追加費用が発生することがあります。", + "home.faq.q7": "データとプライバシーは?", + "home.faq.a7.p1": "無料モデルを使う場合や共有リンクを作成する場合にのみ、データが保存されます。", + "home.faq.a7.p2.beforeModels": "詳しくは", + "home.faq.a7.p2.modelsLink": "モデルのプライバシー", + "home.faq.a7.p2.and": "と", + "home.faq.a7.p2.shareLink": "共有ページのプライバシー", + "home.faq.q8": "OpenCodeはオープンソースですか?", + "home.faq.a8.p1": "はい、OpenCodeは完全にオープンソースです。ソースコードは", + "home.faq.a8.p2": "の", + "home.faq.a8.mitLicense": "MITライセンス", + "home.faq.a8.p3": + "のもとで公開されており、誰でも使用、変更、開発への参加ができます。コミュニティの誰でもissueを起こしたり、pull requestを送ったり、機能を拡張できます。", + + "home.zenCta.title": "コーディングエージェント向けの信頼できる最適化モデル", + "home.zenCta.body": + "Zenは、OpenCodeがコーディングエージェント向けにテスト・ベンチマーク済みのAIモデルを厳選して提供します。プロバイダー間の性能・品質のブレを気にせず、検証済みのモデルを利用できます。", + "home.zenCta.link": "Zenについて知る", + + "zen.title": "OpenCode Zen | コーディングエージェント向けの信頼できる最適化モデル", + "zen.hero.title": "コーディングエージェント向けの信頼できる最適化モデル", + "zen.hero.body": + "Zenは、OpenCodeがコーディングエージェント向けにテスト・ベンチマーク済みのAIモデルを厳選して提供します。プロバイダー間の性能・品質のブレを気にせず、検証済みのモデルを利用できます。", + + "zen.faq.q1": "OpenCode Zenとは?", + "zen.faq.a1": + "Zenは、OpenCodeのチームが作成した、コーディングエージェント向けにテスト・ベンチマークされたAIモデルの厳選セットです。", + "zen.faq.q2": "Zenはなぜ精度が高いのですか?", + "zen.faq.a2": + "Zenはコーディングエージェント向けにテスト・ベンチマークされたモデルだけを提供します。ステーキを切るのにバターナイフを使わないように、コーディングには品質の低いモデルを使わないでください。", + "zen.faq.q3": "Zenは安いですか?", + "zen.faq.a3": + "Zenは営利目的ではありません。Zenはモデル提供元のコストをそのままあなたに渡します。Zenの利用が増えるほど、OpenCodeはより良いレートを交渉し、その分をあなたに還元できます。", + "zen.faq.q4": "Zenの料金は?", + "zen.faq.a4.p1.beforePricing": "Zenは", + "zen.faq.a4.p1.pricingLink": "リクエスト単位で課金", + "zen.faq.a4.p1.afterPricing": "し、マークアップはありません。つまり、モデル提供元の請求額をそのまま支払います。", + "zen.faq.a4.p2.beforeAccount": "総コストは利用量に依存し、月次の支出上限を", + "zen.faq.a4.p2.accountLink": "アカウント", + "zen.faq.a4.p3": "コストを賄うために、OpenCodeは$20の残高チャージあたり$1.23の小さな決済手数料のみを追加します。", + "zen.faq.q5": "データとプライバシーは?", + "zen.faq.a5.beforeExceptions": + "Zenのモデルはすべて米国でホストされています。プロバイダーはゼロ保持ポリシーを守り、データをモデル学習に使用しません(", + "zen.faq.a5.exceptionsLink": "以下の例外", + "zen.faq.q6": "支出上限を設定できますか?", + "zen.faq.a6": "はい、アカウントで月次の支出上限を設定できます。", + "zen.faq.q7": "キャンセルできますか?", + "zen.faq.a7": "はい、いつでも請求を無効化し、残りの残高を利用できます。", + "zen.faq.q8": "他のコーディングエージェントでもZenを使えますか?", + "zen.faq.a8": + "ZenはOpenCodeとの相性が良いですが、どのエージェントでもZenを利用できます。お使いのコーディングエージェントのセットアップ手順に従ってください。", + + "zen.cta.start": "Zenをはじめる", + "zen.pricing.title": "$20の従量課金制残高を追加", + "zen.pricing.fee": "(+$1.23 カード処理手数料)", + "zen.pricing.body": + "任意のエージェントと一緒に使用できます。毎月の支出制限を設定できます。いつでもキャンセルできます。", + "zen.problem.title": "Zenはどのような問題を解決していますか?", + "zen.problem.body": + "利用可能なモデルは非常に多くありますが、コーディングエージェントで適切に機能するモデルはほんのわずかです。ほとんどのプロバイダーは、それらを異なる設定で提供し、結果も異なります。", + "zen.problem.subtitle": "OpenCodeユーザーだけでなく、すべての人を対象にこの問題を修正しています。", + "zen.problem.item1": "選択したモデルをテストし、チームに相談する", + "zen.problem.item2": "プロバイダーと連携して適切に提供されるようにする", + "zen.problem.item3": "私たちが推奨するすべてのモデルとプロバイダーの組み合わせをベンチマークする", + "zen.how.title": "Zenの仕組み", + "zen.how.body": "ZenをOpenCodeとともに使用することをお勧めしますが、Zenはどのエージェントでも使用できます。", + "zen.how.step1.title": "サインアップして$20の残高を追加", + "zen.how.step1.beforeLink": "", + "zen.how.step1.link": "セットアップ手順", + "zen.how.step2.title": "透明性のある価格設定でZenを使用する", + "zen.how.step2.link": "リクエストごとに支払う", + "zen.how.step2.afterLink": "(マークアップなし)", + "zen.how.step3.title": "自動チャージ", + "zen.how.step3.body": "残高が$5に達すると、自動的に$20が追加されます", + "zen.privacy.title": "あなたのプライバシーは私たちにとって重要です", + "zen.privacy.beforeExceptions": + "すべてのZenモデルは米国でホストされています。プロバイダーはゼロ保持ポリシーに従い、モデルのトレーニングにデータを使用しません(", + "zen.privacy.exceptionsLink": "以下の例外", + + "black.meta.title": "OpenCode Black | 世界最高峰のコーディングモデルすべてにアクセス", + "black.meta.description": "OpenCode Black サブスクリプションプランで、Claude、GPT、Gemini などにアクセス。", + "black.hero.title": "世界最高峰のコーディングモデルすべてにアクセス", + "black.hero.subtitle": "Claude、GPT、Gemini などを含む", + "black.title": "OpenCode Black | 料金", + "black.plan.icon20": "Black 20 プラン", + "black.plan.icon100": "Black 100 プラン", + "black.plan.icon200": "Black 200 プラン", + "black.plan.multiplier100": "Black 20 の5倍の利用量", + "black.plan.multiplier200": "Black 20 の20倍の利用量", + "black.price.perMonth": "/月", + "black.price.perPersonBilledMonthly": "1人あたり / 月額請求", + "black.terms.1": "サブスクリプションはすぐには開始されません", + "black.terms.2": "ウェイトリストに追加され、まもなく有効化されます", + "black.terms.3": "サブスクリプションが有効化された時点でのみカードに請求されます", + "black.terms.4": "利用制限が適用されます。過度な自動化利用は早く制限に達する可能性があります", + "black.terms.5": "サブスクリプションは個人向けです。チーム利用はエンタープライズにお問い合わせください", + "black.terms.6": "将来的に制限が調整されたり、プランが廃止される可能性があります", + "black.terms.7": "サブスクリプションはいつでもキャンセル可能です", + "black.action.continue": "続ける", + "black.finePrint.beforeTerms": "表示価格には適用される税金は含まれていません", + "black.finePrint.terms": "利用規約", + "black.workspace.title": "OpenCode Black | ワークスペースの選択", + "black.workspace.selectPlan": "このプランのワークスペースを選択してください", + "black.workspace.name": "ワークスペース {{n}}", + "black.subscribe.title": "OpenCode Black を購読する", + "black.subscribe.paymentMethod": "支払い方法", + "black.subscribe.loadingPaymentForm": "支払いフォームを読み込み中...", + "black.subscribe.selectWorkspaceToContinue": "続けるにはワークスペースを選択してください", + "black.subscribe.failurePrefix": "おっと!", + "black.subscribe.error.generic": "エラーが発生しました", + "black.subscribe.error.invalidPlan": "無効なプランです", + "black.subscribe.error.workspaceRequired": "ワークスペースIDが必要です", + "black.subscribe.error.alreadySubscribed": "このワークスペースは既にサブスクリプションを持っています", + "black.subscribe.processing": "処理中...", + "black.subscribe.submit": "購読する ${{plan}}", + "black.subscribe.form.chargeNotice": "サブスクリプションが有効化された時点でのみ請求されます", + "black.subscribe.success.title": "OpenCode Black ウェイトリストに登録されました", + "black.subscribe.success.subscriptionPlan": "サブスクリプションプラン", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "金額", + "black.subscribe.success.amountValue": "${{plan}} / 月", + "black.subscribe.success.paymentMethod": "支払い方法", + "black.subscribe.success.dateJoined": "登録日", + "black.subscribe.success.chargeNotice": "サブスクリプションが有効化された時点でカードに請求されます", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "APIキー", + "workspace.nav.members": "メンバー", + "workspace.nav.billing": "請求", + "workspace.nav.settings": "設定", + + "workspace.home.banner.beforeLink": "コーディングエージェント向けに信頼性の高い最適化されたモデル。", + "workspace.home.billing.loading": "読み込み中...", + "workspace.home.billing.enable": "課金を有効にする", + "workspace.home.billing.currentBalance": "現在の残高", + + "workspace.newUser.feature.tested.title": "テスト・検証済みモデル", + "workspace.newUser.feature.tested.body": + "最高のパフォーマンスを保証するために、コーディングエージェントに特化したモデルのベンチマークとテストを行いました。", + "workspace.newUser.feature.quality.title": "最高品質", + "workspace.newUser.feature.quality.body": + "最適なパフォーマンスを実現するように構成されたモデルにアクセスします。ダウングレードや安価なプロバイダーへのルーティングはありません。", + "workspace.newUser.feature.lockin.title": "ロックインなし", + "workspace.newUser.feature.lockin.body": + "任意のコーディングエージェントでZenを使用でき、必要に応じていつでもOpenCodeを備えた他のプロバイダーを使用し続けることができます。", + "workspace.newUser.copyApiKey": "APIキーをコピー", + "workspace.newUser.copyKey": "キーをコピー", + "workspace.newUser.copied": "コピーしました!", + "workspace.newUser.step.enableBilling": "課金を有効にする", + "workspace.newUser.step.login.before": "実行", + "workspace.newUser.step.login.after": "してOpenCodeを選択", + "workspace.newUser.step.pasteKey": "APIキーを貼り付け", + "workspace.newUser.step.models.before": "OpenCodeを起動し実行", + "workspace.newUser.step.models.after": "してモデルを選択", + + "workspace.models.title": "モデル", + "workspace.models.subtitle.beforeLink": "ワークスペースのメンバーがアクセスできるモデルを管理します。", + "workspace.models.table.model": "モデル", + "workspace.models.table.enabled": "有効", + + "workspace.providers.title": "APIキーの設定", + "workspace.providers.subtitle": "AIプロバイダーの独自のAPIキーを設定します。", + "workspace.providers.placeholder": "{{provider}} APIキーを入力 ({{prefix}}...)", + "workspace.providers.configure": "設定", + "workspace.providers.edit": "編集", + "workspace.providers.delete": "削除", + "workspace.providers.saving": "保存中...", + "workspace.providers.save": "保存", + "workspace.providers.table.provider": "プロバイダー", + "workspace.providers.table.apiKey": "APIキー", + + "workspace.usage.title": "利用履歴", + "workspace.usage.subtitle": "最近のAPIの使用状況とコスト。", + "workspace.usage.empty": "開始するには、最初のAPI呼び出しを行ってください。", + "workspace.usage.table.date": "日付", + "workspace.usage.table.model": "モデル", + "workspace.usage.table.input": "入力", + "workspace.usage.table.output": "出力", + "workspace.usage.table.cost": "コスト", + "workspace.usage.breakdown.input": "入力", + "workspace.usage.breakdown.cacheRead": "キャッシュ読み取り", + "workspace.usage.breakdown.cacheWrite": "キャッシュ書き込み", + "workspace.usage.breakdown.output": "出力", + "workspace.usage.breakdown.reasoning": "推論", + "workspace.usage.subscription": "サブスクリプション (${{amount}})", + + "workspace.cost.title": "コスト", + "workspace.cost.subtitle": "モデルごとの使用料金の内訳。", + "workspace.cost.allModels": "全モデル", + "workspace.cost.allKeys": "すべてのキー", + "workspace.cost.deletedSuffix": "(削除済み)", + "workspace.cost.empty": "選択した期間の使用状況データはありません。", + "workspace.cost.subscriptionShort": "サブ", + + "workspace.keys.title": "APIキー", + "workspace.keys.subtitle": "OpenCodeサービスにアクセスするためのAPIキーを管理します。", + "workspace.keys.create": "APIキーの作成", + "workspace.keys.placeholder": "キー名を入力してください", + "workspace.keys.empty": "OpenCodeゲートウェイAPIキーを作成する", + "workspace.keys.table.name": "名前", + "workspace.keys.table.key": "キー", + "workspace.keys.table.createdBy": "作成者", + "workspace.keys.table.lastUsed": "最終利用", + "workspace.keys.copyApiKey": "APIキーをコピー", + "workspace.keys.delete": "削除", + + "workspace.members.title": "メンバー", + "workspace.members.subtitle": "ワークスペースのメンバーとその権限を管理します。", + "workspace.members.invite": "メンバーを招待", + "workspace.members.inviting": "招待中...", + "workspace.members.beta.beforeLink": "ベータ期間中、チームはワークスペースを無料で利用できます。", + "workspace.members.form.invitee": "招待する人", + "workspace.members.form.emailPlaceholder": "メールアドレスを入力", + "workspace.members.form.role": "ロール", + "workspace.members.form.monthlyLimit": "月間支出上限", + "workspace.members.noLimit": "制限なし", + "workspace.members.noLimitLowercase": "制限なし", + "workspace.members.invited": "招待済み", + "workspace.members.edit": "編集", + "workspace.members.delete": "削除", + "workspace.members.saving": "保存中...", + "workspace.members.save": "保存", + "workspace.members.table.email": "メールアドレス", + "workspace.members.table.role": "ロール", + "workspace.members.table.monthLimit": "月間上限", + "workspace.members.role.admin": "管理者", + "workspace.members.role.adminDescription": "モデル、メンバー、請求を管理できます", + "workspace.members.role.member": "メンバー", + "workspace.members.role.memberDescription": "自分自身のAPIキーのみを生成できます", + + "workspace.settings.title": "設定", + "workspace.settings.subtitle": "ワークスペース名と設定を更新します。", + "workspace.settings.workspaceName": "ワークスペース名", + "workspace.settings.defaultName": "デフォルト", + "workspace.settings.updating": "更新中...", + "workspace.settings.save": "保存", + "workspace.settings.edit": "編集", + + "workspace.billing.title": "請求", + "workspace.billing.subtitle.beforeLink": "支払い方法を管理します。", + "workspace.billing.contactUs": "お問い合わせ", + "workspace.billing.subtitle.afterLink": "ご質問がございましたら。", + "workspace.billing.currentBalance": "現在の残高", + "workspace.billing.add": "$を追加", + "workspace.billing.enterAmount": "金額を入力", + "workspace.billing.loading": "読み込み中...", + "workspace.billing.addAction": "追加", + "workspace.billing.addBalance": "残高を追加", + "workspace.billing.linkedToStripe": "Stripeと連携済み", + "workspace.billing.manage": "管理", + "workspace.billing.enable": "課金を有効にする", + + "workspace.monthlyLimit.title": "月間上限", + "workspace.monthlyLimit.subtitle": "アカウントの月間使用制限を設定します。", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "設定中...", + "workspace.monthlyLimit.set": "設定", + "workspace.monthlyLimit.edit": "上限を編集", + "workspace.monthlyLimit.noLimit": "使用制限は設定されていません。", + "workspace.monthlyLimit.currentUsage.beforeMonth": "現在の使用状況(", + "workspace.monthlyLimit.currentUsage.beforeAmount": ")は $", + + "workspace.reload.title": "自動チャージ", + "workspace.reload.disabled.before": "自動チャージは", + "workspace.reload.disabled.state": "無効", + "workspace.reload.disabled.after": "です。残高が少なくなったときに自動的にチャージするには有効にしてください。", + "workspace.reload.enabled.before": "自動チャージは", + "workspace.reload.enabled.state": "有効", + "workspace.reload.enabled.middle": "チャージします(", + "workspace.reload.processingFee": "手数料", + "workspace.reload.enabled.after": ")。残高が以下に達したとき:", + "workspace.reload.edit": "編集", + "workspace.reload.enable": "有効にする", + "workspace.reload.enableAutoReload": "自動チャージを有効にする", + "workspace.reload.reloadAmount": "チャージ額 $", + "workspace.reload.whenBalanceReaches": "残高が $ に達したとき", + "workspace.reload.saving": "保存中...", + "workspace.reload.save": "保存", + "workspace.reload.failedAt": "チャージ失敗:", + "workspace.reload.reason": "理由:", + "workspace.reload.updatePaymentMethod": "支払い方法を更新して、もう一度お試しください。", + "workspace.reload.retrying": "再試行中...", + "workspace.reload.retry": "再試行", + + "workspace.payments.title": "支払い履歴", + "workspace.payments.subtitle": "最近の支払い取引。", + "workspace.payments.table.date": "日付", + "workspace.payments.table.paymentId": "支払いID", + "workspace.payments.table.amount": "金額", + "workspace.payments.table.receipt": "領収書", + "workspace.payments.type.credit": "クレジット", + "workspace.payments.type.subscription": "サブスクリプション", + "workspace.payments.view": "表示", + + "workspace.black.loading": "読み込み中...", + "workspace.black.time.day": "日", + "workspace.black.time.days": "日", + "workspace.black.time.hour": "時間", + "workspace.black.time.hours": "時間", + "workspace.black.time.minute": "分", + "workspace.black.time.minutes": "分", + "workspace.black.time.fewSeconds": "数秒", + "workspace.black.subscription.title": "サブスクリプション", + "workspace.black.subscription.message": "あなたは OpenCode Black を月額 ${{plan}} で購読しています。", + "workspace.black.subscription.manage": "サブスクリプションの管理", + "workspace.black.subscription.rollingUsage": "5時間利用", + "workspace.black.subscription.weeklyUsage": "週間利用量", + "workspace.black.subscription.resetsIn": "リセットまで", + "workspace.black.subscription.useBalance": "利用限度額に達したら利用可能な残高を使用する", + "workspace.black.waitlist.title": "ウェイトリスト", + "workspace.black.waitlist.joined": + "あなたは月額 ${{plan}} の OpenCode Black プランのウェイトリストに登録されています。", + "workspace.black.waitlist.ready": "月額 ${{plan}} の OpenCode Black プランに登録する準備ができました。", + "workspace.black.waitlist.leave": "ウェイトリストから抜ける", + "workspace.black.waitlist.leaving": "処理中...", + "workspace.black.waitlist.left": "退会済み", + "workspace.black.waitlist.enroll": "登録する", + "workspace.black.waitlist.enrolling": "登録中...", + "workspace.black.waitlist.enrolled": "登録済み", + "workspace.black.waitlist.enrollNote": + "「登録する」をクリックすると、サブスクリプションがすぐに開始され、カードに請求されます。", + + "download.title": "OpenCode | ダウンロード", + "download.meta.description": "OpenCode を macOS、Windows、Linux 向けにダウンロード", + "download.hero.title": "OpenCode をダウンロード", + "download.hero.subtitle": "macOS、Windows、Linux 向けベータ版を利用可能", + "download.hero.button": "{{os}} 向けダウンロード", + "download.section.terminal": "OpenCode Terminal", + "download.section.desktop": "OpenCode Desktop (Beta)", + "download.section.extensions": "OpenCode Extensions", + "download.section.integrations": "OpenCode Integrations", + "download.action.download": "ダウンロード", + "download.action.install": "インストール", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "必ずしもそうではありませんが、おそらく必要です。OpenCodeを有料プロバイダーに接続したい場合はAIサブスクリプションが必要ですが、", + "download.faq.a3.localLink": "ローカルモデル", + "download.faq.a3.afterLocal.beforeZen": "であれば無料で利用できます。ユーザーには", + "download.faq.a3.afterZen": + "の利用をお勧めしていますが、OpenCodeはOpenAI、Anthropic、xAIなどの主要なプロバイダーに対応しています。", + + "download.faq.a5.p1": "OpenCodeは100%無料で利用できます。", + "download.faq.a5.p2.beforeZen": + "追加コストはモデルプロバイダーのサブスクリプションから発生します。OpenCodeはどのモデルプロバイダーでも利用できますが、", + "download.faq.a5.p2.afterZen": "の利用をおすすめします。", + + "download.faq.a6.p1": "あなたのデータと情報は、OpenCodeで共有リンクを作成したときにのみ保存されます。", + "download.faq.a6.p2.beforeShare": "詳しくは", + "download.faq.a6.shareLink": "共有ページ", + + "enterprise.title": "OpenCode | 組織向けエンタープライズソリューション", + "enterprise.meta.description": "エンタープライズソリューションについてOpenCodeに問い合わせる", + "enterprise.hero.title": "あなたのコードはあなたのもの", + "enterprise.hero.body1": + "OpenCodeは、データやコンテキストを一切保存せず、ライセンス制限や所有権の主張もなく、組織内で安全に動作します。チームでのトライアルから始め、SSOや社内AIゲートウェイと統合して組織全体に展開できます。", + "enterprise.hero.body2": "どのような支援ができるか、お聞かせください。", + "enterprise.form.name.label": "氏名", + "enterprise.form.name.placeholder": "ジェフ・ベゾス", + "enterprise.form.role.label": "役職", + "enterprise.form.role.placeholder": "会長", + "enterprise.form.email.label": "会社メールアドレス", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "どのような課題を解決したいですか?", + "enterprise.form.message.placeholder": "これについて支援が必要です...", + "enterprise.form.send": "送信", + "enterprise.form.sending": "送信中...", + "enterprise.form.success": "送信しました。まもなくご連絡いたします。", + "enterprise.faq.title": "FAQ", + "enterprise.faq.q1": "OpenCode Enterpriseとは?", + "enterprise.faq.a1": + "OpenCode Enterpriseは、コードとデータが決してインフラの外に出ないことを保証したい組織向けです。SSOや社内AIゲートウェイと統合する集中設定を使用することでこれを実現します。", + "enterprise.faq.q2": "OpenCode Enterpriseを始めるには?", + "enterprise.faq.a2": + "まずはチームでの社内トライアルから始めてください。OpenCodeはデフォルトでコードやコンテキストデータを保存しないため、簡単に始められます。その後、価格や導入オプションについてお問い合わせください。", + "enterprise.faq.q3": "エンタープライズ価格の仕組みは?", + "enterprise.faq.a3": + "シート単位(ユーザー数)でのエンタープライズ価格を提供します。独自のLLMゲートウェイをお持ちの場合、使用トークンに対する課金はありません。詳細は、組織の要件に基づいた見積もりのためにお問い合わせください。", + "enterprise.faq.q4": "OpenCode Enterpriseでデータは安全ですか?", + "enterprise.faq.a4": + "はい。OpenCodeはコードやコンテキストデータを保存しません。すべての処理はローカル、またはAIプロバイダーへの直接API呼び出しを通じて行われます。集中設定とSSO統合により、データは組織のインフラ内で安全に保たれます。", + + "brand.title": "OpenCode | ブランド", + "brand.meta.description": "OpenCode ブランドガイドライン", + "brand.heading": "ブランドガイドライン", + "brand.subtitle": "OpenCodeブランドを扱うためのリソースと素材です。", + "brand.downloadAll": "すべての素材をダウンロード", + + "changelog.title": "OpenCode | 変更履歴", + "changelog.meta.description": "OpenCode リリースノートと変更履歴", + "changelog.hero.title": "変更履歴", + "changelog.hero.subtitle": "OpenCodeの新しいアップデートと改善", + "changelog.empty": "変更履歴が見つかりませんでした。", + "changelog.viewJson": "JSONを表示", + + "bench.list.title": "ベンチマーク", + "bench.list.heading": "ベンチマーク", + "bench.list.table.agent": "エージェント", + "bench.list.table.model": "モデル", + "bench.list.table.score": "スコア", + + "bench.detail.title": "ベンチマーク - {{task}}", + "bench.detail.notFound": "タスクが見つかりません", + "bench.detail.na": "N/A", + "bench.detail.labels.agent": "エージェント", + "bench.detail.labels.model": "モデル", + "bench.detail.labels.task": "タスク", + "bench.detail.labels.repo": "リポジトリ", + "bench.detail.labels.from": "From", + "bench.detail.labels.to": "To", + "bench.detail.labels.prompt": "プロンプト", + "bench.detail.labels.commit": "コミット", + "bench.detail.labels.averageDuration": "平均所要時間", + "bench.detail.labels.averageScore": "平均スコア", + "bench.detail.labels.averageCost": "平均コスト", + "bench.detail.labels.summary": "概要", + "bench.detail.labels.runs": "実行回数", + "bench.detail.labels.score": "スコア", + "bench.detail.labels.base": "ベース", + "bench.detail.labels.penalty": "ペナルティ", + "bench.detail.labels.weight": "重み", + "bench.detail.table.run": "実行", + "bench.detail.table.score": "スコア (ベース - ペナルティ)", + "bench.detail.table.cost": "コスト", + "bench.detail.table.duration": "所要時間", + "bench.detail.run.title": "実行 {{n}}", + "bench.detail.rawJson": "Raw JSON", +} satisfies Dict diff --git a/packages/console/app/src/i18n/ko.ts b/packages/console/app/src/i18n/ko.ts new file mode 100644 index 00000000000..984dbbe67b0 --- /dev/null +++ b/packages/console/app/src/i18n/ko.ts @@ -0,0 +1,589 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "문서", + "nav.changelog": "변경 내역", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "엔터프라이즈", + "nav.zen": "Zen", + "nav.login": "로그인", + "nav.free": "무료", + "nav.home": "홈", + "nav.openMenu": "메뉴 열기", + "nav.getStartedFree": "무료로 시작하기", + + "nav.context.copyLogo": "로고를 SVG로 복사", + "nav.context.copyWordmark": "워드마크를 SVG로 복사", + "nav.context.brandAssets": "브랜드 자산", + + "footer.github": "GitHub", + "footer.docs": "문서", + "footer.changelog": "변경 내역", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "브랜드", + "legal.privacy": "개인정보처리방침", + "legal.terms": "이용약관", + + "email.title": "새로운 제품 출시 소식을 가장 먼저 받아보세요", + "email.subtitle": "대기 명단에 등록하여 조기 이용 권한을 받으세요.", + "email.placeholder": "이메일 주소", + "email.subscribe": "구독", + "email.success": "거의 완료되었습니다. 이메일 수신함을 확인하고 주소를 인증해주세요.", + + "notFound.title": "페이지를 찾을 수 없음 | OpenCode", + "notFound.heading": "404 - 페이지를 찾을 수 없음", + "notFound.home": "홈", + "notFound.docs": "문서", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "로그아웃", + + "workspace.select": "워크스페이스 선택", + "workspace.createNew": "+ 새 워크스페이스 만들기", + "workspace.modal.title": "새 워크스페이스 만들기", + "workspace.modal.placeholder": "워크스페이스 이름 입력", + + "common.cancel": "취소", + "common.creating": "생성 중...", + "common.create": "만들기", + + "common.videoUnsupported": "브라우저가 비디오 태그를 지원하지 않습니다.", + "common.figure": "그림 {{n}}.", + "common.faq": "FAQ", + "common.learnMore": "더 알아보기", + + "error.invalidPlan": "유효하지 않은 플랜", + "error.workspaceRequired": "워크스페이스 ID가 필요합니다", + "error.alreadySubscribed": "이 워크스페이스는 이미 구독 중입니다", + "error.limitRequired": "한도가 필요합니다.", + "error.monthlyLimitInvalid": "유효한 월 한도를 설정하세요.", + "error.workspaceNameRequired": "워크스페이스 이름이 필요합니다.", + "error.nameTooLong": "이름은 255자 이하여야 합니다.", + "error.emailRequired": "이메일이 필요합니다", + "error.roleRequired": "역할이 필요합니다", + "error.idRequired": "ID가 필요합니다", + "error.nameRequired": "이름이 필요합니다", + "error.providerRequired": "제공자가 필요합니다", + "error.apiKeyRequired": "API 키가 필요합니다", + "error.modelRequired": "모델이 필요합니다", + "error.reloadAmountMin": "충전 금액은 최소 ${{amount}}이어야 합니다", + "error.reloadTriggerMin": "잔액 트리거는 최소 ${{amount}}이어야 합니다", + + "home.title": "OpenCode | 오픈 소스 AI 코딩 에이전트", + + "temp.title": "OpenCode | 터미널을 위해 만들어진 AI 코딩 에이전트", + "temp.hero.title": "터미널을 위해 만들어진 AI 코딩 에이전트", + "temp.zen": "OpenCode Zen", + "temp.getStarted": "시작하기", + "temp.feature.native.title": "네이티브 TUI", + "temp.feature.native.body": "반응형, 네이티브, 테마 적용 가능한 터미널 UI", + "temp.feature.zen.beforeLink": "OpenCode가 제공하는", + "temp.feature.zen.link": "엄선된 모델 목록", + "temp.feature.zen.afterLink": "", + "temp.feature.models.beforeLink": "로컬 모델을 포함하여", + "temp.feature.models.afterLink": "를 통해 75개 이상의 LLM 제공자 지원", + "temp.screenshot.caption": "tokyonight 테마가 적용된 OpenCode TUI", + "temp.screenshot.alt": "tokyonight 테마가 적용된 OpenCode TUI", + + "home.banner.badge": "신규", + "home.banner.text": "데스크톱 앱 베타 버전 출시", + "home.banner.platforms": "macOS, Windows, Linux 지원", + "home.banner.downloadNow": "지금 다운로드", + "home.banner.downloadBetaNow": "데스크톱 베타 다운로드", + + "home.hero.title": "오픈 소스 AI 코딩 에이전트", + "home.hero.subtitle.a": "무료 모델이 포함되어 있으며, 어떤 제공자의 모델이든 연결 가능합니다.", + "home.hero.subtitle.b": "Claude, GPT, Gemini 등을 포함합니다.", + + "home.install.ariaLabel": "설치 옵션", + + "home.what.title": "OpenCode란 무엇인가요?", + "home.what.body": + "OpenCode는 터미널, IDE, 또는 데스크톱에서 코드를 작성할 수 있도록 도와주는 오픈 소스 에이전트입니다.", + "home.what.lsp.title": "LSP 지원", + "home.what.lsp.body": "LLM에 적합한 LSP를 자동으로 로드합니다", + "home.what.multiSession.title": "멀티 세션", + "home.what.multiSession.body": "동일한 프로젝트에서 여러 에이전트를 병렬로 실행하세요", + "home.what.shareLinks.title": "링크 공유", + "home.what.shareLinks.body": "참조나 디버깅을 위해 세션 링크를 공유하세요", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "GitHub로 로그인하여 Copilot 계정을 사용하세요", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "OpenAI로 로그인하여 ChatGPT Plus 또는 Pro 계정을 사용하세요", + "home.what.anyModel.title": "모든 모델", + "home.what.anyModel.body": "Models.dev를 통해 로컬 모델 포함 75개 이상의 LLM 제공자 지원", + "home.what.anyEditor.title": "모든 에디터", + "home.what.anyEditor.body": "터미널 인터페이스, 데스크톱 앱, IDE 확장 프로그램으로 사용 가능", + "home.what.readDocs": "문서 읽기", + + "home.growth.title": "오픈 소스 AI 코딩 에이전트", + "home.growth.body": + "{{stars}}개 이상의 GitHub 스타, {{contributors}}명의 기여자, {{commits}}개 이상의 커밋과 함께, OpenCode는 매달 {{monthlyUsers}}명 이상의 개발자가 사용하고 신뢰합니다.", + "home.growth.githubStars": "GitHub 스타", + "home.growth.contributors": "기여자", + "home.growth.monthlyDevs": "월간 사용자", + + "home.privacy.title": "프라이버시를 최우선으로 설계", + "home.privacy.body": + "OpenCode는 코드나 컨텍스트 데이터를 저장하지 않으므로, 프라이버시에 민감한 환경에서도 안전하게 작동합니다.", + "home.privacy.learnMore": "더 알아보기:", + "home.privacy.link": "프라이버시", + + "home.faq.q1": "OpenCode란 무엇인가요?", + "home.faq.a1": + "OpenCode는 어떤 AI 모델로든 코드를 작성하고 실행할 수 있도록 도와주는 오픈 소스 에이전트입니다. 터미널 기반 인터페이스, 데스크톱 앱, 또는 IDE 확장 프로그램으로 사용할 수 있습니다.", + "home.faq.q2": "OpenCode는 어떻게 사용하나요?", + "home.faq.a2.before": "가장 쉬운 시작 방법은", + "home.faq.a2.link": "소개", + "home.faq.q3": "OpenCode를 사용하려면 별도의 AI 구독이 필요한가요?", + "home.faq.a3.p1": "꼭 그렇지는 않습니다. OpenCode에는 계정 없이도 사용할 수 있는 무료 모델 세트가 포함되어 있습니다.", + "home.faq.a3.p2.beforeZen": "이 외에도,", + "home.faq.a3.p2.afterZen": " 계정을 생성하여 인기 있는 코딩 모델들을 사용할 수 있습니다.", + "home.faq.a3.p3": "Zen 사용을 권장하지만, OpenCode는 OpenAI, Anthropic, xAI 등 모든 인기 제공자와도 작동합니다.", + "home.faq.a3.p4.beforeLocal": "또한", + "home.faq.a3.p4.localLink": "로컬 모델", + "home.faq.q4": "기존 AI 구독을 OpenCode에서 사용할 수 있나요?", + "home.faq.a4.p1": + "네, OpenCode는 모든 주요 제공자의 구독 플랜을 지원합니다. Claude Pro/Max, ChatGPT Plus/Pro, 또는 GitHub Copilot 구독을 사용할 수 있습니다.", + "home.faq.q5": "OpenCode는 터미널에서만 사용할 수 있나요?", + "home.faq.a5.beforeDesktop": "이제 아닙니다! OpenCode는 이제", + "home.faq.a5.desktop": "데스크톱", + "home.faq.a5.and": "및", + "home.faq.a5.web": "웹", + "home.faq.q6": "OpenCode 비용은 얼마인가요?", + "home.faq.a6": + "OpenCode는 100% 무료로 사용할 수 있습니다. 무료 모델 세트도 포함되어 있습니다. 다른 제공자를 연결할 경우 추가 비용이 발생할 수 있습니다.", + "home.faq.q7": "데이터와 프라이버시는 어떤가요?", + "home.faq.a7.p1": "데이터와 정보는 무료 모델을 사용하거나 공유 링크를 생성할 때만 저장됩니다.", + "home.faq.a7.p2.beforeModels": "더 알아보기:", + "home.faq.a7.p2.modelsLink": "모델", + "home.faq.a7.p2.and": "및", + "home.faq.a7.p2.shareLink": "공유 페이지", + "home.faq.q8": "OpenCode는 오픈 소스인가요?", + "home.faq.a8.p1": "네, OpenCode는 완전히 오픈 소스입니다. 소스 코드는", + "home.faq.a8.p2": "에 공개되어 있으며,", + "home.faq.a8.mitLicense": "MIT 라이선스", + "home.faq.a8.p3": + "를 따릅니다. 즉, 누구나 사용, 수정 또는 개발에 기여할 수 있습니다. 커뮤니티의 누구든지 이슈를 등록하고, 풀 리퀘스트를 제출하고, 기능을 확장할 수 있습니다.", + + "home.zenCta.title": "코딩 에이전트를 위한 신뢰할 수 있고 최적화된 모델", + "home.zenCta.body": + "Zen은 OpenCode가 코딩 에이전트를 위해 특별히 테스트하고 벤치마킹한 엄선된 AI 모델 세트에 대한 액세스를 제공합니다. 제공자 간의 일관되지 않은 성능과 품질에 대해 걱정할 필요 없이, 검증된 모델을 사용하세요.", + "home.zenCta.link": "Zen 알아보기", + + "zen.title": "OpenCode Zen | 코딩 에이전트를 위한 신뢰할 수 있고 최적화된 모델 세트", + "zen.hero.title": "코딩 에이전트를 위한 신뢰할 수 있고 최적화된 모델", + "zen.hero.body": + "Zen은 OpenCode가 코딩 에이전트를 위해 특별히 테스트하고 벤치마킹한 엄선된 AI 모델 세트에 대한 액세스를 제공합니다. 일관되지 않은 성능과 품질에 대해 걱정할 필요 없이, 검증된 모델을 사용하세요.", + + "zen.faq.q1": "OpenCode Zen이란 무엇인가요?", + "zen.faq.a1": "Zen은 OpenCode 팀이 코딩 에이전트를 위해 테스트하고 벤치마킹한 엄선된 AI 모델 세트입니다.", + "zen.faq.q2": "Zen은 왜 더 정확한가요?", + "zen.faq.a2": + "Zen은 코딩 에이전트를 위해 특별히 테스트되고 벤치마킹된 모델만 제공합니다. 스테이크를 버터 나이프로 자르지 않듯이, 코딩에 품질이 낮은 모델을 사용하지 마세요.", + "zen.faq.q3": "Zen이 더 저렴한가요?", + "zen.faq.a3": + "Zen은 영리를 목적으로 하지 않습니다. Zen은 모델 제공자의 비용을 사용자에게 그대로 전달합니다. Zen 사용량이 늘어날수록 OpenCode는 더 좋은 요율을 협상하여 그 혜택을 사용자에게 돌려드릴 수 있습니다.", + "zen.faq.q4": "Zen 비용은 얼마인가요?", + "zen.faq.a4.p1.beforePricing": "Zen은", + "zen.faq.a4.p1.pricingLink": "요청당 비용을 청구하며", + "zen.faq.a4.p1.afterPricing": ", 마크업이 0이므로 모델 제공자가 청구하는 금액 그대로 지불하게 됩니다.", + "zen.faq.a4.p2.beforeAccount": "총 비용은 사용량에 따라 달라지며, 월간 지출 한도를", + "zen.faq.a4.p2.accountLink": "계정", + "zen.faq.a4.p3": "비용을 충당하기 위해 OpenCode는 $20 잔액 충전 시 $1.23의 소액 결제 처리 수수료만 추가합니다.", + "zen.faq.q5": "데이터와 프라이버시는 어떤가요?", + "zen.faq.a5.beforeExceptions": + "모든 Zen 모델은 미국에서 호스팅됩니다. 제공자들은 데이터 보존 금지(zero-retention) 정책을 따르며, 모델 학습에 귀하의 데이터를 사용하지 않습니다. 단,", + "zen.faq.a5.exceptionsLink": "다음 예외", + "zen.faq.q6": "지출 한도를 설정할 수 있나요?", + "zen.faq.a6": "네, 계정에서 월간 지출 한도를 설정할 수 있습니다.", + "zen.faq.q7": "취소할 수 있나요?", + "zen.faq.a7": "네, 언제든지 결제를 비활성화하고 남은 잔액을 사용할 수 있습니다.", + "zen.faq.q8": "다른 코딩 에이전트와 Zen을 사용할 수 있나요?", + "zen.faq.a8": + "Zen은 OpenCode와 훌륭하게 작동하지만, 어떤 에이전트와도 Zen을 사용할 수 있습니다. 선호하는 코딩 에이전트의 설정 지침을 따르세요.", + + "zen.cta.start": "Zen 시작하기", + "zen.pricing.title": "$20 선불 잔액 추가", + "zen.pricing.fee": "(+$1.23 카드 처리 수수료)", + "zen.pricing.body": "모든 에이전트와 함께 사용하세요. 월간 지출 한도 설정 가능. 언제든지 취소 가능.", + "zen.problem.title": "Zen은 어떤 문제를 해결하나요?", + "zen.problem.body": + "사용 가능한 모델은 매우 많지만, 코딩 에이전트와 잘 작동하는 모델은 소수에 불과합니다. 대부분의 제공자들은 모델을 다르게 구성하여 결과가 제각각입니다.", + "zen.problem.subtitle": "우리는 OpenCode 사용자뿐만 아니라 모든 분들을 위해 이 문제를 해결하고 있습니다.", + "zen.problem.item1": "선별된 모델 테스트 및 팀 자문", + "zen.problem.item2": "제공자와 협력하여 올바른 모델 전달 보장", + "zen.problem.item3": "권장하는 모든 모델-제공자 조합 벤치마킹", + "zen.how.title": "Zen 작동 방식", + "zen.how.body": "OpenCode와 함께 사용하는 것을 권장하지만, Zen은 어떤 에이전트와도 사용할 수 있습니다.", + "zen.how.step1.title": "가입 및 $20 잔액 추가", + "zen.how.step1.beforeLink": "", + "zen.how.step1.link": "설정 지침", + "zen.how.step2.title": "투명한 가격으로 Zen 사용", + "zen.how.step2.link": "요청당 지불", + "zen.how.step2.afterLink": "(마크업 0)", + "zen.how.step3.title": "자동 충전", + "zen.how.step3.body": "잔액이 $5에 도달하면 자동으로 $20가 충전됩니다", + "zen.privacy.title": "귀하의 프라이버시는 우리에게 중요합니다", + "zen.privacy.beforeExceptions": + "모든 Zen 모델은 미국에서 호스팅됩니다. 제공자들은 데이터 보존 금지 정책을 따르며 모델 학습에 데이터를 사용하지 않습니다. 단,", + "zen.privacy.exceptionsLink": "다음 예외", + + "black.meta.title": "OpenCode Black | 세계 최고의 코딩 모델에 액세스하세요", + "black.meta.description": "OpenCode Black 구독 플랜으로 Claude, GPT, Gemini 등에 액세스하세요.", + "black.hero.title": "세계 최고의 코딩 모델에 액세스하세요", + "black.hero.subtitle": "Claude, GPT, Gemini 등 포함", + "black.title": "OpenCode Black | 가격", + "black.plan.icon20": "Black 20 플랜", + "black.plan.icon100": "Black 100 플랜", + "black.plan.icon200": "Black 200 플랜", + "black.plan.multiplier100": "Black 20보다 5배 더 많은 사용량", + "black.plan.multiplier200": "Black 20보다 20배 더 많은 사용량", + "black.price.perMonth": "월", + "black.price.perPersonBilledMonthly": "인당 / 월 청구", + "black.terms.1": "구독이 즉시 시작되지 않습니다", + "black.terms.2": "대기 명단에 추가되며 곧 활성화됩니다", + "black.terms.3": "구독이 활성화될 때만 카드가 청구됩니다", + "black.terms.4": "사용량 제한이 적용되며, 과도한 자동화 사용 시 제한에 더 빨리 도달할 수 있습니다", + "black.terms.5": "구독은 개인용이며, 팀용은 엔터프라이즈에 문의하세요", + "black.terms.6": "향후 제한이 조정되거나 플랜이 중단될 수 있습니다", + "black.terms.7": "언제든지 구독을 취소할 수 있습니다", + "black.action.continue": "계속", + "black.finePrint.beforeTerms": "표시된 가격에는 해당 세금이 포함되어 있지 않습니다", + "black.finePrint.terms": "서비스 약관", + "black.workspace.title": "OpenCode Black | 워크스페이스 선택", + "black.workspace.selectPlan": "이 플랜을 사용할 워크스페이스를 선택하세요", + "black.workspace.name": "워크스페이스 {{n}}", + "black.subscribe.title": "OpenCode Black 구독하기", + "black.subscribe.paymentMethod": "결제 수단", + "black.subscribe.loadingPaymentForm": "결제 양식 로드 중...", + "black.subscribe.selectWorkspaceToContinue": "계속하려면 워크스페이스를 선택하세요", + "black.subscribe.failurePrefix": "이런!", + "black.subscribe.error.generic": "오류가 발생했습니다", + "black.subscribe.error.invalidPlan": "유효하지 않은 플랜", + "black.subscribe.error.workspaceRequired": "워크스페이스 ID가 필요합니다", + "black.subscribe.error.alreadySubscribed": "이 워크스페이스는 이미 구독 중입니다", + "black.subscribe.processing": "처리 중...", + "black.subscribe.submit": "${{plan}} 구독하기", + "black.subscribe.form.chargeNotice": "구독이 활성화될 때만 청구됩니다", + "black.subscribe.success.title": "OpenCode Black 대기 명단에 등록되었습니다", + "black.subscribe.success.subscriptionPlan": "구독 플랜", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "금액", + "black.subscribe.success.amountValue": "월 ${{plan}}", + "black.subscribe.success.paymentMethod": "결제 수단", + "black.subscribe.success.dateJoined": "가입일", + "black.subscribe.success.chargeNotice": "구독이 활성화되면 카드에 청구됩니다", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "API 키", + "workspace.nav.members": "멤버", + "workspace.nav.billing": "결제", + "workspace.nav.settings": "설정", + + "workspace.home.banner.beforeLink": "코딩 에이전트를 위한 신뢰할 수 있고 최적화된 모델.", + "workspace.home.billing.loading": "로드 중...", + "workspace.home.billing.enable": "결제 활성화", + "workspace.home.billing.currentBalance": "현재 잔액", + + "workspace.newUser.feature.tested.title": "테스트 및 검증된 모델", + "workspace.newUser.feature.tested.body": + "최고의 성능을 보장하기 위해 코딩 에이전트용 모델을 구체적으로 벤치마킹하고 테스트했습니다.", + "workspace.newUser.feature.quality.title": "최고 품질", + "workspace.newUser.feature.quality.body": + "최적의 성능을 위해 구성된 모델에 액세스하세요 - 다운그레이드나 저렴한 제공자로 라우팅되지 않습니다.", + "workspace.newUser.feature.lockin.title": "락인(Lock-in) 없음", + "workspace.newUser.feature.lockin.body": + "Zen을 어떤 코딩 에이전트와도 함께 사용할 수 있으며, 원할 때 언제든지 OpenCode와 함께 다른 제공자를 계속 사용할 수 있습니다.", + "workspace.newUser.copyApiKey": "API 키 복사", + "workspace.newUser.copyKey": "키 복사", + "workspace.newUser.copied": "복사됨!", + "workspace.newUser.step.enableBilling": "결제 활성화", + "workspace.newUser.step.login.before": "실행", + "workspace.newUser.step.login.after": "후 OpenCode 선택", + "workspace.newUser.step.pasteKey": "API 키 붙여넣기", + "workspace.newUser.step.models.before": "OpenCode를 시작하고 실행", + "workspace.newUser.step.models.after": "하여 모델 선택", + + "workspace.models.title": "모델", + "workspace.models.subtitle.beforeLink": "워크스페이스 멤버가 액세스할 수 있는 모델을 관리합니다.", + "workspace.models.table.model": "모델", + "workspace.models.table.enabled": "활성화됨", + + "workspace.providers.title": "나만의 키 가져오기 (BYOK)", + "workspace.providers.subtitle": "AI 제공자의 자체 API 키를 구성하세요.", + "workspace.providers.placeholder": "{{provider}} API 키 입력 ({{prefix}}...)", + "workspace.providers.configure": "구성", + "workspace.providers.edit": "편집", + "workspace.providers.delete": "삭제", + "workspace.providers.saving": "저장 중...", + "workspace.providers.save": "저장", + "workspace.providers.table.provider": "제공자", + "workspace.providers.table.apiKey": "API 키", + + "workspace.usage.title": "사용 내역", + "workspace.usage.subtitle": "최근 API 사용량 및 비용.", + "workspace.usage.empty": "시작하려면 첫 API 호출을 해보세요.", + "workspace.usage.table.date": "날짜", + "workspace.usage.table.model": "모델", + "workspace.usage.table.input": "입력", + "workspace.usage.table.output": "출력", + "workspace.usage.table.cost": "비용", + "workspace.usage.breakdown.input": "입력", + "workspace.usage.breakdown.cacheRead": "캐시 읽기", + "workspace.usage.breakdown.cacheWrite": "캐시 쓰기", + "workspace.usage.breakdown.output": "출력", + "workspace.usage.breakdown.reasoning": "추론", + "workspace.usage.subscription": "구독 (${{amount}})", + + "workspace.cost.title": "비용", + "workspace.cost.subtitle": "모델별 사용 비용 내역.", + "workspace.cost.allModels": "모든 모델", + "workspace.cost.allKeys": "모든 키", + "workspace.cost.deletedSuffix": "(삭제됨)", + "workspace.cost.empty": "선택한 기간에 사용 데이터가 없습니다.", + "workspace.cost.subscriptionShort": "구독", + + "workspace.keys.title": "API 키", + "workspace.keys.subtitle": "OpenCode 서비스 액세스를 위한 API 키를 관리하세요.", + "workspace.keys.create": "API 키 생성", + "workspace.keys.placeholder": "키 이름 입력", + "workspace.keys.empty": "OpenCode 게이트웨이 API 키 생성", + "workspace.keys.table.name": "이름", + "workspace.keys.table.key": "키", + "workspace.keys.table.createdBy": "생성자", + "workspace.keys.table.lastUsed": "마지막 사용", + "workspace.keys.copyApiKey": "API 키 복사", + "workspace.keys.delete": "삭제", + + "workspace.members.title": "멤버", + "workspace.members.subtitle": "워크스페이스 멤버 및 권한을 관리합니다.", + "workspace.members.invite": "멤버 초대", + "workspace.members.inviting": "초대 중...", + "workspace.members.beta.beforeLink": "베타 기간 동안 팀 워크스페이스는 무료입니다.", + "workspace.members.form.invitee": "초대받는 사람", + "workspace.members.form.emailPlaceholder": "이메일 입력", + "workspace.members.form.role": "역할", + "workspace.members.form.monthlyLimit": "월간 지출 한도", + "workspace.members.noLimit": "제한 없음", + "workspace.members.noLimitLowercase": "제한 없음", + "workspace.members.invited": "초대됨", + "workspace.members.edit": "편집", + "workspace.members.delete": "삭제", + "workspace.members.saving": "저장 중...", + "workspace.members.save": "저장", + "workspace.members.table.email": "이메일", + "workspace.members.table.role": "역할", + "workspace.members.table.monthLimit": "월 한도", + "workspace.members.role.admin": "관리자", + "workspace.members.role.adminDescription": "모델, 멤버, 결제 관리 가능", + "workspace.members.role.member": "멤버", + "workspace.members.role.memberDescription": "자신의 API 키만 생성 가능", + + "workspace.settings.title": "설정", + "workspace.settings.subtitle": "워크스페이스 이름과 환경설정을 업데이트하세요.", + "workspace.settings.workspaceName": "워크스페이스 이름", + "workspace.settings.defaultName": "기본", + "workspace.settings.updating": "업데이트 중...", + "workspace.settings.save": "저장", + "workspace.settings.edit": "편집", + + "workspace.billing.title": "결제", + "workspace.billing.subtitle.beforeLink": "결제 수단을 관리하세요.", + "workspace.billing.contactUs": "문의하기", + "workspace.billing.subtitle.afterLink": "질문이 있으시면 언제든 연락주세요.", + "workspace.billing.currentBalance": "현재 잔액", + "workspace.billing.add": "추가 $", + "workspace.billing.enterAmount": "금액 입력", + "workspace.billing.loading": "로드 중...", + "workspace.billing.addAction": "추가", + "workspace.billing.addBalance": "잔액 추가", + "workspace.billing.linkedToStripe": "Stripe에 연결됨", + "workspace.billing.manage": "관리", + "workspace.billing.enable": "결제 활성화", + + "workspace.monthlyLimit.title": "월 한도", + "workspace.monthlyLimit.subtitle": "계정의 월간 사용 한도를 설정하세요.", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "설정 중...", + "workspace.monthlyLimit.set": "설정", + "workspace.monthlyLimit.edit": "한도 편집", + "workspace.monthlyLimit.noLimit": "사용 한도가 설정되지 않았습니다.", + "workspace.monthlyLimit.currentUsage.beforeMonth": "현재", + "workspace.monthlyLimit.currentUsage.beforeAmount": "사용량: $", + + "workspace.reload.title": "자동 충전", + "workspace.reload.disabled.before": "자동 충전이", + "workspace.reload.disabled.state": "비활성화", + "workspace.reload.disabled.after": "되었습니다. 잔액이 부족할 때 자동으로 충전하려면 활성화하세요.", + "workspace.reload.enabled.before": "자동 충전이", + "workspace.reload.enabled.state": "활성화", + "workspace.reload.enabled.middle": "되었습니다. 잔액이", + "workspace.reload.processingFee": "처리 수수료", + "workspace.reload.enabled.after": "에 도달하면 충전합니다.", + "workspace.reload.edit": "편집", + "workspace.reload.enable": "활성화", + "workspace.reload.enableAutoReload": "자동 충전 활성화", + "workspace.reload.reloadAmount": "충전 금액 $", + "workspace.reload.whenBalanceReaches": "잔액이 다음 금액에 도달할 때 $", + "workspace.reload.saving": "저장 중...", + "workspace.reload.save": "저장", + "workspace.reload.failedAt": "충전 실패 시간:", + "workspace.reload.reason": "사유:", + "workspace.reload.updatePaymentMethod": "결제 수단을 업데이트하고 다시 시도해 주세요.", + "workspace.reload.retrying": "재시도 중...", + "workspace.reload.retry": "재시도", + + "workspace.payments.title": "결제 내역", + "workspace.payments.subtitle": "최근 결제 거래 내역입니다.", + "workspace.payments.table.date": "날짜", + "workspace.payments.table.paymentId": "결제 ID", + "workspace.payments.table.amount": "금액", + "workspace.payments.table.receipt": "영수증", + "workspace.payments.type.credit": "크레딧", + "workspace.payments.type.subscription": "구독", + "workspace.payments.view": "보기", + + "workspace.black.loading": "로드 중...", + "workspace.black.time.day": "일", + "workspace.black.time.days": "일", + "workspace.black.time.hour": "시간", + "workspace.black.time.hours": "시간", + "workspace.black.time.minute": "분", + "workspace.black.time.minutes": "분", + "workspace.black.time.fewSeconds": "몇 초", + "workspace.black.subscription.title": "구독", + "workspace.black.subscription.message": "현재 월 ${{plan}} OpenCode Black 플랜을 구독 중입니다.", + "workspace.black.subscription.manage": "구독 관리", + "workspace.black.subscription.rollingUsage": "5시간 사용량", + "workspace.black.subscription.weeklyUsage": "주간 사용량", + "workspace.black.subscription.resetsIn": "초기화까지 남은 시간:", + "workspace.black.subscription.useBalance": "사용 한도 도달 후에는 보유 잔액 사용", + "workspace.black.waitlist.title": "대기 명단", + "workspace.black.waitlist.joined": "월 ${{plan}} OpenCode Black 플랜 대기 명단에 등록되었습니다.", + "workspace.black.waitlist.ready": "월 ${{plan}} OpenCode Black 플랜에 등록할 준비가 되었습니다.", + "workspace.black.waitlist.leave": "대기 명단에서 나가기", + "workspace.black.waitlist.leaving": "나가는 중...", + "workspace.black.waitlist.left": "나감", + "workspace.black.waitlist.enroll": "등록", + "workspace.black.waitlist.enrolling": "등록 중...", + "workspace.black.waitlist.enrolled": "등록됨", + "workspace.black.waitlist.enrollNote": "등록을 클릭하면 구독이 즉시 시작되며 카드에 요금이 청구됩니다.", + + "download.title": "OpenCode | 다운로드", + "download.meta.description": "macOS, Windows, Linux용 OpenCode 다운로드", + "download.hero.title": "OpenCode 다운로드", + "download.hero.subtitle": "macOS, Windows, Linux용 베타 버전 사용 가능", + "download.hero.button": "{{os}}용 다운로드", + "download.section.terminal": "OpenCode 터미널", + "download.section.desktop": "OpenCode 데스크톱 (베타)", + "download.section.extensions": "OpenCode 확장 프로그램", + "download.section.integrations": "OpenCode 통합", + "download.action.download": "다운로드", + "download.action.install": "설치", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "꼭 그렇지는 않지만, 아마도 필요할 것입니다. OpenCode를 유료 제공자에 연결하려면 AI 구독이 필요할 수 있습니다. 하지만", + "download.faq.a3.localLink": "로컬 모델", + "download.faq.a3.afterLocal.beforeZen": "은 무료로 사용할 수 있습니다. 우리는", + "download.faq.a3.afterZen": " 사용을 권장하지만, OpenCode는 OpenAI, Anthropic, xAI 등 모든 인기 제공자와 작동합니다.", + + "download.faq.a5.p1": "OpenCode는 100% 무료로 사용할 수 있습니다.", + "download.faq.a5.p2.beforeZen": + "추가 비용은 모델 제공자 구독에서 발생합니다. OpenCode는 모든 모델 제공자와 작동하지만, 우리는", + "download.faq.a5.p2.afterZen": " 사용을 권장합니다.", + + "download.faq.a6.p1": "데이터와 정보는 OpenCode에서 공유 링크를 생성할 때만 저장됩니다.", + "download.faq.a6.p2.beforeShare": "더 알아보기:", + "download.faq.a6.shareLink": "공유 페이지", + + "enterprise.title": "OpenCode | 조직을 위한 엔터프라이즈 솔루션", + "enterprise.meta.description": "OpenCode 엔터프라이즈 솔루션 문의", + "enterprise.hero.title": "여러분의 코드는 여러분의 것입니다", + "enterprise.hero.body1": + "OpenCode는 조직 내부에서 안전하게 작동하며, 데이터나 컨텍스트를 저장하지 않고 라이선스 제한이나 소유권 주장도 없습니다. 팀과 함께 트라이얼을 시작한 후, SSO 및 내부 AI 게이트웨이와 통합하여 조직 전체에 배포하세요.", + "enterprise.hero.body2": "어떻게 도와드릴 수 있는지 알려주세요.", + "enterprise.form.name.label": "이름", + "enterprise.form.name.placeholder": "홍길동", + "enterprise.form.role.label": "직책", + "enterprise.form.role.placeholder": "CTO / 개발 팀장", + "enterprise.form.email.label": "회사 이메일", + "enterprise.form.email.placeholder": "name@company.com", + "enterprise.form.message.label": "어떤 문제를 해결하고 싶으신가요?", + "enterprise.form.message.placeholder": "도움이 필요한 부분은...", + "enterprise.form.send": "전송", + "enterprise.form.sending": "전송 중...", + "enterprise.form.success": "메시지가 전송되었습니다. 곧 연락드리겠습니다.", + "enterprise.faq.title": "FAQ", + "enterprise.faq.q1": "OpenCode 엔터프라이즈란 무엇인가요?", + "enterprise.faq.a1": + "OpenCode 엔터프라이즈는 코드와 데이터가 인프라 외부로 유출되지 않도록 보장하려는 조직을 위한 솔루션입니다. SSO 및 내부 AI 게이트웨이와 통합되는 중앙 집중식 설정을 통해 이를 구현합니다.", + "enterprise.faq.q2": "OpenCode 엔터프라이즈는 어떻게 시작하나요?", + "enterprise.faq.a2": + "팀과 함께 내부 트라이얼로 간단히 시작해보세요. OpenCode는 기본적으로 코드나 컨텍스트 데이터를 저장하지 않아 시작하기 쉽습니다. 그 후 가격 및 구현 옵션에 대해 문의해주세요.", + "enterprise.faq.q3": "엔터프라이즈 가격은 어떻게 되나요?", + "enterprise.faq.a3": + "좌석(seat) 당 엔터프라이즈 가격을 제공합니다. 자체 LLM 게이트웨이를 보유한 경우, 사용된 토큰에 대해 비용을 청구하지 않습니다. 자세한 내용은 조직의 요구사항에 따른 맞춤 견적을 위해 문의해주세요.", + "enterprise.faq.q4": "OpenCode 엔터프라이즈에서 데이터는 안전한가요?", + "enterprise.faq.a4": + "네. OpenCode는 코드나 컨텍스트 데이터를 저장하지 않습니다. 모든 처리는 로컬에서 이루어지거나 AI 제공자에 대한 직접 API 호출을 통해 이루어집니다. 중앙 설정 및 SSO 통합을 통해 데이터는 조직의 인프라 내에서 안전하게 유지됩니다.", + + "brand.title": "OpenCode | 브랜드", + "brand.meta.description": "OpenCode 브랜드 가이드라인", + "brand.heading": "브랜드 가이드라인", + "brand.subtitle": "OpenCode 브랜드를 활용하는 데 도움이 되는 리소스와 자산입니다.", + "brand.downloadAll": "모든 자산 다운로드", + + "changelog.title": "OpenCode | 변경 내역", + "changelog.meta.description": "OpenCode 릴리스 노트 및 변경 내역", + "changelog.hero.title": "변경 내역", + "changelog.hero.subtitle": "OpenCode의 새로운 업데이트 및 개선 사항", + "changelog.empty": "변경 내역 항목을 찾을 수 없습니다.", + "changelog.viewJson": "JSON 보기", + + "bench.list.title": "벤치마크", + "bench.list.heading": "벤치마크", + "bench.list.table.agent": "에이전트", + "bench.list.table.model": "모델", + "bench.list.table.score": "점수", + + "bench.detail.title": "벤치마크 - {{task}}", + "bench.detail.notFound": "태스크를 찾을 수 없음", + "bench.detail.na": "N/A", + "bench.detail.labels.agent": "에이전트", + "bench.detail.labels.model": "모델", + "bench.detail.labels.task": "태스크", + "bench.detail.labels.repo": "저장소", + "bench.detail.labels.from": "From", + "bench.detail.labels.to": "To", + "bench.detail.labels.prompt": "프롬프트", + "bench.detail.labels.commit": "커밋", + "bench.detail.labels.averageDuration": "평균 소요 시간", + "bench.detail.labels.averageScore": "평균 점수", + "bench.detail.labels.averageCost": "평균 비용", + "bench.detail.labels.summary": "요약", + "bench.detail.labels.runs": "실행 횟수", + "bench.detail.labels.score": "점수", + "bench.detail.labels.base": "기본", + "bench.detail.labels.penalty": "페널티", + "bench.detail.labels.weight": "가중치", + "bench.detail.table.run": "실행", + "bench.detail.table.score": "점수 (기본 - 페널티)", + "bench.detail.table.cost": "비용", + "bench.detail.table.duration": "소요 시간", + "bench.detail.run.title": "실행 {{n}}", + "bench.detail.rawJson": "Raw JSON", +} satisfies Dict diff --git a/packages/console/app/src/i18n/no.ts b/packages/console/app/src/i18n/no.ts new file mode 100644 index 00000000000..1f9b1b2464f --- /dev/null +++ b/packages/console/app/src/i18n/no.ts @@ -0,0 +1,594 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "Dokumentasjon", + "nav.changelog": "Endringslogg", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "Enterprise", + "nav.zen": "Zen", + "nav.login": "Logg inn", + "nav.free": "Gratis", + "nav.home": "Hjem", + "nav.openMenu": "Åpne meny", + "nav.getStartedFree": "Kom i gang gratis", + + "nav.context.copyLogo": "Kopier logo som SVG", + "nav.context.copyWordmark": "Kopier wordmark som SVG", + "nav.context.brandAssets": "Merkevareressurser", + + "footer.github": "GitHub", + "footer.docs": "Dokumentasjon", + "footer.changelog": "Endringslogg", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "Merkevare", + "legal.privacy": "Personvern", + "legal.terms": "Vilkår", + + "email.title": "Få beskjed først når vi lanserer nye produkter", + "email.subtitle": "Meld deg på ventelisten for tidlig tilgang.", + "email.placeholder": "E-postadresse", + "email.subscribe": "Abonner", + "email.success": "Nesten ferdig - sjekk innboksen din og bekreft e-postadressen", + + "notFound.title": "Ikke funnet | opencode", + "notFound.heading": "404 - Side ikke funnet", + "notFound.home": "Hjem", + "notFound.docs": "Dokumentasjon", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "Logg ut", + + "workspace.select": "Velg arbeidsområde", + "workspace.createNew": "+ Opprett nytt arbeidsområde", + "workspace.modal.title": "Opprett nytt arbeidsområde", + "workspace.modal.placeholder": "Skriv inn navn på arbeidsområde", + + "common.cancel": "Avbryt", + "common.creating": "Oppretter...", + "common.create": "Opprett", + + "common.videoUnsupported": "Nettleseren din støtter ikke video-taggen.", + "common.figure": "Fig {{n}}.", + "common.faq": "FAQ", + "common.learnMore": "Les mer", + + "error.invalidPlan": "Ugyldig plan", + "error.workspaceRequired": "Arbeidsområde-ID er påkrevd", + "error.alreadySubscribed": "Dette arbeidsområdet har allerede et abonnement", + "error.limitRequired": "Grense er påkrevd.", + "error.monthlyLimitInvalid": "Angi en gyldig månedlig grense.", + "error.workspaceNameRequired": "Navn på arbeidsområde er påkrevd.", + "error.nameTooLong": "Navnet må være 255 tegn eller mindre.", + "error.emailRequired": "E-post er påkrevd", + "error.roleRequired": "Rolle er påkrevd", + "error.idRequired": "ID er påkrevd", + "error.nameRequired": "Navn er påkrevd", + "error.providerRequired": "Leverandør er påkrevd", + "error.apiKeyRequired": "API-nøkkel er påkrevd", + "error.modelRequired": "Modell er påkrevd", + "error.reloadAmountMin": "Påfyllingsbeløp må være minst ${{amount}}", + "error.reloadTriggerMin": "Saldo-trigger må være minst ${{amount}}", + + "home.title": "OpenCode | Den åpne kildekode AI-kodingsagenten", + + "temp.title": "opencode | AI-kodingsagent bygget for terminalen", + "temp.hero.title": "AI-kodingsagenten bygget for terminalen", + "temp.zen": "opencode zen", + "temp.getStarted": "Kom i gang", + "temp.feature.native.title": "Native TUI", + "temp.feature.native.body": "Et responsivt, native terminal-brukergrensesnitt som kan temes", + "temp.feature.zen.beforeLink": "En", + "temp.feature.zen.link": "kuratert liste over modeller", + "temp.feature.zen.afterLink": "levert av opencode", + "temp.feature.models.beforeLink": "Støtter 75+ LLM-leverandører gjennom", + "temp.feature.models.afterLink": ", inkludert lokale modeller", + "temp.screenshot.caption": "opencode TUI med tokyonight-tema", + "temp.screenshot.alt": "opencode TUI med tokyonight-tema", + + "home.banner.badge": "Ny", + "home.banner.text": "Desktop-app tilgjengelig i beta", + "home.banner.platforms": "på macOS, Windows og Linux", + "home.banner.downloadNow": "Last ned nå", + "home.banner.downloadBetaNow": "Last ned desktop-betaen nå", + + "home.hero.title": "Den åpne kildekode AI-kodingsagenten", + "home.hero.subtitle.a": + "Gratis modeller inkludert, eller koble til hvilken som helst modell fra hvilken som helst leverandør,", + "home.hero.subtitle.b": "inkludert Claude, GPT, Gemini og mer.", + + "home.install.ariaLabel": "Installeringsalternativer", + + "home.what.title": "Hva er OpenCode?", + "home.what.body": "OpenCode er en åpen kildekode-agent som hjelper deg å skrive kode i terminal, IDE eller desktop.", + "home.what.lsp.title": "LSP aktivert", + "home.what.lsp.body": "Laster automatisk de riktige LSP-ene for LLM-en", + "home.what.multiSession.title": "Multi-sesjon", + "home.what.multiSession.body": "Start flere agenter parallelt på samme prosjekt", + "home.what.shareLinks.title": "Del lenker", + "home.what.shareLinks.body": "Del en lenke til en sesjon for referanse eller feilsøking", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "Logg inn med GitHub for å bruke Copilot-kontoen din", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "Logg inn med OpenAI for å bruke ChatGPT Plus- eller Pro-kontoen din", + "home.what.anyModel.title": "Hvilken som helst modell", + "home.what.anyModel.body": "75+ LLM-leverandører via Models.dev, inkludert lokale modeller", + "home.what.anyEditor.title": "Hvilken som helst editor", + "home.what.anyEditor.body": "Tilgjengelig som terminalgrensesnitt, desktop-app og IDE-utvidelse", + "home.what.readDocs": "Les dokumentasjonen", + + "home.growth.title": "Den åpne kildekode AI-kodingsagenten", + "home.growth.body": + "Med over {{stars}} GitHub-stjerner, {{contributors}} bidragsytere og over {{commits}} commits, brukes OpenCode av over {{monthlyUsers}} utviklere hver måned.", + "home.growth.githubStars": "GitHub-stjerner", + "home.growth.contributors": "Bidragsytere", + "home.growth.monthlyDevs": "Månedlige utviklere", + + "home.privacy.title": "Bygget med personvern først", + "home.privacy.body": + "OpenCode lagrer ikke koden din eller kontekstdata, slik at den kan fungere i personvernsensitive miljøer.", + "home.privacy.learnMore": "Les mer om", + "home.privacy.link": "personvern", + + "home.faq.q1": "Hva er OpenCode?", + "home.faq.a1": + "OpenCode er en åpen kildekode-agent som hjelper deg å skrive og kjøre kode med hvilken som helst AI-modell. Den er tilgjengelig som terminalgrensesnitt, desktop-app eller IDE-utvidelse.", + "home.faq.q2": "Hvordan bruker jeg OpenCode?", + "home.faq.a2.before": "Den enkleste måten å komme i gang på er å lese", + "home.faq.a2.link": "introen", + "home.faq.q3": "Trenger jeg ekstra AI-abonnementer for å bruke OpenCode?", + "home.faq.a3.p1": + "Ikke nødvendigvis. OpenCode kommer med et sett gratis modeller du kan bruke uten å opprette en konto.", + "home.faq.a3.p2.beforeZen": "I tillegg kan du bruke populære kodemodeller ved å opprette en", + "home.faq.a3.p2.afterZen": " konto.", + "home.faq.a3.p3": + "Vi oppfordrer til å bruke Zen, men OpenCode fungerer også med populære leverandører som OpenAI, Anthropic, xAI osv.", + "home.faq.a3.p4.beforeLocal": "Du kan til og med koble til dine", + "home.faq.a3.p4.localLink": "lokale modeller", + "home.faq.q4": "Kan jeg bruke mine eksisterende AI-abonnementer med OpenCode?", + "home.faq.a4.p1": + "Ja, OpenCode støtter abonnementer fra alle store leverandører. Du kan bruke Claude Pro/Max, ChatGPT Plus/Pro eller GitHub Copilot-abonnementer.", + "home.faq.q5": "Kan jeg bare bruke OpenCode i terminalen?", + "home.faq.a5.beforeDesktop": "Ikke lenger! OpenCode er nå tilgjengelig som en app for", + "home.faq.a5.desktop": "desktop", + "home.faq.a5.and": "og", + "home.faq.a5.web": "web", + "home.faq.q6": "Hva koster OpenCode?", + "home.faq.a6": + "OpenCode er 100% gratis å bruke. Det kommer også med et sett gratis modeller. Det kan være ekstra kostnader hvis du kobler til en annen leverandør.", + "home.faq.q7": "Hva med data og personvern?", + "home.faq.a7.p1": "Dataene dine lagres kun når du bruker våre gratis modeller eller lager delbare lenker.", + "home.faq.a7.p2.beforeModels": "Les mer om", + "home.faq.a7.p2.modelsLink": "våre modeller", + "home.faq.a7.p2.and": "og", + "home.faq.a7.p2.shareLink": "delingssider", + "home.faq.q8": "Er OpenCode åpen kildekode?", + "home.faq.a8.p1": "Ja, OpenCode er fullt open source. Kildekoden er offentlig på", + "home.faq.a8.p2": "under", + "home.faq.a8.mitLicense": "MIT-lisensen", + "home.faq.a8.p3": + ", som betyr at hvem som helst kan bruke, endre eller bidra til utviklingen. Alle i communityet kan opprette issues, sende inn pull requests og utvide funksjonalitet.", + + "home.zenCta.title": "Få tilgang til pålitelige, optimaliserte modeller for kodeagenter", + "home.zenCta.body": + "Zen gir deg tilgang til et håndplukket sett med AI-modeller som OpenCode har testet og benchmarked spesielt for kodeagenter. Du slipper å bekymre deg for ujevn ytelse og kvalitet på tvers av leverandører; bruk validerte modeller som fungerer.", + "home.zenCta.link": "Les om Zen", + + "zen.title": "OpenCode Zen | Et kuratert sett med pålitelige, optimaliserte modeller for kodeagenter", + "zen.hero.title": "Pålitelige optimaliserte modeller for kodeagenter", + "zen.hero.body": + "Zen gir deg tilgang til et kuratert sett med AI-modeller som OpenCode har testet og benchmarked spesielt for kodeagenter. Du slipper å bekymre deg for ujevn ytelse og kvalitet; bruk validerte modeller som fungerer.", + + "zen.faq.q1": "Hva er OpenCode Zen?", + "zen.faq.a1": + "Zen er et kuratert sett med AI-modeller testet og benchmarked for kodeagenter, laget av teamet bak OpenCode.", + "zen.faq.q2": "Hva gjør Zen mer presis?", + "zen.faq.a2": + "Zen tilbyr bare modeller som er testet og benchmarked spesifikt for kodeagenter. Du ville ikke brukt en smørkniv til å skjære biff; ikke bruk dårlige modeller til koding.", + "zen.faq.q3": "Er Zen billigere?", + "zen.faq.a3": + "Zen er ikke for profitt. Zen videreformidler kostnadene fra modellleverandørene direkte til deg. Jo mer Zen brukes, desto bedre priser kan OpenCode forhandle og gi videre til deg.", + "zen.faq.q4": "Hva koster Zen?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "tar betalt per forespørsel", + "zen.faq.a4.p1.afterPricing": "uten påslag, så du betaler akkurat det modellleverandøren tar betalt.", + "zen.faq.a4.p2.beforeAccount": "Totalprisen avhenger av bruk, og du kan sette månedlige utgiftsgrenser i din", + "zen.faq.a4.p2.accountLink": "konto", + "zen.faq.a4.p3": + "For å dekke kostnader legger OpenCode til bare et lite betalingsbehandlingsgebyr på $1.23 per $20 saldo-påfyll.", + "zen.faq.q5": "Hva med data og personvern?", + "zen.faq.a5.beforeExceptions": + "Alle Zen-modeller hostes i USA. Leverandører følger en policy om null oppbevaring og bruker ikke dataene dine til modelltrening, med de", + "zen.faq.a5.exceptionsLink": "følgende unntakene", + "zen.faq.q6": "Kan jeg sette utgiftsgrenser?", + "zen.faq.a6": "Ja, du kan sette månedlige utgiftsgrenser i kontoen din.", + "zen.faq.q7": "Kan jeg avslutte?", + "zen.faq.a7": "Ja, du kan deaktivere fakturering når som helst og bruke gjenværende saldo.", + "zen.faq.q8": "Kan jeg bruke Zen med andre kodeagenter?", + "zen.faq.a8": + "Selv om Zen fungerer veldig bra med OpenCode, kan du bruke Zen med hvilken som helst agent. Følg oppsettinstruksjonene i din foretrukne kodeagent.", + + "zen.cta.start": "Kom i gang med Zen", + "zen.pricing.title": "Legg til $20 Pay as you go-saldo", + "zen.pricing.fee": "(+$1.23 kortbehandlingsgebyr)", + "zen.pricing.body": "Bruk med hvilken som helst agent. Angi månedlige forbruksgrenser. Avslutt når som helst.", + "zen.problem.title": "Hvilket problem løser Zen?", + "zen.problem.body": + "Det er så mange modeller tilgjengelig, men bare noen få fungerer bra med kodeagenter. De fleste leverandører konfigurerer dem annerledes med varierende resultater.", + "zen.problem.subtitle": "Vi fikser dette for alle, ikke bare OpenCode-brukere.", + "zen.problem.item1": "Tester utvalgte modeller og konsulterer teamene deres", + "zen.problem.item2": "Samarbeider med leverandører for å sikre at de blir levert riktig", + "zen.problem.item3": "Benchmarker alle modell-leverandør-kombinasjoner vi anbefaler", + "zen.how.title": "Hvordan Zen fungerer", + "zen.how.body": "Selv om vi foreslår at du bruker Zen med OpenCode, kan du bruke Zen med hvilken som helst agent.", + "zen.how.step1.title": "Registrer deg og legg til $20 saldo", + "zen.how.step1.beforeLink": "følg", + "zen.how.step1.link": "oppsettsinstruksjonene", + "zen.how.step2.title": "Bruk Zen med transparente priser", + "zen.how.step2.link": "betal per forespørsel", + "zen.how.step2.afterLink": "uten påslag", + "zen.how.step3.title": "Auto-påfyll", + "zen.how.step3.body": "når saldoen din når $5, fyller vi automatisk på $20", + "zen.privacy.title": "Personvernet ditt er viktig for oss", + "zen.privacy.beforeExceptions": + "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", + + "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", + "black.hero.subtitle": "Inkludert Claude, GPT, Gemini og mer", + "black.title": "OpenCode Black | Priser", + "black.plan.icon20": "Black 20-plan", + "black.plan.icon100": "Black 100-plan", + "black.plan.icon200": "Black 200-plan", + "black.plan.multiplier100": "5x mer bruk enn Black 20", + "black.plan.multiplier200": "20x mer bruk enn Black 20", + "black.price.perMonth": "per måned", + "black.price.perPersonBilledMonthly": "per person fakturert månedlig", + "black.terms.1": "Abonnementet ditt starter ikke umiddelbart", + "black.terms.2": "Du blir lagt til i ventelisten og aktivert snart", + "black.terms.3": "Kortet ditt belastes kun når abonnementet aktiveres", + "black.terms.4": "Bruksgrenser gjelder, tung automatisert bruk kan nå grensene raskere", + "black.terms.5": "Abonnementer er for enkeltpersoner, kontakt Enterprise for team", + "black.terms.6": "Grenser kan justeres og planer kan avvikles i fremtiden", + "black.terms.7": "Avslutt abonnementet når som helst", + "black.action.continue": "Fortsett", + "black.finePrint.beforeTerms": "Priser vist inkluderer ikke gjeldende skatt", + "black.finePrint.terms": "Vilkår for bruk", + "black.workspace.title": "OpenCode Black | Velg arbeidsområde", + "black.workspace.selectPlan": "Velg et arbeidsområde for denne planen", + "black.workspace.name": "Arbeidsområde {{n}}", + "black.subscribe.title": "Abonner på OpenCode Black", + "black.subscribe.paymentMethod": "Betalingsmetode", + "black.subscribe.loadingPaymentForm": "Laster betalingsskjema...", + "black.subscribe.selectWorkspaceToContinue": "Velg et arbeidsområde for å fortsette", + "black.subscribe.failurePrefix": "Å nei!", + "black.subscribe.error.generic": "Det oppstod en feil", + "black.subscribe.error.invalidPlan": "Ugyldig plan", + "black.subscribe.error.workspaceRequired": "Arbeidsområde-ID er påkrevd", + "black.subscribe.error.alreadySubscribed": "Dette arbeidsområdet har allerede et abonnement", + "black.subscribe.processing": "Behandler...", + "black.subscribe.submit": "Abonner ${{plan}}", + "black.subscribe.form.chargeNotice": "Du blir kun belastet når abonnementet ditt aktiveres", + "black.subscribe.success.title": "Du er på ventelisten for OpenCode Black", + "black.subscribe.success.subscriptionPlan": "Abonnementsplan", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "Beløp", + "black.subscribe.success.amountValue": "${{plan}} per måned", + "black.subscribe.success.paymentMethod": "Betalingsmetode", + "black.subscribe.success.dateJoined": "Dato meldt på", + "black.subscribe.success.chargeNotice": "Kortet ditt vil bli belastet når abonnementet aktiveres", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "API-nøkler", + "workspace.nav.members": "Medlemmer", + "workspace.nav.billing": "Fakturering", + "workspace.nav.settings": "Innstillinger", + + "workspace.home.banner.beforeLink": "Pålitelige optimaliserte modeller for kodeagenter.", + "workspace.home.billing.loading": "Laster...", + "workspace.home.billing.enable": "Aktiver fakturering", + "workspace.home.billing.currentBalance": "Gjeldende saldo", + + "workspace.newUser.feature.tested.title": "Testede og verifiserte modeller", + "workspace.newUser.feature.tested.body": + "Vi har benchmarked og testet modeller spesifikt for kodeagenter for å sikre best mulig ytelse.", + "workspace.newUser.feature.quality.title": "Høyeste kvalitet", + "workspace.newUser.feature.quality.body": + "Få tilgang til modeller konfigurert for optimal ytelse – ingen nedgraderinger eller ruting til billigere leverandører.", + "workspace.newUser.feature.lockin.title": "Ingen innlåsing", + "workspace.newUser.feature.lockin.body": + "Bruk Zen med hvilken som helst kodeagent, og fortsett å bruke andre leverandører med opencode når du vil.", + "workspace.newUser.copyApiKey": "Kopier API-nøkkel", + "workspace.newUser.copyKey": "Kopier nøkkel", + "workspace.newUser.copied": "Kopiert!", + "workspace.newUser.step.enableBilling": "Aktiver fakturering", + "workspace.newUser.step.login.before": "Kjør", + "workspace.newUser.step.login.after": "og velg opencode", + "workspace.newUser.step.pasteKey": "Lim inn API-nøkkelen", + "workspace.newUser.step.models.before": "Start opencode og kjør", + "workspace.newUser.step.models.after": "for å velge en modell", + + "workspace.models.title": "Modeller", + "workspace.models.subtitle.beforeLink": "Administrer hvilke modeller medlemmene i arbeidsområdet har tilgang til.", + "workspace.models.table.model": "Modell", + "workspace.models.table.enabled": "Aktivert", + + "workspace.providers.title": "Ta med din egen nøkkel", + "workspace.providers.subtitle": "Konfigurer dine egne API-nøkler fra AI-leverandører.", + "workspace.providers.placeholder": "Skriv inn {{provider}} API-nøkkel ({{prefix}}...)", + "workspace.providers.configure": "Konfigurer", + "workspace.providers.edit": "Rediger", + "workspace.providers.delete": "Slett", + "workspace.providers.saving": "Lagrer...", + "workspace.providers.save": "Lagre", + "workspace.providers.table.provider": "Leverandør", + "workspace.providers.table.apiKey": "API-nøkkel", + + "workspace.usage.title": "Brukshistorikk", + "workspace.usage.subtitle": "Nylig API-bruk og kostnader.", + "workspace.usage.empty": "Gjør ditt første API-kall for å komme i gang.", + "workspace.usage.table.date": "Dato", + "workspace.usage.table.model": "Modell", + "workspace.usage.table.input": "Input", + "workspace.usage.table.output": "Output", + "workspace.usage.table.cost": "Kostnad", + "workspace.usage.breakdown.input": "Input", + "workspace.usage.breakdown.cacheRead": "Cache Lest", + "workspace.usage.breakdown.cacheWrite": "Cache Skrevet", + "workspace.usage.breakdown.output": "Output", + "workspace.usage.breakdown.reasoning": "Resonnering", + "workspace.usage.subscription": "abonnement (${{amount}})", + + "workspace.cost.title": "Kostnad", + "workspace.cost.subtitle": "Brukskostnader fordelt på modell.", + "workspace.cost.allModels": "Alle modeller", + "workspace.cost.allKeys": "Alle nøkler", + "workspace.cost.deletedSuffix": "(slettet)", + "workspace.cost.empty": "Ingen bruksdata tilgjengelig for den valgte perioden.", + "workspace.cost.subscriptionShort": "sub", + + "workspace.keys.title": "API-nøkler", + "workspace.keys.subtitle": "Administrer API-nøklene dine for å få tilgang til opencode-tjenester.", + "workspace.keys.create": "Opprett API-nøkkel", + "workspace.keys.placeholder": "Skriv inn navn på nøkkel", + "workspace.keys.empty": "Opprett en opencode Gateway API-nøkkel", + "workspace.keys.table.name": "Navn", + "workspace.keys.table.key": "Nøkkel", + "workspace.keys.table.createdBy": "Opprettet av", + "workspace.keys.table.lastUsed": "Sist brukt", + "workspace.keys.copyApiKey": "Kopier API-nøkkel", + "workspace.keys.delete": "Slett", + + "workspace.members.title": "Medlemmer", + "workspace.members.subtitle": "Administrer medlemmer i arbeidsområdet og deres tillatelser.", + "workspace.members.invite": "Inviter medlem", + "workspace.members.inviting": "Inviterer...", + "workspace.members.beta.beforeLink": "Arbeidsområder er gratis for team i beta-perioden.", + "workspace.members.form.invitee": "Invitert", + "workspace.members.form.emailPlaceholder": "Skriv inn e-post", + "workspace.members.form.role": "Rolle", + "workspace.members.form.monthlyLimit": "Månedlig utgiftsgrense", + "workspace.members.noLimit": "Ingen grense", + "workspace.members.noLimitLowercase": "ingen grense", + "workspace.members.invited": "invitert", + "workspace.members.edit": "Rediger", + "workspace.members.delete": "Slett", + "workspace.members.saving": "Lagrer...", + "workspace.members.save": "Lagre", + "workspace.members.table.email": "E-post", + "workspace.members.table.role": "Rolle", + "workspace.members.table.monthLimit": "Månedsgrense", + "workspace.members.role.admin": "Admin", + "workspace.members.role.adminDescription": "Kan administrere modeller, medlemmer og fakturering", + "workspace.members.role.member": "Medlem", + "workspace.members.role.memberDescription": "Kan kun generere API-nøkler for seg selv", + + "workspace.settings.title": "Innstillinger", + "workspace.settings.subtitle": "Oppdater arbeidsområdets navn og preferanser.", + "workspace.settings.workspaceName": "Navn på arbeidsområde", + "workspace.settings.defaultName": "Standard", + "workspace.settings.updating": "Oppdaterer...", + "workspace.settings.save": "Lagre", + "workspace.settings.edit": "Rediger", + + "workspace.billing.title": "Fakturering", + "workspace.billing.subtitle.beforeLink": "Administrer betalingsmetoder.", + "workspace.billing.contactUs": "Kontakt oss", + "workspace.billing.subtitle.afterLink": "hvis du har spørsmål.", + "workspace.billing.currentBalance": "Gjeldende saldo", + "workspace.billing.add": "Legg til $", + "workspace.billing.enterAmount": "Angi beløp", + "workspace.billing.loading": "Laster...", + "workspace.billing.addAction": "Legg til", + "workspace.billing.addBalance": "Legg til saldo", + "workspace.billing.linkedToStripe": "Koblet til Stripe", + "workspace.billing.manage": "Administrer", + "workspace.billing.enable": "Aktiver fakturering", + + "workspace.monthlyLimit.title": "Månedlig grense", + "workspace.monthlyLimit.subtitle": "Angi en månedlig bruksgrense for kontoen din.", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "Angir...", + "workspace.monthlyLimit.set": "Sett", + "workspace.monthlyLimit.edit": "Rediger grense", + "workspace.monthlyLimit.noLimit": "Ingen bruksgrense satt.", + "workspace.monthlyLimit.currentUsage.beforeMonth": "Gjeldende forbruk for", + "workspace.monthlyLimit.currentUsage.beforeAmount": "er $", + + "workspace.reload.title": "Auto-påfyll", + "workspace.reload.disabled.before": "Auto-påfyll er", + "workspace.reload.disabled.state": "deaktivert", + "workspace.reload.disabled.after": "Aktiver for å fylle på automatisk når saldoen er lav.", + "workspace.reload.enabled.before": "Auto-påfyll er", + "workspace.reload.enabled.state": "aktivert", + "workspace.reload.enabled.middle": "Vi fyller på", + "workspace.reload.processingFee": "behandlingsgebyr", + "workspace.reload.enabled.after": "når saldoen når", + "workspace.reload.edit": "Rediger", + "workspace.reload.enable": "Aktiver", + "workspace.reload.enableAutoReload": "Aktiver Auto-påfyll", + "workspace.reload.reloadAmount": "Fyll på $", + "workspace.reload.whenBalanceReaches": "Når saldoen når $", + "workspace.reload.saving": "Lagrer...", + "workspace.reload.save": "Lagre", + "workspace.reload.failedAt": "Påfylling mislyktes kl", + "workspace.reload.reason": "Årsak:", + "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.payments.title": "Betalingshistorikk", + "workspace.payments.subtitle": "Nylige betalingstransaksjoner.", + "workspace.payments.table.date": "Dato", + "workspace.payments.table.paymentId": "Betalings-ID", + "workspace.payments.table.amount": "Beløp", + "workspace.payments.table.receipt": "Kvittering", + "workspace.payments.type.credit": "kreditt", + "workspace.payments.type.subscription": "abonnement", + "workspace.payments.view": "Vis", + + "workspace.black.loading": "Laster...", + "workspace.black.time.day": "dag", + "workspace.black.time.days": "dager", + "workspace.black.time.hour": "time", + "workspace.black.time.hours": "timer", + "workspace.black.time.minute": "minutt", + "workspace.black.time.minutes": "minutter", + "workspace.black.time.fewSeconds": "noen få sekunder", + "workspace.black.subscription.title": "Abonnement", + "workspace.black.subscription.message": "Du abonnerer på OpenCode Black for ${{plan}} per måned.", + "workspace.black.subscription.manage": "Administrer abonnement", + "workspace.black.subscription.rollingUsage": "5-timers bruk", + "workspace.black.subscription.weeklyUsage": "Ukentlig bruk", + "workspace.black.subscription.resetsIn": "Nullstilles om", + "workspace.black.subscription.useBalance": "Bruk din tilgjengelige saldo etter å ha nådd bruksgrensene", + "workspace.black.waitlist.title": "Venteliste", + "workspace.black.waitlist.joined": "Du står på venteliste for OpenCode Black-planen til ${{plan}} per måned.", + "workspace.black.waitlist.ready": "Vi er klare til å melde deg på OpenCode Black-planen til ${{plan}} per måned.", + "workspace.black.waitlist.leave": "Forlat venteliste", + "workspace.black.waitlist.leaving": "Forlater...", + "workspace.black.waitlist.left": "Forlot", + "workspace.black.waitlist.enroll": "Meld på", + "workspace.black.waitlist.enrolling": "Melder på...", + "workspace.black.waitlist.enrolled": "Påmeldt", + "workspace.black.waitlist.enrollNote": + "Når du klikker på Meld på, starter abonnementet umiddelbart og kortet ditt belastes.", + + "download.title": "OpenCode | Last ned", + "download.meta.description": "Last ned OpenCode for macOS, Windows og Linux", + "download.hero.title": "Last ned OpenCode", + "download.hero.subtitle": "Tilgjengelig i beta for macOS, Windows og Linux", + "download.hero.button": "Last ned for {{os}}", + "download.section.terminal": "OpenCode Terminal", + "download.section.desktop": "OpenCode Desktop (Beta)", + "download.section.extensions": "OpenCode Extensions", + "download.section.integrations": "OpenCode Integrations", + "download.action.download": "Last ned", + "download.action.install": "Installer", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "Ikke nødvendigvis, men sannsynligvis. Du trenger et AI-abonnement hvis du vil koble OpenCode til en betalt leverandør, selv om du kan jobbe med", + "download.faq.a3.localLink": "lokale modeller", + "download.faq.a3.afterLocal.beforeZen": "gratis. Selv om vi oppfordrer brukere til å bruke", + "download.faq.a3.afterZen": ", fungerer OpenCode med alle populære leverandører som OpenAI, Anthropic, xAI osv.", + + "download.faq.a5.p1": "OpenCode er 100% gratis å bruke.", + "download.faq.a5.p2.beforeZen": + "Eventuelle ekstra kostnader kommer fra abonnementet ditt hos en modellleverandør. Selv om OpenCode fungerer med enhver modellleverandør, anbefaler vi å bruke", + "download.faq.a5.p2.afterZen": ".", + + "download.faq.a6.p1": "Dataene og informasjonen din lagres bare når du oppretter delbare lenker i OpenCode.", + "download.faq.a6.p2.beforeShare": "Les mer om", + "download.faq.a6.shareLink": "delingssider", + + "enterprise.title": "OpenCode | Enterprise-løsninger for din organisasjon", + "enterprise.meta.description": "Kontakt OpenCode for enterprise-løsninger", + "enterprise.hero.title": "Koden din er din", + "enterprise.hero.body1": + "OpenCode opererer sikkert inne i organisasjonen din uten at data eller kontekst lagres, og uten lisensbegrensninger eller eierskapskrav. Start en prøveperiode med teamet ditt, og rull den deretter ut i hele organisasjonen ved å integrere den med SSO og din interne AI-gateway.", + "enterprise.hero.body2": "Fortell oss hvordan vi kan hjelpe.", + "enterprise.form.name.label": "Fullt navn", + "enterprise.form.name.placeholder": "Jeff Bezos", + "enterprise.form.role.label": "Rolle", + "enterprise.form.role.placeholder": "Styreleder", + "enterprise.form.email.label": "Bedrifts-e-post", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "Hvilket problem prøver dere å løse?", + "enterprise.form.message.placeholder": "Vi trenger hjelp med...", + "enterprise.form.send": "Send", + "enterprise.form.sending": "Sender...", + "enterprise.form.success": "Melding sendt, vi tar kontakt snart.", + "enterprise.faq.title": "FAQ", + "enterprise.faq.q1": "Hva er OpenCode Enterprise?", + "enterprise.faq.a1": + "OpenCode Enterprise er for organisasjoner som vil sikre at koden og dataene deres aldri forlater infrastrukturen. Dette kan gjøres med en sentral konfigurasjon som integreres med SSO og intern AI-gateway.", + "enterprise.faq.q2": "Hvordan kommer jeg i gang med OpenCode Enterprise?", + "enterprise.faq.a2": + "Start enkelt med en intern prøveperiode med teamet ditt. OpenCode lagrer som standard ikke koden din eller kontekstdata, noe som gjør det enkelt å komme i gang. Kontakt oss deretter for å diskutere priser og implementeringsalternativer.", + "enterprise.faq.q3": "Hvordan fungerer enterprise-prising?", + "enterprise.faq.a3": + "Vi tilbyr enterprise-prising per sete. Har du din egen LLM-gateway, tar vi ikke betalt for brukte tokens. Kontakt oss for flere detaljer og et tilpasset tilbud basert på organisasjonens behov.", + "enterprise.faq.q4": "Er dataene mine sikre med OpenCode Enterprise?", + "enterprise.faq.a4": + "Ja. OpenCode lagrer ikke koden din eller kontekstdata. All behandling skjer lokalt eller gjennom direkte API-kall til AI-leverandøren din. Med sentral konfigurasjon og SSO-integrasjon forblir dataene dine sikre innenfor organisasjonens infrastruktur.", + + "brand.title": "OpenCode | Merkevare", + "brand.meta.description": "OpenCode retningslinjer for merkevare", + "brand.heading": "Retningslinjer for merkevare", + "brand.subtitle": "Ressurser og assets som hjelper deg å jobbe med OpenCode-brandet.", + "brand.downloadAll": "Last ned alle assets", + + "changelog.title": "OpenCode | Endringslogg", + "changelog.meta.description": "Utgivelsesnotater og endringslogg for OpenCode", + "changelog.hero.title": "Endringslogg", + "changelog.hero.subtitle": "Nye oppdateringer og forbedringer for OpenCode", + "changelog.empty": "Ingen endringsloggoppføringer funnet.", + "changelog.viewJson": "Vis JSON", + + "bench.list.title": "Benchmark", + "bench.list.heading": "Benchmarks", + "bench.list.table.agent": "Agent", + "bench.list.table.model": "Modell", + "bench.list.table.score": "Poengsum", + + "bench.detail.title": "Benchmark - {{task}}", + "bench.detail.notFound": "Oppgave ikke funnet", + "bench.detail.na": "I/T", + "bench.detail.labels.agent": "Agent", + "bench.detail.labels.model": "Modell", + "bench.detail.labels.task": "Oppgave", + "bench.detail.labels.repo": "Repo", + "bench.detail.labels.from": "Fra", + "bench.detail.labels.to": "Til", + "bench.detail.labels.prompt": "Prompt", + "bench.detail.labels.commit": "Commit", + "bench.detail.labels.averageDuration": "Gjennomsnittlig varighet", + "bench.detail.labels.averageScore": "Gjennomsnittlig poengsum", + "bench.detail.labels.averageCost": "Gjennomsnittlig kostnad", + "bench.detail.labels.summary": "Sammendrag", + "bench.detail.labels.runs": "Kjøringer", + "bench.detail.labels.score": "Poengsum", + "bench.detail.labels.base": "Basis", + "bench.detail.labels.penalty": "Straff", + "bench.detail.labels.weight": "vekt", + "bench.detail.table.run": "Kjøring", + "bench.detail.table.score": "Poengsum (Basis - Straff)", + "bench.detail.table.cost": "Kostnad", + "bench.detail.table.duration": "Varighet", + "bench.detail.run.title": "Kjøring {{n}}", + "bench.detail.rawJson": "Rå JSON", +} satisfies Dict diff --git a/packages/console/app/src/i18n/pl.ts b/packages/console/app/src/i18n/pl.ts new file mode 100644 index 00000000000..f35300710cf --- /dev/null +++ b/packages/console/app/src/i18n/pl.ts @@ -0,0 +1,600 @@ +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "Dokumentacja", + "nav.changelog": "Dziennik zmian", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "Enterprise", + "nav.zen": "Zen", + "nav.login": "Zaloguj się", + "nav.free": "Darmowe", + "nav.home": "Strona główna", + "nav.openMenu": "Otwórz menu", + "nav.getStartedFree": "Zacznij za darmo", + + "nav.context.copyLogo": "Skopiuj logo jako SVG", + "nav.context.copyWordmark": "Skopiuj logotyp jako SVG", + "nav.context.brandAssets": "Zasoby marki", + + "footer.github": "GitHub", + "footer.docs": "Dokumentacja", + "footer.changelog": "Dziennik zmian", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "Marka", + "legal.privacy": "Prywatność", + "legal.terms": "Warunki", + + "email.title": "Bądź pierwszym, który dowie się o nowych produktach", + "email.subtitle": "Dołącz do listy oczekujących na wczesny dostęp.", + "email.placeholder": "Adres e-mail", + "email.subscribe": "Subskrybuj", + "email.success": "Prawie gotowe, sprawdź skrzynkę i potwierdź swój adres e-mail", + + "notFound.title": "Nie znaleziono | opencode", + "notFound.heading": "404 - Nie znaleziono strony", + "notFound.home": "Strona główna", + "notFound.docs": "Dokumentacja", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "Wyloguj się", + + "workspace.select": "Wybierz obszar roboczy", + "workspace.createNew": "+ Utwórz nowy obszar roboczy", + "workspace.modal.title": "Utwórz nowy obszar roboczy", + "workspace.modal.placeholder": "Wpisz nazwę obszaru roboczego", + + "common.cancel": "Anuluj", + "common.creating": "Tworzenie...", + "common.create": "Utwórz", + + "common.videoUnsupported": "Twoja przeglądarka nie obsługuje znacznika wideo.", + "common.figure": "Rys. {{n}}.", + "common.faq": "FAQ", + "common.learnMore": "Dowiedz się więcej", + + "error.invalidPlan": "Nieprawidłowy plan", + "error.workspaceRequired": "ID obszaru roboczego jest wymagane", + "error.alreadySubscribed": "Ten obszar roboczy ma już subskrypcję", + "error.limitRequired": "Limit jest wymagany.", + "error.monthlyLimitInvalid": "Ustaw prawidłowy limit miesięczny.", + "error.workspaceNameRequired": "Nazwa obszaru roboczego jest wymagana.", + "error.nameTooLong": "Nazwa musi mieć 255 znaków lub mniej.", + "error.emailRequired": "E-mail jest wymagany", + "error.roleRequired": "Rola jest wymagana", + "error.idRequired": "ID jest wymagane", + "error.nameRequired": "Nazwa jest wymagana", + "error.providerRequired": "Dostawca jest wymagany", + "error.apiKeyRequired": "Klucz API jest wymagany", + "error.modelRequired": "Model jest wymagany", + "error.reloadAmountMin": "Kwota doładowania musi wynosić co najmniej ${{amount}}", + "error.reloadTriggerMin": "Próg salda musi wynosić co najmniej ${{amount}}", + + "home.title": "OpenCode | Open source'owy agent AI do kodowania", + + "temp.title": "opencode | Agent AI do kodowania zbudowany dla terminala", + "temp.hero.title": "Agent AI do kodowania zbudowany dla terminala", + "temp.zen": "opencode zen", + "temp.getStarted": "Rozpocznij", + "temp.feature.native.title": "Natywny TUI", + "temp.feature.native.body": "Responsywny, natywny, tematyczny interfejs terminala", + "temp.feature.zen.beforeLink": "A", + "temp.feature.zen.link": "wyselekcjonowana lista modeli", + "temp.feature.zen.afterLink": "dostarczana przez opencode", + "temp.feature.models.beforeLink": "Obsługuje 75+ dostawców LLM przez", + "temp.feature.models.afterLink": ", w tym modele lokalne", + "temp.screenshot.caption": "OpenCode TUI z motywem tokyonight", + "temp.screenshot.alt": "OpenCode TUI z motywem tokyonight", + + "home.banner.badge": "Nowość", + "home.banner.text": "Aplikacja desktopowa dostępna w wersji beta", + "home.banner.platforms": "na macOS, Windows i Linux", + "home.banner.downloadNow": "Pobierz teraz", + "home.banner.downloadBetaNow": "Pobierz betę wersji desktopowej", + + "home.hero.title": "Open source'owy agent AI do kodowania", + "home.hero.subtitle.a": "Darmowe modele w zestawie lub podłącz dowolny model od dowolnego dostawcy,", + "home.hero.subtitle.b": "w tym Claude, GPT, Gemini i inne.", + + "home.install.ariaLabel": "Opcje instalacji", + + "home.what.title": "Czym jest OpenCode?", + "home.what.body": + "OpenCode to open source'owy agent, który pomaga pisać kod w terminalu, IDE lub aplikacji desktopowej.", + "home.what.lsp.title": "LSP włączone", + "home.what.lsp.body": "Automatycznie ładuje odpowiednie LSP dla LLM", + "home.what.multiSession.title": "Wielosesyjność", + "home.what.multiSession.body": "Uruchom wiele agentów równolegle w tym samym projekcie", + "home.what.shareLinks.title": "Udostępnianie linków", + "home.what.shareLinks.body": "Udostępnij link do dowolnej sesji w celach referencyjnych lub do debugowania", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "Zaloguj się przez GitHub, aby używać swojego konta Copilot", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "Zaloguj się przez OpenAI, aby używać swojego konta ChatGPT Plus lub Pro", + "home.what.anyModel.title": "Dowolny model", + "home.what.anyModel.body": "75+ dostawców LLM przez Models.dev, w tym modele lokalne", + "home.what.anyEditor.title": "Dowolny edytor", + "home.what.anyEditor.body": "Dostępny jako interfejs terminalowy, aplikacja desktopowa i rozszerzenie IDE", + "home.what.readDocs": "Czytaj dokumentację", + + "home.growth.title": "Open source'owy agent AI do kodowania", + "home.growth.body": + "Z ponad {{stars}} gwiazdkami na GitHubie, {{contributors}} współtwórcami i ponad {{commits}} commitami, OpenCode jest używany i ceniony przez ponad {{monthlyUsers}} deweloperów każdego miesiąca.", + "home.growth.githubStars": "Gwiazdki GitHub", + "home.growth.contributors": "Współtwórcy", + "home.growth.monthlyDevs": "Miesięczni użytkownicy", + + "home.privacy.title": "Zbudowany z myślą o prywatności", + "home.privacy.body": + "OpenCode nie przechowuje Twojego kodu ani danych kontekstowych, dzięki czemu może działać w środowiskach wrażliwych na prywatność.", + "home.privacy.learnMore": "Dowiedz się więcej o", + "home.privacy.link": "prywatności", + + "home.faq.q1": "Czym jest OpenCode?", + "home.faq.a1": + "OpenCode to open source'owy agent, który pomaga pisać i uruchamiać kod z dowolnym modelem AI. Jest dostępny jako interfejs terminalowy, aplikacja desktopowa lub rozszerzenie IDE.", + "home.faq.q2": "Jak korzystać z OpenCode?", + "home.faq.a2.before": "Najłatwiej zacząć od przeczytania", + "home.faq.a2.link": "wprowadzenia", + "home.faq.q3": "Czy potrzebuję dodatkowych subskrypcji AI, aby używać OpenCode?", + "home.faq.a3.p1": + "Niekoniecznie. OpenCode posiada zestaw darmowych modeli, z których możesz korzystać bez zakładania konta.", + "home.faq.a3.p2.beforeZen": "Poza tym możesz używać dowolnych popularnych modeli do kodowania, tworząc konto", + "home.faq.a3.p2.afterZen": ".", + "home.faq.a3.p3": + "Chociaż zachęcamy do korzystania z Zen, OpenCode działa również ze wszystkimi popularnymi dostawcami, takimi jak OpenAI, Anthropic, xAI itp.", + "home.faq.a3.p4.beforeLocal": "Możesz nawet podłączyć swoje", + "home.faq.a3.p4.localLink": "lokalne modele", + "home.faq.q4": "Czy mogę używać moich istniejących subskrypcji AI z OpenCode?", + "home.faq.a4.p1": + "Tak, OpenCode obsługuje plany subskrypcyjne od wszystkich głównych dostawców. Możesz używać swoich subskrypcji Claude Pro/Max, ChatGPT Plus/Pro lub GitHub Copilot.", + "home.faq.q5": "Czy mogę używać OpenCode tylko w terminalu?", + "home.faq.a5.beforeDesktop": "Już nie! OpenCode jest teraz dostępny jako aplikacja na", + "home.faq.a5.desktop": "pulpit (desktop)", + "home.faq.a5.and": "i", + "home.faq.a5.web": "web", + "home.faq.q6": "Ile kosztuje OpenCode?", + "home.faq.a6": + "OpenCode jest w 100% darmowy. Zawiera również zestaw darmowych modeli. Mogą pojawić się dodatkowe koszty, jeśli podłączysz innego dostawcę.", + "home.faq.q7": "A co z danymi i prywatnością?", + "home.faq.a7.p1": + "Twoje dane i informacje są przechowywane tylko wtedy, gdy używasz naszych darmowych modeli lub tworzysz linki do udostępniania.", + "home.faq.a7.p2.beforeModels": "Dowiedz się więcej o", + "home.faq.a7.p2.modelsLink": "naszych modelach", + "home.faq.a7.p2.and": "i", + "home.faq.a7.p2.shareLink": "stronach udostępniania", + "home.faq.q8": "Czy OpenCode jest open source?", + "home.faq.a8.p1": "Tak, OpenCode jest w pełni open source. Kod źródłowy jest publicznie dostępny na", + "home.faq.a8.p2": "na licencji", + "home.faq.a8.mitLicense": "MIT License", + "home.faq.a8.p3": + ", co oznacza, że każdy może go używać, modyfikować i wspierać jego rozwój. Każdy ze społeczności może zgłaszać błędy, przesyłać pull requesty i rozszerzać funkcjonalność.", + + "home.zenCta.title": "Uzyskaj dostęp do niezawodnych, zoptymalizowanych modeli dla agentów kodujących", + "home.zenCta.body": + "Zen daje dostęp do wyselekcjonowanego zestawu modeli AI, które OpenCode przetestował i sprawdził (benchmark) specjalnie dla agentów kodujących. Nie musisz martwić się o niespójną wydajność i jakość u różnych dostawców, używaj sprawdzonych modeli, które działają.", + "home.zenCta.link": "Dowiedz się więcej o Zen", + + "zen.title": "OpenCode Zen | Wyselekcjonowany zestaw niezawodnych, zoptymalizowanych modeli dla agentów kodujących", + "zen.hero.title": "Niezawodne, zoptymalizowane modele dla agentów kodujących", + "zen.hero.body": + "Zen daje dostęp do wyselekcjonowanego zestawu modeli AI, które OpenCode przetestował i sprawdził (benchmark) specjalnie dla agentów kodujących. Nie musisz martwić się o niespójną wydajność i jakość, używaj sprawdzonych modeli, które działają.", + + "zen.faq.q1": "Czym jest OpenCode Zen?", + "zen.faq.a1": + "Zen to wyselekcjonowany zestaw modeli AI przetestowanych i sprawdzonych pod kątem agentów kodujących, stworzony przez zespół stojący za OpenCode.", + "zen.faq.q2": "Co sprawia, że Zen jest bardziej precyzyjny?", + "zen.faq.a2": + "Zen oferuje tylko modele, które zostały specjalnie przetestowane i sprawdzone dla agentów kodujących. Nie używasz noża do masła do krojenia steku, więc nie używaj słabych modeli do kodowania.", + "zen.faq.q3": "Czy Zen jest tańszy?", + "zen.faq.a3": + "Zen nie jest nastawiony na zysk. Zen przekazuje koszty od dostawców modeli bezpośrednio do Ciebie. Im większe użycie Zen, tym lepsze stawki OpenCode może wynegocjować i przekazać Tobie.", + "zen.faq.q4": "Ile kosztuje Zen?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "pobiera opłaty za żądanie", + "zen.faq.a4.p1.afterPricing": "bez marży, więc płacisz dokładnie tyle, ile pobiera dostawca modelu.", + "zen.faq.a4.p2.beforeAccount": + "Twój całkowity koszt zależy od użycia, i możesz ustawić miesięczne limity wydatków na swoim", + "zen.faq.a4.p2.accountLink": "koncie", + "zen.faq.a4.p3": + "Aby pokryć koszty, OpenCode dolicza jedynie niewielką opłatę za przetwarzanie płatności w wysokości $1.23 przy każdym doładowaniu salda o $20.", + "zen.faq.q5": "A co z danymi i prywatnością?", + "zen.faq.a5.beforeExceptions": + "Wszystkie modele Zen są hostowane w USA. Dostawcy stosują politykę zerowej retencji i nie używają Twoich danych do trenowania modeli, z", + "zen.faq.a5.exceptionsLink": "następującymi wyjątkami", + "zen.faq.q6": "Czy mogę ustawić limity wydatków?", + "zen.faq.a6": "Tak, możesz ustawić miesięczne limity wydatków na swoim koncie.", + "zen.faq.q7": "Czy mogę anulować?", + "zen.faq.a7": "Tak, możesz wyłączyć rozliczenia w dowolnym momencie i wykorzystać pozostałe saldo.", + "zen.faq.q8": "Czy mogę używać Zen z innymi agentami kodującymi?", + "zen.faq.a8": + "Chociaż Zen świetnie działa z OpenCode, możesz używać Zen z dowolnym agentem. Postępuj zgodnie z instrukcjami konfiguracji w swoim preferowanym agencie.", + + "zen.cta.start": "Zacznij korzystać z Zen", + "zen.pricing.title": "Dodaj 20$ salda Pay as you go", + "zen.pricing.fee": "(+$1.23 opłaty za przetwarzanie karty)", + "zen.pricing.body": "Używaj z dowolnym agentem. Ustaw miesięczne limity wydatków. Anuluj w dowolnym momencie.", + "zen.problem.title": "Jaki problem rozwiązuje Zen?", + "zen.problem.body": + "Dostępnych jest wiele modeli, ale tylko nieliczne dobrze współpracują z agentami kodującymi. Większość dostawców konfiguruje je inaczej, co daje różne wyniki.", + "zen.problem.subtitle": "Naprawiamy to dla wszystkich, nie tylko dla użytkowników OpenCode.", + "zen.problem.item1": "Testowanie wybranych modeli i konsultacje z ich zespołami", + "zen.problem.item2": "Współpraca z dostawcami w celu zapewnienia ich prawidłowego dostarczania", + "zen.problem.item3": "Benchmark wszystkich rekomendowanych przez nas kombinacji modeli i dostawców", + "zen.how.title": "Jak działa Zen", + "zen.how.body": "Chociaż sugerujemy używanie Zen z OpenCode, możesz używać Zen z dowolnym agentem.", + "zen.how.step1.title": "Zarejestruj się i doładuj saldo 20$", + "zen.how.step1.beforeLink": "postępuj zgodnie z", + "zen.how.step1.link": "instrukcją konfiguracji", + "zen.how.step2.title": "Używaj Zen z przejrzystym cennikiem", + "zen.how.step2.link": "płać za żądanie", + "zen.how.step2.afterLink": "bez marży", + "zen.how.step3.title": "Automatyczne doładowanie", + "zen.how.step3.body": "gdy Twoje saldo osiągnie 5$, automatycznie dodamy 20$", + "zen.privacy.title": "Twoja prywatność jest dla nas ważna", + "zen.privacy.beforeExceptions": + "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", + + "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", + "black.hero.subtitle": "W tym Claude, GPT, Gemini i inne", + "black.title": "OpenCode Black | Cennik", + "black.plan.icon20": "Plan Black 20", + "black.plan.icon100": "Plan Black 100", + "black.plan.icon200": "Plan Black 200", + "black.plan.multiplier100": "5x większe użycie niż Black 20", + "black.plan.multiplier200": "20x większe użycie niż Black 20", + "black.price.perMonth": "miesięcznie", + "black.price.perPersonBilledMonthly": "za osobę rozliczane miesięcznie", + "black.terms.1": "Twoja subskrypcja nie rozpocznie się natychmiast", + "black.terms.2": "Zostaniesz dodany do listy oczekujących i aktywowany wkrótce", + "black.terms.3": "Twoja karta zostanie obciążona dopiero po aktywacji subskrypcji", + "black.terms.4": "Obowiązują limity użycia, intensywne automatyczne użycie może wyczerpać limity szybciej", + "black.terms.5": "Subskrypcje są dla osób indywidualnych, skontaktuj się z Enterprise dla zespołów", + "black.terms.6": "Limity mogą zostać dostosowane, a plany mogą zostać wycofane w przyszłości", + "black.terms.7": "Anuluj subskrypcję w dowolnym momencie", + "black.action.continue": "Kontynuuj", + "black.finePrint.beforeTerms": "Podane ceny nie zawierają stosownego podatku", + "black.finePrint.terms": "Warunki świadczenia usług", + "black.workspace.title": "OpenCode Black | Wybierz obszar roboczy", + "black.workspace.selectPlan": "Wybierz obszar roboczy dla tego planu", + "black.workspace.name": "Obszar roboczy {{n}}", + "black.subscribe.title": "Subskrybuj OpenCode Black", + "black.subscribe.paymentMethod": "Metoda płatności", + "black.subscribe.loadingPaymentForm": "Ładowanie formularza płatności...", + "black.subscribe.selectWorkspaceToContinue": "Wybierz obszar roboczy, aby kontynuować", + "black.subscribe.failurePrefix": "O nie!", + "black.subscribe.error.generic": "Wystąpił błąd", + "black.subscribe.error.invalidPlan": "Nieprawidłowy plan", + "black.subscribe.error.workspaceRequired": "ID obszaru roboczego jest wymagane", + "black.subscribe.error.alreadySubscribed": "Ten obszar roboczy ma już subskrypcję", + "black.subscribe.processing": "Przetwarzanie...", + "black.subscribe.submit": "Subskrybuj ${{plan}}", + "black.subscribe.form.chargeNotice": "Zostaniesz obciążony dopiero po aktywacji subskrypcji", + "black.subscribe.success.title": "Jesteś na liście oczekujących OpenCode Black", + "black.subscribe.success.subscriptionPlan": "Plan subskrypcji", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "Kwota", + "black.subscribe.success.amountValue": "${{plan}} miesięcznie", + "black.subscribe.success.paymentMethod": "Metoda płatności", + "black.subscribe.success.dateJoined": "Data dołączenia", + "black.subscribe.success.chargeNotice": "Twoja karta zostanie obciążona po aktywacji subskrypcji", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "Klucze API", + "workspace.nav.members": "Członkowie", + "workspace.nav.billing": "Rozliczenia", + "workspace.nav.settings": "Ustawienia", + + "workspace.home.banner.beforeLink": "Niezawodne, zoptymalizowane modele dla agentów kodujących.", + "workspace.home.billing.loading": "Ładowanie...", + "workspace.home.billing.enable": "Włącz rozliczenia", + "workspace.home.billing.currentBalance": "Aktualne saldo", + + "workspace.newUser.feature.tested.title": "Przetestowane i zweryfikowane modele", + "workspace.newUser.feature.tested.body": + "Przeprowadziliśmy testy porównawcze i przetestowaliśmy modele specjalnie dla agentów kodujących, aby zapewnić najlepszą wydajność.", + "workspace.newUser.feature.quality.title": "Najwyższa jakość", + "workspace.newUser.feature.quality.body": + "Dostęp do modeli skonfigurowanych pod kątem optymalnej wydajności - bez degradacji jakości czy przekierowywania do tańszych dostawców.", + "workspace.newUser.feature.lockin.title": "Brak blokady (Lock-in)", + "workspace.newUser.feature.lockin.body": + "Używaj Zen z dowolnym agentem kodującym i kontynuuj korzystanie z innych dostawców z OpenCode, kiedy tylko chcesz.", + "workspace.newUser.copyApiKey": "Skopiuj klucz API", + "workspace.newUser.copyKey": "Skopiuj klucz", + "workspace.newUser.copied": "Skopiowano!", + "workspace.newUser.step.enableBilling": "Włącz rozliczenia", + "workspace.newUser.step.login.before": "Uruchom", + "workspace.newUser.step.login.after": "i wybierz opencode", + "workspace.newUser.step.pasteKey": "Wklej swój klucz API", + "workspace.newUser.step.models.before": "Uruchom opencode i wpisz", + "workspace.newUser.step.models.after": "aby wybrać model", + + "workspace.models.title": "Modele", + "workspace.models.subtitle.beforeLink": "Zarządzaj dostępem członków obszaru roboczego do modeli.", + "workspace.models.table.model": "Model", + "workspace.models.table.enabled": "Włączony", + + "workspace.providers.title": "Przynieś własny klucz (BYOK)", + "workspace.providers.subtitle": "Skonfiguruj własne klucze API od dostawców AI.", + "workspace.providers.placeholder": "Wprowadź klucz API {{provider}} ({{prefix}}...)", + "workspace.providers.configure": "Konfiguruj", + "workspace.providers.edit": "Edytuj", + "workspace.providers.delete": "Usuń", + "workspace.providers.saving": "Zapisywanie...", + "workspace.providers.save": "Zapisz", + "workspace.providers.table.provider": "Dostawca", + "workspace.providers.table.apiKey": "Klucz API", + + "workspace.usage.title": "Historia użycia", + "workspace.usage.subtitle": "Ostatnie użycie API i koszty.", + "workspace.usage.empty": "Wykonaj pierwsze wywołanie API, aby rozpocząć.", + "workspace.usage.table.date": "Data", + "workspace.usage.table.model": "Model", + "workspace.usage.table.input": "Wejście", + "workspace.usage.table.output": "Wyjście", + "workspace.usage.table.cost": "Koszt", + "workspace.usage.breakdown.input": "Wejście", + "workspace.usage.breakdown.cacheRead": "Odczyt Cache", + "workspace.usage.breakdown.cacheWrite": "Zapis Cache", + "workspace.usage.breakdown.output": "Wyjście", + "workspace.usage.breakdown.reasoning": "Rozumowanie", + "workspace.usage.subscription": "subskrypcja (${{amount}})", + + "workspace.cost.title": "Koszt", + "workspace.cost.subtitle": "Koszty użycia w podziale na modele.", + "workspace.cost.allModels": "Wszystkie modele", + "workspace.cost.allKeys": "Wszystkie klucze", + "workspace.cost.deletedSuffix": "(usunięte)", + "workspace.cost.empty": "Brak danych o użyciu dla wybranego okresu.", + "workspace.cost.subscriptionShort": "sub", + + "workspace.keys.title": "Klucze API", + "workspace.keys.subtitle": "Zarządzaj kluczami API do usług opencode.", + "workspace.keys.create": "Utwórz klucz API", + "workspace.keys.placeholder": "Wpisz nazwę klucza", + "workspace.keys.empty": "Utwórz klucz API bramy opencode", + "workspace.keys.table.name": "Nazwa", + "workspace.keys.table.key": "Klucz", + "workspace.keys.table.createdBy": "Utworzony przez", + "workspace.keys.table.lastUsed": "Ostatnio użyty", + "workspace.keys.copyApiKey": "Skopiuj klucz API", + "workspace.keys.delete": "Usuń", + + "workspace.members.title": "Członkowie", + "workspace.members.subtitle": "Zarządzaj członkami obszaru roboczego i ich uprawnieniami.", + "workspace.members.invite": "Zaproś członka", + "workspace.members.inviting": "Zapraszanie...", + "workspace.members.beta.beforeLink": "Obszary robocze są darmowe dla zespołów w fazie beta.", + "workspace.members.form.invitee": "Zaproszona osoba", + "workspace.members.form.emailPlaceholder": "Wpisz e-mail", + "workspace.members.form.role": "Rola", + "workspace.members.form.monthlyLimit": "Miesięczny limit wydatków", + "workspace.members.noLimit": "Bez limitu", + "workspace.members.noLimitLowercase": "bez limitu", + "workspace.members.invited": "zaproszono", + "workspace.members.edit": "Edytuj", + "workspace.members.delete": "Usuń", + "workspace.members.saving": "Zapisywanie...", + "workspace.members.save": "Zapisz", + "workspace.members.table.email": "E-mail", + "workspace.members.table.role": "Rola", + "workspace.members.table.monthLimit": "Limit miesięczny", + "workspace.members.role.admin": "Administrator", + "workspace.members.role.adminDescription": "Może zarządzać modelami, członkami i rozliczeniami", + "workspace.members.role.member": "Członek", + "workspace.members.role.memberDescription": "Może generować klucze API tylko dla siebie", + + "workspace.settings.title": "Ustawienia", + "workspace.settings.subtitle": "Zaktualizuj nazwę i preferencje obszaru roboczego.", + "workspace.settings.workspaceName": "Nazwa obszaru roboczego", + "workspace.settings.defaultName": "Domyślny", + "workspace.settings.updating": "Aktualizowanie...", + "workspace.settings.save": "Zapisz", + "workspace.settings.edit": "Edytuj", + + "workspace.billing.title": "Rozliczenia", + "workspace.billing.subtitle.beforeLink": "Zarządzaj metodami płatności.", + "workspace.billing.contactUs": "Skontaktuj się z nami", + "workspace.billing.subtitle.afterLink": "jeśli masz jakiekolwiek pytania.", + "workspace.billing.currentBalance": "Aktualne saldo", + "workspace.billing.add": "Dodaj $", + "workspace.billing.enterAmount": "Wpisz kwotę", + "workspace.billing.loading": "Ładowanie...", + "workspace.billing.addAction": "Dodaj", + "workspace.billing.addBalance": "Doładuj saldo", + "workspace.billing.linkedToStripe": "Połączono ze Stripe", + "workspace.billing.manage": "Zarządzaj", + "workspace.billing.enable": "Włącz rozliczenia", + + "workspace.monthlyLimit.title": "Limit miesięczny", + "workspace.monthlyLimit.subtitle": "Ustaw miesięczny limit użycia dla swojego konta.", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "Ustawianie...", + "workspace.monthlyLimit.set": "Ustaw", + "workspace.monthlyLimit.edit": "Edytuj limit", + "workspace.monthlyLimit.noLimit": "Brak ustawionego limitu użycia.", + "workspace.monthlyLimit.currentUsage.beforeMonth": "Aktualne użycie za", + "workspace.monthlyLimit.currentUsage.beforeAmount": "wynosi $", + + "workspace.reload.title": "Automatyczne doładowanie", + "workspace.reload.disabled.before": "Automatyczne doładowanie jest", + "workspace.reload.disabled.state": "wyłączone", + "workspace.reload.disabled.after": "Włącz, aby automatycznie doładować, gdy saldo jest niskie.", + "workspace.reload.enabled.before": "Automatyczne doładowanie jest", + "workspace.reload.enabled.state": "włączone", + "workspace.reload.enabled.middle": "Doładujemy", + "workspace.reload.processingFee": "opłata procesowa", + "workspace.reload.enabled.after": "gdy saldo osiągnie", + "workspace.reload.edit": "Edytuj", + "workspace.reload.enable": "Włącz", + "workspace.reload.enableAutoReload": "Włącz automatyczne doładowanie", + "workspace.reload.reloadAmount": "Doładuj kwotą $", + "workspace.reload.whenBalanceReaches": "Gdy saldo osiągnie $", + "workspace.reload.saving": "Zapisywanie...", + "workspace.reload.save": "Zapisz", + "workspace.reload.failedAt": "Doładowanie nie powiodło się o", + "workspace.reload.reason": "Powód:", + "workspace.reload.updatePaymentMethod": "Zaktualizuj metodę płatności i spróbuj ponownie.", + "workspace.reload.retrying": "Ponawianie...", + "workspace.reload.retry": "Spróbuj ponownie", + + "workspace.payments.title": "Historia płatności", + "workspace.payments.subtitle": "Ostatnie transakcje płatnicze.", + "workspace.payments.table.date": "Data", + "workspace.payments.table.paymentId": "ID płatności", + "workspace.payments.table.amount": "Kwota", + "workspace.payments.table.receipt": "Rachunek", + "workspace.payments.type.credit": "środki", + "workspace.payments.type.subscription": "subskrypcja", + "workspace.payments.view": "Zobacz", + + "workspace.black.loading": "Ładowanie...", + "workspace.black.time.day": "dzień", + "workspace.black.time.days": "dni", + "workspace.black.time.hour": "godzina", + "workspace.black.time.hours": "godzin(y)", + "workspace.black.time.minute": "minuta", + "workspace.black.time.minutes": "minut(y)", + "workspace.black.time.fewSeconds": "kilka sekund", + "workspace.black.subscription.title": "Subskrypcja", + "workspace.black.subscription.message": "Subskrybujesz OpenCode Black za ${{plan}} miesięcznie.", + "workspace.black.subscription.manage": "Zarządzaj subskrypcją", + "workspace.black.subscription.rollingUsage": "Użycie (okno 5h)", + "workspace.black.subscription.weeklyUsage": "Użycie tygodniowe", + "workspace.black.subscription.resetsIn": "Resetuje się za", + "workspace.black.subscription.useBalance": "Użyj dostępnego salda po osiągnięciu limitów użycia", + "workspace.black.waitlist.title": "Lista oczekujących", + "workspace.black.waitlist.joined": "Jesteś na liście oczekujących na plan OpenCode Black za ${{plan}} miesięcznie.", + "workspace.black.waitlist.ready": "Jesteśmy gotowi zapisać Cię do planu OpenCode Black za ${{plan}} miesięcznie.", + "workspace.black.waitlist.leave": "Opuść listę oczekujących", + "workspace.black.waitlist.leaving": "Opuszczanie...", + "workspace.black.waitlist.left": "Opuszczono", + "workspace.black.waitlist.enroll": "Zapisz się", + "workspace.black.waitlist.enrolling": "Zapisywanie...", + "workspace.black.waitlist.enrolled": "Zapisano", + "workspace.black.waitlist.enrollNote": + "Po kliknięciu Zapisz się, Twoja subskrypcja rozpocznie się natychmiast, a karta zostanie obciążona.", + + "download.title": "OpenCode | Pobierz", + "download.meta.description": "Pobierz OpenCode na macOS, Windows i Linux", + "download.hero.title": "Pobierz OpenCode", + "download.hero.subtitle": "Dostępne w wersji Beta na macOS, Windows i Linux", + "download.hero.button": "Pobierz na {{os}}", + "download.section.terminal": "Terminal OpenCode", + "download.section.desktop": "Pulpit OpenCode (Beta)", + "download.section.extensions": "Rozszerzenia OpenCode", + "download.section.integrations": "Integracje OpenCode", + "download.action.download": "Pobierz", + "download.action.install": "Zainstaluj", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "Niekoniecznie, ale prawdopodobnie. Będziesz potrzebować subskrypcji AI, jeśli chcesz połączyć OpenCode z płatnym dostawcą, chociaż możesz pracować z", + "download.faq.a3.localLink": "modelami lokalnymi", + "download.faq.a3.afterLocal.beforeZen": "za darmo. Chociaż zachęcamy użytkowników do korzystania z", + "download.faq.a3.afterZen": + ", OpenCode współpracuje ze wszystkimi popularnymi dostawcami, takimi jak OpenAI, Anthropic, xAI itp.", + + "download.faq.a5.p1": "OpenCode jest w 100% darmowy.", + "download.faq.a5.p2.beforeZen": + "Wszelkie dodatkowe koszty będą pochodzić z Twojej subskrypcji u dostawcy modelu. Chociaż OpenCode współpracuje z dowolnym dostawcą modeli, zalecamy korzystanie z", + "download.faq.a5.p2.afterZen": ".", + + "download.faq.a6.p1": + "Twoje dane i informacje są przechowywane tylko wtedy, gdy tworzysz linki do udostępniania w OpenCode.", + "download.faq.a6.p2.beforeShare": "Dowiedz się więcej o", + "download.faq.a6.shareLink": "stronach udostępniania", + + "enterprise.title": "OpenCode | Rozwiązania Enterprise dla Twojej organizacji", + "enterprise.meta.description": "Skontaktuj się z OpenCode w sprawie rozwiązań dla przedsiębiorstw", + "enterprise.hero.title": "Twój kod jest Twój", + "enterprise.hero.body1": + "OpenCode działa bezpiecznie wewnątrz Twojej organizacji bez przechowywania danych czy kontekstu, oraz bez ograniczeń licencyjnych czy roszczeń własnościowych. Rozpocznij okres próbny ze swoim zespołem, a następnie wdróż go w całej organizacji, integrując z SSO i wewnętrzną bramą AI.", + "enterprise.hero.body2": "Daj nam znać, jak możemy pomóc.", + "enterprise.form.name.label": "Imię i nazwisko", + "enterprise.form.name.placeholder": "Jeff Bezos", + "enterprise.form.role.label": "Rola", + "enterprise.form.role.placeholder": "Prezes Zarządu", + "enterprise.form.email.label": "E-mail firmowy", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "Jaki problem próbujesz rozwiązać?", + "enterprise.form.message.placeholder": "Potrzebujemy pomocy z...", + "enterprise.form.send": "Wyślij", + "enterprise.form.sending": "Wysyłanie...", + "enterprise.form.success": "Wiadomość wysłana, skontaktujemy się wkrótce.", + "enterprise.faq.title": "FAQ", + "enterprise.faq.q1": "Czym jest OpenCode Enterprise?", + "enterprise.faq.a1": + "OpenCode Enterprise jest dla organizacji, które chcą mieć pewność, że ich kod i dane nigdy nie opuszczą ich infrastruktury. Można to osiągnąć dzięki scentralizowanej konfiguracji, która integruje się z Twoim SSO i wewnętrzną bramą AI.", + "enterprise.faq.q2": "Jak zacząć z OpenCode Enterprise?", + "enterprise.faq.a2": + "Po prostu rozpocznij wewnętrzny okres próbny ze swoim zespołem. OpenCode domyślnie nie przechowuje Twojego kodu ani danych kontekstowych, co ułatwia start. Następnie skontaktuj się z nami, aby omówić opcje cenowe i wdrożeniowe.", + "enterprise.faq.q3": "Jak działa cennik enterprise?", + "enterprise.faq.a3": + "Oferujemy cennik enterprise za stanowisko (per-seat). Jeśli masz własną bramę LLM, nie pobieramy opłat za wykorzystane tokeny. Aby uzyskać więcej szczegółów, skontaktuj się z nami w celu uzyskania wyceny dostosowanej do potrzeb Twojej organizacji.", + "enterprise.faq.q4": "Czy moje dane są bezpieczne z OpenCode Enterprise?", + "enterprise.faq.a4": + "Tak. OpenCode nie przechowuje Twojego kodu ani danych kontekstowych. Całe przetwarzanie odbywa się lokalnie lub poprzez bezpośrednie wywołania API do Twojego dostawcy AI. Dzięki centralnej konfiguracji i integracji SSO, Twoje dane pozostają bezpieczne w infrastrukturze Twojej organizacji.", + + "brand.title": "OpenCode | Marka", + "brand.meta.description": "Wytyczne marki OpenCode", + "brand.heading": "Wytyczne marki", + "brand.subtitle": "Zasoby i aktywa, które pomogą Ci pracować z marką OpenCode.", + "brand.downloadAll": "Pobierz wszystkie zasoby", + + "changelog.title": "OpenCode | Dziennik zmian", + "changelog.meta.description": "Notatki o wydaniu i dziennik zmian OpenCode", + "changelog.hero.title": "Dziennik zmian", + "changelog.hero.subtitle": "Nowe aktualizacje i ulepszenia OpenCode", + "changelog.empty": "Nie znaleziono wpisów w dzienniku zmian.", + "changelog.viewJson": "Zobacz JSON", + + "bench.list.title": "Benchmark", + "bench.list.heading": "Benchmarki", + "bench.list.table.agent": "Agent", + "bench.list.table.model": "Model", + "bench.list.table.score": "Wynik", + + "bench.detail.title": "Benchmark - {{task}}", + "bench.detail.notFound": "Nie znaleziono zadania", + "bench.detail.na": "Brak danych", + "bench.detail.labels.agent": "Agent", + "bench.detail.labels.model": "Model", + "bench.detail.labels.task": "Zadanie", + "bench.detail.labels.repo": "Repozytorium", + "bench.detail.labels.from": "Z", + "bench.detail.labels.to": "Do", + "bench.detail.labels.prompt": "Prompt", + "bench.detail.labels.commit": "Commit", + "bench.detail.labels.averageDuration": "Średni czas trwania", + "bench.detail.labels.averageScore": "Średni wynik", + "bench.detail.labels.averageCost": "Średni koszt", + "bench.detail.labels.summary": "Podsumowanie", + "bench.detail.labels.runs": "Uruchomienia", + "bench.detail.labels.score": "Wynik", + "bench.detail.labels.base": "Baza", + "bench.detail.labels.penalty": "Kara", + "bench.detail.labels.weight": "waga", + "bench.detail.table.run": "Uruchomienie", + "bench.detail.table.score": "Wynik (Baza - Kara)", + "bench.detail.table.cost": "Koszt", + "bench.detail.table.duration": "Czas trwania", + "bench.detail.run.title": "Uruchomienie {{n}}", + "bench.detail.rawJson": "Surowy JSON", +} as const + +export type Key = keyof typeof dict +export type Dict = Record diff --git a/packages/console/app/src/i18n/ru.ts b/packages/console/app/src/i18n/ru.ts new file mode 100644 index 00000000000..27a30cc815e --- /dev/null +++ b/packages/console/app/src/i18n/ru.ts @@ -0,0 +1,601 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "Документация", + "nav.changelog": "Список изменений", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "Enterprise", + "nav.zen": "Zen", + "nav.login": "Войти", + "nav.free": "Бесплатно", + "nav.home": "Главная", + "nav.openMenu": "Открыть меню", + "nav.getStartedFree": "Начать бесплатно", + + "nav.context.copyLogo": "Скопировать логотип как SVG", + "nav.context.copyWordmark": "Скопировать название как SVG", + "nav.context.brandAssets": "Ресурсы бренда", + + "footer.github": "GitHub", + "footer.docs": "Документация", + "footer.changelog": "Список изменений", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "Бренд", + "legal.privacy": "Конфиденциальность", + "legal.terms": "Условия", + + "email.title": "Узнайте первыми о выходе новых продуктов", + "email.subtitle": "Присоединяйтесь к списку ожидания для раннего доступа.", + "email.placeholder": "Email адрес", + "email.subscribe": "Подписаться", + "email.success": "Почти готово, проверьте почту и подтвердите ваш email", + + "notFound.title": "Не найдено | opencode", + "notFound.heading": "404 - Страница не найдена", + "notFound.home": "Главная", + "notFound.docs": "Документация", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "Выйти", + + "workspace.select": "Выбрать рабочее пространство", + "workspace.createNew": "+ Создать рабочее пространство", + "workspace.modal.title": "Создать рабочее пространство", + "workspace.modal.placeholder": "Введите название рабочего пространства", + + "common.cancel": "Отмена", + "common.creating": "Создание...", + "common.create": "Создать", + + "common.videoUnsupported": "Ваш браузер не поддерживает видео тег.", + "common.figure": "Рис {{n}}.", + "common.faq": "FAQ", + "common.learnMore": "Подробнее", + + "error.invalidPlan": "Неверный план", + "error.workspaceRequired": "Требуется ID рабочего пространства", + "error.alreadySubscribed": "У этого рабочего пространства уже есть подписка", + "error.limitRequired": "Требуется лимит.", + "error.monthlyLimitInvalid": "Укажите корректный ежемесячный лимит.", + "error.workspaceNameRequired": "Требуется название рабочего пространства.", + "error.nameTooLong": "Название должно быть не более 255 символов.", + "error.emailRequired": "Требуется email", + "error.roleRequired": "Требуется роль", + "error.idRequired": "Требуется ID", + "error.nameRequired": "Требуется имя", + "error.providerRequired": "Требуется провайдер", + "error.apiKeyRequired": "Требуется API ключ", + "error.modelRequired": "Требуется модель", + "error.reloadAmountMin": "Сумма пополнения должна быть не менее ${{amount}}", + "error.reloadTriggerMin": "Порог баланса должен быть не менее ${{amount}}", + + "home.title": "OpenCode | AI-агент с открытым кодом для программирования", + + "temp.title": "opencode | AI-агент для программирования в терминале", + "temp.hero.title": "AI-агент для программирования в терминале", + "temp.zen": "opencode zen", + "temp.getStarted": "Начать", + "temp.feature.native.title": "Нативный TUI", + "temp.feature.native.body": "Отзывчивый, нативный, темизируемый терминальный интерфейс", + "temp.feature.zen.beforeLink": "", + "temp.feature.zen.link": "Отобранный список моделей", + "temp.feature.zen.afterLink": "от opencode", + "temp.feature.models.beforeLink": "Поддерживает 75+ провайдеров LLM через", + "temp.feature.models.afterLink": ", включая локальные модели", + "temp.screenshot.caption": "OpenCode TUI с темой tokyonight", + "temp.screenshot.alt": "OpenCode TUI с темой tokyonight", + + "home.banner.badge": "Новое", + "home.banner.text": "Доступно десктопное приложение (бета)", + "home.banner.platforms": "на macOS, Windows и Linux", + "home.banner.downloadNow": "Скачать", + "home.banner.downloadBetaNow": "Скачать бету для десктопа", + + "home.hero.title": "AI-агент с открытым кодом для программирования", + "home.hero.subtitle.a": "Бесплатные модели включены, или подключите любую модель от любого провайдера,", + "home.hero.subtitle.b": "включая Claude, GPT, Gemini и другие.", + + "home.install.ariaLabel": "Варианты установки", + + "home.what.title": "Что такое OpenCode?", + "home.what.body": + "OpenCode — это агент с открытым исходным кодом, который помогает писать код в терминале, IDE или на десктопе.", + "home.what.lsp.title": "Поддержка LSP", + "home.what.lsp.body": "Автоматически загружает нужные LSP для LLM", + "home.what.multiSession.title": "Мульти-сессии", + "home.what.multiSession.body": "Запускайте несколько агентов параллельно в одном проекте", + "home.what.shareLinks.title": "Общие ссылки", + "home.what.shareLinks.body": "Делитесь ссылкой на любую сессию для справки или отладки", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "Войдите через GitHub, чтобы использовать ваш аккаунт Copilot", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "Войдите через OpenAI, чтобы использовать ваш аккаунт ChatGPT Plus или Pro", + "home.what.anyModel.title": "Любая модель", + "home.what.anyModel.body": "75+ провайдеров LLM через Models.dev, включая локальные модели", + "home.what.anyEditor.title": "Любой редактор", + "home.what.anyEditor.body": "Доступно как терминальный интерфейс, десктопное приложение и расширение для IDE", + "home.what.readDocs": "Читать документацию", + + "home.growth.title": "AI-агент с открытым кодом для программирования", + "home.growth.body": + "С более чем {{stars}} звезд на GitHub, {{contributors}} контрибьюторов и {{commits}} коммитов, OpenCode доверяют более {{monthlyUsers}} разработчиков ежемесячно.", + "home.growth.githubStars": "Звезд на GitHub", + "home.growth.contributors": "Контрибьюторов", + "home.growth.monthlyDevs": "Разработчиков в месяц", + + "home.privacy.title": "Создан с заботой о приватности", + "home.privacy.body": + "OpenCode не хранит ваш код или контекстные данные, поэтому он может работать в средах, чувствительных к приватности.", + "home.privacy.learnMore": "Подробнее о", + "home.privacy.link": "приватности", + + "home.faq.q1": "Что такое OpenCode?", + "home.faq.a1": + "OpenCode — это агент с открытым исходным кодом, который помогает писать и запускать код с любой AI-моделью. Доступен как терминальный интерфейс, десктопное приложение или расширение для IDE.", + "home.faq.q2": "Как использовать OpenCode?", + "home.faq.a2.before": "Проще всего начать с чтения", + "home.faq.a2.link": "введения", + "home.faq.q3": "Нужны ли дополнительные подписки на AI для использования OpenCode?", + "home.faq.a3.p1": + "Не обязательно, OpenCode поставляется с набором бесплатных моделей, которые можно использовать без создания аккаунта.", + "home.faq.a3.p2.beforeZen": + "Помимо этого, вы можете использовать любые популярные модели для кодинга, создав аккаунт", + "home.faq.a3.p2.afterZen": ".", + "home.faq.a3.p3": + "Хотя мы рекомендуем использовать Zen, OpenCode также работает со всеми популярными провайдерами, такими как OpenAI, Anthropic, xAI и др.", + "home.faq.a3.p4.beforeLocal": "Вы даже можете подключить ваши", + "home.faq.a3.p4.localLink": "локальные модели", + "home.faq.q4": "Могу ли я использовать мои существующие AI-подписки с OpenCode?", + "home.faq.a4.p1": + "Да, OpenCode поддерживает подписки всех основных провайдеров. Вы можете использовать ваши подписки Claude Pro/Max, ChatGPT Plus/Pro или GitHub Copilot.", + "home.faq.q5": "Можно ли использовать OpenCode только в терминале?", + "home.faq.a5.beforeDesktop": "Больше нет! OpenCode теперь доступен как приложение для", + "home.faq.a5.desktop": "десктопа", + "home.faq.a5.and": "и", + "home.faq.a5.web": "веба", + "home.faq.q6": "Сколько стоит OpenCode?", + "home.faq.a6": + "OpenCode на 100% бесплатен. Он также включает набор бесплатных моделей. Дополнительные расходы могут возникнуть, если вы подключите другого провайдера.", + "home.faq.q7": "Как насчет данных и приватности?", + "home.faq.a7.p1": + "Ваши данные сохраняются только тогда, когда вы используете наши бесплатные модели или создаете ссылки для шеринга.", + "home.faq.a7.p2.beforeModels": "Подробнее о", + "home.faq.a7.p2.modelsLink": "наших моделях", + "home.faq.a7.p2.and": "и", + "home.faq.a7.p2.shareLink": "страницах шеринга", + "home.faq.q8": "OpenCode — это open source?", + "home.faq.a8.p1": "Да, OpenCode полностью open source. Исходный код доступен публично на", + "home.faq.a8.p2": "под", + "home.faq.a8.mitLicense": "лицензией MIT", + "home.faq.a8.p3": + ", что означает, что любой может использовать, изменять или вносить вклад в его развитие. Любой участник сообщества может создавать issues, отправлять pull requests и расширять функциональность.", + + "home.zenCta.title": "Доступ к надежным оптимизированным моделям для кодинг-агентов", + "home.zenCta.body": + "Zen дает доступ к отобранному набору AI-моделей, которые OpenCode протестировал и проверил специально для кодинг-агентов. Не нужно беспокоиться о нестабильной производительности и качестве разных провайдеров, используйте проверенные модели, которые работают.", + "home.zenCta.link": "Узнать о Zen", + + "zen.title": "OpenCode Zen | Набор надежных оптимизированных моделей для кодинг-агентов", + "zen.hero.title": "Надежные оптимизированные модели для кодинг-агентов", + "zen.hero.body": + "Zen дает доступ к отобранному набору AI-моделей, которые OpenCode протестировал и проверил специально для кодинг-агентов. Не нужно беспокоиться о нестабильной производительности и качестве, используйте проверенные модели, которые работают.", + + "zen.faq.q1": "Что такое OpenCode Zen?", + "zen.faq.a1": + "Zen — это отобранный набор AI-моделей, протестированных и проверенных для кодинг-агентов командой, стоящей за OpenCode.", + "zen.faq.q2": "Почему Zen точнее?", + "zen.faq.a2": + "Zen предоставляет только те модели, которые были специально протестированы и проверены для кодинг-агентов. Вы же не режете стейк ножом для масла, не используйте плохие модели для кодинга.", + "zen.faq.q3": "Zen дешевле?", + "zen.faq.a3": + "Zen — некоммерческий проект. Zen транслирует расходы от провайдеров моделей вам. Чем больше использование Zen, тем лучшие тарифы OpenCode может согласовать и передать вам.", + "zen.faq.q4": "Сколько стоит Zen?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "взимает плату за запрос", + "zen.faq.a4.p1.afterPricing": + "с нулевой наценкой, так что вы платите ровно столько, сколько взимает провайдер модели.", + "zen.faq.a4.p2.beforeAccount": + "Общая стоимость зависит от использования, и вы можете установить ежемесячные лимиты расходов в своем", + "zen.faq.a4.p2.accountLink": "аккаунте", + "zen.faq.a4.p3": + "Для покрытия расходов OpenCode добавляет лишь небольшую комиссию за обработку платежа в размере $1.23 при пополнении баланса на $20.", + "zen.faq.q5": "Как насчет данных и приватности?", + "zen.faq.a5.beforeExceptions": + "Все модели Zen размещены в США. Провайдеры следуют политике нулевого хранения и не используют ваши данные для обучения моделей, за", + "zen.faq.a5.exceptionsLink": "следующими исключениями", + "zen.faq.q6": "Могу ли я установить лимиты расходов?", + "zen.faq.a6": "Да, вы можете установить ежемесячные лимиты расходов в своем аккаунте.", + "zen.faq.q7": "Могу ли я отменить?", + "zen.faq.a7": "Да, вы можете отключить оплату в любое время и использовать оставшийся баланс.", + "zen.faq.q8": "Могу ли я использовать Zen с другими кодинг-агентами?", + "zen.faq.a8": + "Хотя Zen отлично работает с OpenCode, вы можете использовать Zen с любым агентом. Следуйте инструкциям по настройке в вашем любимом агенте.", + + "zen.cta.start": "Начать работу с Zen", + "zen.pricing.title": "Пополнить баланс на $20 (Pay as you go)", + "zen.pricing.fee": "(+$1.23 комиссия за обработку карты)", + "zen.pricing.body": "Используйте с любым агентом. Установите ежемесячные лимиты. Отмените в любое время.", + "zen.problem.title": "Какую проблему решает Zen?", + "zen.problem.body": + "Доступно множество моделей, но лишь немногие хорошо работают с кодинг-агентами. Большинство провайдеров настраивают их по-разному с разными результатами.", + "zen.problem.subtitle": "Мы исправляем это для всех, а не только для пользователей OpenCode.", + "zen.problem.item1": "Тестирование избранных моделей и консультации с их командами", + "zen.problem.item2": "Работа с провайдерами для обеспечения правильной доставки", + "zen.problem.item3": "Бенчмаркинг всех рекомендуемых нами комбинаций модель-провайдер", + "zen.how.title": "Как работает Zen", + "zen.how.body": "Хотя мы предлагаем использовать Zen с OpenCode, вы можете использовать его с любым агентом.", + "zen.how.step1.title": "Зарегистрируйтесь и пополните баланс на $20", + "zen.how.step1.beforeLink": "следуйте", + "zen.how.step1.link": "инструкциям по настройке", + "zen.how.step2.title": "Используйте Zen с прозрачным ценообразованием", + "zen.how.step2.link": "оплата за запрос", + "zen.how.step2.afterLink": "с нулевой наценкой", + "zen.how.step3.title": "Автопополнение", + "zen.how.step3.body": "когда ваш баланс достигнет $5, мы автоматически добавим $20", + "zen.privacy.title": "Ваша приватность важна для нас", + "zen.privacy.beforeExceptions": + "Все модели Zen размещены в США. Провайдеры следуют политике нулевого хранения и не используют ваши данные для обучения моделей, за", + "zen.privacy.exceptionsLink": "следующими исключениями", + + "black.meta.title": "OpenCode Black | Доступ к лучшим моделям для кодинга в мире", + "black.meta.description": "Получите доступ к Claude, GPT, Gemini и другим моделям с подпиской OpenCode Black.", + "black.hero.title": "Доступ к лучшим моделям для кодинга в мире", + "black.hero.subtitle": "Включая Claude, GPT, Gemini и другие", + "black.title": "OpenCode Black | Цены", + "black.plan.icon20": "План Black 20", + "black.plan.icon100": "План Black 100", + "black.plan.icon200": "План Black 200", + "black.plan.multiplier100": "в 5x больше использования, чем Black 20", + "black.plan.multiplier200": "в 20x больше использования, чем Black 20", + "black.price.perMonth": "в месяц", + "black.price.perPersonBilledMonthly": "за человека при ежемесячной оплате", + "black.terms.1": "Ваша подписка начнется не сразу", + "black.terms.2": "Вы будете добавлены в список ожидания и активированы в ближайшее время", + "black.terms.3": "Оплата с карты будет списана только при активации подписки", + "black.terms.4": + "Действуют лимиты использования; интенсивное автоматизированное использование может исчерпать лимиты быстрее", + "black.terms.5": "Подписки предназначены для частных лиц, для команд обратитесь в Enterprise", + "black.terms.6": "Лимиты могут быть скорректированы, а планы могут быть прекращены в будущем", + "black.terms.7": "Отмените подписку в любое время", + "black.action.continue": "Продолжить", + "black.finePrint.beforeTerms": "Указанные цены не включают применимые налоги", + "black.finePrint.terms": "Условия обслуживания", + "black.workspace.title": "OpenCode Black | Выбор рабочего пространства", + "black.workspace.selectPlan": "Выберите рабочее пространство для этого плана", + "black.workspace.name": "Рабочее пространство {{n}}", + "black.subscribe.title": "Подписаться на OpenCode Black", + "black.subscribe.paymentMethod": "Способ оплаты", + "black.subscribe.loadingPaymentForm": "Загрузка формы оплаты...", + "black.subscribe.selectWorkspaceToContinue": "Выберите рабочее пространство для продолжения", + "black.subscribe.failurePrefix": "Ой!", + "black.subscribe.error.generic": "Произошла ошибка", + "black.subscribe.error.invalidPlan": "Неверный план", + "black.subscribe.error.workspaceRequired": "Требуется ID рабочего пространства", + "black.subscribe.error.alreadySubscribed": "У этого рабочего пространства уже есть подписка", + "black.subscribe.processing": "Обработка...", + "black.subscribe.submit": "Подписаться на ${{plan}}", + "black.subscribe.form.chargeNotice": "Оплата будет списана только при активации вашей подписки", + "black.subscribe.success.title": "Вы в списке ожидания OpenCode Black", + "black.subscribe.success.subscriptionPlan": "План подписки", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "Сумма", + "black.subscribe.success.amountValue": "${{plan}} в месяц", + "black.subscribe.success.paymentMethod": "Способ оплаты", + "black.subscribe.success.dateJoined": "Дата присоединения", + "black.subscribe.success.chargeNotice": "С вашей карты будет списана оплата при активации подписки", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "API Ключи", + "workspace.nav.members": "Участники", + "workspace.nav.billing": "Оплата", + "workspace.nav.settings": "Настройки", + + "workspace.home.banner.beforeLink": "Надежные оптимизированные модели для кодинг-агентов.", + "workspace.home.billing.loading": "Загрузка...", + "workspace.home.billing.enable": "Включить оплату", + "workspace.home.billing.currentBalance": "Текущий баланс", + + "workspace.newUser.feature.tested.title": "Протестированные и проверенные модели", + "workspace.newUser.feature.tested.body": + "Мы провели бенчмаркинг и тестирование моделей специально для кодинг-агентов, чтобы обеспечить лучшую производительность.", + "workspace.newUser.feature.quality.title": "Высочайшее качество", + "workspace.newUser.feature.quality.body": + "Доступ к моделям, настроенным для оптимальной производительности — никаких даунгрейдов или перенаправления к дешевым провайдерам.", + "workspace.newUser.feature.lockin.title": "Без привязки (Lock-in)", + "workspace.newUser.feature.lockin.body": + "Используйте Zen с любым кодинг-агентом и продолжайте использовать других провайдеров с opencode, когда захотите.", + "workspace.newUser.copyApiKey": "Копировать API ключ", + "workspace.newUser.copyKey": "Копировать ключ", + "workspace.newUser.copied": "Скопировано!", + "workspace.newUser.step.enableBilling": "Включить оплату", + "workspace.newUser.step.login.before": "Запустите", + "workspace.newUser.step.login.after": "и выберите opencode", + "workspace.newUser.step.pasteKey": "Вставьте ваш API ключ", + "workspace.newUser.step.models.before": "Запустите opencode и выполните", + "workspace.newUser.step.models.after": "для выбора модели", + + "workspace.models.title": "Модели", + "workspace.models.subtitle.beforeLink": + "Управляйте тем, к каким моделям имеют доступ участники рабочего пространства.", + "workspace.models.table.model": "Модель", + "workspace.models.table.enabled": "Включено", + + "workspace.providers.title": "Использовать свой ключ (BYOK)", + "workspace.providers.subtitle": "Настройте свои собственные API ключи от AI-провайдеров.", + "workspace.providers.placeholder": "Введите API ключ {{provider}} ({{prefix}}...)", + "workspace.providers.configure": "Настроить", + "workspace.providers.edit": "Изменить", + "workspace.providers.delete": "Удалить", + "workspace.providers.saving": "Сохранение...", + "workspace.providers.save": "Сохранить", + "workspace.providers.table.provider": "Провайдер", + "workspace.providers.table.apiKey": "API ключ", + + "workspace.usage.title": "История использования", + "workspace.usage.subtitle": "Недавнее использование API и расходы.", + "workspace.usage.empty": "Сделайте первый API вызов, чтобы начать.", + "workspace.usage.table.date": "Дата", + "workspace.usage.table.model": "Модель", + "workspace.usage.table.input": "Вход", + "workspace.usage.table.output": "Выход", + "workspace.usage.table.cost": "Стоимость", + "workspace.usage.breakdown.input": "Вход", + "workspace.usage.breakdown.cacheRead": "Чтение кэша", + "workspace.usage.breakdown.cacheWrite": "Запись кэша", + "workspace.usage.breakdown.output": "Выход", + "workspace.usage.breakdown.reasoning": "Reasoning (рассуждения)", + "workspace.usage.subscription": "подписка (${{amount}})", + + "workspace.cost.title": "Расходы", + "workspace.cost.subtitle": "Расходы на использование с разбивкой по моделям.", + "workspace.cost.allModels": "Все модели", + "workspace.cost.allKeys": "Все ключи", + "workspace.cost.deletedSuffix": "(удалено)", + "workspace.cost.empty": "Нет данных об использовании за выбранный период.", + "workspace.cost.subscriptionShort": "подписка", + + "workspace.keys.title": "API Ключи", + "workspace.keys.subtitle": "Управляйте вашими API ключами для доступа к сервисам opencode.", + "workspace.keys.create": "Создать API ключ", + "workspace.keys.placeholder": "Введите название ключа", + "workspace.keys.empty": "Создайте API ключ для шлюза opencode", + "workspace.keys.table.name": "Название", + "workspace.keys.table.key": "Ключ", + "workspace.keys.table.createdBy": "Создан", + "workspace.keys.table.lastUsed": "Использован", + "workspace.keys.copyApiKey": "Копировать API ключ", + "workspace.keys.delete": "Удалить", + + "workspace.members.title": "Участники", + "workspace.members.subtitle": "Управляйте участниками рабочего пространства и их правами.", + "workspace.members.invite": "Пригласить участника", + "workspace.members.inviting": "Отправка приглашения...", + "workspace.members.beta.beforeLink": "Рабочие пространства бесплатны для команд во время беты.", + "workspace.members.form.invitee": "Приглашаемый", + "workspace.members.form.emailPlaceholder": "Введите email", + "workspace.members.form.role": "Роль", + "workspace.members.form.monthlyLimit": "Ежемесячный лимит расходов", + "workspace.members.noLimit": "Без лимита", + "workspace.members.noLimitLowercase": "без лимита", + "workspace.members.invited": "приглашен", + "workspace.members.edit": "Изменить", + "workspace.members.delete": "Удалить", + "workspace.members.saving": "Сохранение...", + "workspace.members.save": "Сохранить", + "workspace.members.table.email": "Email", + "workspace.members.table.role": "Роль", + "workspace.members.table.monthLimit": "Лимит на месяц", + "workspace.members.role.admin": "Админ", + "workspace.members.role.adminDescription": "Может управлять моделями, участниками и оплатой", + "workspace.members.role.member": "Участник", + "workspace.members.role.memberDescription": "Может создавать API ключи только для себя", + + "workspace.settings.title": "Настройки", + "workspace.settings.subtitle": "Обновите название и настройки вашего рабочего пространства.", + "workspace.settings.workspaceName": "Название рабочего пространства", + "workspace.settings.defaultName": "По умолчанию", + "workspace.settings.updating": "Обновление...", + "workspace.settings.save": "Сохранить", + "workspace.settings.edit": "Изменить", + + "workspace.billing.title": "Оплата", + "workspace.billing.subtitle.beforeLink": "Управление способами оплаты.", + "workspace.billing.contactUs": "Свяжитесь с нами", + "workspace.billing.subtitle.afterLink": "если у вас есть вопросы.", + "workspace.billing.currentBalance": "Текущий баланс", + "workspace.billing.add": "Пополнить $", + "workspace.billing.enterAmount": "Введите сумму", + "workspace.billing.loading": "Загрузка...", + "workspace.billing.addAction": "Пополнить", + "workspace.billing.addBalance": "Пополнить баланс", + "workspace.billing.linkedToStripe": "Привязано к Stripe", + "workspace.billing.manage": "Управление", + "workspace.billing.enable": "Включить оплату", + + "workspace.monthlyLimit.title": "Ежемесячный лимит", + "workspace.monthlyLimit.subtitle": "Установите ежемесячный лимит расходов для вашего аккаунта.", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "Сохранение...", + "workspace.monthlyLimit.set": "Установить", + "workspace.monthlyLimit.edit": "Изменить лимит", + "workspace.monthlyLimit.noLimit": "Лимит использования не установлен.", + "workspace.monthlyLimit.currentUsage.beforeMonth": "Текущее использование за", + "workspace.monthlyLimit.currentUsage.beforeAmount": "составляет $", + + "workspace.reload.title": "Автопополнение", + "workspace.reload.disabled.before": "Автопополнение", + "workspace.reload.disabled.state": "отключено", + "workspace.reload.disabled.after": "Включите для автоматического пополнения при низком балансе.", + "workspace.reload.enabled.before": "Автопополнение", + "workspace.reload.enabled.state": "включено", + "workspace.reload.enabled.middle": "Мы пополним на", + "workspace.reload.processingFee": "комиссия", + "workspace.reload.enabled.after": "когда баланс достигнет", + "workspace.reload.edit": "Изменить", + "workspace.reload.enable": "Включить", + "workspace.reload.enableAutoReload": "Включить автопополнение", + "workspace.reload.reloadAmount": "Пополнить на $", + "workspace.reload.whenBalanceReaches": "Когда баланс достигнет $", + "workspace.reload.saving": "Сохранение...", + "workspace.reload.save": "Сохранить", + "workspace.reload.failedAt": "Пополнение не удалось", + "workspace.reload.reason": "Причина:", + "workspace.reload.updatePaymentMethod": "Пожалуйста, обновите способ оплаты и попробуйте снова.", + "workspace.reload.retrying": "Повторная попытка...", + "workspace.reload.retry": "Повторить", + + "workspace.payments.title": "История платежей", + "workspace.payments.subtitle": "Недавние транзакции.", + "workspace.payments.table.date": "Дата", + "workspace.payments.table.paymentId": "ID платежа", + "workspace.payments.table.amount": "Сумма", + "workspace.payments.table.receipt": "Квитанция", + "workspace.payments.type.credit": "кредит", + "workspace.payments.type.subscription": "подписка", + "workspace.payments.view": "Просмотр", + + "workspace.black.loading": "Загрузка...", + "workspace.black.time.day": "день", + "workspace.black.time.days": "дней", + "workspace.black.time.hour": "час", + "workspace.black.time.hours": "часов", + "workspace.black.time.minute": "минута", + "workspace.black.time.minutes": "минут", + "workspace.black.time.fewSeconds": "несколько секунд", + "workspace.black.subscription.title": "Подписка", + "workspace.black.subscription.message": "Вы подписаны на OpenCode Black за ${{plan}} в месяц.", + "workspace.black.subscription.manage": "Управление подпиской", + "workspace.black.subscription.rollingUsage": "5-часовое использование", + "workspace.black.subscription.weeklyUsage": "Недельное использование", + "workspace.black.subscription.resetsIn": "Сброс через", + "workspace.black.subscription.useBalance": "Использовать доступный баланс после достижения лимитов", + "workspace.black.waitlist.title": "Список ожидания", + "workspace.black.waitlist.joined": "Вы в списке ожидания плана OpenCode Black за ${{plan}} в месяц.", + "workspace.black.waitlist.ready": "Мы готовы подключить вас к плану OpenCode Black за ${{plan}} в месяц.", + "workspace.black.waitlist.leave": "Покинуть список ожидания", + "workspace.black.waitlist.leaving": "Выход...", + "workspace.black.waitlist.left": "Вы покинули", + "workspace.black.waitlist.enroll": "Подключиться", + "workspace.black.waitlist.enrolling": "Подключение...", + "workspace.black.waitlist.enrolled": "Подключен", + "workspace.black.waitlist.enrollNote": + "Когда вы нажмете Подключиться, ваша подписка начнется немедленно, и с карты будет списана оплата.", + + "download.title": "OpenCode | Скачать", + "download.meta.description": "Скачать OpenCode для macOS, Windows и Linux", + "download.hero.title": "Скачать OpenCode", + "download.hero.subtitle": "Доступна бета для macOS, Windows и Linux", + "download.hero.button": "Скачать для {{os}}", + "download.section.terminal": "OpenCode Terminal", + "download.section.desktop": "OpenCode Desktop (Beta)", + "download.section.extensions": "Расширения OpenCode", + "download.section.integrations": "Интеграции OpenCode", + "download.action.download": "Скачать", + "download.action.install": "Установить", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "Не обязательно, но возможно. Вам понадобится AI подписка, если вы хотите подключить OpenCode к платному провайдеру, хотя вы можете работать с", + "download.faq.a3.localLink": "локальными моделями", + "download.faq.a3.afterLocal.beforeZen": "бесплатно. Хотя мы рекомендуем использовать", + "download.faq.a3.afterZen": + ", OpenCode работает со всеми популярными провайдерами, такими как OpenAI, Anthropic, xAI и др.", + + "download.faq.a5.p1": "OpenCode на 100% бесплатен.", + "download.faq.a5.p2.beforeZen": + "Любые дополнительные расходы будут связаны с вашей подпиской у провайдера моделей. Хотя OpenCode работает с любым провайдером моделей, мы рекомендуем использовать", + "download.faq.a5.p2.afterZen": ".", + + "download.faq.a6.p1": "Ваши данные и информация сохраняются только при создании ссылок для шеринга в OpenCode.", + "download.faq.a6.p2.beforeShare": "Подробнее о", + "download.faq.a6.shareLink": "страницах шеринга", + + "enterprise.title": "OpenCode | Корпоративные решения для вашей организации", + "enterprise.meta.description": "Свяжитесь с OpenCode для корпоративных решений", + "enterprise.hero.title": "Ваш код принадлежит вам", + "enterprise.hero.body1": + "OpenCode безопасно работает внутри вашей организации: не хранит данные и контекст, без лицензионных ограничений и претензий на собственность. Начните пробный период с командой, затем разверните по всей организации, интегрировав с SSO и внутренним AI-шлюзом.", + "enterprise.hero.body2": "Сообщите нам, чем мы можем помочь.", + "enterprise.form.name.label": "Полное имя", + "enterprise.form.name.placeholder": "Джефф Безос", + "enterprise.form.role.label": "Роль", + "enterprise.form.role.placeholder": "Исполнительный председатель", + "enterprise.form.email.label": "Корпоративная почта", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "Какую проблему вы пытаетесь решить?", + "enterprise.form.message.placeholder": "Нам нужна помощь с...", + "enterprise.form.send": "Отправить", + "enterprise.form.sending": "Отправка...", + "enterprise.form.success": "Сообщение отправлено, мы скоро свяжемся с вами.", + "enterprise.faq.title": "FAQ", + "enterprise.faq.q1": "Что такое OpenCode Enterprise?", + "enterprise.faq.a1": + "OpenCode Enterprise предназначен для организаций, которые хотят гарантировать, что их код и данные никогда не покинут их инфраструктуру. Это достигается за счет централизованной конфигурации, интегрированной с вашим SSO и внутренним AI-шлюзом.", + "enterprise.faq.q2": "Как начать работу с OpenCode Enterprise?", + "enterprise.faq.a2": + "Просто начните с внутреннего триала с вашей командой. OpenCode по умолчанию не хранит ваш код или контекстные данные, поэтому начать легко. Затем свяжитесь с нами, чтобы обсудить цены и варианты внедрения.", + "enterprise.faq.q3": "Как работает корпоративное ценообразование?", + "enterprise.faq.a3": + "Мы предлагаем модель ценообразования за рабочее место (per-seat). Если у вас есть собственный LLM-шлюз, мы не взимаем плату за использованные токены. Для получения подробной информации свяжитесь с нами для индивидуального расчета на основе потребностей вашей организации.", + "enterprise.faq.q4": "Безопасны ли мои данные с OpenCode Enterprise?", + "enterprise.faq.a4": + "Да. OpenCode не хранит ваш код или контекстные данные. Вся обработка происходит локально или через прямые вызовы API к вашему AI-провайдеру. Благодаря централизованной конфигурации и интеграции SSO ваши данные остаются защищенными внутри инфраструктуры вашей организации.", + + "brand.title": "OpenCode | Бренд", + "brand.meta.description": "Гайдлайны бренда OpenCode", + "brand.heading": "Гайдлайны бренда", + "brand.subtitle": "Ресурсы и активы, которые помогут вам работать с брендом OpenCode.", + "brand.downloadAll": "Скачать все ресурсы", + + "changelog.title": "OpenCode | Список изменений", + "changelog.meta.description": "Примечания к релизам и список изменений OpenCode", + "changelog.hero.title": "Список изменений", + "changelog.hero.subtitle": "Новые обновления и улучшения OpenCode", + "changelog.empty": "Записи в списке изменений не найдены.", + "changelog.viewJson": "Посмотреть JSON", + + "bench.list.title": "Бенчмарк", + "bench.list.heading": "Бенчмарки", + "bench.list.table.agent": "Агент", + "bench.list.table.model": "Модель", + "bench.list.table.score": "Оценка", + + "bench.detail.title": "Бенчмарк - {{task}}", + "bench.detail.notFound": "Задача не найдена", + "bench.detail.na": "Н/Д", + "bench.detail.labels.agent": "Агент", + "bench.detail.labels.model": "Модель", + "bench.detail.labels.task": "Задача", + "bench.detail.labels.repo": "Репозиторий", + "bench.detail.labels.from": "От", + "bench.detail.labels.to": "До", + "bench.detail.labels.prompt": "Промпт", + "bench.detail.labels.commit": "Коммит", + "bench.detail.labels.averageDuration": "Средняя длительность", + "bench.detail.labels.averageScore": "Средняя оценка", + "bench.detail.labels.averageCost": "Средняя стоимость", + "bench.detail.labels.summary": "Сводка", + "bench.detail.labels.runs": "Запуски", + "bench.detail.labels.score": "Оценка", + "bench.detail.labels.base": "База", + "bench.detail.labels.penalty": "Штраф", + "bench.detail.labels.weight": "вес", + "bench.detail.table.run": "Запуск", + "bench.detail.table.score": "Оценка (База - Штраф)", + "bench.detail.table.cost": "Стоимость", + "bench.detail.table.duration": "Длительность", + "bench.detail.run.title": "Запуск {{n}}", + "bench.detail.rawJson": "Raw JSON", +} satisfies Dict diff --git a/packages/console/app/src/i18n/th.ts b/packages/console/app/src/i18n/th.ts new file mode 100644 index 00000000000..d94be479c9f --- /dev/null +++ b/packages/console/app/src/i18n/th.ts @@ -0,0 +1,593 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "เอกสาร", + "nav.changelog": "บันทึกการเปลี่ยนแปลง", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "องค์กร", + "nav.zen": "Zen", + "nav.login": "เข้าสู่ระบบ", + "nav.free": "ฟรี", + "nav.home": "หน้าหลัก", + "nav.openMenu": "เปิดเมนู", + "nav.getStartedFree": "เริ่มต้นฟรี", + + "nav.context.copyLogo": "คัดลอกโลโก้เป็น SVG", + "nav.context.copyWordmark": "คัดลอกตัวอักษรแบรนด์เป็น SVG", + "nav.context.brandAssets": "แอสเซทแบรนด์", + + "footer.github": "GitHub", + "footer.docs": "เอกสาร", + "footer.changelog": "บันทึกการเปลี่ยนแปลง", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "แบรนด์", + "legal.privacy": "ความเป็นส่วนตัว", + "legal.terms": "ข้อกำหนด", + + "email.title": "รู้ก่อนใครเมื่อเราปล่อยผลิตภัณฑ์ใหม่", + "email.subtitle": "เข้าร่วมรายชื่อรอเพื่อรับสิทธิ์เข้าถึงก่อนใคร", + "email.placeholder": "ที่อยู่อีเมล", + "email.subscribe": "สมัครรับข่าวสาร", + "email.success": "เกือบเสร็จแล้ว ตรวจสอบกล่องจดหมายและยืนยันที่อยู่อีเมลของคุณ", + + "notFound.title": "ไม่พบหน้า | OpenCode", + "notFound.heading": "404 - ไม่พบหน้าที่ค้นหา", + "notFound.home": "หน้าหลัก", + "notFound.docs": "เอกสาร", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "ออกจากระบบ", + + "workspace.select": "เลือก Workspace", + "workspace.createNew": "+ สร้าง Workspace ใหม่", + "workspace.modal.title": "สร้าง Workspace ใหม่", + "workspace.modal.placeholder": "กรอกชื่อ Workspace", + + "common.cancel": "ยกเลิก", + "common.creating": "กำลังสร้าง...", + "common.create": "สร้าง", + + "common.videoUnsupported": "เบราว์เซอร์ของคุณไม่รองรับแท็ก video", + "common.figure": "รูปที่ {{n}}", + "common.faq": "คำถามที่พบบ่อย", + "common.learnMore": "ดูเพิ่มเติม", + + "error.invalidPlan": "แผนไม่ถูกต้อง", + "error.workspaceRequired": "จำเป็นต้องมี Workspace ID", + "error.alreadySubscribed": "Workspace นี้มีการสมัครสมาชิกอยู่แล้ว", + "error.limitRequired": "จำเป็นต้องระบุขีดจำกัด", + "error.monthlyLimitInvalid": "โปรดระบุขีดจำกัดรายเดือนที่ถูกต้อง", + "error.workspaceNameRequired": "จำเป็นต้องระบุชื่อ Workspace", + "error.nameTooLong": "ชื่อต้องมีความยาวไม่เกิน 255 ตัวอักษร", + "error.emailRequired": "จำเป็นต้องระบุอีเมล", + "error.roleRequired": "จำเป็นต้องระบุบทบาท", + "error.idRequired": "จำเป็นต้องระบุ ID", + "error.nameRequired": "จำเป็นต้องระบุชื่อ", + "error.providerRequired": "จำเป็นต้องระบุผู้ให้บริการ", + "error.apiKeyRequired": "จำเป็นต้องระบุ API key", + "error.modelRequired": "จำเป็นต้องระบุโมเดล", + "error.reloadAmountMin": "จำนวนเงินที่โหลดซ้ำต้องมีอย่างน้อย ${{amount}}", + "error.reloadTriggerMin": "ยอดคงเหลือที่กระตุ้นต้องมีอย่างน้อย ${{amount}}", + + "home.title": "OpenCode | เอเจนต์เขียนโค้ดด้วย AI แบบโอเพนซอร์ส", + + "temp.title": "OpenCode | เอเจนต์เขียนโค้ด AI ที่สร้างมาเพื่อเทอร์มินัล", + "temp.hero.title": "เอเจนต์เขียนโค้ด AI ที่สร้างมาเพื่อเทอร์มินัล", + "temp.zen": "OpenCode Zen", + "temp.getStarted": "เริ่มต้นใช้งาน", + "temp.feature.native.title": "Native TUI", + "temp.feature.native.body": "UI เทอร์มินัลแบบเนทีฟที่ตอบสนองไวและปรับแต่งธีมได้", + "temp.feature.zen.beforeLink": "", + "temp.feature.zen.link": "รายการโมเดลที่คัดสรรแล้ว", + "temp.feature.zen.afterLink": "โดย OpenCode", + "temp.feature.models.beforeLink": "รองรับผู้ให้บริการ LLM กว่า 75 รายผ่าน", + "temp.feature.models.afterLink": "รวมถึงโมเดล Local", + "temp.screenshot.caption": "OpenCode TUI พร้อมธีม tokyonight", + "temp.screenshot.alt": "OpenCode TUI พร้อมธีม tokyonight", + + "home.banner.badge": "ใหม่", + "home.banner.text": "แอปเดสก์ท็อปพร้อมใช้งานในเวอร์ชันเบต้า", + "home.banner.platforms": "บน macOS, Windows และ Linux", + "home.banner.downloadNow": "ดาวน์โหลดตอนนี้", + "home.banner.downloadBetaNow": "ดาวน์โหลดเบต้าเดสก์ท็อปตอนนี้", + + "home.hero.title": "เอเจนต์เขียนโค้ดด้วย AI แบบโอเพนซอร์ส", + "home.hero.subtitle.a": "มีโมเดลฟรีรวมอยู่ หรือเชื่อมต่อโมเดลใดก็ได้จากผู้ให้บริการรายใดก็ได้,", + "home.hero.subtitle.b": "รวมถึง Claude, GPT, Gemini และอีกมากมาย", + + "home.install.ariaLabel": "ตัวเลือกการติดตั้ง", + + "home.what.title": "OpenCode คืออะไร?", + "home.what.body": "OpenCode คือเอเจนต์โอเพนซอร์สที่ช่วยคุณเขียนโค้ดในเทอร์มินัล, IDE หรือเดสก์ท็อป", + "home.what.lsp.title": "รองรับ LSP", + "home.what.lsp.body": "โหลด LSP ที่เหมาะสมสำหรับ LLM โดยอัตโนมัติ", + "home.what.multiSession.title": "หลายเซสชัน", + "home.what.multiSession.body": "เริ่มเอเจนต์หลายตัวทำงานคู่ขนานกันในโปรเจกต์เดียวกัน", + "home.what.shareLinks.title": "แชร์ลิงก์", + "home.what.shareLinks.body": "แชร์ลิงก์ไปยังเซสชันใดก็ได้เพื่อการอ้างอิงหรือ Debug", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "เข้าสู่ระบบด้วย GitHub เพื่อใช้บัญชี Copilot ของคุณ", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "เข้าสู่ระบบด้วย OpenAI เพื่อใช้บัญชี ChatGPT Plus หรือ Pro ของคุณ", + "home.what.anyModel.title": "โมเดลใดก็ได้", + "home.what.anyModel.body": "ผู้ให้บริการ LLM กว่า 75 รายผ่าน Models.dev รวมถึงโมเดล Local", + "home.what.anyEditor.title": "อีดิเตอร์ใดก็ได้", + "home.what.anyEditor.body": "ใช้งานได้ทั้งแบบเทอร์มินัล, แอปเดสก์ท็อป และส่วนขยาย IDE", + "home.what.readDocs": "อ่านเอกสาร", + + "home.growth.title": "เอเจนต์เขียนโค้ดด้วย AI แบบโอเพนซอร์ส", + "home.growth.body": + "ด้วยยอดดาวบน GitHub กว่า {{stars}} ดวง, ผู้ร่วมพัฒนา {{contributors}} คน, และการคอมมิตกว่า {{commits}} ครั้ง, OpenCode ได้รับความไว้วางใจจากนักพัฒนากว่า {{monthlyUsers}} คนในทุกเดือน", + "home.growth.githubStars": "GitHub Stars", + "home.growth.contributors": "ผู้ร่วมพัฒนา", + "home.growth.monthlyDevs": "นักพัฒนารายเดือน", + + "home.privacy.title": "สร้างโดยคำนึงถึงความเป็นส่วนตัวเป็นหลัก", + "home.privacy.body": + "OpenCode ไม่จัดเก็บโค้ดหรือข้อมูลบริบทของคุณ เพื่อให้สามารถทำงานในสภาพแวดล้อมที่ให้ความสำคัญกับความเป็นส่วนตัวได้", + "home.privacy.learnMore": "เรียนรู้เพิ่มเติมเกี่ยวกับ", + "home.privacy.link": "ความเป็นส่วนตัว", + + "home.faq.q1": "OpenCode คืออะไร?", + "home.faq.a1": + "OpenCode เป็นเอเจนต์โอเพนซอร์สที่ช่วยให้คุณเขียนและรันโค้ดด้วยโมเดล AI ใดก็ได้ มีให้เลือกใช้ทั้งแบบอินเทอร์เฟซเทอร์มินัล, แอปเดสก์ท็อป หรือส่วนขยาย IDE", + "home.faq.q2": "ฉันจะเริ่มใช้ OpenCode ได้อย่างไร?", + "home.faq.a2.before": "วิธีเริ่มต้นที่ง่ายที่สุดคืออ่าน", + "home.faq.a2.link": "บทนำ", + "home.faq.q3": "ต้องสมัครสมาชิก AI เพิ่มเติมเพื่อใช้ OpenCode หรือไม่?", + "home.faq.a3.p1": "ไม่จำเป็นเสมอไป OpenCode มาพร้อมกับชุดโมเดลฟรีที่คุณสามารถใช้ได้โดยไม่ต้องสร้างบัญชี", + "home.faq.a3.p2.beforeZen": "นอกจากนี้ คุณสามารถใช้โมเดลยอดนิยมใดก็ได้โดยการสร้างบัญชี", + "home.faq.a3.p2.afterZen": "", + "home.faq.a3.p3": + "แม้เราจะแนะนำให้ใช้ Zen แต่ OpenCode ก็ทำงานร่วมกับผู้ให้บริการยอดนิยมทั้งหมด เช่น OpenAI, Anthropic, xAI เป็นต้น", + "home.faq.a3.p4.beforeLocal": "คุณยังสามารถเชื่อมต่อกับ", + "home.faq.a3.p4.localLink": "โมเดล Local ของคุณ", + "home.faq.q4": "ฉันสามารถใช้การสมัครสมาชิก AI ที่มีอยู่กับ OpenCode ได้หรือไม่?", + "home.faq.a4.p1": + "ได้ OpenCode รองรับแผนการสมัครสมาชิกจากผู้ให้บริการหลักทั้งหมด คุณสามารถใช้การสมัครสมาชิก Claude Pro/Max, ChatGPT Plus/Pro หรือ GitHub Copilot ของคุณได้", + "home.faq.q5": "ฉันใช้ OpenCode ได้เฉพาะในเทอร์มินัลใช่หรือไม่?", + "home.faq.a5.beforeDesktop": "ไม่อีกต่อไป! OpenCode มีแอปสำหรับ", + "home.faq.a5.desktop": "เดสก์ท็อป", + "home.faq.a5.and": "และ", + "home.faq.a5.web": "เว็บ", + "home.faq.q6": "OpenCode ราคาเท่าไหร่?", + "home.faq.a6": + "OpenCode ใช้งานได้ฟรี 100% และมาพร้อมกับชุดโมเดลฟรี อาจมีค่าใช้จ่ายเพิ่มเติมหากคุณเชื่อมต่อกับผู้ให้บริการรายอื่น", + "home.faq.q7": "แล้วเรื่องข้อมูลและความเป็นส่วนตัวล่ะ?", + "home.faq.a7.p1": "ข้อมูลของคุณจะถูกจัดเก็บเฉพาะเมื่อคุณใช้โมเดลฟรีของเราหรือสร้างลิงก์ที่แชร์ได้", + "home.faq.a7.p2.beforeModels": "เรียนรู้เพิ่มเติมเกี่ยวกับ", + "home.faq.a7.p2.modelsLink": "โมเดลของเรา", + "home.faq.a7.p2.and": "และ", + "home.faq.a7.p2.shareLink": "หน้าแชร์", + "home.faq.q8": "OpenCode เป็นโอเพนซอร์สหรือไม่?", + "home.faq.a8.p1": "ใช่ OpenCode เป็นโอเพนซอร์สเต็มรูปแบบ ซอร์สโค้ดเปิดเผยต่อสาธารณะบน", + "home.faq.a8.p2": "ภายใต้", + "home.faq.a8.mitLicense": "MIT License", + "home.faq.a8.p3": + " ซึ่งหมายความว่าใครๆ ก็สามารถใช้ แก้ไข หรือร่วมพัฒนาได้ ทุกคนในชุมชนสามารถเปิด issue, ส่ง pull request และขยายฟังก์ชันการทำงานได้", + + "home.zenCta.title": "เข้าถึงโมเดลที่เชื่อถือได้และปรับแต่งมาแล้วสำหรับเอเจนต์เขียนโค้ด", + "home.zenCta.body": + "Zen ให้คุณเข้าถึงชุดโมเดล AI ที่คัดสรรมาแล้ว ซึ่ง OpenCode ได้ทดสอบและทำเบนช์มาร์กโดยเฉพาะสำหรับเอเจนต์เขียนโค้ด ไม่ต้องกังวลเรื่องประสิทธิภาพและคุณภาพที่ไม่สม่ำเสมอจากผู้ให้บริการ ใช้โมเดลที่ผ่านการตรวจสอบแล้วว่าใช้งานได้จริง", + "home.zenCta.link": "เรียนรู้เกี่ยวกับ Zen", + + "zen.title": "OpenCode Zen | ชุดโมเดลที่คัดสรรมาอย่างดี เชื่อถือได้ และปรับแต่งแล้วสำหรับเอเจนต์เขียนโค้ด", + "zen.hero.title": "โมเดลที่ปรับแต่งมาอย่างดีและเชื่อถือได้สำหรับเอเจนต์เขียนโค้ด", + "zen.hero.body": + "Zen ให้คุณเข้าถึงชุดโมเดล AI ที่คัดสรรมาแล้ว ซึ่ง OpenCode ได้ทดสอบและทำเบนช์มาร์กโดยเฉพาะสำหรับเอเจนต์เขียนโค้ด ไม่ต้องกังวลเรื่องประสิทธิภาพและคุณภาพที่ไม่สม่ำเสมอ ใช้โมเดลที่ผ่านการตรวจสอบแล้วว่าใช้งานได้จริง", + + "zen.faq.q1": "OpenCode Zen คืออะไร?", + "zen.faq.a1": + "Zen คือชุดโมเดล AI ที่คัดสรรมาอย่างดี ผ่านการทดสอบและทำเบนช์มาร์กสำหรับเอเจนต์เขียนโค้ด สร้างโดยทีมงานผู้อยู่เบื้องหลัง OpenCode", + "zen.faq.q2": "อะไรทำให้ Zen แม่นยำกว่า?", + "zen.faq.a2": + "Zen ให้บริการเฉพาะโมเดลที่ได้รับการทดสอบและทำเบนช์มาร์กสำหรับเอเจนต์เขียนโค้ดโดยเฉพาะ คุณคงไม่ใช้มีดทาเนยมาหั่นสเต็ก ดังนั้นอย่าใช้โมเดลคุณภาพต่ำสำหรับการเขียนโค้ด", + "zen.faq.q3": "Zen ราคาถูกกว่าหรือไม่?", + "zen.faq.a3": + "Zen ไม่ได้แสวงหากำไร Zen ส่งผ่านต้นทุนจากผู้ให้บริการโมเดลมาถึงคุณ ยิ่งมีการใช้งาน Zen มากเท่าไหร่ OpenCode ก็ยิ่งสามารถต่อรองเรตราคาที่ดีกว่าและส่งต่อให้คุณได้มากขึ้นเท่านั้น", + "zen.faq.q4": "Zen ราคาเท่าไหร่?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "คิดค่าบริการต่อคำขอ", + "zen.faq.a4.p1.afterPricing": "โดยไม่มีการบวกเพิ่ม ดังนั้นคุณจ่ายเท่ากับที่ผู้ให้บริการโมเดลเรียกเก็บ", + "zen.faq.a4.p2.beforeAccount": + "ค่าใช้จ่ายรวมของคุณขึ้นอยู่กับการใช้งาน และคุณสามารถตั้งวงเงินการใช้จ่ายรายเดือนได้ใน", + "zen.faq.a4.p2.accountLink": "บัญชีของคุณ", + "zen.faq.a4.p3": + "เพื่อครอบคลุมต้นทุน OpenCode คิดค่าธรรมเนียมการประมวลผลการชำระเงินเพียงเล็กน้อย $1.23 ต่อการเติมเงิน $20", + "zen.faq.q5": "แล้วเรื่องข้อมูลและความเป็นส่วนตัวล่ะ?", + "zen.faq.a5.beforeExceptions": + "โมเดล Zen ทั้งหมดโฮสต์ในสหรัฐอเมริกา ผู้ให้บริการปฏิบัติตามนโยบายไม่เก็บรักษาข้อมูล (zero-retention policy) และไม่ใช้ข้อมูลของคุณสำหรับการฝึกโมเดล โดยมี", + "zen.faq.a5.exceptionsLink": "ข้อยกเว้นดังนี้", + "zen.faq.q6": "ฉันสามารถตั้งวงเงินการใช้จ่ายได้หรือไม่?", + "zen.faq.a6": "ได้ คุณสามารถตั้งวงเงินการใช้จ่ายรายเดือนได้ในบัญชีของคุณ", + "zen.faq.q7": "ฉันสามารถยกเลิกได้หรือไม่?", + "zen.faq.a7": "ได้ คุณสามารถปิดการเรียกเก็บเงินได้ตลอดเวลาและใช้ยอดเงินคงเหลือของคุณจนหมด", + "zen.faq.q8": "ฉันสามารถใช้ Zen กับเอเจนต์เขียนโค้ดอื่นได้หรือไม่?", + "zen.faq.a8": + "แม้ว่า Zen จะทำงานได้ดีเยี่ยมกับ OpenCode แต่คุณสามารถใช้ Zen กับเอเจนต์ใดก็ได้ เพียงทำตามคำแนะนำการตั้งค่าในเอเจนต์เขียนโค้ดที่คุณต้องการ", + + "zen.cta.start": "เริ่มต้นใช้งาน Zen", + "zen.pricing.title": "เติมเงิน $20 แบบ Pay as you go", + "zen.pricing.fee": "(+ค่าธรรมเนียมประมวลผลบัตร $1.23)", + "zen.pricing.body": "ใช้ได้กับทุกเอเจนต์ ตั้งวงเงินรายเดือนได้ ยกเลิกได้ตลอดเวลา", + "zen.problem.title": "Zen กำลังแก้ปัญหาอะไร?", + "zen.problem.body": + "มีโมเดลมากมายให้เลือก แต่มีเพียงไม่กี่ตัวที่ทำงานได้ดีกับเอเจนต์เขียนโค้ด ผู้ให้บริการส่วนใหญ่กำหนดค่าแตกต่างกันไปซึ่งให้ผลลัพธ์ที่หลากหลาย", + "zen.problem.subtitle": "เรากำลังแก้ไขปัญหานี้สำหรับทุกคน ไม่ใช่แค่ผู้ใช้ OpenCode เท่านั้น", + "zen.problem.item1": "ทดสอบโมเดลที่คัดเลือกมาและปรึกษากับทีมของโมเดลนั้นๆ", + "zen.problem.item2": "ทำงานร่วมกับผู้ให้บริการเพื่อให้มั่นใจว่าโมเดลถูกส่งมอบอย่างถูกต้อง", + "zen.problem.item3": "ทำเบนช์มาร์กทุกการจับคู่ระหว่างโมเดลและผู้ให้บริการที่เราแนะนำ", + "zen.how.title": "Zen ทำงานอย่างไร", + "zen.how.body": "แม้เราจะแนะนำให้คุณใช้ Zen กับ OpenCode แต่คุณสามารถใช้ Zen กับเอเจนต์ใดก็ได้", + "zen.how.step1.title": "ลงทะเบียนและเติมเงิน $20", + "zen.how.step1.beforeLink": "ทำตาม", + "zen.how.step1.link": "คำแนะนำการตั้งค่า", + "zen.how.step2.title": "ใช้ Zen ด้วยราคาที่โปร่งใส", + "zen.how.step2.link": "จ่ายตามคำขอ (pay per request)", + "zen.how.step2.afterLink": "โดยไม่มีการบวกเพิ่ม", + "zen.how.step3.title": "เติมเงินอัตโนมัติ", + "zen.how.step3.body": "เมื่อยอดเงินของคุณเหลือ $5 เราจะเติมเงิน $20 ให้โดยอัตโนมัติ", + "zen.privacy.title": "ความเป็นส่วนตัวของคุณสำคัญสำหรับเรา", + "zen.privacy.beforeExceptions": + "โมเดล Zen ทั้งหมดโฮสต์ในสหรัฐอเมริกา ผู้ให้บริการปฏิบัติตามนโยบายไม่เก็บรักษาข้อมูล (zero-retention policy) และไม่ใช้ข้อมูลของคุณสำหรับการฝึกโมเดล โดยมี", + "zen.privacy.exceptionsLink": "ข้อยกเว้นดังนี้", + + "black.meta.title": "OpenCode Black | เข้าถึงโมเดลเขียนโค้ดที่ดีที่สุดในโลก", + "black.meta.description": "เข้าถึง Claude, GPT, Gemini และอื่นๆ ด้วยแผนสมาชิก OpenCode Black", + "black.hero.title": "เข้าถึงโมเดลเขียนโค้ดที่ดีที่สุดในโลก", + "black.hero.subtitle": "รวมถึง Claude, GPT, Gemini และอื่นๆ อีกมากมาย", + "black.title": "OpenCode Black | ราคา", + "black.plan.icon20": "แผน Black 20", + "black.plan.icon100": "แผน Black 100", + "black.plan.icon200": "แผน Black 200", + "black.plan.multiplier100": "ใช้งานได้มากกว่า Black 20 ถึง 5 เท่า", + "black.plan.multiplier200": "ใช้งานได้มากกว่า Black 20 ถึง 20 เท่า", + "black.price.perMonth": "ต่อเดือน", + "black.price.perPersonBilledMonthly": "ต่อคน เรียกเก็บรายเดือน", + "black.terms.1": "การสมัครสมาชิกของคุณจะยังไม่เริ่มต้นทันที", + "black.terms.2": "คุณจะถูกเพิ่มในรายชื่อรอและจะได้รับการเปิดใช้งานเร็วๆ นี้", + "black.terms.3": "บัตรของคุณจะถูกตัดเงินเมื่อการสมัครสมาชิกของคุณถูกเปิดใช้งานเท่านั้น", + "black.terms.4": "มีขีดจำกัดการใช้งาน การใช้ระบบอัตโนมัติอย่างหนักอาจทำให้ถึงขีดจำกัดเร็วขึ้น", + "black.terms.5": "การสมัครสมาชิกสำหรับบุคคลธรรมดา ติดต่อฝ่ายองค์กรสำหรับทีม", + "black.terms.6": "ขีดจำกัดอาจมีการปรับเปลี่ยนและแผนอาจถูกยกเลิกในอนาคต", + "black.terms.7": "ยกเลิกการสมัครสมาชิกได้ตลอดเวลา", + "black.action.continue": "ดำเนินการต่อ", + "black.finePrint.beforeTerms": "ราคาที่แสดงยังไม่รวมภาษีที่เกี่ยวข้อง", + "black.finePrint.terms": "ข้อกำหนดการให้บริการ", + "black.workspace.title": "OpenCode Black | เลือก Workspace", + "black.workspace.selectPlan": "เลือก Workspace สำหรับแผนนี้", + "black.workspace.name": "Workspace {{n}}", + "black.subscribe.title": "สมัครสมาชิก OpenCode Black", + "black.subscribe.paymentMethod": "วิธีการชำระเงิน", + "black.subscribe.loadingPaymentForm": "กำลังโหลดแบบฟอร์มการชำระเงิน...", + "black.subscribe.selectWorkspaceToContinue": "เลือก Workspace เพื่อดำเนินการต่อ", + "black.subscribe.failurePrefix": "โอ๊ะโอ!", + "black.subscribe.error.generic": "เกิดข้อผิดพลาด", + "black.subscribe.error.invalidPlan": "แผนไม่ถูกต้อง", + "black.subscribe.error.workspaceRequired": "จำเป็นต้องมี Workspace ID", + "black.subscribe.error.alreadySubscribed": "Workspace นี้มีการสมัครสมาชิกอยู่แล้ว", + "black.subscribe.processing": "กำลังดำเนินการ...", + "black.subscribe.submit": "สมัครสมาชิก ${{plan}}", + "black.subscribe.form.chargeNotice": "คุณจะถูกเรียกเก็บเงินเมื่อการสมัครสมาชิกของคุณถูกเปิดใช้งานเท่านั้น", + "black.subscribe.success.title": "คุณอยู่ในรายชื่อรอ OpenCode Black แล้ว", + "black.subscribe.success.subscriptionPlan": "แผนการสมัครสมาชิก", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "จำนวนเงิน", + "black.subscribe.success.amountValue": "${{plan}} ต่อเดือน", + "black.subscribe.success.paymentMethod": "วิธีการชำระเงิน", + "black.subscribe.success.dateJoined": "วันที่เข้าร่วม", + "black.subscribe.success.chargeNotice": "บัตรของคุณจะถูกเรียกเก็บเงินเมื่อการสมัครสมาชิกของคุณถูกเปิดใช้งาน", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "API Keys", + "workspace.nav.members": "สมาชิก", + "workspace.nav.billing": "การเรียกเก็บเงิน", + "workspace.nav.settings": "การตั้งค่า", + + "workspace.home.banner.beforeLink": "โมเดลที่เชื่อถือได้และปรับแต่งแล้วสำหรับเอเจนต์เขียนโค้ด", + "workspace.home.billing.loading": "กำลังโหลด...", + "workspace.home.billing.enable": "เปิดใช้งานการเรียกเก็บเงิน", + "workspace.home.billing.currentBalance": "ยอดคงเหลือปัจจุบัน", + + "workspace.newUser.feature.tested.title": "โมเดลที่ผ่านการทดสอบและตรวจสอบแล้ว", + "workspace.newUser.feature.tested.body": + "เราได้ทำเบนช์มาร์กและทดสอบโมเดลสำหรับเอเจนต์เขียนโค้ดโดยเฉพาะเพื่อให้มั่นใจถึงประสิทธิภาพที่ดีที่สุด", + "workspace.newUser.feature.quality.title": "คุณภาพสูงสุด", + "workspace.newUser.feature.quality.body": + "เข้าถึงโมเดลที่กำหนดค่าไว้เพื่อประสิทธิภาพสูงสุด - ไม่มีการลดเกรดหรือส่งงานไปยังผู้ให้บริการที่ราคาถูกกว่า", + "workspace.newUser.feature.lockin.title": "ไม่มีการผูกมัด (Lock-in)", + "workspace.newUser.feature.lockin.body": + "ใช้ Zen กับเอเจนต์เขียนโค้ดใดก็ได้ และกลับมาใช้ผู้ให้บริการรายอื่นด้วย OpenCode ได้ทุกเมื่อที่คุณต้องการ", + "workspace.newUser.copyApiKey": "คัดลอก API key", + "workspace.newUser.copyKey": "คัดลอก Key", + "workspace.newUser.copied": "คัดลอกแล้ว!", + "workspace.newUser.step.enableBilling": "เปิดใช้งานการเรียกเก็บเงิน", + "workspace.newUser.step.login.before": "รัน", + "workspace.newUser.step.login.after": "และเลือก OpenCode", + "workspace.newUser.step.pasteKey": "วาง API key ของคุณ", + "workspace.newUser.step.models.before": "เริ่ม OpenCode และรัน", + "workspace.newUser.step.models.after": "เพื่อเลือกโมเดล", + + "workspace.models.title": "โมเดล", + "workspace.models.subtitle.beforeLink": "จัดการว่าโมเดลใดที่สมาชิกใน Workspace สามารถเข้าถึงได้", + "workspace.models.table.model": "โมเดล", + "workspace.models.table.enabled": "เปิดใช้งาน", + + "workspace.providers.title": "Bring Your Own Key", + "workspace.providers.subtitle": "กำหนดค่า API keys ของคุณเองจากผู้ให้บริการ AI", + "workspace.providers.placeholder": "ป้อน {{provider}} API key ({{prefix}}...)", + "workspace.providers.configure": "กำหนดค่า", + "workspace.providers.edit": "แก้ไข", + "workspace.providers.delete": "ลบ", + "workspace.providers.saving": "กำลังบันทึก...", + "workspace.providers.save": "บันทึก", + "workspace.providers.table.provider": "ผู้ให้บริการ", + "workspace.providers.table.apiKey": "API Key", + + "workspace.usage.title": "ประวัติการใช้งาน", + "workspace.usage.subtitle": "การใช้งานและต้นทุน API ล่าสุด", + "workspace.usage.empty": "ทำการเรียก API ครั้งแรกเพื่อเริ่มต้น", + "workspace.usage.table.date": "วันที่", + "workspace.usage.table.model": "โมเดล", + "workspace.usage.table.input": "Input", + "workspace.usage.table.output": "Output", + "workspace.usage.table.cost": "ค่าใช้จ่าย", + "workspace.usage.breakdown.input": "Input", + "workspace.usage.breakdown.cacheRead": "Cache Read", + "workspace.usage.breakdown.cacheWrite": "Cache Write", + "workspace.usage.breakdown.output": "Output", + "workspace.usage.breakdown.reasoning": "Reasoning", + "workspace.usage.subscription": "สมัครสมาชิก (${{amount}})", + + "workspace.cost.title": "ค่าใช้จ่าย", + "workspace.cost.subtitle": "ต้นทุนการใช้งานแยกตามโมเดล", + "workspace.cost.allModels": "ทุกโมเดล", + "workspace.cost.allKeys": "ทุก Key", + "workspace.cost.deletedSuffix": "(ลบแล้ว)", + "workspace.cost.empty": "ไม่มีข้อมูลการใช้งานในช่วงเวลาที่เลือก", + "workspace.cost.subscriptionShort": "sub", + + "workspace.keys.title": "API Keys", + "workspace.keys.subtitle": "จัดการ API keys ของคุณสำหรับการเข้าถึงบริการ OpenCode", + "workspace.keys.create": "สร้าง API Key", + "workspace.keys.placeholder": "ป้อนชื่อ Key", + "workspace.keys.empty": "สร้าง OpenCode Gateway API key", + "workspace.keys.table.name": "ชื่อ", + "workspace.keys.table.key": "Key", + "workspace.keys.table.createdBy": "สร้างโดย", + "workspace.keys.table.lastUsed": "ใช้ล่าสุด", + "workspace.keys.copyApiKey": "คัดลอก API key", + "workspace.keys.delete": "ลบ", + + "workspace.members.title": "สมาชิก", + "workspace.members.subtitle": "จัดการสมาชิก Workspace และสิทธิ์ของพวกเขา", + "workspace.members.invite": "เชิญสมาชิก", + "workspace.members.inviting": "กำลังเชิญ...", + "workspace.members.beta.beforeLink": "Workspace ให้บริการฟรีสำหรับทีมในช่วงเบต้า", + "workspace.members.form.invitee": "ผู้ได้รับเชิญ", + "workspace.members.form.emailPlaceholder": "ใส่อีเมล", + "workspace.members.form.role": "บทบาท", + "workspace.members.form.monthlyLimit": "วงเงินการใช้จ่ายรายเดือน", + "workspace.members.noLimit": "ไม่มีขีดจำกัด", + "workspace.members.noLimitLowercase": "ไม่มีขีดจำกัด", + "workspace.members.invited": "เชิญแล้ว", + "workspace.members.edit": "แก้ไข", + "workspace.members.delete": "ลบ", + "workspace.members.saving": "กำลังบันทึก...", + "workspace.members.save": "บันทึก", + "workspace.members.table.email": "อีเมล", + "workspace.members.table.role": "บทบาท", + "workspace.members.table.monthLimit": "วงเงินเดือน", + "workspace.members.role.admin": "แอดมิน", + "workspace.members.role.adminDescription": "สามารถจัดการโมเดล สมาชิก และการเรียกเก็บเงินได้", + "workspace.members.role.member": "สมาชิก", + "workspace.members.role.memberDescription": "สามารถสร้าง API keys สำหรับตัวเองได้เท่านั้น", + + "workspace.settings.title": "การตั้งค่า", + "workspace.settings.subtitle": "อัปเดตชื่อ Workspace และการตั้งค่าของคุณ", + "workspace.settings.workspaceName": "ชื่อ Workspace", + "workspace.settings.defaultName": "ค่าเริ่มต้น", + "workspace.settings.updating": "กำลังอัปเดต...", + "workspace.settings.save": "บันทึก", + "workspace.settings.edit": "แก้ไข", + + "workspace.billing.title": "การเรียกเก็บเงิน", + "workspace.billing.subtitle.beforeLink": "จัดการวิธีการชำระเงิน", + "workspace.billing.contactUs": "ติดต่อเรา", + "workspace.billing.subtitle.afterLink": "หากคุณมีคำถามใดๆ", + "workspace.billing.currentBalance": "ยอดคงเหลือปัจจุบัน", + "workspace.billing.add": "เพิ่ม $", + "workspace.billing.enterAmount": "ใส่จำนวนเงิน", + "workspace.billing.loading": "กำลังโหลด...", + "workspace.billing.addAction": "เพิ่ม", + "workspace.billing.addBalance": "เพิ่มยอดคงเหลือ", + "workspace.billing.linkedToStripe": "เชื่อมโยงกับ Stripe", + "workspace.billing.manage": "จัดการ", + "workspace.billing.enable": "เปิดใช้งานการเรียกเก็บเงิน", + + "workspace.monthlyLimit.title": "วงเงินรายเดือน", + "workspace.monthlyLimit.subtitle": "ตั้งขีดจำกัดการใช้งานรายเดือนสำหรับบัญชีของคุณ", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "กำลังตั้งค่า...", + "workspace.monthlyLimit.set": "ตั้งค่า", + "workspace.monthlyLimit.edit": "แก้ไขขีดจำกัด", + "workspace.monthlyLimit.noLimit": "ไม่ได้ตั้งขีดจำกัดการใช้งาน", + "workspace.monthlyLimit.currentUsage.beforeMonth": "การใช้งานปัจจุบันสำหรับ", + "workspace.monthlyLimit.currentUsage.beforeAmount": "คือ $", + + "workspace.reload.title": "โหลดซ้ำอัตโนมัติ", + "workspace.reload.disabled.before": "การโหลดซ้ำอัตโนมัติ", + "workspace.reload.disabled.state": "ปิดใช้งานอยู่", + "workspace.reload.disabled.after": "เปิดใช้งานเพื่อเติมเงินอัตโนมัติเมื่อยอดคงเหลือต่ำ", + "workspace.reload.enabled.before": "การโหลดซ้ำอัตโนมัติ", + "workspace.reload.enabled.state": "เปิดใช้งานอยู่", + "workspace.reload.enabled.middle": "เราจะเติมเงิน", + "workspace.reload.processingFee": "ค่าธรรมเนียมดำเนินการ", + "workspace.reload.enabled.after": "เมื่อยอดคงเหลือถึง", + "workspace.reload.edit": "แก้ไข", + "workspace.reload.enable": "เปิดใช้งาน", + "workspace.reload.enableAutoReload": "เปิดใช้งานการโหลดซ้ำอัตโนมัติ", + "workspace.reload.reloadAmount": "เติมเงิน $", + "workspace.reload.whenBalanceReaches": "เมื่อยอดถึง $", + "workspace.reload.saving": "กำลังบันทึก...", + "workspace.reload.save": "บันทึก", + "workspace.reload.failedAt": "เติมเงินล้มเหลวเมื่อ", + "workspace.reload.reason": "เหตุผล:", + "workspace.reload.updatePaymentMethod": "โปรดอัปเดตวิธีการชำระเงินของคุณแล้วลองอีกครั้ง", + "workspace.reload.retrying": "กำลังลองอีกครั้ง...", + "workspace.reload.retry": "ลองอีกครั้ง", + + "workspace.payments.title": "ประวัติการชำระเงิน", + "workspace.payments.subtitle": "รายการธุรกรรมการชำระเงินล่าสุด", + "workspace.payments.table.date": "วันที่", + "workspace.payments.table.paymentId": "Payment ID", + "workspace.payments.table.amount": "จำนวนเงิน", + "workspace.payments.table.receipt": "ใบเสร็จ", + "workspace.payments.type.credit": "credit", + "workspace.payments.type.subscription": "subscription", + "workspace.payments.view": "ดู", + + "workspace.black.loading": "กำลังโหลด...", + "workspace.black.time.day": "วัน", + "workspace.black.time.days": "วัน", + "workspace.black.time.hour": "ชั่วโมง", + "workspace.black.time.hours": "ชั่วโมง", + "workspace.black.time.minute": "นาที", + "workspace.black.time.minutes": "นาที", + "workspace.black.time.fewSeconds": "ไม่กี่วินาที", + "workspace.black.subscription.title": "การสมัครสมาชิก", + "workspace.black.subscription.message": "คุณสมัครสมาชิก OpenCode Black ในราคา ${{plan}} ต่อเดือน", + "workspace.black.subscription.manage": "จัดการการสมัครสมาชิก", + "workspace.black.subscription.rollingUsage": "การใช้งาน 5 ชั่วโมง", + "workspace.black.subscription.weeklyUsage": "การใช้งานรายสัปดาห์", + "workspace.black.subscription.resetsIn": "รีเซ็ตใน", + "workspace.black.subscription.useBalance": "ใช้ยอดเงินคงเหลือของคุณหลังจากถึงขีดจำกัดการใช้งานแล้ว", + "workspace.black.waitlist.title": "รายชื่อรอ", + "workspace.black.waitlist.joined": "คุณอยู่ในรายชื่อรอสำหรับแผน OpenCode Black ราคา ${{plan}} ต่อเดือน", + "workspace.black.waitlist.ready": "เราพร้อมที่จะลงทะเบียนให้คุณเข้าสู่แผน OpenCode Black ราคา ${{plan}} ต่อเดือนแล้ว", + "workspace.black.waitlist.leave": "ออกจากรายชื่อรอ", + "workspace.black.waitlist.leaving": "กำลังออกจาก...", + "workspace.black.waitlist.left": "ออกแล้ว", + "workspace.black.waitlist.enroll": "ลงทะเบียน", + "workspace.black.waitlist.enrolling": "กำลังลงทะเบียน...", + "workspace.black.waitlist.enrolled": "ลงทะเบียนแล้ว", + "workspace.black.waitlist.enrollNote": + "เมื่อคุณคลิกลงทะเบียน การสมัครสมาชิกของคุณจะเริ่มต้นทันทีและบัตรของคุณจะถูกเรียกเก็บเงิน", + + "download.title": "OpenCode | ดาวน์โหลด", + "download.meta.description": "ดาวน์โหลด OpenCode สำหรับ macOS, Windows และ Linux", + "download.hero.title": "ดาวน์โหลด OpenCode", + "download.hero.subtitle": "พร้อมใช้งานในเวอร์ชันเบต้าสำหรับ macOS, Windows และ Linux", + "download.hero.button": "ดาวน์โหลดสำหรับ {{os}}", + "download.section.terminal": "OpenCode Terminal", + "download.section.desktop": "OpenCode Desktop (Beta)", + "download.section.extensions": "ส่วนขยาย OpenCode", + "download.section.integrations": "การเชื่อมต่อ OpenCode", + "download.action.download": "ดาวน์โหลด", + "download.action.install": "ติดตั้ง", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "ไม่จำเป็นเสมอไป แต่อาจจะต้องมี คุณจะต้องมีการสมัครสมาชิก AI หากต้องการเชื่อมต่อ OpenCode กับผู้ให้บริการที่มีค่าใช้จ่าย แม้ว่าคุณจะสามารถทำงานกับ", + "download.faq.a3.localLink": "โมเดล Local", + "download.faq.a3.afterLocal.beforeZen": "ได้ฟรี แม้ว่าเราจะแนะนำให้ผู้ใช้ใช้งาน", + "download.faq.a3.afterZen": ", OpenCode ก็ทำงานร่วมกับผู้ให้บริการยอดนิยมทั้งหมด เช่น OpenAI, Anthropic, xAI เป็นต้น", + + "download.faq.a5.p1": "OpenCode ใช้งานได้ฟรี 100%", + "download.faq.a5.p2.beforeZen": + "ค่าใช้จ่ายเพิ่มเติมใดๆ จะมาจากการสมัครสมาชิกของคุณกับผู้ให้บริการโมเดล แม้ว่า OpenCode จะทำงานร่วมกับผู้ให้บริการโมเดลใดก็ได้ แต่เราแนะนำให้ใช้", + "download.faq.a5.p2.afterZen": "", + + "download.faq.a6.p1": "ข้อมูลของคุณจะถูกจัดเก็บเฉพาะเมื่อคุณสร้างลิงก์ที่แชร์ได้ใน OpenCode เท่านั้น", + "download.faq.a6.p2.beforeShare": "เรียนรู้เพิ่มเติมเกี่ยวกับ", + "download.faq.a6.shareLink": "หน้าแชร์", + + "enterprise.title": "OpenCode | โซลูชันระดับองค์กรสำหรับองค์กรของคุณ", + "enterprise.meta.description": "ติดต่อ OpenCode สำหรับโซลูชันระดับองค์กร", + "enterprise.hero.title": "โค้ดของคุณเป็นของคุณ", + "enterprise.hero.body1": + "OpenCode ทำงานอย่างปลอดภัยภายในองค์กรของคุณ โดยไม่มีการจัดเก็บข้อมูลหรือบริบท และไม่มีข้อจำกัดด้านไลเซนส์หรือการอ้างสิทธิ์ความเป็นเจ้าของ เริ่มทดลองใช้งานกับทีมของคุณ แล้วนำไปใช้งานทั่วทั้งองค์กรโดยการผสานรวมกับ SSO และ AI gateway ภายในของคุณ", + "enterprise.hero.body2": "บอกเราว่าเราจะช่วยได้อย่างไร", + "enterprise.form.name.label": "ชื่อ-นามสกุล", + "enterprise.form.name.placeholder": "Jeff Bezos", + "enterprise.form.role.label": "ตำแหน่ง", + "enterprise.form.role.placeholder": "ประธานกรรมการบริหาร", + "enterprise.form.email.label": "อีเมลบริษัท", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "คุณกำลังพยายามแก้ปัญหาอะไร?", + "enterprise.form.message.placeholder": "เราต้องการความช่วยเหลือเรื่อง...", + "enterprise.form.send": "ส่ง", + "enterprise.form.sending": "กำลังส่ง...", + "enterprise.form.success": "ส่งข้อความแล้ว เราจะติดต่อกลับเร็วๆ นี้", + "enterprise.faq.title": "คำถามที่พบบ่อย", + "enterprise.faq.q1": "OpenCode Enterprise คืออะไร?", + "enterprise.faq.a1": + "OpenCode Enterprise สำหรับองค์กรที่ต้องการให้มั่นใจว่าโค้ดและข้อมูลจะไม่ออกนอกโครงสร้างพื้นฐานของตน ทำได้โดยใช้การตั้งค่าแบบศูนย์กลางที่ผสานรวมกับ SSO และ AI gateway ภายในของคุณ", + "enterprise.faq.q2": "จะเริ่มต้นกับ OpenCode Enterprise ได้อย่างไร?", + "enterprise.faq.a2": + "เพียงเริ่มจากการทดลองใช้งานภายในกับทีมของคุณ โดยค่าเริ่มต้น OpenCode ไม่จัดเก็บโค้ดหรือข้อมูลบริบทของคุณ ทำให้เริ่มต้นได้ง่าย จากนั้นติดต่อเราเพื่อพูดคุยเรื่องราคาและตัวเลือกการติดตั้งใช้งาน", + "enterprise.faq.q3": "ราคาสำหรับองค์กรคิดอย่างไร?", + "enterprise.faq.a3": + "เราเสนอราคาแบบต่อที่นั่ง (per-seat) หากคุณมี LLM gateway ของคุณเอง เราจะไม่คิดค่าบริการตามโทเค็นที่ใช้ สำหรับรายละเอียดเพิ่มเติม โปรดติดต่อเราเพื่อขอใบเสนอราคาตามความต้องการขององค์กรของคุณ", + "enterprise.faq.q4": "ข้อมูลของฉันปลอดภัยกับ OpenCode Enterprise หรือไม่?", + "enterprise.faq.a4": + "ใช่ OpenCode ไม่จัดเก็บโค้ดหรือข้อมูลบริบทของคุณ การประมวลผลทั้งหมดเกิดขึ้นในเครื่องหรือผ่านการเรียก API โดยตรงไปยังผู้ให้บริการ AI ของคุณ ด้วยการตั้งค่าแบบศูนย์กลางและการผสานรวม SSO ข้อมูลของคุณจะยังคงปลอดภัยอยู่ภายในโครงสร้างพื้นฐานขององค์กร", + + "brand.title": "OpenCode | แบรนด์", + "brand.meta.description": "แนวทางการใช้แบรนด์ OpenCode", + "brand.heading": "แนวทางการใช้แบรนด์", + "brand.subtitle": "ทรัพยากรและแอสเซทเพื่อช่วยให้คุณใช้งานแบรนด์ OpenCode", + "brand.downloadAll": "ดาวน์โหลดแอสเซททั้งหมด", + + "changelog.title": "OpenCode | บันทึกการเปลี่ยนแปลง", + "changelog.meta.description": "บันทึกการออกรุ่นและบันทึกการเปลี่ยนแปลง OpenCode", + "changelog.hero.title": "บันทึกการเปลี่ยนแปลง", + "changelog.hero.subtitle": "การอัปเดตและการปรับปรุงใหม่ใน OpenCode", + "changelog.empty": "ไม่พบรายการบันทึกการเปลี่ยนแปลง", + "changelog.viewJson": "ดู JSON", + + "bench.list.title": "Benchmark", + "bench.list.heading": "Benchmarks", + "bench.list.table.agent": "เอเจนต์", + "bench.list.table.model": "โมเดล", + "bench.list.table.score": "คะแนน", + + "bench.detail.title": "Benchmark - {{task}}", + "bench.detail.notFound": "ไม่พบงาน", + "bench.detail.na": "N/A", + "bench.detail.labels.agent": "เอเจนต์", + "bench.detail.labels.model": "โมเดล", + "bench.detail.labels.task": "งาน", + "bench.detail.labels.repo": "Repo", + "bench.detail.labels.from": "จาก", + "bench.detail.labels.to": "ถึง", + "bench.detail.labels.prompt": "Prompt", + "bench.detail.labels.commit": "Commit", + "bench.detail.labels.averageDuration": "ระยะเวลาเฉลี่ย", + "bench.detail.labels.averageScore": "คะแนนเฉลี่ย", + "bench.detail.labels.averageCost": "ค่าใช้จ่ายเฉลี่ย", + "bench.detail.labels.summary": "สรุป", + "bench.detail.labels.runs": "Runs", + "bench.detail.labels.score": "คะแนน", + "bench.detail.labels.base": "ฐาน", + "bench.detail.labels.penalty": "บทลงโทษ", + "bench.detail.labels.weight": "น้ำหนัก", + "bench.detail.table.run": "Run", + "bench.detail.table.score": "คะแนน (ฐาน - บทลงโทษ)", + "bench.detail.table.cost": "ค่าใช้จ่าย", + "bench.detail.table.duration": "ระยะเวลา", + "bench.detail.run.title": "Run {{n}}", + "bench.detail.rawJson": "Raw JSON", +} satisfies Dict diff --git a/packages/console/app/src/i18n/tr.ts b/packages/console/app/src/i18n/tr.ts new file mode 100644 index 00000000000..e2f747704e7 --- /dev/null +++ b/packages/console/app/src/i18n/tr.ts @@ -0,0 +1,598 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "Dokümantasyon", + "nav.changelog": "Değişiklik günlüğü", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "Kurumsal", + "nav.zen": "Zen", + "nav.login": "Giriş", + "nav.free": "Ücretsiz", + "nav.home": "Ana sayfa", + "nav.openMenu": "Menüyü aç", + "nav.getStartedFree": "Ücretsiz başla", + + "nav.context.copyLogo": "Logoyu SVG olarak kopyala", + "nav.context.copyWordmark": "Wordmark'ı SVG olarak kopyala", + "nav.context.brandAssets": "Marka varlıkları", + + "footer.github": "GitHub", + "footer.docs": "Dokümantasyon", + "footer.changelog": "Değişiklik günlüğü", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "Marka", + "legal.privacy": "Gizlilik", + "legal.terms": "Koşullar", + + "email.title": "Yeni ürünler yayınladığımızda ilk siz haberdar olun", + "email.subtitle": "Erken erişim için bekleme listesine katılın.", + "email.placeholder": "E-posta adresi", + "email.subscribe": "Abone ol", + "email.success": "Neredeyse bitti, gelen kutunuzu kontrol edin ve e-postanızı onaylayın", + + "notFound.title": "Bulunamadı | opencode", + "notFound.heading": "404 - Sayfa bulunamadı", + "notFound.home": "Ana sayfa", + "notFound.docs": "Dokümantasyon", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "Çıkış", + + "workspace.select": "Çalışma alanı seç", + "workspace.createNew": "+ Yeni çalışma alanı oluştur", + "workspace.modal.title": "Yeni çalışma alanı oluştur", + "workspace.modal.placeholder": "Çalışma alanı adını girin", + + "common.cancel": "İptal", + "common.creating": "Oluşturuluyor...", + "common.create": "Oluştur", + + "common.videoUnsupported": "Tarayıcınız video etiketini desteklemiyor.", + "common.figure": "Şekil {{n}}.", + "common.faq": "SSS", + "common.learnMore": "Daha fazla bilgi", + + "error.invalidPlan": "Geçersiz plan", + "error.workspaceRequired": "Çalışma alanı kimliği (ID) gerekli", + "error.alreadySubscribed": "Bu çalışma alanının zaten bir aboneliği var", + "error.limitRequired": "Limit gerekli.", + "error.monthlyLimitInvalid": "Geçerli bir aylık limit belirleyin.", + "error.workspaceNameRequired": "Çalışma alanı adı gerekli.", + "error.nameTooLong": "İsim 255 karakter veya daha az olmalıdır.", + "error.emailRequired": "E-posta gerekli", + "error.roleRequired": "Rol gerekli", + "error.idRequired": "Kimlik (ID) gerekli", + "error.nameRequired": "İsim gerekli", + "error.providerRequired": "Sağlayıcı gerekli", + "error.apiKeyRequired": "API anahtarı gerekli", + "error.modelRequired": "Model gerekli", + "error.reloadAmountMin": "Yükleme tutarı en az ${{amount}} olmalıdır", + "error.reloadTriggerMin": "Bakiye tetikleyicisi en az ${{amount}} olmalıdır", + + "home.title": "OpenCode | Açık kaynaklı yapay zeka kodlama ajanı", + + "temp.title": "opencode | Terminal için geliştirilmiş yapay zeka kodlama ajanı", + "temp.hero.title": "Terminal için geliştirilmiş yapay zeka kodlama ajanı", + "temp.zen": "opencode zen", + "temp.getStarted": "Başlayın", + "temp.feature.native.title": "Yerel (Native) TUI", + "temp.feature.native.body": "Duyarlı, yerel, temalandırılabilir bir terminal arayüzü", + "temp.feature.zen.beforeLink": "opencode tarafından sağlanan ", + "temp.feature.zen.link": "seçkin modeller listesi", + "temp.feature.zen.afterLink": "", + "temp.feature.models.beforeLink": "Yerel modeller dahil 75+ LLM sağlayıcısını ", + "temp.feature.models.afterLink": " üzerinden destekler", + "temp.screenshot.caption": "opencode TUI ve tokyonight teması", + "temp.screenshot.alt": "tokyonight temalı opencode TUI", + + "home.banner.badge": "Yeni", + "home.banner.text": "Masaüstü uygulaması beta olarak kullanılabilir", + "home.banner.platforms": "macOS, Windows ve Linux'ta", + "home.banner.downloadNow": "Şimdi indir", + "home.banner.downloadBetaNow": "Masaüstü betayı şimdi indir", + + "home.hero.title": "Açık kaynaklı yapay zeka kodlama ajanı", + "home.hero.subtitle.a": "Ücretsiz modeller dahil veya herhangi bir sağlayıcıdan herhangi bir modeli bağlayın,", + "home.hero.subtitle.b": "Claude, GPT, Gemini ve daha fazlası dahil.", + + "home.install.ariaLabel": "Kurulum seçenekleri", + + "home.what.title": "OpenCode nedir?", + "home.what.body": + "OpenCode, terminalinizde, IDE'nizde veya masaüstünde kod yazmanıza yardım eden açık kaynaklı bir ajandır.", + "home.what.lsp.title": "LSP etkin", + "home.what.lsp.body": "LLM için doğru LSP'leri otomatik olarak yükler", + "home.what.multiSession.title": "Çoklu oturum", + "home.what.multiSession.body": "Aynı projede birden fazla ajanı paralel çalıştırın", + "home.what.shareLinks.title": "Paylaşım bağlantıları", + "home.what.shareLinks.body": "Referans veya hata ayıklama için herhangi bir oturumu bağlantı olarak paylaşın", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "Copilot hesabınızı kullanmak için GitHub ile giriş yapın", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "ChatGPT Plus veya Pro hesabınızı kullanmak için OpenAI ile giriş yapın", + "home.what.anyModel.title": "Herhangi bir model", + "home.what.anyModel.body": "Models.dev üzerinden 75+ LLM sağlayıcısı, yerel modeller dahil", + "home.what.anyEditor.title": "Herhangi bir editör", + "home.what.anyEditor.body": "Terminal arayüzü, masaüstü uygulaması ve IDE uzantısı olarak kullanılabilir", + "home.what.readDocs": "Dokümanları oku", + + "home.growth.title": "Açık kaynaklı yapay zeka kodlama ajanı", + "home.growth.body": + "GitHub'da {{stars}}+ yıldız, {{contributors}} katılımcı ve {{commits}}+ commit ile OpenCode, her ay {{monthlyUsers}}+ geliştirici tarafından kullanılıyor ve güveniliyor.", + "home.growth.githubStars": "GitHub Yıldızları", + "home.growth.contributors": "Katılımcılar", + "home.growth.monthlyDevs": "Aylık Geliştiriciler", + + "home.privacy.title": "Önce gizlilik için 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:", + "home.privacy.link": "gizlilik", + + "home.faq.q1": "OpenCode nedir?", + "home.faq.a1": + "OpenCode, herhangi bir AI modeliyle kod yazmanıza ve çalıştırmanıza yardım eden açık kaynaklı bir ajandır. Terminal arayüzü, masaüstü uygulaması veya IDE uzantısı olarak kullanılabilir.", + "home.faq.q2": "OpenCode'u nasıl kullanırım?", + "home.faq.a2.before": "Başlamanın en kolay yolu", + "home.faq.a2.link": "girişi okumaktır", + "home.faq.q3": "OpenCode için ek AI aboneliklerine ihtiyacım var mı?", + "home.faq.a3.p1": "Şart değil. OpenCode, hesap açmadan kullanabileceğiniz ücretsiz modellerle gelir.", + "home.faq.a3.p2.beforeZen": "Bunun dışında, popüler kodlama modellerini kullanmak için bir", + "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.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.desktop": "masaüstü", + "home.faq.a5.and": "ve", + "home.faq.a5.web": "web", + "home.faq.q6": "OpenCode ne kadar?", + "home.faq.a6": + "OpenCode %100 ücretsizdir. Ayrıca ücretsiz model setiyle gelir. Başka bir sağlayıcı bağlarsanız ek maliyetler olabilir.", + "home.faq.q7": "Veri ve gizlilik ne olacak?", + "home.faq.a7.p1": + "Verileriniz yalnızca ücretsiz modellerimizi kullandığınızda veya paylaşılabilir bağlantılar oluşturduğunuzda saklanır.", + "home.faq.a7.p2.beforeModels": "Daha fazla bilgi:", + "home.faq.a7.p2.modelsLink": "modellerimiz", + "home.faq.a7.p2.and": "ve", + "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.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.", + + "home.zenCta.title": "Kodlama ajanları için güvenilir, optimize modeller", + "home.zenCta.body": + "Zen, OpenCode'un kodlama ajanları için özel olarak test edip benchmark ettiği seçilmiş AI modellerine erişim sağlar. Sağlayıcılar arasında tutarsız performans ve kalite konusunda endişelenmeyin; çalışan, doğrulanmış modelleri kullanın.", + "home.zenCta.link": "Zen hakkında", + + "zen.title": "OpenCode Zen | Kodlama ajanları için güvenilir, optimize edilmiş modellerin seçilmiş seti", + "zen.hero.title": "Kodlama ajanları için güvenilir, optimize modeller", + "zen.hero.body": + "Zen, OpenCode'un kodlama ajanları için özel olarak test edip benchmark ettiği seçilmiş AI modellerine erişim sağlar. Sağlayıcılar arasında tutarsız performans ve kalite konusunda endişelenmeyin; çalışan, doğrulanmış modelleri kullanın.", + + "zen.faq.q1": "OpenCode Zen nedir?", + "zen.faq.a1": + "Zen, OpenCode ekibi tarafından oluşturulan ve kodlama ajanları için test edilip benchmark edilen seçilmiş bir AI model setidir.", + "zen.faq.q2": "Zen'i daha doğru yapan nedir?", + "zen.faq.a2": + "Zen yalnızca kodlama ajanları için özel olarak test edilip benchmark edilmiş modelleri sunar. Biftek kesmek için tereyağı bıçağı kullanmazsın; kodlama için kötü modeller kullanma.", + "zen.faq.q3": "Zen daha ucuz mu?", + "zen.faq.a3": + "Zen kâr amaçlı değildir. Zen, model sağlayıcılarının maliyetlerini size yansıtır. Zen'in kullanımı arttıkça OpenCode daha iyi fiyatlar pazarlayabilir ve bunları size yansıtabilir.", + "zen.faq.q4": "Zen ne kadar?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "istek başı ücret alır", + "zen.faq.a4.p1.afterPricing": + "ve hiçbir markup eklemez, yani model sağlayıcının ücretlendirdiği tutarı aynen ödersiniz.", + "zen.faq.a4.p2.beforeAccount": "Toplam maliyetiniz kullanım miktarına bağlıdır ve aylık harcama limitlerini", + "zen.faq.a4.p2.accountLink": "hesabınızda ayarlayabilirsiniz", + "zen.faq.a4.p3": + "Maliyetleri karşılamak için OpenCode, $20 bakiye yüklemesi başına yalnızca $1.23 tutarında küçük bir ödeme işleme ücreti ekler.", + "zen.faq.q5": "Veri ve gizlilik ne olacak?", + "zen.faq.a5.beforeExceptions": + "Tüm Zen modelleri ABD'de barındırılır. Sağlayıcılar sıfır-retention politikasını uygular ve verilerinizi model eğitimi için kullanmaz; şu", + "zen.faq.a5.exceptionsLink": "istisnalarla", + "zen.faq.q6": "Harcama limitleri ayarlayabilir miyim?", + "zen.faq.a6": "Evet, hesabınızda aylık harcama limitleri ayarlayabilirsiniz.", + "zen.faq.q7": "İptal edebilir miyim?", + "zen.faq.a7": + "Evet, istediğiniz zaman faturalandırmayı devre dışı bırakabilir ve kalan bakiyenizi kullanabilirsiniz.", + "zen.faq.q8": "Zen'i diğer kodlama ajanlarıyla kullanabilir miyim?", + "zen.faq.a8": + "Zen OpenCode ile harika çalışır, ama Zen'i herhangi bir ajan ile kullanabilirsiniz. Tercih ettiğiniz kodlama ajanında kurulum talimatlarını izleyin.", + + "zen.cta.start": "Zen'i kullanmaya başlayın", + "zen.pricing.title": "20$ Kullandıkça öde bakiyesi ekle", + "zen.pricing.fee": "(+1,23$ kart işlem ücreti)", + "zen.pricing.body": + "Herhangi bir ajan ile kullanın. Aylık harcama limitlerini belirleyin. İstediğiniz zaman iptal edin.", + "zen.problem.title": "Zen hangi sorunu çözüyor?", + "zen.problem.body": + "Pek çok model mevcut ancak yalnızca birkaçı kodlama ajanlarıyla iyi çalışıyor. Çoğu sağlayıcı, bunları değişen sonuçlarla farklı şekilde yapılandırır.", + "zen.problem.subtitle": "Bu sorunu yalnızca OpenCode kullanıcıları için değil, herkes için düzeltiyoruz.", + "zen.problem.item1": "Seçilen modelleri test etme ve ekiplerine danışmanlık yapma", + "zen.problem.item2": "Düzgün bir şekilde teslim edildiklerinden emin olmak için sağlayıcılarla çalışmak", + "zen.problem.item3": "Önerdiğimiz tüm model-sağlayıcı kombinasyonlarının karşılaştırılması", + "zen.how.title": "Zen nasıl çalışır?", + "zen.how.body": "Zen'i OpenCode ile kullanmanızı önersek de, Zen'i herhangi bir ajan ile kullanabilirsiniz.", + "zen.how.step1.title": "Kaydolun ve 20$ bakiye ekleyin", + "zen.how.step1.beforeLink": "takip edin", + "zen.how.step1.link": "kurulum talimatları", + "zen.how.step2.title": "Şeffaf fiyatlandırmayla Zen kullanın", + "zen.how.step2.link": "istek başına ödeme", + "zen.how.step2.afterLink": "sıfır işaretlemeyle", + "zen.how.step3.title": "Otomatik yükleme", + "zen.how.step3.body": "bakiyeniz 5$'a ulaştığında otomatik olarak 20$ ekleyeceğiz", + "zen.privacy.title": "Gizliliğiniz bizim için önemlidir", + "zen.privacy.beforeExceptions": + "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", + + "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", + "black.hero.subtitle": "Claude, GPT, Gemini ve daha fazlası dahil", + "black.title": "OpenCode Black | Fiyatlandırma", + "black.plan.icon20": "Black 20 planı", + "black.plan.icon100": "Black 100 planı", + "black.plan.icon200": "Black 200 planı", + "black.plan.multiplier100": "Black 20'den 5 kat daha fazla kullanım", + "black.plan.multiplier200": "Black 20'den 20 kat daha fazla kullanım", + "black.price.perMonth": "aylık", + "black.price.perPersonBilledMonthly": "kişi başı aylık faturalandırılır", + "black.terms.1": "Aboneliğiniz hemen başlamayacak", + "black.terms.2": "Bekleme listesine ekleneceksiniz ve yakında aktive edileceksiniz", + "black.terms.3": "Kartınızdan sadece aboneliğiniz aktive edildiğinde ödeme alınacaktır", + "black.terms.4": "Kullanım limitleri geçerlidir, yoğun otomatik kullanım limitlere daha erken ulaşabilir", + "black.terms.5": "Abonelikler bireyler içindir, ekipler için Enterprise ile iletişime geçin", + "black.terms.6": "Limitler ayarlanabilir ve planlar gelecekte sonlandırılabilir", + "black.terms.7": "Aboneliğinizi istediğiniz zaman iptal edin", + "black.action.continue": "Devam et", + "black.finePrint.beforeTerms": "Gösterilen fiyatlara geçerli vergiler dahil değildir", + "black.finePrint.terms": "Hizmet Şartları", + "black.workspace.title": "OpenCode Black | Çalışma Alanı Seç", + "black.workspace.selectPlan": "Bu plan için bir çalışma alanı seçin", + "black.workspace.name": "Çalışma Alanı {{n}}", + "black.subscribe.title": "OpenCode Black'e Abone Ol", + "black.subscribe.paymentMethod": "Ödeme yöntemi", + "black.subscribe.loadingPaymentForm": "Ödeme formu yükleniyor...", + "black.subscribe.selectWorkspaceToContinue": "Devam etmek için bir çalışma alanı seçin", + "black.subscribe.failurePrefix": "Olamaz!", + "black.subscribe.error.generic": "Bir hata oluştu", + "black.subscribe.error.invalidPlan": "Geçersiz plan", + "black.subscribe.error.workspaceRequired": "Çalışma alanı ID'si gerekli", + "black.subscribe.error.alreadySubscribed": "Bu çalışma alanının zaten bir aboneliği var", + "black.subscribe.processing": "İşleniyor...", + "black.subscribe.submit": "${{plan}} Abone Ol", + "black.subscribe.form.chargeNotice": "Sadece aboneliğiniz aktive edildiğinde ücretlendirileceksiniz", + "black.subscribe.success.title": "OpenCode Black bekleme listesindesiniz", + "black.subscribe.success.subscriptionPlan": "Abonelik planı", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "Tutar", + "black.subscribe.success.amountValue": "Aylık ${{plan}}", + "black.subscribe.success.paymentMethod": "Ödeme yöntemi", + "black.subscribe.success.dateJoined": "Katılma tarihi", + "black.subscribe.success.chargeNotice": "Aboneliğiniz aktive edildiğinde kartınızdan ödeme alınacaktır", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "API Anahtarları", + "workspace.nav.members": "Üyeler", + "workspace.nav.billing": "Faturalandırma", + "workspace.nav.settings": "Ayarlar", + + "workspace.home.banner.beforeLink": "Kodlama ajanları için güvenilir optimize edilmiş modeller.", + "workspace.home.billing.loading": "Yükleniyor...", + "workspace.home.billing.enable": "Faturalandırmayı etkinleştir", + "workspace.home.billing.currentBalance": "Mevcut bakiye", + + "workspace.newUser.feature.tested.title": "Test Edilmiş ve Doğrulanmış Modeller", + "workspace.newUser.feature.tested.body": + "En iyi performansı sağlamak için modelleri özellikle kodlama ajanlarına yönelik olarak karşılaştırdık ve test ettik.", + "workspace.newUser.feature.quality.title": "En Yüksek Kalite", + "workspace.newUser.feature.quality.body": + "Optimum performans için yapılandırılmış modellere erişin; sürüm düşürme veya daha ucuz sağlayıcılara yönlendirme yok.", + "workspace.newUser.feature.lockin.title": "Kilitlenme Yok", + "workspace.newUser.feature.lockin.body": + "Zen'i herhangi bir kodlama ajanıyla kullanın ve istediğiniz zaman opencode ile diğer sağlayıcıları kullanmaya devam edin.", + "workspace.newUser.copyApiKey": "API anahtarını kopyala", + "workspace.newUser.copyKey": "Anahtarı Kopyala", + "workspace.newUser.copied": "Kopyalandı!", + "workspace.newUser.step.enableBilling": "Faturalandırmayı etkinleştir", + "workspace.newUser.step.login.before": "Çalıştır", + "workspace.newUser.step.login.after": "ve opencode seçeneğini seçin", + "workspace.newUser.step.pasteKey": "API anahtarınızı yapıştırın", + "workspace.newUser.step.models.before": "opencode'u başlatın ve çalıştırın", + "workspace.newUser.step.models.after": "bir model seçmek için", + + "workspace.models.title": "Modeller", + "workspace.models.subtitle.beforeLink": "Çalışma alanı üyelerinin hangi modellere erişebileceğini yönetin.", + "workspace.models.table.model": "Model", + "workspace.models.table.enabled": "Etkin", + + "workspace.providers.title": "Kendi Anahtarınızı Getirin", + "workspace.providers.subtitle": "Yapay zeka sağlayıcılarından kendi API anahtarlarınızı yapılandırın.", + "workspace.providers.placeholder": "{{provider}} API anahtarını girin ({{prefix}}...)", + "workspace.providers.configure": "Yapılandır", + "workspace.providers.edit": "Düzenle", + "workspace.providers.delete": "Sil", + "workspace.providers.saving": "Kaydediliyor...", + "workspace.providers.save": "Kaydet", + "workspace.providers.table.provider": "Sağlayıcı", + "workspace.providers.table.apiKey": "API Anahtarı", + + "workspace.usage.title": "Kullanım Geçmişi", + "workspace.usage.subtitle": "Son API kullanımı ve maliyetleri.", + "workspace.usage.empty": "Başlamak için ilk API çağrınızı yapın.", + "workspace.usage.table.date": "Tarih", + "workspace.usage.table.model": "Model", + "workspace.usage.table.input": "Giriş", + "workspace.usage.table.output": "Çıkış", + "workspace.usage.table.cost": "Maliyet", + "workspace.usage.breakdown.input": "Giriş", + "workspace.usage.breakdown.cacheRead": "Önbellek Okuması", + "workspace.usage.breakdown.cacheWrite": "Önbellek Yazma", + "workspace.usage.breakdown.output": "Çıkış", + "workspace.usage.breakdown.reasoning": "Muhakeme", + "workspace.usage.subscription": "abonelik (${{amount}})", + + "workspace.cost.title": "Maliyet", + "workspace.cost.subtitle": "Modele göre ayrılmış kullanım maliyetleri.", + "workspace.cost.allModels": "Tüm Modeller", + "workspace.cost.allKeys": "Tüm Anahtarlar", + "workspace.cost.deletedSuffix": "(silindi)", + "workspace.cost.empty": "Seçilen döneme ait kullanım verisi yok.", + "workspace.cost.subscriptionShort": "abonelik", + + "workspace.keys.title": "API Anahtarları", + "workspace.keys.subtitle": "opencode hizmetlerine erişim için API anahtarlarınızı yönetin.", + "workspace.keys.create": "API Anahtarı Oluştur", + "workspace.keys.placeholder": "Anahtar adını girin", + "workspace.keys.empty": "Bir opencode Gateway API anahtarı oluşturun", + "workspace.keys.table.name": "İsim", + "workspace.keys.table.key": "Anahtar", + "workspace.keys.table.createdBy": "Oluşturan", + "workspace.keys.table.lastUsed": "Son Kullanılan", + "workspace.keys.copyApiKey": "API anahtarını kopyala", + "workspace.keys.delete": "Sil", + + "workspace.members.title": "Üyeler", + "workspace.members.subtitle": "Çalışma alanı üyelerini ve izinlerini yönetin.", + "workspace.members.invite": "Üyeyi Davet Et", + "workspace.members.inviting": "Davet ediliyor...", + "workspace.members.beta.beforeLink": "Beta süresince çalışma alanları ekipler için ücretsizdir.", + "workspace.members.form.invitee": "Davetli", + "workspace.members.form.emailPlaceholder": "E-posta girin", + "workspace.members.form.role": "Rol", + "workspace.members.form.monthlyLimit": "Aylık harcama limiti", + "workspace.members.noLimit": "Limit yok", + "workspace.members.noLimitLowercase": "limit yok", + "workspace.members.invited": "davet edildi", + "workspace.members.edit": "Düzenle", + "workspace.members.delete": "Sil", + "workspace.members.saving": "Kaydediliyor...", + "workspace.members.save": "Kaydet", + "workspace.members.table.email": "E-posta", + "workspace.members.table.role": "Rol", + "workspace.members.table.monthLimit": "Ay limiti", + "workspace.members.role.admin": "Yönetici", + "workspace.members.role.adminDescription": "Modelleri, üyeleri ve faturalamayı yönetebilir", + "workspace.members.role.member": "Üye", + "workspace.members.role.memberDescription": "Yalnızca kendileri için API anahtarları oluşturabilirler", + + "workspace.settings.title": "Ayarlar", + "workspace.settings.subtitle": "Çalışma alanı adınızı ve tercihlerinizi güncelleyin.", + "workspace.settings.workspaceName": "Çalışma alanı adı", + "workspace.settings.defaultName": "Varsayılan", + "workspace.settings.updating": "Güncelleniyor...", + "workspace.settings.save": "Kaydet", + "workspace.settings.edit": "Düzenle", + + "workspace.billing.title": "Faturalandırma", + "workspace.billing.subtitle.beforeLink": "Ödeme yöntemlerini yönetin.", + "workspace.billing.contactUs": "Bize Ulaşın", + "workspace.billing.subtitle.afterLink": "herhangi bir sorunuz varsa.", + "workspace.billing.currentBalance": "Güncel Bakiye", + "workspace.billing.add": "$ ekle", + "workspace.billing.enterAmount": "Tutarı girin", + "workspace.billing.loading": "Yükleniyor...", + "workspace.billing.addAction": "Ekle", + "workspace.billing.addBalance": "Bakiye Ekle", + "workspace.billing.linkedToStripe": "Stripe'a bağlı", + "workspace.billing.manage": "Yönet", + "workspace.billing.enable": "Faturalandırmayı Etkinleştir", + + "workspace.monthlyLimit.title": "Aylık Limit", + "workspace.monthlyLimit.subtitle": "Hesabınız için aylık kullanım limiti belirleyin.", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "Ayarlanıyor...", + "workspace.monthlyLimit.set": "Ayarla", + "workspace.monthlyLimit.edit": "Limiti Düzenle", + "workspace.monthlyLimit.noLimit": "Kullanım limiti belirlenmedi.", + "workspace.monthlyLimit.currentUsage.beforeMonth": "Şu anki kullanım", + "workspace.monthlyLimit.currentUsage.beforeAmount": "$", + + "workspace.reload.title": "Otomatik Yeniden Yükleme", + "workspace.reload.disabled.before": "Otomatik yeniden yükleme:", + "workspace.reload.disabled.state": "devre dışı", + "workspace.reload.disabled.after": "Bakiye azaldığında otomatik olarak yeniden yüklemeyi etkinleştirin.", + "workspace.reload.enabled.before": "Otomatik yeniden yükleme:", + "workspace.reload.enabled.state": "etkin", + "workspace.reload.enabled.middle": "Yeniden yükleyeceğiz", + "workspace.reload.processingFee": "işlem ücreti", + "workspace.reload.enabled.after": "dengeye ulaşıldığında", + "workspace.reload.edit": "Düzenle", + "workspace.reload.enable": "Etkinleştir", + "workspace.reload.enableAutoReload": "Otomatik Yeniden Yüklemeyi Etkinleştir", + "workspace.reload.reloadAmount": "Yükle $", + "workspace.reload.whenBalanceReaches": "Bakiye $ seviyesine ulaştığında", + "workspace.reload.saving": "Kaydediliyor...", + "workspace.reload.save": "Kaydet", + "workspace.reload.failedAt": "Yeniden yükleme başarısız oldu:", + "workspace.reload.reason": "Sebep:", + "workspace.reload.updatePaymentMethod": "Lütfen ödeme yönteminizi güncelleyin ve tekrar deneyin.", + "workspace.reload.retrying": "Yeniden deneniyor...", + "workspace.reload.retry": "Yeniden dene", + + "workspace.payments.title": "Ödeme Geçmişi", + "workspace.payments.subtitle": "Son ödeme işlemleri.", + "workspace.payments.table.date": "Tarih", + "workspace.payments.table.paymentId": "Ödeme Kimliği", + "workspace.payments.table.amount": "Tutar", + "workspace.payments.table.receipt": "Makbuz", + "workspace.payments.type.credit": "kredi", + "workspace.payments.type.subscription": "abonelik", + "workspace.payments.view": "Görüntüle", + + "workspace.black.loading": "Yükleniyor...", + "workspace.black.time.day": "gün", + "workspace.black.time.days": "gün", + "workspace.black.time.hour": "saat", + "workspace.black.time.hours": "saat", + "workspace.black.time.minute": "dakika", + "workspace.black.time.minutes": "dakika", + "workspace.black.time.fewSeconds": "birkaç saniye", + "workspace.black.subscription.title": "Abonelik", + "workspace.black.subscription.message": "Aylık ${{plan}} karşılığında OpenCode Black'e abonesiniz.", + "workspace.black.subscription.manage": "Aboneliği Yönet", + "workspace.black.subscription.rollingUsage": "5 Saatlik Kullanım", + "workspace.black.subscription.weeklyUsage": "Haftalık Kullanım", + "workspace.black.subscription.resetsIn": "Sıfırlama süresi", + "workspace.black.subscription.useBalance": "Kullanım limitlerine ulaştıktan sonra mevcut bakiyenizi kullanın", + "workspace.black.waitlist.title": "Bekleme listesi", + "workspace.black.waitlist.joined": "Aylık ${{plan}} OpenCode Black planı için bekleme listesindesiniz.", + "workspace.black.waitlist.ready": "Sizi ayda {{plan}} $ tutarındaki OpenCode Black planına kaydetmeye hazırız.", + "workspace.black.waitlist.leave": "Bekleme Listesinden Ayrıl", + "workspace.black.waitlist.leaving": "Ayrılıyor...", + "workspace.black.waitlist.left": "Ayrıldı", + "workspace.black.waitlist.enroll": "Kayıt ol", + "workspace.black.waitlist.enrolling": "Kaydediliyor...", + "workspace.black.waitlist.enrolled": "Kayıtlı", + "workspace.black.waitlist.enrollNote": + "Kayıt Ol'a tıkladığınızda aboneliğiniz hemen başlar ve kartınızdan çekim yapılır.", + + "download.title": "OpenCode | İndir", + "download.meta.description": "OpenCode'u macOS, Windows ve Linux için indirin", + "download.hero.title": "OpenCode'u İndir", + "download.hero.subtitle": "macOS, Windows ve Linux için Beta olarak sunuluyor", + "download.hero.button": "{{os}} için indir", + "download.section.terminal": "OpenCode Terminal", + "download.section.desktop": "OpenCode Desktop (Beta)", + "download.section.extensions": "OpenCode Eklentileri", + "download.section.integrations": "OpenCode Entegrasyonları", + "download.action.download": "İndir", + "download.action.install": "Kur", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "Tam olarak değil, ama muhtemelen. OpenCode'u ücretli bir sağlayıcıya bağlamak istiyorsanız bir AI aboneliği gerekir, ancak", + "download.faq.a3.localLink": "yerel modeller", + "download.faq.a3.afterLocal.beforeZen": "ile ücretsiz çalışabilirsiniz. Kullanıcıları", + "download.faq.a3.afterZen": + " kullanmaya teşvik ediyoruz, ancak OpenCode OpenAI, Anthropic, xAI vb. gibi tüm popüler sağlayıcılarla çalışır.", + + "download.faq.a5.p1": "OpenCode %100 ücretsizdir.", + "download.faq.a5.p2.beforeZen": + "Ek maliyetler, bir model sağlayıcısına olan aboneliğinizden gelir. OpenCode herhangi bir model sağlayıcısıyla çalışır, ancak", + "download.faq.a5.p2.afterZen": " kullanmanızı öneririz.", + + "download.faq.a6.p1": + "Verileriniz ve bilginiz yalnızca OpenCode'da paylaşılabilir bağlantılar oluşturduğunuzda saklanır.", + "download.faq.a6.p2.beforeShare": "Daha fazla bilgi:", + "download.faq.a6.shareLink": "paylaşım sayfaları", + + "enterprise.title": "OpenCode | Kurumunuz için kurumsal çözümler", + "enterprise.meta.description": "Kurumsal çözümler için OpenCode ile iletişime geçin", + "enterprise.hero.title": "Kodunuz size aittir", + "enterprise.hero.body1": + "OpenCode, hiçbir veri veya bağlam saklamadan ve lisans kısıtlamaları ya da sahiplik iddiaları olmadan kuruluşunuzun içinde güvenli şekilde çalışır. Ekibinizle bir deneme başlatın, ardından SSO'nuz ve dahili AI geçidiniz ile entegre ederek tüm kuruluşunuzda devreye alın.", + "enterprise.hero.body2": "Nasıl yardımcı olabileceğimizi bize söyleyin.", + "enterprise.form.name.label": "Ad soyad", + "enterprise.form.name.placeholder": "Jeff Bezos", + "enterprise.form.role.label": "Rol", + "enterprise.form.role.placeholder": "Yönetim Kurulu Başkanı", + "enterprise.form.email.label": "Şirket e-postası", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "Hangi problemi çözmeye çalışıyorsunuz?", + "enterprise.form.message.placeholder": "Şu konuda yardıma ihtiyacımız var...", + "enterprise.form.send": "Gönder", + "enterprise.form.sending": "Gönderiliyor...", + "enterprise.form.success": "Mesaj gönderildi, yakında size dönüş yapacağız.", + "enterprise.faq.title": "SSS", + "enterprise.faq.q1": "OpenCode Enterprise nedir?", + "enterprise.faq.a1": + "OpenCode Enterprise, kodunuzun ve verilerinizin asla altyapınızı terk etmemesini sağlamak isteyen kurumlar içindir. Bunu, SSO'nuz ve dahili AI geçidiniz ile entegre olan merkezileştirilmiş bir konfigürasyonla sağlar.", + "enterprise.faq.q2": "OpenCode Enterprise'a nasıl başlarım?", + "enterprise.faq.a2": + "Ekibinizle dahili bir deneme ile başlayın. OpenCode varsayılan olarak kodunuzu veya bağlam verilerinizi saklamaz, bu da başlamayı kolaylaştırır. Ardından fiyatlandırma ve uygulama seçeneklerini görüşmek için bize ulaşın.", + "enterprise.faq.q3": "Kurumsal fiyatlandırma nasıl çalışır?", + "enterprise.faq.a3": + "Kullanıcı başı (per-seat) kurumsal fiyatlandırma sunuyoruz. Kendi LLM geçidiniz varsa, kullanılan tokenlar için ücret almıyoruz. Daha fazla bilgi için, kurumunuzun ihtiyaçlarına göre özel bir teklif için bize ulaşın.", + "enterprise.faq.q4": "OpenCode Enterprise ile verilerim güvende mi?", + "enterprise.faq.a4": + "Evet. OpenCode kodunuzu veya bağlam verilerinizi saklamaz. Tüm işleme yerel olarak ya da AI sağlayıcınıza doğrudan API çağrıları ile gerçekleştirilir. Merkezileştirilmiş konfigürasyon ve SSO entegrasyonu ile verileriniz kurumunuzun altyapısı içinde güvende kalır.", + + "brand.title": "OpenCode | Marka", + "brand.meta.description": "OpenCode marka kılavuzu", + "brand.heading": "Marka kılavuzu", + "brand.subtitle": "OpenCode markası ile çalışmanıza yardımcı olacak kaynaklar ve varlıklar.", + "brand.downloadAll": "Tüm varlıkları indir", + + "changelog.title": "OpenCode | Değişiklik günlüğü", + "changelog.meta.description": "OpenCode sürüm notları ve değişiklik günlüğü", + "changelog.hero.title": "Değişiklik günlüğü", + "changelog.hero.subtitle": "OpenCode için yeni güncellemeler ve iyileştirmeler", + "changelog.empty": "Değişiklik günlüğü kaydı bulunamadı.", + "changelog.viewJson": "JSON'u görüntüle", + + "bench.list.title": "Benchmark", + "bench.list.heading": "Benchmarklar", + "bench.list.table.agent": "Ajan", + "bench.list.table.model": "Model", + "bench.list.table.score": "Puan", + + "bench.detail.title": "Benchmark - {{task}}", + "bench.detail.notFound": "Görev bulunamadı", + "bench.detail.na": "N/A", + "bench.detail.labels.agent": "Ajan", + "bench.detail.labels.model": "Model", + "bench.detail.labels.task": "Görev", + "bench.detail.labels.repo": "Repo", + "bench.detail.labels.from": "Başlangıç", + "bench.detail.labels.to": "Bitiş", + "bench.detail.labels.prompt": "İstem", + "bench.detail.labels.commit": "Commit", + "bench.detail.labels.averageDuration": "Ortalama Süre", + "bench.detail.labels.averageScore": "Ortalama Puan", + "bench.detail.labels.averageCost": "Ortalama Maliyet", + "bench.detail.labels.summary": "Özet", + "bench.detail.labels.runs": "Çalıştırmalar", + "bench.detail.labels.score": "Puan", + "bench.detail.labels.base": "Baz", + "bench.detail.labels.penalty": "Ceza", + "bench.detail.labels.weight": "ağırlık", + "bench.detail.table.run": "Çalıştırma", + "bench.detail.table.score": "Puan (Baz - Ceza)", + "bench.detail.table.cost": "Maliyet", + "bench.detail.table.duration": "Süre", + "bench.detail.run.title": "Çalıştırma {{n}}", + "bench.detail.rawJson": "Ham JSON", +} satisfies Dict diff --git a/packages/console/app/src/i18n/zh.ts b/packages/console/app/src/i18n/zh.ts new file mode 100644 index 00000000000..c31b9ea6610 --- /dev/null +++ b/packages/console/app/src/i18n/zh.ts @@ -0,0 +1,580 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "文档", + "nav.changelog": "更新日志", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "企业版", + "nav.zen": "Zen", + "nav.login": "登录", + "nav.free": "免费", + "nav.home": "首页", + "nav.openMenu": "打开菜单", + "nav.getStartedFree": "免费开始", + + "nav.context.copyLogo": "复制 Logo (SVG)", + "nav.context.copyWordmark": "复制商标 (SVG)", + "nav.context.brandAssets": "品牌资产", + + "footer.github": "GitHub", + "footer.docs": "文档", + "footer.changelog": "更新日志", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "品牌", + "legal.privacy": "隐私", + "legal.terms": "条款", + + "email.title": "第一时间获知我们的新产品发布", + "email.subtitle": "加入候补名单,获取抢先体验资格。", + "email.placeholder": "电子邮箱地址", + "email.subscribe": "订阅", + "email.success": "即将完成,请检查您的收件箱并确认您的邮箱地址", + + "notFound.title": "未找到页面 | OpenCode", + "notFound.heading": "404 - 页面未找到", + "notFound.home": "首页", + "notFound.docs": "文档", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "退出登录", + + "workspace.select": "选择工作区", + "workspace.createNew": "+ 新建工作区", + "workspace.modal.title": "新建工作区", + "workspace.modal.placeholder": "输入工作区名称", + + "common.cancel": "取消", + "common.creating": "正在创建...", + "common.create": "创建", + + "common.videoUnsupported": "您的浏览器不支持 video 标签。", + "common.figure": "图 {{n}}.", + "common.faq": "常见问题", + "common.learnMore": "了解更多", + + "error.invalidPlan": "无效的计划", + "error.workspaceRequired": "缺少工作区 ID", + "error.alreadySubscribed": "此工作区已有订阅", + "error.limitRequired": "缺少限制设置。", + "error.monthlyLimitInvalid": "设置有效的每月限额。", + "error.workspaceNameRequired": "缺少工作区名称。", + "error.nameTooLong": "名称必须少于 255 个字符。", + "error.emailRequired": "缺少电子邮箱", + "error.roleRequired": "缺少角色", + "error.idRequired": "缺少 ID", + "error.nameRequired": "缺少名称", + "error.providerRequired": "缺少提供商", + "error.apiKeyRequired": "缺少 API 密钥", + "error.modelRequired": "缺少模型", + "error.reloadAmountMin": "充值金额必须至少为 ${{amount}}", + "error.reloadTriggerMin": "余额触发阈值必须至少为 ${{amount}}", + + "home.title": "OpenCode | 开源 AI 编程代理", + + "temp.title": "OpenCode | 专为终端打造的 AI 编程代理", + "temp.hero.title": "专为终端打造的 AI 编程代理", + "temp.zen": "OpenCode Zen", + "temp.getStarted": "开始使用", + "temp.feature.native.title": "原生 TUI", + "temp.feature.native.body": "响应迅速、原生的、可定制主题的终端 UI", + "temp.feature.zen.beforeLink": "由 OpenCode 提供的", + "temp.feature.zen.link": "精选模型列表", + "temp.feature.zen.afterLink": "", + "temp.feature.models.beforeLink": "通过 Models.dev 支持 75+ LLM 提供商", + "temp.feature.models.afterLink": ",包括本地模型", + "temp.screenshot.caption": "使用 Tokyonight 主题的 OpenCode TUI", + "temp.screenshot.alt": "使用 Tokyonight 主题的 OpenCode TUI", + + "home.banner.badge": "新", + "home.banner.text": "桌面应用 Beta 版现已推出", + "home.banner.platforms": "支持 macOS, Windows, 和 Linux", + "home.banner.downloadNow": "立即下载", + "home.banner.downloadBetaNow": "立即下载桌面 Beta 版", + + "home.hero.title": "开源 AI 编程代理", + "home.hero.subtitle.a": "内置免费模型,或连接任意提供商的任意模型,", + "home.hero.subtitle.b": "包括 Claude, GPT, Gemini 等。", + + "home.install.ariaLabel": "安装选项", + + "home.what.title": "什么是 OpenCode?", + "home.what.body": "OpenCode 是一个开源代理,帮助您在终端、IDE 或桌面端编写代码。", + "home.what.lsp.title": "支持 LSP", + "home.what.lsp.body": "为 LLM 自动加载合适的 LSP", + "home.what.multiSession.title": "多会话", + "home.what.multiSession.body": "在同一个项目中并行启动多个代理", + "home.what.shareLinks.title": "分享链接", + "home.what.shareLinks.body": "分享任意会话链接以供参考或调试", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "使用 GitHub 登录以使用您的 Copilot 账户", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "使用 OpenAI 登录以使用您的 ChatGPT Plus 或 Pro 账户", + "home.what.anyModel.title": "任意模型", + "home.what.anyModel.body": "通过 Models.dev 支持 75+ LLM 提供商,包括本地模型", + "home.what.anyEditor.title": "任意编辑器", + "home.what.anyEditor.body": "提供终端界面、桌面应用及 IDE 扩展", + "home.what.readDocs": "阅读文档", + + "home.growth.title": "开源 AI 编程代理", + "home.growth.body": + "拥有超过 {{stars}} 颗 GitHub Star,{{contributors}} 位贡献者,以及超过 {{commits}} 次提交,OpenCode 每月被超过 {{monthlyUsers}} 名开发者使用并信赖。", + "home.growth.githubStars": "GitHub Stars", + "home.growth.contributors": "贡献者", + "home.growth.monthlyDevs": "月活开发者", + + "home.privacy.title": "隐私优先的设计", + "home.privacy.body": "OpenCode 不存储您的任何代码或上下文数据,确保可以在对隐私敏感的环境中运行。", + "home.privacy.learnMore": "了解更多关于", + "home.privacy.link": "隐私", + + "home.faq.q1": "什么是 OpenCode?", + "home.faq.a1": "OpenCode 是一个开源代理,帮助您使用任意 AI 模型编写和运行代码。它提供终端界面、桌面应用及 IDE 扩展。", + "home.faq.q2": "如何使用 OpenCode?", + "home.faq.a2.before": "最简单的入门方式是阅读", + "home.faq.a2.link": "介绍", + "home.faq.q3": "使用 OpenCode 需要额外的 AI 订阅吗?", + "home.faq.a3.p1": "不一定。OpenCode 自带一组免费模型,无需创建账户即可使用。", + "home.faq.a3.p2.beforeZen": "此外,您可以通过创建", + "home.faq.a3.p2.afterZen": "账户来使用流行的编程模型。", + "home.faq.a3.p3": "虽然我们鼓励使用 Zen,但 OpenCode 也支持所有主流提供商,如 OpenAI, Anthropic, xAI 等。", + "home.faq.a3.p4.beforeLocal": "您甚至可以连接您的", + "home.faq.a3.p4.localLink": "本地模型", + "home.faq.q4": "我可以使用现有的 AI 订阅吗?", + "home.faq.a4.p1": + "可以,OpenCode 支持所有主流提供商的订阅计划。您可以使用您的 Claude Pro/Max, ChatGPT Plus/Pro, 或 GitHub Copilot 订阅。", + "home.faq.q5": "OpenCode 只能在终端使用吗?", + "home.faq.a5.beforeDesktop": "不再是了!OpenCode 现在也提供", + "home.faq.a5.desktop": "桌面端应用", + "home.faq.a5.and": "和", + "home.faq.a5.web": "网页端", + "home.faq.q6": "OpenCode 多少钱?", + "home.faq.a6": "OpenCode 是 100% 免费使用的。它还自带一组免费模型。如果您连接其他提供商,可能会产生额外费用。", + "home.faq.q7": "数据和隐私如何?", + "home.faq.a7.p1": "只有当您使用我们的免费模型或创建分享链接时,您的数据和信息才会被存储。", + "home.faq.a7.p2.beforeModels": "了解更多关于", + "home.faq.a7.p2.modelsLink": "我们的模型", + "home.faq.a7.p2.and": "和", + "home.faq.a7.p2.shareLink": "分享页面", + "home.faq.q8": "OpenCode 是开源的吗?", + "home.faq.a8.p1": "是的,OpenCode 是完全开源的。源代码公开在", + "home.faq.a8.p2": "遵循", + "home.faq.a8.mitLicense": "MIT 许可证", + "home.faq.a8.p3": + ",这意味着任何人都可以使用、修改或为它的发展做贡献。社区中的任何人都可以提交 issue、提交 PR 并扩展功能。", + + "home.zenCta.title": "访问可靠、优化的编程代理模型", + "home.zenCta.body": + "Zen 为您提供一组精选的 AI 模型,这些模型经过 OpenCode 专门针对编程代理的测试和基准测试。无需担心不同提供商之间不稳定的性能和质量,直接使用行之有效的验证模型。", + "home.zenCta.link": "了解 Zen", + + "zen.title": "OpenCode Zen | 为编程代理精选的可靠、优化模型", + "zen.hero.title": "为编程代理打造的可靠、优化模型", + "zen.hero.body": + "Zen 为您提供一组精选的 AI 模型,这些模型经过 OpenCode 专门针对编程代理的测试和基准测试。无需担心不稳定的性能和质量,直接使用行之有效的验证模型。", + + "zen.faq.q1": "什么是 OpenCode Zen?", + "zen.faq.a1": "Zen 是一组由 OpenCode 团队创建的,专门针对编程代理进行测试和基准测试的 AI 模型精选集。", + "zen.faq.q2": "为什么 Zen 更准确?", + "zen.faq.a2": + "Zen 仅提供经过专门针对编程代理测试和基准测试的模型。正如你不会用黄油刀切牛排一样,也不要用糟糕的模型来写代码。", + "zen.faq.q3": "Zen 更便宜吗?", + "zen.faq.a3": + "Zen 不以盈利为目的。Zen 将模型提供商的成本直接传递给您。Zen 的使用量越高,OpenCode 就越能协商出更好的费率并回馈给您。", + "zen.faq.q4": "Zen 多少钱?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "按请求收费", + "zen.faq.a4.p1.afterPricing": "零加价,所以您只需支付模型提供商收取的费用。", + "zen.faq.a4.p2.beforeAccount": "您的总费用取决于使用量,且您可以在您的", + "zen.faq.a4.p2.accountLink": "账户中设置每月支出限额", + "zen.faq.a4.p3": "为覆盖成本,OpenCode 仅收取少量支付处理费,每充值 $20 收取 $1.23。", + "zen.faq.q5": "数据和隐私如何?", + "zen.faq.a5.beforeExceptions": "所有 Zen 模型均托管在美国。提供商遵循零留存政策,不使用您的数据进行模型训练,", + "zen.faq.a5.exceptionsLink": "以下例外情况除外", + "zen.faq.q6": "我可以设置支出限额吗?", + "zen.faq.a6": "可以,您可以在账户中设置每月支出限额。", + "zen.faq.q7": "我可以取消吗?", + "zen.faq.a7": "可以,您可以随时禁用计费并使用剩余余额。", + "zen.faq.q8": "我可以在其他编程代理中使用 Zen 吗?", + "zen.faq.a8": + "虽然 Zen 与 OpenCode 配合效果极佳,但您可以在任何代理中使用 Zen。请按照您首选编程代理中的设置说明进行操作。", + + "zen.cta.start": "开始使用 Zen", + "zen.pricing.title": "充值 $20 (即用即付)", + "zen.pricing.fee": "(+ $1.23 银行卡手续费)", + "zen.pricing.body": "可配合任何代理使用。支持设置月度消费限额。随时取消。", + "zen.problem.title": "Zen 解决了什么问题?", + "zen.problem.body": "市面上有太多模型,但只有少数能与编程代理良好配合。大多数提供商配置不同,导致结果参差不齐。", + "zen.problem.subtitle": "我们要为所有人解决这个问题,不仅仅是 OpenCode 用户。", + "zen.problem.item1": "测试精选模型并咨询其团队", + "zen.problem.item2": "与提供商合作确保正确交付", + "zen.problem.item3": "对所有推荐的模型-提供商组合进行基准测试", + "zen.how.title": "Zen 如何工作", + "zen.how.body": "虽然我们建议您配合 OpenCode 使用 Zen,但您也可以将其用于任何代理。", + "zen.how.step1.title": "注册并充值 $20", + "zen.how.step1.beforeLink": "遵循", + "zen.how.step1.link": "设置说明", + "zen.how.step2.title": "使用 Zen,价格透明", + "zen.how.step2.link": "按请求付费", + "zen.how.step2.afterLink": "零加价", + "zen.how.step3.title": "自动充值", + "zen.how.step3.body": "当您的余额低于 $5 时,我们将自动充值 $20", + "zen.privacy.title": "您的隐私对我们很重要", + "zen.privacy.beforeExceptions": "所有 Zen 模型均托管在美国。提供商遵循零留存政策,不使用您的数据进行模型训练,", + "zen.privacy.exceptionsLink": "以下例外情况除外", + + "black.meta.title": "OpenCode Black | 访问全球顶尖编程模型", + "black.meta.description": "通过 OpenCode Black 订阅计划使用 Claude, GPT, Gemini 等模型。", + "black.hero.title": "访问全球顶尖编程模型", + "black.hero.subtitle": "包括 Claude, GPT, Gemini 等", + "black.title": "OpenCode Black | 定价", + "black.plan.icon20": "Black 20 计划", + "black.plan.icon100": "Black 100 计划", + "black.plan.icon200": "Black 200 计划", + "black.plan.multiplier100": "用量是 Black 20 的 5 倍", + "black.plan.multiplier200": "用量是 Black 20 的 20 倍", + "black.price.perMonth": "/ 月", + "black.price.perPersonBilledMonthly": "每人每月", + "black.terms.1": "您的订阅不会立即开始", + "black.terms.2": "您将被加入候补名单,并很快激活", + "black.terms.3": "您的卡只会在订阅激活时扣费", + "black.terms.4": "适用使用限制,高度自动化的使用可能会更快达到限制", + "black.terms.5": "订阅仅限个人,团队请联系企业版", + "black.terms.6": "未来可能会调整限制或停止计划", + "black.terms.7": "随时取消订阅", + "black.action.continue": "继续", + "black.finePrint.beforeTerms": "显示价格不含税", + "black.finePrint.terms": "服务条款", + "black.workspace.title": "OpenCode Black | 选择工作区", + "black.workspace.selectPlan": "为此计划选择一个工作区", + "black.workspace.name": "工作区 {{n}}", + "black.subscribe.title": "订阅 OpenCode Black", + "black.subscribe.paymentMethod": "付款方式", + "black.subscribe.loadingPaymentForm": "正在加载付款表单...", + "black.subscribe.selectWorkspaceToContinue": "选择一个工作区以继续", + "black.subscribe.failurePrefix": "哎呀!", + "black.subscribe.error.generic": "发生错误", + "black.subscribe.error.invalidPlan": "无效的计划", + "black.subscribe.error.workspaceRequired": "缺少工作区 ID", + "black.subscribe.error.alreadySubscribed": "此工作区已有订阅", + "black.subscribe.processing": "处理中...", + "black.subscribe.submit": "订阅 ${{plan}}", + "black.subscribe.form.chargeNotice": "您的卡只会在订阅激活时扣费", + "black.subscribe.success.title": "您已加入 OpenCode Black 候补名单", + "black.subscribe.success.subscriptionPlan": "订阅计划", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "金额", + "black.subscribe.success.amountValue": "${{plan}} / 月", + "black.subscribe.success.paymentMethod": "付款方式", + "black.subscribe.success.dateJoined": "加入日期", + "black.subscribe.success.chargeNotice": "您的卡将在订阅激活时扣费", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "API 密钥", + "workspace.nav.members": "成员", + "workspace.nav.billing": "计费", + "workspace.nav.settings": "设置", + + "workspace.home.banner.beforeLink": "可靠、优化的编程代理模型。", + "workspace.home.billing.loading": "加载中...", + "workspace.home.billing.enable": "启用计费", + "workspace.home.billing.currentBalance": "当前余额", + + "workspace.newUser.feature.tested.title": "经过测试与验证的模型", + "workspace.newUser.feature.tested.body": "我们专门针对编程代理对模型进行了基准测试和测试,以确保最佳性能。", + "workspace.newUser.feature.quality.title": "最高质量", + "workspace.newUser.feature.quality.body": "访问配置为最佳性能的模型 - 无需降级或路由到更便宜的提供商。", + "workspace.newUser.feature.lockin.title": "无锁定", + "workspace.newUser.feature.lockin.body": + "将 Zen 与任何编程代理结合使用,并在需要时继续在 OpenCode 中使用其他提供商。", + "workspace.newUser.copyApiKey": "复制 API 密钥", + "workspace.newUser.copyKey": "复制密钥", + "workspace.newUser.copied": "已复制!", + "workspace.newUser.step.enableBilling": "启用计费", + "workspace.newUser.step.login.before": "运行", + "workspace.newUser.step.login.after": "并选择 OpenCode", + "workspace.newUser.step.pasteKey": "粘贴您的 API 密钥", + "workspace.newUser.step.models.before": "启动 OpenCode 并运行", + "workspace.newUser.step.models.after": "以选择模型", + + "workspace.models.title": "模型", + "workspace.models.subtitle.beforeLink": "管理工作区成员可以访问哪些模型。", + "workspace.models.table.model": "模型", + "workspace.models.table.enabled": "已启用", + + "workspace.providers.title": "自带密钥 (BYOK)", + "workspace.providers.subtitle": "配置您自己的 AI 提供商 API 密钥。", + "workspace.providers.placeholder": "输入 {{provider}} API 密钥 ({{prefix}}...)", + "workspace.providers.configure": "配置", + "workspace.providers.edit": "编辑", + "workspace.providers.delete": "删除", + "workspace.providers.saving": "正在保存...", + "workspace.providers.save": "保存", + "workspace.providers.table.provider": "提供商", + "workspace.providers.table.apiKey": "API 密钥", + + "workspace.usage.title": "使用历史", + "workspace.usage.subtitle": "近期 API 使用情况和成本。", + "workspace.usage.empty": "发起第一个 API 调用以开始。", + "workspace.usage.table.date": "日期", + "workspace.usage.table.model": "模型", + "workspace.usage.table.input": "输入", + "workspace.usage.table.output": "输出", + "workspace.usage.table.cost": "成本", + "workspace.usage.breakdown.input": "输入", + "workspace.usage.breakdown.cacheRead": "缓存读取", + "workspace.usage.breakdown.cacheWrite": "缓存写入", + "workspace.usage.breakdown.output": "输出", + "workspace.usage.breakdown.reasoning": "推理", + "workspace.usage.subscription": "订阅 (${{amount}})", + + "workspace.cost.title": "成本", + "workspace.cost.subtitle": "按模型细分的使用成本。", + "workspace.cost.allModels": "所有模型", + "workspace.cost.allKeys": "所有密钥", + "workspace.cost.deletedSuffix": "(已删除)", + "workspace.cost.empty": "所选期间无可用使用数据。", + "workspace.cost.subscriptionShort": "订阅", + + "workspace.keys.title": "API 密钥", + "workspace.keys.subtitle": "管理访问 OpenCode 服务的 API 密钥。", + "workspace.keys.create": "创建 API 密钥", + "workspace.keys.placeholder": "输入密钥名称", + "workspace.keys.empty": "创建 OpenCode 网关 API 密钥", + "workspace.keys.table.name": "名称", + "workspace.keys.table.key": "密钥", + "workspace.keys.table.createdBy": "创建者", + "workspace.keys.table.lastUsed": "最后使用", + "workspace.keys.copyApiKey": "复制 API 密钥", + "workspace.keys.delete": "删除", + + "workspace.members.title": "成员", + "workspace.members.subtitle": "管理工作区成员及其权限。", + "workspace.members.invite": "邀请成员", + "workspace.members.inviting": "正在邀请...", + "workspace.members.beta.beforeLink": "Beta 期间工作区对团队免费。", + "workspace.members.form.invitee": "受邀者", + "workspace.members.form.emailPlaceholder": "输入电子邮箱", + "workspace.members.form.role": "角色", + "workspace.members.form.monthlyLimit": "每月消费限额", + "workspace.members.noLimit": "无限制", + "workspace.members.noLimitLowercase": "无限制", + "workspace.members.invited": "已邀请", + "workspace.members.edit": "编辑", + "workspace.members.delete": "删除", + "workspace.members.saving": "正在保存...", + "workspace.members.save": "保存", + "workspace.members.table.email": "邮箱", + "workspace.members.table.role": "角色", + "workspace.members.table.monthLimit": "月限额", + "workspace.members.role.admin": "管理员", + "workspace.members.role.adminDescription": "可以管理模型、成员和计费", + "workspace.members.role.member": "成员", + "workspace.members.role.memberDescription": "只能为自己生成 API 密钥", + + "workspace.settings.title": "设置", + "workspace.settings.subtitle": "更新您的工作区名称和偏好。", + "workspace.settings.workspaceName": "工作区名称", + "workspace.settings.defaultName": "默认", + "workspace.settings.updating": "正在更新...", + "workspace.settings.save": "保存", + "workspace.settings.edit": "编辑", + + "workspace.billing.title": "计费", + "workspace.billing.subtitle.beforeLink": "管理付款方式。", + "workspace.billing.contactUs": "联系我们", + "workspace.billing.subtitle.afterLink": "如果您有任何问题。", + "workspace.billing.currentBalance": "当前余额", + "workspace.billing.add": "充值 $", + "workspace.billing.enterAmount": "输入金额", + "workspace.billing.loading": "加载中...", + "workspace.billing.addAction": "充值", + "workspace.billing.addBalance": "充值余额", + "workspace.billing.linkedToStripe": "已关联 Stripe", + "workspace.billing.manage": "管理", + "workspace.billing.enable": "启用计费", + + "workspace.monthlyLimit.title": "每月限额", + "workspace.monthlyLimit.subtitle": "为您的账户设置每月使用限额。", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "正在设置...", + "workspace.monthlyLimit.set": "设置", + "workspace.monthlyLimit.edit": "编辑限额", + "workspace.monthlyLimit.noLimit": "未设置使用限额。", + "workspace.monthlyLimit.currentUsage.beforeMonth": "当前", + "workspace.monthlyLimit.currentUsage.beforeAmount": "的使用量为 $", + + "workspace.reload.title": "自动充值", + "workspace.reload.disabled.before": "自动充值已", + "workspace.reload.disabled.state": "禁用", + "workspace.reload.disabled.after": "启用后将在余额不足时自动充值。", + "workspace.reload.enabled.before": "自动充值已", + "workspace.reload.enabled.state": "启用", + "workspace.reload.enabled.middle": "我们将自动充值", + "workspace.reload.processingFee": "手续费", + "workspace.reload.enabled.after": "当余额达到", + "workspace.reload.edit": "编辑", + "workspace.reload.enable": "启用", + "workspace.reload.enableAutoReload": "启用自动充值", + "workspace.reload.reloadAmount": "充值 $", + "workspace.reload.whenBalanceReaches": "当余额达到 $", + "workspace.reload.saving": "正在保存...", + "workspace.reload.save": "保存", + "workspace.reload.failedAt": "充值失败于", + "workspace.reload.reason": "原因:", + "workspace.reload.updatePaymentMethod": "请更新您的付款方式并重试。", + "workspace.reload.retrying": "正在重试...", + "workspace.reload.retry": "重试", + + "workspace.payments.title": "支付历史", + "workspace.payments.subtitle": "近期支付交易。", + "workspace.payments.table.date": "日期", + "workspace.payments.table.paymentId": "支付 ID", + "workspace.payments.table.amount": "金额", + "workspace.payments.table.receipt": "收据", + "workspace.payments.type.credit": "充值", + "workspace.payments.type.subscription": "订阅", + "workspace.payments.view": "查看", + + "workspace.black.loading": "加载中...", + "workspace.black.time.day": "天", + "workspace.black.time.days": "天", + "workspace.black.time.hour": "小时", + "workspace.black.time.hours": "小时", + "workspace.black.time.minute": "分钟", + "workspace.black.time.minutes": "分钟", + "workspace.black.time.fewSeconds": "几秒钟", + "workspace.black.subscription.title": "订阅", + "workspace.black.subscription.message": "您已订阅 OpenCode Black,价格为每月 ${{plan}}。", + "workspace.black.subscription.manage": "管理订阅", + "workspace.black.subscription.rollingUsage": "5 小时用量", + "workspace.black.subscription.weeklyUsage": "每周用量", + "workspace.black.subscription.resetsIn": "重置于", + "workspace.black.subscription.useBalance": "达到使用限额后使用您的可用余额", + "workspace.black.waitlist.title": "候补名单", + "workspace.black.waitlist.joined": "您已加入每月 ${{plan}} 的 OpenCode Black 计划候补名单。", + "workspace.black.waitlist.ready": "我们已准备好将您加入每月 ${{plan}} 的 OpenCode Black 计划。", + "workspace.black.waitlist.leave": "退出候补名单", + "workspace.black.waitlist.leaving": "正在退出...", + "workspace.black.waitlist.left": "已退出", + "workspace.black.waitlist.enroll": "加入", + "workspace.black.waitlist.enrolling": "正在加入...", + "workspace.black.waitlist.enrolled": "已加入", + "workspace.black.waitlist.enrollNote": "点击加入后,您的订阅将立即开始,并将从您的卡中扣费。", + + "download.title": "OpenCode | 下载", + "download.meta.description": "下载适用于 macOS, Windows, 和 Linux 的 OpenCode", + "download.hero.title": "下载 OpenCode", + "download.hero.subtitle": "适用于 macOS, Windows, 和 Linux 的 Beta 版", + "download.hero.button": "下载 {{os}} 版", + "download.section.terminal": "OpenCode 终端", + "download.section.desktop": "OpenCode 桌面版 (Beta)", + "download.section.extensions": "OpenCode 扩展", + "download.section.integrations": "OpenCode 集成", + "download.action.download": "下载", + "download.action.install": "安装", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "不一定,但可能需要。如果您想将 OpenCode 连接到付费提供商,您需要 AI 订阅,尽管您可以配合", + "download.faq.a3.localLink": "本地模型", + "download.faq.a3.afterLocal.beforeZen": "免费使用。虽然我们鼓励用户使用", + "download.faq.a3.afterZen": ",但 OpenCode 支持所有主流提供商,如 OpenAI, Anthropic, xAI 等。", + + "download.faq.a5.p1": "OpenCode 是 100% 免费使用的。", + "download.faq.a5.p2.beforeZen": + "任何额外费用都来自您对模型提供商的订阅。虽然 OpenCode 支持任何模型提供商,但我们建议使用", + "download.faq.a5.p2.afterZen": "。", + + "download.faq.a6.p1": "只有当您在 OpenCode 中创建分享链接时,您的数据和信息才会被存储。", + "download.faq.a6.p2.beforeShare": "了解更多关于", + "download.faq.a6.shareLink": "分享页面", + + "enterprise.title": "OpenCode | 面向组织的 OpenCode 企业版解决方案", + "enterprise.meta.description": "联系 OpenCode 获取企业版解决方案", + "enterprise.hero.title": "您的代码属于您", + "enterprise.hero.body1": + "OpenCode 在您的组织内部安全运行,不存储任何数据或上下文,也没有许可限制或所有权主张。您可以先与团队开始试用,然后通过集成 SSO 和内部 AI 网关将其部署到整个组织。", + "enterprise.hero.body2": "告诉我们如何为您提供帮助。", + "enterprise.form.name.label": "全名", + "enterprise.form.name.placeholder": "Jeff Bezos", + "enterprise.form.role.label": "角色", + "enterprise.form.role.placeholder": "执行主席", + "enterprise.form.email.label": "公司邮箱", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "您想解决什么问题?", + "enterprise.form.message.placeholder": "我们需要帮助...", + "enterprise.form.send": "发送", + "enterprise.form.sending": "正在发送...", + "enterprise.form.success": "消息已发送,我们会尽快与您联系。", + "enterprise.faq.title": "常见问题", + "enterprise.faq.q1": "什么是 OpenCode 企业版?", + "enterprise.faq.a1": + "OpenCode 企业版专为那些希望确保代码和数据永远不离开其基础设施的组织而设计。它通过使用集中式配置,与您的 SSO 和内部 AI 网关集成来实现这一点。", + "enterprise.faq.q2": "如何开始使用 OpenCode 企业版?", + "enterprise.faq.a2": + "只需从您的团队内部试用开始即可。OpenCode 默认不存储您的代码或上下文数据,使得入门非常容易。然后联系我们讨论定价和实施选项。", + "enterprise.faq.q3": "企业版定价如何运作?", + "enterprise.faq.a3": + "我们提供按席位计费的企业定价。如果您拥有自己的 LLM 网关,我们不收取 token 使用费。如需了解更多详情,请联系我们获取基于您组织需求的定制报价。", + "enterprise.faq.q4": "OpenCode 企业版安全吗?", + "enterprise.faq.a4": + "是的。OpenCode 不存储您的代码或上下文数据。所有处理均在本地进行,或通过直接 API 调用您的 AI 提供商。通过集中配置和 SSO 集成,您的数据始终保留在您组织的基础设施内。", + + "brand.title": "OpenCode | 品牌", + "brand.meta.description": "OpenCode 品牌指南", + "brand.heading": "品牌指南", + "brand.subtitle": "帮助您使用 OpenCode 品牌的资源和资产。", + "brand.downloadAll": "下载所有资产", + + "changelog.title": "OpenCode | 更新日志", + "changelog.meta.description": "OpenCode 发布说明和更新日志", + "changelog.hero.title": "更新日志", + "changelog.hero.subtitle": "OpenCode 的新更新和改进", + "changelog.empty": "未找到更新日志条目。", + "changelog.viewJson": "查看 JSON", + + "bench.list.title": "基准测试", + "bench.list.heading": "基准测试", + "bench.list.table.agent": "代理", + "bench.list.table.model": "模型", + "bench.list.table.score": "分数", + + "bench.detail.title": "基准测试 - {{task}}", + "bench.detail.notFound": "未找到任务", + "bench.detail.na": "N/A", + "bench.detail.labels.agent": "代理", + "bench.detail.labels.model": "模型", + "bench.detail.labels.task": "任务", + "bench.detail.labels.repo": "仓库", + "bench.detail.labels.from": "来源", + "bench.detail.labels.to": "目标", + "bench.detail.labels.prompt": "提示词", + "bench.detail.labels.commit": "Commit", + "bench.detail.labels.averageDuration": "平均耗时", + "bench.detail.labels.averageScore": "平均分数", + "bench.detail.labels.averageCost": "平均成本", + "bench.detail.labels.summary": "摘要", + "bench.detail.labels.runs": "运行次数", + "bench.detail.labels.score": "分数", + "bench.detail.labels.base": "基础", + "bench.detail.labels.penalty": "惩罚", + "bench.detail.labels.weight": "权重", + "bench.detail.table.run": "运行", + "bench.detail.table.score": "分数 (基础 - 惩罚)", + "bench.detail.table.cost": "成本", + "bench.detail.table.duration": "耗时", + "bench.detail.run.title": "运行 {{n}}", + "bench.detail.rawJson": "原始 JSON", +} satisfies Dict diff --git a/packages/console/app/src/i18n/zht.ts b/packages/console/app/src/i18n/zht.ts new file mode 100644 index 00000000000..c7b411ca5b5 --- /dev/null +++ b/packages/console/app/src/i18n/zht.ts @@ -0,0 +1,579 @@ +import type { Dict } from "./en" +import { dict as en } from "./en" + +export const dict = { + ...en, + "nav.github": "GitHub", + "nav.docs": "文件", + "nav.changelog": "更新日誌", + "nav.discord": "Discord", + "nav.x": "X", + "nav.enterprise": "企業", + "nav.zen": "Zen", + "nav.login": "登入", + "nav.free": "免費", + "nav.home": "首頁", + "nav.openMenu": "開啟選單", + "nav.getStartedFree": "免費開始使用", + + "nav.context.copyLogo": "複製標誌(SVG)", + "nav.context.copyWordmark": "複製字標(SVG)", + "nav.context.brandAssets": "品牌資產", + + "footer.github": "GitHub", + "footer.docs": "文件", + "footer.changelog": "更新日誌", + "footer.discord": "Discord", + "footer.x": "X", + + "legal.brand": "品牌", + "legal.privacy": "隱私", + "legal.terms": "條款", + + "email.title": "第一時間獲取我們發布新產品的消息", + "email.subtitle": "加入候補名單,搶先體驗。", + "email.placeholder": "電子郵件地址", + "email.subscribe": "訂閱", + "email.success": "就差一步,請查收你的信箱並確認電子郵件地址", + + "notFound.title": "找不到頁面 | OpenCode", + "notFound.heading": "404 - 找不到頁面", + "notFound.home": "首頁", + "notFound.docs": "文件", + "notFound.github": "GitHub", + "notFound.discord": "Discord", + + "user.logout": "登出", + + "workspace.select": "選取工作區", + "workspace.createNew": "+ 建立新工作區", + "workspace.modal.title": "建立新工作區", + "workspace.modal.placeholder": "輸入工作區名稱", + + "common.cancel": "取消", + "common.creating": "正在建立...", + "common.create": "建立", + + "common.videoUnsupported": "你的瀏覽器不支援 video 標籤。", + "common.figure": "圖 {{n}}.", + "common.faq": "常見問題", + "common.learnMore": "了解更多", + + "error.invalidPlan": "無效的方案", + "error.workspaceRequired": "需要工作區 ID", + "error.alreadySubscribed": "此工作區已有訂閱", + "error.limitRequired": "需要設定限額。", + "error.monthlyLimitInvalid": "請設定有效的每月限額。", + "error.workspaceNameRequired": "需要工作區名稱。", + "error.nameTooLong": "名稱長度不能超過 255 個字元。", + "error.emailRequired": "需要電子郵件", + "error.roleRequired": "需要角色", + "error.idRequired": "需要 ID", + "error.nameRequired": "需要名稱", + "error.providerRequired": "需要供應商", + "error.apiKeyRequired": "需要 API 金鑰", + "error.modelRequired": "需要模型", + "error.reloadAmountMin": "儲值金額必須至少為 ${{amount}}", + "error.reloadTriggerMin": "餘額觸發門檻必須至少為 ${{amount}}", + + "home.title": "OpenCode | 開源 AI 編碼代理", + + "temp.title": "OpenCode | 專為終端打造的 AI 編碼代理", + "temp.hero.title": "專為終端打造的 AI 編碼代理", + "temp.zen": "OpenCode Zen", + "temp.getStarted": "開始使用", + "temp.feature.native.title": "原生 TUI", + "temp.feature.native.body": "響應式、原生、可自訂主題的終端介面", + "temp.feature.zen.beforeLink": "", + "temp.feature.zen.link": "精選模型列表", + "temp.feature.zen.afterLink": "由 OpenCode 提供", + "temp.feature.models.beforeLink": "透過", + "temp.feature.models.afterLink": "支援 75+ 家 LLM 供應商,包括本地模型", + "temp.screenshot.caption": "使用 tokyonight 主題的 OpenCode TUI", + "temp.screenshot.alt": "使用 tokyonight 主題的 OpenCode TUI", + + "home.banner.badge": "新", + "home.banner.text": "桌面應用已推出 Beta", + "home.banner.platforms": "支援 macOS、Windows 與 Linux", + "home.banner.downloadNow": "立即下載", + "home.banner.downloadBetaNow": "立即下載桌面 Beta 版", + + "home.hero.title": "開源 AI 編碼代理", + "home.hero.subtitle.a": "內建免費模型,或連接任意供應商的任意模型,", + "home.hero.subtitle.b": "包括 Claude、GPT、Gemini 等。", + + "home.install.ariaLabel": "安裝選項", + + "home.what.title": "什麼是 OpenCode?", + "home.what.body": "OpenCode 是一個開源代理,幫助你在終端、IDE 或桌面端編寫程式碼。", + "home.what.lsp.title": "支援 LSP", + "home.what.lsp.body": "為 LLM 自動載入合適的 LSP", + "home.what.multiSession.title": "多工作階段", + "home.what.multiSession.body": "在同一專案中平行啟動多個代理", + "home.what.shareLinks.title": "分享連結", + "home.what.shareLinks.body": "將任意階段的連結分享給他人供參考或除錯", + "home.what.copilot.title": "GitHub Copilot", + "home.what.copilot.body": "使用 GitHub 登入以使用你的 Copilot 帳號", + "home.what.chatgptPlus.title": "ChatGPT Plus/Pro", + "home.what.chatgptPlus.body": "使用 OpenAI 登入以使用你的 ChatGPT Plus 或 Pro 帳號", + "home.what.anyModel.title": "任意模型", + "home.what.anyModel.body": "透過 Models.dev 連接 75+ 家 LLM 供應商,包括本地模型", + "home.what.anyEditor.title": "任意編輯器", + "home.what.anyEditor.body": "可作為終端介面、桌面應用程式與 IDE 擴充功能使用", + "home.what.readDocs": "閱讀文件", + + "home.growth.title": "開源 AI 編碼代理", + "home.growth.body": + "擁有超過 {{stars}} 個 GitHub Star、{{contributors}} 位貢獻者以及超過 {{commits}} 次提交,OpenCode 每月被超過 {{monthlyUsers}} 名開發者使用並信賴。", + "home.growth.githubStars": "GitHub Star", + "home.growth.contributors": "貢獻者", + "home.growth.monthlyDevs": "每月活躍開發者", + + "home.privacy.title": "隱私優先", + "home.privacy.body": "OpenCode 不儲存你的程式碼或上下文資料,因此可以在注重隱私的環境中運作。", + "home.privacy.learnMore": "了解更多關於", + "home.privacy.link": "隱私", + + "home.faq.q1": "什麼是 OpenCode?", + "home.faq.a1": + "OpenCode 是一個開源代理,幫助你使用任意 AI 模型編寫並執行程式碼。它提供終端介面、桌面應用程式或 IDE 擴充功能。", + "home.faq.q2": "如何使用 OpenCode?", + "home.faq.a2.before": "最簡單的方式是先閱讀", + "home.faq.a2.link": "入門介紹", + "home.faq.q3": "使用 OpenCode 需要額外的 AI 訂閱嗎?", + "home.faq.a3.p1": "不一定。OpenCode 自帶一組免費模型,無需建立帳號即可使用。", + "home.faq.a3.p2.beforeZen": "此外,你可以透過建立", + "home.faq.a3.p2.afterZen": "帳號使用常見的編碼模型。", + "home.faq.a3.p3": "我們鼓勵使用 Zen,但 OpenCode 也支援 OpenAI、Anthropic、xAI 等主流供應商。", + "home.faq.a3.p4.beforeLocal": "你還可以連接你的", + "home.faq.a3.p4.localLink": "本地模型", + "home.faq.q4": "可以使用我現有的 AI 訂閱嗎?", + "home.faq.a4.p1": + "可以。OpenCode 支援主流供應商的訂閱方案,包括 Claude Pro/Max、ChatGPT Plus/Pro 與 GitHub Copilot。", + "home.faq.q5": "OpenCode 只能在終端中使用嗎?", + "home.faq.a5.beforeDesktop": "不再是了!OpenCode 現在也提供", + "home.faq.a5.desktop": "桌面端", + "home.faq.a5.and": "與", + "home.faq.a5.web": "網頁端", + "home.faq.q6": "OpenCode 價格如何?", + "home.faq.a6": "OpenCode 100% 免費使用。它也自帶一組免費模型。如果你連接其他供應商,可能會產生額外費用。", + "home.faq.q7": "資料與隱私怎麼辦?", + "home.faq.a7.p1": "僅當你使用我們的免費模型或建立可分享連結時,才會儲存你的資料與資訊。", + "home.faq.a7.p2.beforeModels": "了解更多關於", + "home.faq.a7.p2.modelsLink": "我們的模型", + "home.faq.a7.p2.and": "與", + "home.faq.a7.p2.shareLink": "分享頁面", + "home.faq.q8": "OpenCode 是開源的嗎?", + "home.faq.a8.p1": "是的,OpenCode 完全開源。原始碼公開在", + "home.faq.a8.p2": "並採用", + "home.faq.a8.mitLicense": "MIT 授權條款", + "home.faq.a8.p3": ",意味著任何人都可以使用、修改或貢獻。社群中的任何人都可以提交 issue、pull requests 並擴充功能。", + + "home.zenCta.title": "存取可靠且最佳化的編碼代理模型", + "home.zenCta.body": + "Zen 提供一組精選的 AI 模型,這些模型是 OpenCode 為了編碼代理專門測試與評測過的。無需擔心不同供應商之間效能與品質參差不齊,使用經過驗證的模型即可。", + "home.zenCta.link": "了解 Zen", + + "zen.title": "OpenCode Zen | 專為編碼代理精選的可靠最佳化模型", + "zen.hero.title": "專為編碼代理提供的可靠最佳化模型", + "zen.hero.body": + "Zen 提供一組精選的 AI 模型,這些模型是 OpenCode 為了編碼代理專門測試與評測過的。無需擔心效能與品質參差不齊,使用經過驗證的模型即可。", + + "zen.faq.q1": "什麼是 OpenCode Zen?", + "zen.faq.a1": "Zen 是由 OpenCode 團隊打造、專為編碼代理測試與評測的 AI 模型精選集合。", + "zen.faq.q2": "是什麼讓 Zen 更準確?", + "zen.faq.a2": "Zen 只提供專為編碼代理測試與評測的模型。你不會用奶油刀切牛排,也別用糟糕的模型來寫程式。", + "zen.faq.q3": "Zen 更便宜嗎?", + "zen.faq.a3": + "Zen 不以營利為目的。Zen 會把模型供應商的成本原樣轉給你。Zen 的使用量越高,OpenCode 就越能談到更好的價格並把優惠讓利給你。", + "zen.faq.q4": "Zen 費用是多少?", + "zen.faq.a4.p1.beforePricing": "Zen", + "zen.faq.a4.p1.pricingLink": "按請求付費", + "zen.faq.a4.p1.afterPricing": "且零加價,因此你支付的就是模型供應商的原價。", + "zen.faq.a4.p2.beforeAccount": "總費用取決於使用量,你可以在", + "zen.faq.a4.p2.accountLink": "帳戶中設定每月支出上限", + "zen.faq.a4.p3": "為了覆蓋成本,OpenCode 只會收取很小的支付處理費:每次儲值 $20 會額外收取 $1.23。", + "zen.faq.q5": "資料與隱私如何?", + "zen.faq.a5.beforeExceptions": "所有 Zen 模型都託管在美國。供應商遵循零留存政策,不會將你的資料用於模型訓練,但有", + "zen.faq.a5.exceptionsLink": "以下例外", + "zen.faq.q6": "我可以設定支出上限嗎?", + "zen.faq.a6": "可以,你可以在帳戶中設定每月支出上限。", + "zen.faq.q7": "我可以取消嗎?", + "zen.faq.a7": "可以,你可以隨時停用計費並使用剩餘餘額。", + "zen.faq.q8": "我可以在其他編碼代理中使用 Zen 嗎?", + "zen.faq.a8": + "Zen 與 OpenCode 搭配得很好,但你也可以在任何代理中使用 Zen。請在你偏好的編碼代理中按照設定說明進行配置。", + + "zen.cta.start": "開始使用 Zen", + "zen.pricing.title": "儲值 $20 即用即付餘額", + "zen.pricing.fee": "(+$1.23 刷卡手續費)", + "zen.pricing.body": "可與任何代理一起使用。設定每月支出限額。隨時取消。", + "zen.problem.title": "Zen 正在解決什麼問題?", + "zen.problem.body": + "可用的模型有很多,但只有少數可以與編碼代理配合良好。大多數供應商以不同的方式配置它們,導致結果參差不齊。", + "zen.problem.subtitle": "我們正在為所有人解決此問題,而不僅僅是 OpenCode 使用者。", + "zen.problem.item1": "測試選定的模型並諮詢其團隊", + "zen.problem.item2": "與供應商合作以確保正確交付", + "zen.problem.item3": "對我們推薦的所有模型-供應商組合進行基準測試", + "zen.how.title": "Zen 如何運作", + "zen.how.body": "雖然我們建議你將 Zen 與 OpenCode 一起使用,但你可以將 Zen 與任何代理一起使用。", + "zen.how.step1.title": "註冊並儲值 $20 餘額", + "zen.how.step1.beforeLink": "遵循", + "zen.how.step1.link": "設定說明", + "zen.how.step2.title": "使用 Zen 並享有透明定價", + "zen.how.step2.link": "按請求付費", + "zen.how.step2.afterLink": "零加價", + "zen.how.step3.title": "自動儲值", + "zen.how.step3.body": "當你的餘額達到 $5 時,我們會自動儲值 $20", + "zen.privacy.title": "你的隱私對我們很重要", + "zen.privacy.beforeExceptions": "所有 Zen 模型均在美國託管。供應商遵循零留存政策,不會將你的資料用於模型訓練,並且有", + "zen.privacy.exceptionsLink": "以下例外情況", + + "black.meta.title": "OpenCode Black | 存取全球最佳編碼模型", + "black.meta.description": "透過 OpenCode Black 訂閱方案存取 Claude、GPT、Gemini 等模型。", + "black.hero.title": "存取全球最佳編碼模型", + "black.hero.subtitle": "包括 Claude、GPT、Gemini 等", + "black.title": "OpenCode Black | 定價", + "black.plan.icon20": "Black 20 方案", + "black.plan.icon100": "Black 100 方案", + "black.plan.icon200": "Black 200 方案", + "black.plan.multiplier100": "比 Black 20 多 5 倍使用量", + "black.plan.multiplier200": "比 Black 20 多 20 倍使用量", + "black.price.perMonth": "每月", + "black.price.perPersonBilledMonthly": "每人每月計費", + "black.terms.1": "你的訂閱不會立即開始", + "black.terms.2": "你將被加入候補名單並在不久後啟用", + "black.terms.3": "你的卡片僅在訂閱啟用時才會扣款", + "black.terms.4": "適用使用限制,高度自動化的使用可能會更快達到限制", + "black.terms.5": "訂閱僅限個人使用,團隊請聯繫企業版", + "black.terms.6": "未來可能會調整限制或終止方案", + "black.terms.7": "隨時取消你的訂閱", + "black.action.continue": "繼續", + "black.finePrint.beforeTerms": "顯示價格未包含適用稅項", + "black.finePrint.terms": "服務條款", + "black.workspace.title": "OpenCode Black | 選擇工作區", + "black.workspace.selectPlan": "為此方案選擇一個工作區", + "black.workspace.name": "工作區 {{n}}", + "black.subscribe.title": "訂閱 OpenCode Black", + "black.subscribe.paymentMethod": "付款方式", + "black.subscribe.loadingPaymentForm": "正在載入付款表單...", + "black.subscribe.selectWorkspaceToContinue": "選擇一個工作區以繼續", + "black.subscribe.failurePrefix": "噢不!", + "black.subscribe.error.generic": "發生錯誤", + "black.subscribe.error.invalidPlan": "無效的方案", + "black.subscribe.error.workspaceRequired": "需要工作區 ID", + "black.subscribe.error.alreadySubscribed": "此工作區已有訂閱", + "black.subscribe.processing": "處理中...", + "black.subscribe.submit": "訂閱 ${{plan}}", + "black.subscribe.form.chargeNotice": "你僅在訂閱啟用時才會被扣款", + "black.subscribe.success.title": "你已在 OpenCode Black 候補名單上", + "black.subscribe.success.subscriptionPlan": "訂閱方案", + "black.subscribe.success.planName": "OpenCode Black {{plan}}", + "black.subscribe.success.amount": "金額", + "black.subscribe.success.amountValue": "${{plan}} 每月", + "black.subscribe.success.paymentMethod": "付款方式", + "black.subscribe.success.dateJoined": "加入日期", + "black.subscribe.success.chargeNotice": "你的卡片將在訂閱啟用時扣款", + + "workspace.nav.zen": "Zen", + "workspace.nav.apiKeys": "API 金鑰", + "workspace.nav.members": "成員", + "workspace.nav.billing": "帳務", + "workspace.nav.settings": "設定", + + "workspace.home.banner.beforeLink": "編碼代理的可靠最佳化模型。", + "workspace.home.billing.loading": "載入中...", + "workspace.home.billing.enable": "啟用帳務", + "workspace.home.billing.currentBalance": "目前餘額", + + "workspace.newUser.feature.tested.title": "經過測試與驗證的模型", + "workspace.newUser.feature.tested.body": "我們專門針對編碼代理對模型進行了基準測試和測試,以確保最佳效能。", + "workspace.newUser.feature.quality.title": "最高品質", + "workspace.newUser.feature.quality.body": "存取配置為最佳效能的模型 - 無需降級或路由到更便宜的供應商。", + "workspace.newUser.feature.lockin.title": "無綁定", + "workspace.newUser.feature.lockin.body": + "將 Zen 與任何編碼代理結合使用,並在需要時隨時使用 OpenCode 連接其他供應商。", + "workspace.newUser.copyApiKey": "複製 API 金鑰", + "workspace.newUser.copyKey": "複製金鑰", + "workspace.newUser.copied": "已複製!", + "workspace.newUser.step.enableBilling": "啟用帳務", + "workspace.newUser.step.login.before": "執行", + "workspace.newUser.step.login.after": "並選擇 OpenCode", + "workspace.newUser.step.pasteKey": "貼上你的 API 金鑰", + "workspace.newUser.step.models.before": "啟動 OpenCode 並執行", + "workspace.newUser.step.models.after": "以選擇模型", + + "workspace.models.title": "模型", + "workspace.models.subtitle.beforeLink": "管理工作區成員可以存取哪些模型。", + "workspace.models.table.model": "模型", + "workspace.models.table.enabled": "啟用", + + "workspace.providers.title": "自帶金鑰", + "workspace.providers.subtitle": "設定你自己的 AI 供應商 API 金鑰。", + "workspace.providers.placeholder": "輸入 {{provider}} API 金鑰({{prefix}}...)", + "workspace.providers.configure": "設定", + "workspace.providers.edit": "編輯", + "workspace.providers.delete": "刪除", + "workspace.providers.saving": "儲存中...", + "workspace.providers.save": "儲存", + "workspace.providers.table.provider": "供應商", + "workspace.providers.table.apiKey": "API 金鑰", + + "workspace.usage.title": "使用紀錄", + "workspace.usage.subtitle": "最近的 API 使用情況與成本。", + "workspace.usage.empty": "進行第一次 API 呼叫即可開始。", + "workspace.usage.table.date": "日期", + "workspace.usage.table.model": "模型", + "workspace.usage.table.input": "輸入", + "workspace.usage.table.output": "輸出", + "workspace.usage.table.cost": "成本", + "workspace.usage.breakdown.input": "輸入", + "workspace.usage.breakdown.cacheRead": "快取讀取", + "workspace.usage.breakdown.cacheWrite": "快取寫入", + "workspace.usage.breakdown.output": "輸出", + "workspace.usage.breakdown.reasoning": "推理", + "workspace.usage.subscription": "訂閱 (${{amount}})", + + "workspace.cost.title": "成本", + "workspace.cost.subtitle": "按模型細分的使用成本。", + "workspace.cost.allModels": "所有模型", + "workspace.cost.allKeys": "所有金鑰", + "workspace.cost.deletedSuffix": "(已刪除)", + "workspace.cost.empty": "所選期間沒有可用的使用資料。", + "workspace.cost.subscriptionShort": "訂", + + "workspace.keys.title": "API 金鑰", + "workspace.keys.subtitle": "管理你的 API 金鑰以存取 OpenCode 服務。", + "workspace.keys.create": "建立 API 金鑰", + "workspace.keys.placeholder": "輸入金鑰名稱", + "workspace.keys.empty": "建立 OpenCode 閘道器 API 金鑰", + "workspace.keys.table.name": "名稱", + "workspace.keys.table.key": "金鑰", + "workspace.keys.table.createdBy": "建立者", + "workspace.keys.table.lastUsed": "最後使用", + "workspace.keys.copyApiKey": "複製 API 金鑰", + "workspace.keys.delete": "刪除", + + "workspace.members.title": "成員", + "workspace.members.subtitle": "管理工作區成員及其權限。", + "workspace.members.invite": "邀請成員", + "workspace.members.inviting": "邀請中...", + "workspace.members.beta.beforeLink": "Beta 測試期間,工作區對團隊免費。", + "workspace.members.form.invitee": "受邀者", + "workspace.members.form.emailPlaceholder": "輸入電子郵件", + "workspace.members.form.role": "角色", + "workspace.members.form.monthlyLimit": "每月支出限額", + "workspace.members.noLimit": "無限制", + "workspace.members.noLimitLowercase": "無限制", + "workspace.members.invited": "已邀請", + "workspace.members.edit": "編輯", + "workspace.members.delete": "刪除", + "workspace.members.saving": "儲存中...", + "workspace.members.save": "儲存", + "workspace.members.table.email": "電子郵件", + "workspace.members.table.role": "角色", + "workspace.members.table.monthLimit": "月限額", + "workspace.members.role.admin": "管理員", + "workspace.members.role.adminDescription": "可以管理模型、成員和帳務", + "workspace.members.role.member": "成員", + "workspace.members.role.memberDescription": "只能為自己生成 API 金鑰", + + "workspace.settings.title": "設定", + "workspace.settings.subtitle": "更新你的工作區名稱與偏好設定。", + "workspace.settings.workspaceName": "工作區名稱", + "workspace.settings.defaultName": "預設", + "workspace.settings.updating": "更新中...", + "workspace.settings.save": "儲存", + "workspace.settings.edit": "編輯", + + "workspace.billing.title": "帳務", + "workspace.billing.subtitle.beforeLink": "管理付款方式。", + "workspace.billing.contactUs": "聯絡我們", + "workspace.billing.subtitle.afterLink": "如果你有任何問題。", + "workspace.billing.currentBalance": "目前餘額", + "workspace.billing.add": "儲值 $", + "workspace.billing.enterAmount": "輸入金額", + "workspace.billing.loading": "載入中...", + "workspace.billing.addAction": "儲值", + "workspace.billing.addBalance": "儲值餘額", + "workspace.billing.linkedToStripe": "已連結 Stripe", + "workspace.billing.manage": "管理", + "workspace.billing.enable": "啟用帳務", + + "workspace.monthlyLimit.title": "每月限額", + "workspace.monthlyLimit.subtitle": "為你的帳戶設定每月使用限額。", + "workspace.monthlyLimit.placeholder": "50", + "workspace.monthlyLimit.setting": "設定中...", + "workspace.monthlyLimit.set": "設定", + "workspace.monthlyLimit.edit": "編輯限額", + "workspace.monthlyLimit.noLimit": "未設定使用限額。", + "workspace.monthlyLimit.currentUsage.beforeMonth": "目前", + "workspace.monthlyLimit.currentUsage.beforeAmount": "的使用量為 $", + + "workspace.reload.title": "自動儲值", + "workspace.reload.disabled.before": "自動儲值已", + "workspace.reload.disabled.state": "停用", + "workspace.reload.disabled.after": "啟用後會在餘額偏低時自動儲值。", + "workspace.reload.enabled.before": "自動儲值已", + "workspace.reload.enabled.state": "啟用", + "workspace.reload.enabled.middle": "我們將自動儲值", + "workspace.reload.processingFee": "手續費", + "workspace.reload.enabled.after": "當餘額達到", + "workspace.reload.edit": "編輯", + "workspace.reload.enable": "啟用", + "workspace.reload.enableAutoReload": "啟用自動儲值", + "workspace.reload.reloadAmount": "儲值 $", + "workspace.reload.whenBalanceReaches": "當餘額達到 $", + "workspace.reload.saving": "儲存中...", + "workspace.reload.save": "儲存", + "workspace.reload.failedAt": "儲值失敗於", + "workspace.reload.reason": "原因:", + "workspace.reload.updatePaymentMethod": "請更新你的付款方式並重試。", + "workspace.reload.retrying": "重試中...", + "workspace.reload.retry": "重試", + + "workspace.payments.title": "付款紀錄", + "workspace.payments.subtitle": "最近的付款交易。", + "workspace.payments.table.date": "日期", + "workspace.payments.table.paymentId": "付款 ID", + "workspace.payments.table.amount": "金額", + "workspace.payments.table.receipt": "收據", + "workspace.payments.type.credit": "信用額度", + "workspace.payments.type.subscription": "訂閱", + "workspace.payments.view": "檢視", + + "workspace.black.loading": "載入中...", + "workspace.black.time.day": "天", + "workspace.black.time.days": "天", + "workspace.black.time.hour": "小時", + "workspace.black.time.hours": "小時", + "workspace.black.time.minute": "分鐘", + "workspace.black.time.minutes": "分鐘", + "workspace.black.time.fewSeconds": "幾秒鐘", + "workspace.black.subscription.title": "訂閱", + "workspace.black.subscription.message": "你已訂閱 OpenCode Black,費用為每月 ${{plan}}。", + "workspace.black.subscription.manage": "管理訂閱", + "workspace.black.subscription.rollingUsage": "5 小時使用量", + "workspace.black.subscription.weeklyUsage": "每週使用量", + "workspace.black.subscription.resetsIn": "重置於", + "workspace.black.subscription.useBalance": "達到使用限額後使用你的可用餘額", + "workspace.black.waitlist.title": "候補名單", + "workspace.black.waitlist.joined": "你已加入每月 ${{plan}} 的 OpenCode Black 方案候補名單。", + "workspace.black.waitlist.ready": "我們已準備好將你加入每月 ${{plan}} 的 OpenCode Black 方案。", + "workspace.black.waitlist.leave": "離開候補名單", + "workspace.black.waitlist.leaving": "離開中...", + "workspace.black.waitlist.left": "已離開", + "workspace.black.waitlist.enroll": "加入", + "workspace.black.waitlist.enrolling": "加入中...", + "workspace.black.waitlist.enrolled": "已加入", + "workspace.black.waitlist.enrollNote": "當你點選「加入」後,你的訂閱將立即開始,並且將從你的卡片中扣款。", + + "download.title": "OpenCode | 下載", + "download.meta.description": "下載適用於 macOS、Windows 與 Linux 的 OpenCode", + "download.hero.title": "下載 OpenCode", + "download.hero.subtitle": "適用於 macOS、Windows 與 Linux 的 Beta 版現已提供", + "download.hero.button": "下載 {{os}} 版", + "download.section.terminal": "OpenCode 終端", + "download.section.desktop": "OpenCode 桌面版(Beta)", + "download.section.extensions": "OpenCode 擴充功能", + "download.section.integrations": "OpenCode 整合", + "download.action.download": "下載", + "download.action.install": "安裝", + + "download.platform.macosAppleSilicon": "macOS (Apple Silicon)", + "download.platform.macosIntel": "macOS (Intel)", + "download.platform.windowsX64": "Windows (x64)", + "download.platform.linuxDeb": "Linux (.deb)", + "download.platform.linuxRpm": "Linux (.rpm)", + + "download.faq.a3.beforeLocal": + "不一定,但很可能需要。如果你想將 OpenCode 連接到付費供應商,你需要 AI 訂閱,不過你也可以使用", + "download.faq.a3.localLink": "本地模型", + "download.faq.a3.afterLocal.beforeZen": "免費。我們也推薦使用", + "download.faq.a3.afterZen": ",但 OpenCode 同樣支援 OpenAI、Anthropic、xAI 等所有主流供應商。", + + "download.faq.a5.p1": "OpenCode 100% 免費使用。", + "download.faq.a5.p2.beforeZen": "額外費用來自你對模型供應商的訂閱。雖然 OpenCode 支援任何模型供應商,但我們建議使用", + "download.faq.a5.p2.afterZen": "。", + + "download.faq.a6.p1": "你的資料與資訊只會在你於 OpenCode 中建立可分享連結時被儲存。", + "download.faq.a6.p2.beforeShare": "了解更多關於", + "download.faq.a6.shareLink": "分享頁面", + + "enterprise.title": "OpenCode | 面向組織的企業解決方案", + "enterprise.meta.description": "聯絡 OpenCode 取得企業解決方案", + "enterprise.hero.title": "你的程式碼屬於你", + "enterprise.hero.body1": + "OpenCode 在你的組織內部安全運作,不會儲存任何資料或上下文,也沒有授權限制或所有權主張。你可以先與團隊進行試用,然後透過與你的 SSO 與內部 AI 閘道器整合,將其部署到整個組織。", + "enterprise.hero.body2": "告訴我們能如何幫助你。", + "enterprise.form.name.label": "全名", + "enterprise.form.name.placeholder": "傑夫·貝佐斯", + "enterprise.form.role.label": "職稱", + "enterprise.form.role.placeholder": "執行董事長", + "enterprise.form.email.label": "公司 Email", + "enterprise.form.email.placeholder": "jeff@amazon.com", + "enterprise.form.message.label": "你想解決什麼問題?", + "enterprise.form.message.placeholder": "我們需要幫助來...", + "enterprise.form.send": "傳送", + "enterprise.form.sending": "傳送中...", + "enterprise.form.success": "訊息已傳送,我們會盡快與你聯絡。", + "enterprise.faq.title": "常見問題", + "enterprise.faq.q1": "什麼是 OpenCode Enterprise?", + "enterprise.faq.a1": + "OpenCode Enterprise 適用於希望確保程式碼與資料絕不離開自己基礎設施的組織。透過中央化設定,它可與你的 SSO 與內部 AI 閘道器整合,以達成此目標。", + "enterprise.faq.q2": "如何開始使用 OpenCode Enterprise?", + "enterprise.faq.a2": + "只要先以團隊的內部試用開始。OpenCode 預設不會儲存你的程式碼或上下文資料,所以上手非常容易。之後聯絡我們,討論定價與完整實作方案。", + "enterprise.faq.q3": "企業定價是如何進行的?", + "enterprise.faq.a3": + "我們提供按席位的企業定價。如果你有自己的 LLM 閘道器,我們不會對使用的 token 另外收費。更多詳情,請聯絡我們以獲得依據組織需求的客製報價。", + "enterprise.faq.q4": "我的資料在 OpenCode Enterprise 中是安全的嗎?", + "enterprise.faq.a4": + "是的。OpenCode 不會儲存你的程式碼或上下文資料。所有處理都會在本地或透過直接呼叫你的 AI 供應商 API 完成。透過中央化設定與 SSO 整合,你的資料會安全保留在組織的基礎設施內部。", + + "brand.title": "OpenCode | 品牌", + "brand.meta.description": "OpenCode 品牌指南", + "brand.heading": "品牌指南", + "brand.subtitle": "協助你使用 OpenCode 品牌的資源與素材。", + "brand.downloadAll": "下載所有素材", + + "changelog.title": "OpenCode | 更新日誌", + "changelog.meta.description": "OpenCode 發布說明與更新日誌", + "changelog.hero.title": "更新日誌", + "changelog.hero.subtitle": "OpenCode 的新更新與改善", + "changelog.empty": "找不到更新日誌項目。", + "changelog.viewJson": "檢視 JSON", + + "bench.list.title": "評測", + "bench.list.heading": "評測", + "bench.list.table.agent": "代理", + "bench.list.table.model": "模型", + "bench.list.table.score": "分數", + + "bench.detail.title": "評測 - {{task}}", + "bench.detail.notFound": "找不到任務", + "bench.detail.na": "N/A", + "bench.detail.labels.agent": "代理", + "bench.detail.labels.model": "模型", + "bench.detail.labels.task": "任務", + "bench.detail.labels.repo": "儲存庫", + "bench.detail.labels.from": "起點", + "bench.detail.labels.to": "終點", + "bench.detail.labels.prompt": "提示詞", + "bench.detail.labels.commit": "提交", + "bench.detail.labels.averageDuration": "平均耗時", + "bench.detail.labels.averageScore": "平均分數", + "bench.detail.labels.averageCost": "平均成本", + "bench.detail.labels.summary": "摘要", + "bench.detail.labels.runs": "執行次數", + "bench.detail.labels.score": "分數", + "bench.detail.labels.base": "基準", + "bench.detail.labels.penalty": "扣分", + "bench.detail.labels.weight": "權重", + "bench.detail.table.run": "執行", + "bench.detail.table.score": "分數(基準 - 扣分)", + "bench.detail.table.cost": "成本", + "bench.detail.table.duration": "耗時", + "bench.detail.run.title": "執行 {{n}}", + "bench.detail.rawJson": "原始 JSON", +} satisfies Dict diff --git a/packages/console/app/src/lib/form-error.ts b/packages/console/app/src/lib/form-error.ts new file mode 100644 index 00000000000..1f6e2ea1e69 --- /dev/null +++ b/packages/console/app/src/lib/form-error.ts @@ -0,0 +1,83 @@ +import type { Key } from "~/i18n" + +export const formError = { + invalidPlan: "error.invalidPlan", + workspaceRequired: "error.workspaceRequired", + alreadySubscribed: "error.alreadySubscribed", + limitRequired: "error.limitRequired", + monthlyLimitInvalid: "error.monthlyLimitInvalid", + workspaceNameRequired: "error.workspaceNameRequired", + nameTooLong: "error.nameTooLong", + emailRequired: "error.emailRequired", + roleRequired: "error.roleRequired", + idRequired: "error.idRequired", + nameRequired: "error.nameRequired", + providerRequired: "error.providerRequired", + apiKeyRequired: "error.apiKeyRequired", + modelRequired: "error.modelRequired", +} as const + +const map = { + [formError.invalidPlan]: "error.invalidPlan", + [formError.workspaceRequired]: "error.workspaceRequired", + [formError.alreadySubscribed]: "error.alreadySubscribed", + [formError.limitRequired]: "error.limitRequired", + [formError.monthlyLimitInvalid]: "error.monthlyLimitInvalid", + [formError.workspaceNameRequired]: "error.workspaceNameRequired", + [formError.nameTooLong]: "error.nameTooLong", + [formError.emailRequired]: "error.emailRequired", + [formError.roleRequired]: "error.roleRequired", + [formError.idRequired]: "error.idRequired", + [formError.nameRequired]: "error.nameRequired", + [formError.providerRequired]: "error.providerRequired", + [formError.apiKeyRequired]: "error.apiKeyRequired", + [formError.modelRequired]: "error.modelRequired", + "Invalid plan": "error.invalidPlan", + "Workspace ID is required": "error.workspaceRequired", + "Workspace ID is required.": "error.workspaceRequired", + "This workspace already has a subscription": "error.alreadySubscribed", + "Limit is required.": "error.limitRequired", + "Set a valid monthly limit": "error.monthlyLimitInvalid", + "Set a valid monthly limit.": "error.monthlyLimitInvalid", + "Workspace name is required.": "error.workspaceNameRequired", + "Name must be 255 characters or less.": "error.nameTooLong", + "Email is required": "error.emailRequired", + "Role is required": "error.roleRequired", + "ID is required": "error.idRequired", + "Name is required": "error.nameRequired", + "Provider is required": "error.providerRequired", + "API key is required": "error.apiKeyRequired", + "Model is required": "error.modelRequired", +} as const satisfies Record + +export function formErrorReloadAmountMin(amount: number) { + return `error.reloadAmountMin:${amount}` +} + +export function formErrorReloadTriggerMin(amount: number) { + return `error.reloadTriggerMin:${amount}` +} + +export function localizeError(t: (key: Key, params?: Record) => string, error?: string) { + if (!error) return "" + + if (error.startsWith("error.reloadAmountMin:")) { + const amount = Number(error.split(":")[1] ?? 0) + return t("error.reloadAmountMin", { amount }) + } + + if (error.startsWith("error.reloadTriggerMin:")) { + const amount = Number(error.split(":")[1] ?? 0) + return t("error.reloadTriggerMin", { amount }) + } + + const amount = error.match(/^Reload amount must be at least \$(\d+)$/) + if (amount) return t("error.reloadAmountMin", { amount: Number(amount[1]) }) + + const trigger = error.match(/^Balance trigger must be at least \$(\d+)$/) + if (trigger) return t("error.reloadTriggerMin", { amount: Number(trigger[1]) }) + + const key = map[error as keyof typeof map] + if (key) return t(key) + return error +} diff --git a/packages/console/app/src/lib/language.ts b/packages/console/app/src/lib/language.ts new file mode 100644 index 00000000000..54321d23438 --- /dev/null +++ b/packages/console/app/src/lib/language.ts @@ -0,0 +1,287 @@ +export const LOCALES = [ + "en", + "zh", + "zht", + "ko", + "de", + "es", + "fr", + "it", + "da", + "ja", + "pl", + "ru", + "ar", + "no", + "br", + "th", + "tr", +] as const + +export type Locale = (typeof LOCALES)[number] + +export const LOCALE_COOKIE = "oc_locale" as const +export const LOCALE_HEADER = "x-opencode-locale" as const + +function fix(pathname: string) { + if (pathname.startsWith("/")) return pathname + return `/${pathname}` +} + +const LABEL = { + en: "English", + zh: "简体中文", + zht: "繁體中文", + ko: "한국어", + de: "Deutsch", + es: "Español", + fr: "Français", + it: "Italiano", + da: "Dansk", + ja: "日本語", + pl: "Polski", + ru: "Русский", + ar: "العربية", + no: "Norsk", + br: "Português (Brasil)", + th: "ไทย", + tr: "Türkçe", +} satisfies Record + +const TAG = { + en: "en", + zh: "zh-Hans", + zht: "zh-Hant", + ko: "ko", + de: "de", + es: "es", + fr: "fr", + it: "it", + da: "da", + ja: "ja", + pl: "pl", + ru: "ru", + ar: "ar", + no: "no", + br: "pt-BR", + th: "th", + tr: "tr", +} satisfies Record + +const DOCS = { + en: "root", + zh: "zh-cn", + zht: "zh-tw", + ko: "ko", + de: "de", + es: "es", + fr: "fr", + it: "it", + da: "da", + ja: "ja", + pl: "pl", + ru: "ru", + ar: "ar", + no: "nb", + br: "pt-br", + th: "th", + tr: "tr", +} satisfies Record + +const DOCS_SEGMENT = new Set([ + "ar", + "bs", + "da", + "de", + "es", + "fr", + "it", + "ja", + "ko", + "nb", + "pl", + "pt-br", + "ru", + "th", + "tr", + "zh-cn", + "zh-tw", +]) + +function suffix(pathname: string) { + const index = pathname.search(/[?#]/) + if (index === -1) { + return { + path: fix(pathname), + suffix: "", + } + } + + return { + path: fix(pathname.slice(0, index)), + suffix: pathname.slice(index), + } +} + +export function docs(locale: Locale, pathname: string) { + const value = DOCS[locale] + const next = suffix(pathname) + if (next.path !== "/docs" && next.path !== "/docs/" && !next.path.startsWith("/docs/")) { + return `${next.path}${next.suffix}` + } + + if (value === "root") return `${next.path}${next.suffix}` + + if (next.path === "/docs") return `/docs/${value}${next.suffix}` + if (next.path === "/docs/") return `/docs/${value}/${next.suffix}` + + const head = next.path.slice("/docs/".length).split("/")[0] ?? "" + if (!head) return `/docs/${value}/${next.suffix}` + if (DOCS_SEGMENT.has(head)) return `${next.path}${next.suffix}` + if (head.startsWith("_")) return `${next.path}${next.suffix}` + if (head.includes(".")) return `${next.path}${next.suffix}` + + return `/docs/${value}${next.path.slice("/docs".length)}${next.suffix}` +} + +export function parseLocale(value: unknown): Locale | null { + if (typeof value !== "string") return null + if ((LOCALES as readonly string[]).includes(value)) return value as Locale + return null +} + +export function fromPathname(pathname: string) { + return parseLocale(fix(pathname).split("/")[1]) +} + +export function strip(pathname: string) { + const locale = fromPathname(pathname) + if (!locale) return fix(pathname) + + const next = fix(pathname).slice(locale.length + 1) + if (!next) return "/" + if (next.startsWith("/")) return next + return `/${next}` +} + +export function route(locale: Locale, pathname: string) { + const next = strip(pathname) + if (next.startsWith("/docs")) return docs(locale, next) + if (next.startsWith("/auth")) return next + if (next.startsWith("/workspace")) return next + if (locale === "en") return next + if (next === "/") return `/${locale}` + return `/${locale}${next}` +} + +export function label(locale: Locale) { + return LABEL[locale] +} + +export function tag(locale: Locale) { + return TAG[locale] +} + +export function dir(locale: Locale) { + if (locale === "ar") return "rtl" + return "ltr" +} + +function match(input: string): Locale | null { + const value = input.trim().toLowerCase() + if (!value) return null + + if (value.startsWith("zh")) { + if (value.includes("hant") || value.includes("-tw") || value.includes("-hk") || value.includes("-mo")) return "zht" + return "zh" + } + + if (value.startsWith("ko")) return "ko" + if (value.startsWith("de")) return "de" + if (value.startsWith("es")) return "es" + if (value.startsWith("fr")) return "fr" + if (value.startsWith("it")) return "it" + if (value.startsWith("da")) return "da" + if (value.startsWith("ja")) return "ja" + if (value.startsWith("pl")) return "pl" + if (value.startsWith("ru")) return "ru" + if (value.startsWith("ar")) return "ar" + if (value.startsWith("tr")) return "tr" + if (value.startsWith("th")) return "th" + if (value.startsWith("pt")) return "br" + if (value.startsWith("no") || value.startsWith("nb") || value.startsWith("nn")) return "no" + if (value.startsWith("en")) return "en" + return null +} + +export function detectFromLanguages(languages: readonly string[]) { + for (const language of languages) { + const locale = match(language) + if (locale) return locale + } + return "en" satisfies Locale +} + +export function detectFromAcceptLanguage(header: string | null) { + if (!header) return "en" satisfies Locale + + const items = header + .split(",") + .map((raw) => raw.trim()) + .filter(Boolean) + .map((raw) => { + const parts = raw.split(";").map((x) => x.trim()) + const lang = parts[0] ?? "" + const q = parts + .slice(1) + .find((x) => x.startsWith("q=")) + ?.slice(2) + return { + lang, + q: q ? Number.parseFloat(q) : 1, + } + }) + .sort((a, b) => b.q - a.q) + + for (const item of items) { + if (!item.lang || item.lang === "*") continue + const locale = match(item.lang) + if (locale) return locale + } + + return "en" satisfies Locale +} + +export function localeFromCookieHeader(header: string | null) { + if (!header) return null + + const raw = header + .split(";") + .map((x) => x.trim()) + .find((x) => x.startsWith(`${LOCALE_COOKIE}=`)) + ?.slice(`${LOCALE_COOKIE}=`.length) + + if (!raw) return null + return parseLocale(decodeURIComponent(raw)) +} + +export function localeFromRequest(request: Request) { + const fromHeader = parseLocale(request.headers.get(LOCALE_HEADER)) + if (fromHeader) return fromHeader + + const fromPath = fromPathname(new URL(request.url).pathname) + if (fromPath) return fromPath + + return ( + localeFromCookieHeader(request.headers.get("cookie")) ?? + detectFromAcceptLanguage(request.headers.get("accept-language")) + ) +} + +export function cookie(locale: Locale) { + return `${LOCALE_COOKIE}=${encodeURIComponent(locale)}; Path=/; Max-Age=31536000; SameSite=Lax` +} + +export function clearCookie() { + return `${LOCALE_COOKIE}=; Path=/; Max-Age=0; SameSite=Lax` +} diff --git a/packages/console/app/test/rateLimiter.test.ts b/packages/console/app/test/rateLimiter.test.ts new file mode 100644 index 00000000000..864f907d669 --- /dev/null +++ b/packages/console/app/test/rateLimiter.test.ts @@ -0,0 +1,92 @@ +import { describe, expect, test } from "bun:test" +import { getRetryAfterDay, getRetryAfterHour } from "../src/routes/zen/util/rateLimiter" + +describe("getRetryAfterDay", () => { + test("returns full day at midnight UTC", () => { + const midnight = Date.UTC(2026, 0, 15, 0, 0, 0, 0) + expect(getRetryAfterDay(midnight)).toBe(86_400) + }) + + test("returns remaining seconds until next UTC day", () => { + const noon = Date.UTC(2026, 0, 15, 12, 0, 0, 0) + expect(getRetryAfterDay(noon)).toBe(43_200) + }) + + test("rounds up to nearest second", () => { + const almost = Date.UTC(2026, 0, 15, 23, 59, 59, 500) + expect(getRetryAfterDay(almost)).toBe(1) + }) +}) + +describe("getRetryAfterHour", () => { + // 14:30:00 UTC — 30 minutes into the current hour + const now = Date.UTC(2026, 0, 15, 14, 30, 0, 0) + const intervals = ["2026011514", "2026011513", "2026011512"] + + test("waits 3 hours when all usage is in current hour", () => { + const rows = [{ interval: "2026011514", count: 10 }] + // only current hour has usage — it won't leave the window for 3 hours from hour start + // 3 * 3600 - 1800 = 9000s + expect(getRetryAfterHour(rows, intervals, 10, now)).toBe(9000) + }) + + test("waits 1 hour when dropping oldest interval is sufficient", () => { + const rows = [ + { interval: "2026011514", count: 2 }, + { interval: "2026011512", count: 10 }, + ] + // total=12, drop oldest (-2h, count=10) -> 2 < 10 + // hours = 3 - 2 = 1 -> 1 * 3600 - 1800 = 1800s + expect(getRetryAfterHour(rows, intervals, 10, now)).toBe(1800) + }) + + test("waits 2 hours when usage spans oldest two intervals", () => { + const rows = [ + { interval: "2026011513", count: 8 }, + { interval: "2026011512", count: 5 }, + ] + // total=13, drop -2h (5) -> 8, 8 >= 8, drop -1h (8) -> 0 < 8 + // hours = 3 - 1 = 2 -> 2 * 3600 - 1800 = 5400s + expect(getRetryAfterHour(rows, intervals, 8, now)).toBe(5400) + }) + + test("waits 1 hour when oldest interval alone pushes over limit", () => { + const rows = [ + { interval: "2026011514", count: 1 }, + { interval: "2026011513", count: 1 }, + { interval: "2026011512", count: 10 }, + ] + // total=12, drop -2h (10) -> 2 < 10 + // hours = 3 - 2 = 1 -> 1800s + expect(getRetryAfterHour(rows, intervals, 10, now)).toBe(1800) + }) + + test("waits 2 hours when middle interval keeps total over limit", () => { + const rows = [ + { interval: "2026011514", count: 4 }, + { interval: "2026011513", count: 4 }, + { interval: "2026011512", count: 4 }, + ] + // total=12, drop -2h (4) -> 8, 8 >= 5, drop -1h (4) -> 4 < 5 + // hours = 3 - 1 = 2 -> 5400s + expect(getRetryAfterHour(rows, intervals, 5, now)).toBe(5400) + }) + + test("rounds up to nearest second", () => { + const offset = Date.UTC(2026, 0, 15, 14, 30, 0, 500) + const rows = [ + { interval: "2026011514", count: 2 }, + { interval: "2026011512", count: 10 }, + ] + // hours=1 -> 3_600_000 - 1_800_500 = 1_799_500ms -> ceil(1799.5) = 1800 + expect(getRetryAfterHour(rows, intervals, 10, offset)).toBe(1800) + }) + + test("fallback returns time until next hour when rows are empty", () => { + // edge case: rows empty but function called (shouldn't happen in practice) + // loop drops all zeros, running stays 0 which is < any positive limit on first iteration + const rows: { interval: string; count: number }[] = [] + // drop -2h (0) -> 0 < 1 -> hours = 3 - 2 = 1 -> 1800s + expect(getRetryAfterHour(rows, intervals, 1, now)).toBe(1800) + }) +}) diff --git a/packages/console/core/script/disable-reload.ts b/packages/console/core/script/disable-reload.ts new file mode 100644 index 00000000000..860739eb000 --- /dev/null +++ b/packages/console/core/script/disable-reload.ts @@ -0,0 +1,34 @@ +import { Database, eq } from "../src/drizzle/index.js" +import { BillingTable } from "../src/schema/billing.sql.js" +import { WorkspaceTable } from "../src/schema/workspace.sql.js" + +const workspaceID = process.argv[2] + +if (!workspaceID) { + console.error("Usage: bun disable-reload.ts ") + process.exit(1) +} + +const billing = await Database.use((tx) => + tx + .select({ reload: BillingTable.reload }) + .from(BillingTable) + .innerJoin(WorkspaceTable, eq(WorkspaceTable.id, BillingTable.workspaceID)) + .where(eq(BillingTable.workspaceID, workspaceID)) + .then((rows) => rows[0]), +) +if (!billing) { + console.error("Error: Workspace or billing record not found") + process.exit(1) +} + +if (!billing.reload) { + console.log(`Reload is already disabled for workspace ${workspaceID}`) + process.exit(0) +} + +await Database.use((tx) => + tx.update(BillingTable).set({ reload: false }).where(eq(BillingTable.workspaceID, workspaceID)), +) + +console.log(`Disabled reload for workspace ${workspaceID}`) diff --git a/packages/desktop/AGENTS.md b/packages/desktop/AGENTS.md new file mode 100644 index 00000000000..3839db1a904 --- /dev/null +++ b/packages/desktop/AGENTS.md @@ -0,0 +1,4 @@ +# Desktop package notes + +- Never call `invoke` manually in this package. +- Use the generated bindings in `packages/desktop/src/bindings.ts` for core commands/events. diff --git a/packages/desktop/src-tauri/src/constants.rs b/packages/desktop/src-tauri/src/constants.rs new file mode 100644 index 00000000000..9d50d00e202 --- /dev/null +++ b/packages/desktop/src-tauri/src/constants.rs @@ -0,0 +1,10 @@ +use tauri_plugin_window_state::StateFlags; + +pub const SETTINGS_STORE: &str = "opencode.settings.dat"; +pub const DEFAULT_SERVER_URL_KEY: &str = "defaultServerUrl"; +pub const WSL_ENABLED_KEY: &str = "wslEnabled"; +pub const UPDATER_ENABLED: bool = option_env!("TAURI_SIGNING_PRIVATE_KEY").is_some(); + +pub fn window_state_flags() -> StateFlags { + StateFlags::all() - StateFlags::DECORATIONS - StateFlags::VISIBLE +} diff --git a/packages/desktop/src-tauri/src/linux_display.rs b/packages/desktop/src-tauri/src/linux_display.rs new file mode 100644 index 00000000000..0179cf8bbb3 --- /dev/null +++ b/packages/desktop/src-tauri/src/linux_display.rs @@ -0,0 +1,53 @@ +use serde::{Deserialize, Serialize}; +use serde_json::json; +use std::path::PathBuf; +use tauri::AppHandle; +use tauri_plugin_store::StoreExt; + +use crate::constants::SETTINGS_STORE; + +pub const LINUX_DISPLAY_CONFIG_KEY: &str = "linuxDisplayConfig"; + +#[derive(Default, Serialize, Deserialize)] +struct DisplayConfig { + wayland: Option, +} + +fn dir() -> Option { + Some(dirs::data_dir()?.join(if cfg!(debug_assertions) { + "ai.opencode.desktop.dev" + } else { + "ai.opencode.desktop" + })) +} + +fn path() -> Option { + dir().map(|dir| dir.join(SETTINGS_STORE)) +} + +pub fn read_wayland() -> Option { + let raw = std::fs::read_to_string(path()?).ok()?; + let root = serde_json::from_str::(&raw) + .ok()? + .get(LINUX_DISPLAY_CONFIG_KEY) + .cloned()?; + serde_json::from_value::(root).ok()?.wayland +} + +pub fn write_wayland(app: &AppHandle, value: bool) -> Result<(), String> { + let store = app + .store(SETTINGS_STORE) + .map_err(|e| format!("Failed to open settings store: {}", e))?; + + store.set( + LINUX_DISPLAY_CONFIG_KEY, + json!(DisplayConfig { + wayland: Some(value), + }), + ); + store + .save() + .map_err(|e| format!("Failed to save settings store: {}", e))?; + + Ok(()) +} diff --git a/packages/desktop/src-tauri/src/logging.rs b/packages/desktop/src-tauri/src/logging.rs new file mode 100644 index 00000000000..f794f9c1bc4 --- /dev/null +++ b/packages/desktop/src-tauri/src/logging.rs @@ -0,0 +1,83 @@ +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::{Path, PathBuf}; +use tracing_appender::non_blocking::WorkerGuard; +use tracing_subscriber::{EnvFilter, fmt, layer::SubscriberExt, util::SubscriberInitExt}; + +const MAX_LOG_AGE_DAYS: u64 = 7; +const TAIL_LINES: usize = 1000; + +static LOG_PATH: std::sync::OnceLock = std::sync::OnceLock::new(); + +pub fn init(log_dir: &Path) -> WorkerGuard { + std::fs::create_dir_all(log_dir).expect("failed to create log directory"); + + cleanup(log_dir); + + let timestamp = chrono::Local::now().format("%Y-%m-%d_%H-%M-%S"); + let filename = format!("opencode-desktop_{timestamp}.log"); + let log_path = log_dir.join(&filename); + + LOG_PATH + .set(log_path.clone()) + .expect("logging already initialized"); + + let file = File::create(&log_path).expect("failed to create log file"); + let (non_blocking, guard) = tracing_appender::non_blocking(file); + + let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| { + if cfg!(debug_assertions) { + EnvFilter::new("opencode_lib=debug,opencode_desktop=debug,sidecar=debug") + } else { + EnvFilter::new("opencode_lib=info,opencode_desktop=info,sidecar=info") + } + }); + + tracing_subscriber::registry() + .with(filter) + .with(fmt::layer().with_writer(std::io::stderr)) + .with( + fmt::layer() + .with_writer(non_blocking) + .with_ansi(false), + ) + .init(); + + guard +} + +pub fn tail() -> String { + let Some(path) = LOG_PATH.get() else { + return String::new(); + }; + + let Ok(file) = File::open(path) else { + return String::new(); + }; + + let lines: Vec = BufReader::new(file) + .lines() + .map_while(Result::ok) + .collect(); + + let start = lines.len().saturating_sub(TAIL_LINES); + lines[start..].join("\n") +} + +fn cleanup(log_dir: &Path) { + let cutoff = std::time::SystemTime::now() + - std::time::Duration::from_secs(MAX_LOG_AGE_DAYS * 24 * 60 * 60); + + let Ok(entries) = std::fs::read_dir(log_dir) else { + return; + }; + + for entry in entries.flatten() { + if let Ok(meta) = entry.metadata() + && let Ok(modified) = meta.modified() + && modified < cutoff + { + let _ = std::fs::remove_file(entry.path()); + } + } +} diff --git a/packages/desktop/src-tauri/src/server.rs b/packages/desktop/src-tauri/src/server.rs new file mode 100644 index 00000000000..81e0595af71 --- /dev/null +++ b/packages/desktop/src-tauri/src/server.rs @@ -0,0 +1,255 @@ +use std::time::{Duration, Instant}; + +use tauri::AppHandle; +use tauri_plugin_dialog::{DialogExt, MessageDialogButtons, MessageDialogResult}; +use tauri_plugin_shell::process::CommandChild; +use tauri_plugin_store::StoreExt; +use tokio::task::JoinHandle; + +use crate::{ + cli, + constants::{DEFAULT_SERVER_URL_KEY, SETTINGS_STORE, WSL_ENABLED_KEY}, +}; + +#[derive(Clone, serde::Serialize, serde::Deserialize, specta::Type, Debug)] +pub struct WslConfig { + pub enabled: bool, +} + +impl Default for WslConfig { + fn default() -> Self { + Self { enabled: false } + } +} + +#[tauri::command] +#[specta::specta] +pub fn get_default_server_url(app: AppHandle) -> Result, String> { + let store = app + .store(SETTINGS_STORE) + .map_err(|e| format!("Failed to open settings store: {}", e))?; + + let value = store.get(DEFAULT_SERVER_URL_KEY); + match value { + Some(v) => Ok(v.as_str().map(String::from)), + None => Ok(None), + } +} + +#[tauri::command] +#[specta::specta] +pub async fn set_default_server_url(app: AppHandle, url: Option) -> Result<(), String> { + let store = app + .store(SETTINGS_STORE) + .map_err(|e| format!("Failed to open settings store: {}", e))?; + + match url { + Some(u) => { + store.set(DEFAULT_SERVER_URL_KEY, serde_json::Value::String(u)); + } + None => { + store.delete(DEFAULT_SERVER_URL_KEY); + } + } + + store + .save() + .map_err(|e| format!("Failed to save settings: {}", e))?; + + Ok(()) +} + +#[tauri::command] +#[specta::specta] +pub fn get_wsl_config(app: AppHandle) -> Result { + let store = app + .store(SETTINGS_STORE) + .map_err(|e| format!("Failed to open settings store: {}", e))?; + + let enabled = store + .get(WSL_ENABLED_KEY) + .as_ref() + .and_then(|v| v.as_bool()) + .unwrap_or(false); + + Ok(WslConfig { enabled }) +} + +#[tauri::command] +#[specta::specta] +pub fn set_wsl_config(app: AppHandle, config: WslConfig) -> Result<(), String> { + let store = app + .store(SETTINGS_STORE) + .map_err(|e| format!("Failed to open settings store: {}", e))?; + + store.set(WSL_ENABLED_KEY, serde_json::Value::Bool(config.enabled)); + + store + .save() + .map_err(|e| format!("Failed to save settings: {}", e))?; + + Ok(()) +} + +pub async fn get_saved_server_url(app: &tauri::AppHandle) -> Option { + if let Some(url) = get_default_server_url(app.clone()).ok().flatten() { + tracing::info!(%url, "Using desktop-specific custom URL"); + return Some(url); + } + + if let Some(cli_config) = cli::get_config(app).await + && let Some(url) = get_server_url_from_config(&cli_config) + { + tracing::info!(%url, "Using custom server URL from config"); + return Some(url); + } + + None +} + +pub fn spawn_local_server( + app: AppHandle, + hostname: String, + port: u32, + password: String, +) -> (CommandChild, HealthCheck) { + let (child, exit) = cli::serve(&app, &hostname, port, &password); + + let health_check = HealthCheck(tokio::spawn(async move { + let url = format!("http://{hostname}:{port}"); + let timestamp = Instant::now(); + + let ready = async { + loop { + tokio::time::sleep(Duration::from_millis(100)).await; + + if check_health(&url, Some(&password)).await { + tracing::info!(elapsed = ?timestamp.elapsed(), "Server ready"); + return Ok(()); + } + } + }; + + let terminated = async { + match exit.await { + Ok(payload) => Err(format!( + "Sidecar terminated before becoming healthy (code={:?} signal={:?})", + payload.code, payload.signal + )), + Err(_) => Err("Sidecar terminated before becoming healthy".to_string()), + } + }; + + tokio::select! { + res = ready => res, + res = terminated => res, + } + })); + + (child, health_check) +} + +pub struct HealthCheck(pub JoinHandle>); + +pub async fn check_health(url: &str, password: Option<&str>) -> bool { + let Ok(url) = reqwest::Url::parse(url) else { + return false; + }; + + let mut builder = reqwest::Client::builder().timeout(Duration::from_secs(3)); + + if url_is_localhost(&url) { + // Some environments set proxy variables (HTTP_PROXY/HTTPS_PROXY/ALL_PROXY) without + // excluding loopback. reqwest respects these by default, which can prevent the desktop + // app from reaching its own local sidecar server. + builder = builder.no_proxy(); + }; + + let Ok(client) = builder.build() else { + return false; + }; + let Ok(health_url) = url.join("/global/health") else { + return false; + }; + + let mut req = client.get(health_url); + + if let Some(password) = password { + req = req.basic_auth("opencode", Some(password)); + } + + req.send() + .await + .map(|r| r.status().is_success()) + .unwrap_or(false) +} + +fn url_is_localhost(url: &reqwest::Url) -> bool { + url.host_str().is_some_and(|host| { + host.eq_ignore_ascii_case("localhost") + || host + .parse::() + .is_ok_and(|ip| ip.is_loopback()) + }) +} + +/// Converts a bind address hostname to a valid URL hostname for connection. +/// - `0.0.0.0` and `::` are wildcard bind addresses, not valid connect targets +/// - IPv6 addresses need brackets in URLs (e.g., `::1` -> `[::1]`) +fn normalize_hostname_for_url(hostname: &str) -> String { + // Wildcard bind addresses -> localhost equivalents + if hostname == "0.0.0.0" { + return "127.0.0.1".to_string(); + } + if hostname == "::" { + return "[::1]".to_string(); + } + + // IPv6 addresses need brackets in URLs + if hostname.contains(':') && !hostname.starts_with('[') { + return format!("[{}]", hostname); + } + + hostname.to_string() +} + +fn get_server_url_from_config(config: &cli::Config) -> Option { + let server = config.server.as_ref()?; + let port = server.port?; + tracing::debug!(port, "server.port found in OC config"); + let hostname = server + .hostname + .as_ref() + .map(|v| normalize_hostname_for_url(v)) + .unwrap_or_else(|| "127.0.0.1".to_string()); + + Some(format!("http://{}:{}", hostname, port)) +} + +pub async fn check_health_or_ask_retry(app: &AppHandle, url: &str) -> bool { + tracing::debug!(%url, "Checking health"); + loop { + if check_health(url, None).await { + return true; + } + + const RETRY: &str = "Retry"; + + let res = app.dialog() + .message(format!("Could not connect to configured server:\n{}\n\nWould you like to retry or start a local server instead?", url)) + .title("Connection Failed") + .buttons(MessageDialogButtons::OkCancelCustom(RETRY.to_string(), "Start Local".to_string())) + .blocking_show_with_result(); + + match res { + MessageDialogResult::Custom(name) if name == RETRY => { + continue; + } + _ => { + break; + } + } + } + + false +} diff --git a/packages/desktop/src-tauri/src/windows.rs b/packages/desktop/src-tauri/src/windows.rs new file mode 100644 index 00000000000..2ddcb0506d8 --- /dev/null +++ b/packages/desktop/src-tauri/src/windows.rs @@ -0,0 +1,149 @@ +use crate::{ + constants::{UPDATER_ENABLED, window_state_flags}, + server::get_wsl_config, +}; +use std::{ops::Deref, time::Duration}; +use tauri::{AppHandle, Manager, Runtime, WebviewUrl, WebviewWindow, WebviewWindowBuilder}; +use tauri_plugin_window_state::AppHandleExt; +use tokio::sync::mpsc; + +pub struct MainWindow(WebviewWindow); + +impl Deref for MainWindow { + type Target = WebviewWindow; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl MainWindow { + pub const LABEL: &str = "main"; + + pub fn create(app: &AppHandle) -> Result { + if let Some(window) = app.get_webview_window(Self::LABEL) { + return Ok(Self(window)); + } + + let wsl_enabled = get_wsl_config(app.clone()) + .ok() + .map(|v| v.enabled) + .unwrap_or(false); + + let window_builder = base_window_config( + WebviewWindowBuilder::new(app, Self::LABEL, WebviewUrl::App("/".into())), + app, + ) + .title("OpenCode") + .decorations(true) + .disable_drag_drop_handler() + .zoom_hotkeys_enabled(false) + .visible(true) + .maximized(true) + .initialization_script(format!( + r#" + window.__OPENCODE__ ??= {{}}; + window.__OPENCODE__.updaterEnabled = {UPDATER_ENABLED}; + window.__OPENCODE__.wsl = {wsl_enabled}; + "# + )); + + let window = window_builder.build()?; + + setup_window_state_listener(app, &window); + + #[cfg(windows)] + { + use tauri_plugin_decorum::WebviewWindowExt; + let _ = window.create_overlay_titlebar(); + } + + Ok(Self(window)) + } +} + +fn setup_window_state_listener(app: &AppHandle, window: &WebviewWindow) { + let (tx, mut rx) = mpsc::channel::<()>(1); + + window.on_window_event(move |event| { + use tauri::WindowEvent; + if !matches!(event, WindowEvent::Moved(_) | WindowEvent::Resized(_)) { + return; + } + let _ = tx.try_send(()); + }); + + tokio::spawn({ + let app = app.clone(); + + async move { + let save = || { + let handle = app.clone(); + let app = app.clone(); + let _ = handle.run_on_main_thread(move || { + let _ = app.save_window_state(window_state_flags()); + }); + }; + + while rx.recv().await.is_some() { + tokio::time::sleep(Duration::from_millis(200)).await; + + save(); + } + } + }); +} + +pub struct LoadingWindow(WebviewWindow); + +impl Deref for LoadingWindow { + type Target = WebviewWindow; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl LoadingWindow { + pub const LABEL: &str = "loading"; + + pub fn create(app: &AppHandle) -> Result { + let window_builder = base_window_config( + WebviewWindowBuilder::new(app, Self::LABEL, tauri::WebviewUrl::App("/loading".into())), + app, + ) + .center() + .resizable(false) + .inner_size(640.0, 480.0) + .visible(true); + + Ok(Self(window_builder.build()?)) + } +} + +fn base_window_config<'a, R: Runtime, M: Manager>( + window_builder: WebviewWindowBuilder<'a, R, M>, + _app: &AppHandle, +) -> WebviewWindowBuilder<'a, R, M> { + let window_builder = window_builder.decorations(true); + + #[cfg(windows)] + let window_builder = window_builder + // Some VPNs set a global/system proxy that WebView2 applies even for loopback + // connections, which breaks the app's localhost sidecar server. + // Note: when setting additional args, we must re-apply wry's default + // `--disable-features=...` flags. + .additional_browser_args( + "--proxy-bypass-list=<-loopback> --disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection", + ) + .data_directory(_app.path().config_dir().expect("Failed to get config dir").join(_app.config().product_name.clone().unwrap())) + .decorations(false); + + #[cfg(target_os = "macos")] + let window_builder = window_builder + .title_bar_style(tauri::TitleBarStyle::Overlay) + .hidden_title(true) + .traffic_light_position(tauri::LogicalPosition::new(12.0, 18.0)); + + window_builder +} diff --git a/packages/desktop/src/bindings.ts b/packages/desktop/src/bindings.ts new file mode 100644 index 00000000000..3d588a17155 --- /dev/null +++ b/packages/desktop/src/bindings.ts @@ -0,0 +1,62 @@ +// This file has been generated by Tauri Specta. Do not edit this file manually. + +import { invoke as __TAURI_INVOKE, Channel } from '@tauri-apps/api/core'; +import * as __TAURI_EVENT from "@tauri-apps/api/event"; + +/** Commands */ +export const commands = { + killSidecar: () => __TAURI_INVOKE("kill_sidecar"), + installCli: () => __TAURI_INVOKE("install_cli"), + awaitInitialization: (events: Channel) => __TAURI_INVOKE("await_initialization", { events }), + getDefaultServerUrl: () => __TAURI_INVOKE("get_default_server_url"), + setDefaultServerUrl: (url: string | null) => __TAURI_INVOKE("set_default_server_url", { url }), + getWslConfig: () => __TAURI_INVOKE("get_wsl_config"), + setWslConfig: (config: WslConfig) => __TAURI_INVOKE("set_wsl_config", { config }), + getDisplayBackend: () => __TAURI_INVOKE<"wayland" | "auto" | null>("get_display_backend"), + setDisplayBackend: (backend: LinuxDisplayBackend) => __TAURI_INVOKE("set_display_backend", { backend }), + parseMarkdownCommand: (markdown: string) => __TAURI_INVOKE("parse_markdown_command", { markdown }), + checkAppExists: (appName: string) => __TAURI_INVOKE("check_app_exists", { appName }), + wslPath: (path: string, mode: "windows" | "linux" | null) => __TAURI_INVOKE("wsl_path", { path, mode }), + resolveAppPath: (appName: string) => __TAURI_INVOKE("resolve_app_path", { appName }), +}; + +/** Events */ +export const events = { + loadingWindowComplete: makeEvent("loading-window-complete"), +}; + +/* Types */ +export type InitStep = { phase: "server_waiting" } | { phase: "sqlite_waiting" } | { phase: "done" }; + +export type LinuxDisplayBackend = "wayland" | "auto"; + +export type LoadingWindowComplete = null; + +export type ServerReadyData = { + url: string, + password: string | null, + }; + +export type WslConfig = { + enabled: boolean, + }; + +export type WslPathMode = "windows" | "linux"; + +/* Tauri Specta runtime */ +function makeEvent(name: string) { + const base = { + listen: (cb: __TAURI_EVENT.EventCallback) => __TAURI_EVENT.listen(name, cb), + once: (cb: __TAURI_EVENT.EventCallback) => __TAURI_EVENT.once(name, cb), + emit: (payload: T) => __TAURI_EVENT.emit(name, payload) as unknown as (T extends null ? () => Promise : (payload: T) => Promise) + }; + + const fn = (target: import("@tauri-apps/api/webview").Webview | import("@tauri-apps/api/window").Window) => ({ + listen: (cb: __TAURI_EVENT.EventCallback) => target.listen(name, cb), + once: (cb: __TAURI_EVENT.EventCallback) => target.once(name, cb), + emit: (payload: T) => target.emit(name, payload) as unknown as (T extends null ? () => Promise : (payload: T) => Promise) + }); + + return Object.assign(fn, base); +} + diff --git a/packages/desktop/src/entry.tsx b/packages/desktop/src/entry.tsx new file mode 100644 index 00000000000..b1c9f13f9c4 --- /dev/null +++ b/packages/desktop/src/entry.tsx @@ -0,0 +1,5 @@ +if (location.pathname === "/loading") { + import("./loading") +} else { + import("./") +} diff --git a/packages/desktop/src/i18n/bs.ts b/packages/desktop/src/i18n/bs.ts new file mode 100644 index 00000000000..58c266f5305 --- /dev/null +++ b/packages/desktop/src/i18n/bs.ts @@ -0,0 +1,28 @@ +export const dict = { + "desktop.menu.checkForUpdates": "Provjeri ažuriranja...", + "desktop.menu.installCli": "Instaliraj CLI...", + "desktop.menu.reloadWebview": "Ponovo učitavanje webview-a", + "desktop.menu.restart": "Restartuj", + + "desktop.dialog.chooseFolder": "Odaberi folder", + "desktop.dialog.chooseFile": "Odaberi datoteku", + "desktop.dialog.saveFile": "Sačuvaj datoteku", + + "desktop.updater.checkFailed.title": "Provjera ažuriranja nije uspjela", + "desktop.updater.checkFailed.message": "Nije moguće provjeriti ažuriranja", + "desktop.updater.none.title": "Nema dostupnog ažuriranja", + "desktop.updater.none.message": "Već koristiš najnoviju verziju OpenCode-a", + "desktop.updater.downloadFailed.title": "Ažuriranje nije uspjelo", + "desktop.updater.downloadFailed.message": "Neuspjelo preuzimanje ažuriranja", + "desktop.updater.downloaded.title": "Ažuriranje preuzeto", + "desktop.updater.downloaded.prompt": + "Verzija {{version}} OpenCode-a je preuzeta. Želiš li da je instaliraš i ponovo pokreneš aplikaciju?", + "desktop.updater.installFailed.title": "Ažuriranje nije uspjelo", + "desktop.updater.installFailed.message": "Neuspjela instalacija ažuriranja", + + "desktop.cli.installed.title": "CLI instaliran", + "desktop.cli.installed.message": + "CLI je instaliran u {{path}}\n\nRestartuj terminal da bi koristio komandu 'opencode'.", + "desktop.cli.failed.title": "Instalacija nije uspjela", + "desktop.cli.failed.message": "Neuspjela instalacija CLI-a: {{error}}", +} diff --git a/packages/desktop/src/loading.tsx b/packages/desktop/src/loading.tsx new file mode 100644 index 00000000000..752cde893b7 --- /dev/null +++ b/packages/desktop/src/loading.tsx @@ -0,0 +1,77 @@ +import { render } from "solid-js/web" +import { MetaProvider } from "@solidjs/meta" +import "@opencode-ai/app/index.css" +import { Font } from "@opencode-ai/ui/font" +import { Splash } from "@opencode-ai/ui/logo" +import "./styles.css" +import { createSignal, Match, onMount } from "solid-js" +import { commands, events, InitStep } from "./bindings" +import { Channel } from "@tauri-apps/api/core" +import { Switch } from "solid-js" + +const root = document.getElementById("root")! + +render(() => { + let splash!: SVGSVGElement + const [state, setState] = createSignal(null) + + const channel = new Channel() + channel.onmessage = (e) => setState(e) + commands.awaitInitialization(channel as any).then(() => { + const currentOpacity = getComputedStyle(splash).opacity + + splash.style.animation = "none" + splash.style.animationPlayState = "paused" + splash.style.opacity = currentOpacity + + requestAnimationFrame(() => { + splash.style.transition = "opacity 0.3s ease" + requestAnimationFrame(() => { + splash.style.opacity = "1" + }) + }) + }) + + return ( + +
+ +
+ + + + + {(_) => { + onMount(() => { + setTimeout(() => events.loadingWindowComplete.emit(null), 1000) + }) + + return "All done" + }} + + + {(_) => { + const textItems = [ + "Just a moment...", + "Migrating your database", + "This could take a couple of minutes", + ] + const [textIndex, setTextIndex] = createSignal(0) + + onMount(async () => { + await new Promise((res) => setTimeout(res, 3000)) + setTextIndex(1) + await new Promise((res) => setTimeout(res, 6000)) + setTextIndex(2) + }) + + return <>{textItems[textIndex()]} + }} + + + +
+
+
+ ) +}, root) diff --git a/packages/opencode/docs/features/layouts.md b/packages/opencode/docs/features/layouts.md new file mode 100644 index 00000000000..bffc8c5d012 --- /dev/null +++ b/packages/opencode/docs/features/layouts.md @@ -0,0 +1,526 @@ +# Custom Layouts + +OpenCode's TUI layout system lets you customize spacing, padding, and UI element visibility to optimize your workspace for different terminal sizes and preferences. + +## Quick Start + +### Switching Layouts + +Use the `/layout` command to switch between available layouts: + +1. Type `/layout` in the prompt +2. Select from the list: + - **default** - Original OpenCode spacing (comfortable, spacious) + - **dense** - Compact mode for small terminals + - Your custom layouts (if any) + +Or use the command palette: + +- Press `Ctrl+P` (or your configured keybind) +- Search for "Switch layout" +- Select a layout + +### Built-in Layouts + +**default** - The original OpenCode layout + +- Comfortable spacing throughout +- Shows all UI elements (header, footer, agent info) +- Best for: Large terminals (100+ columns, 30+ rows) + +**dense** - Optimized for small terminals + +- Minimal spacing between messages +- Agent/model info on status line (not below input) +- LSP/MCP status on right instead of keybind hints (more useful for experienced users) +- No decorative borders +- Centered cursor in input box (blank line above and below) +- Best for: 80x24 terminals, scaled text, screen readers + +## Creating Custom Layouts + +### Location + +Create layout files in: `~/.config/opencode/layout/` + +Supported formats: + +- `.json` - Standard JSON +- `.jsonc` - JSON with comments (recommended) + +### Basic Structure + +```jsonc +{ + "$schema": "https://opencode.ai/layout.json", + "name": "my-layout", + "description": "Brief description of your layout", + "config": { + // Your configuration here + }, +} +``` + +### Example: Minimal Layout + +Create `~/.config/opencode/layout/minimal.jsonc`: + +```jsonc +{ + "$schema": "https://opencode.ai/layout.json", + "name": "minimal", + "description": "Ultra-compact layout for maximum content", + "config": { + // No spacing between messages + "messageSeparation": 0, + + // No padding in message containers + "userMessagePaddingTop": 0, + "userMessagePaddingBottom": 0, + "assistantMessagePaddingTop": 0, + "assistantMessagePaddingBottom": 0, + "messagePaddingLeft": 1, + + // Minimal container padding + "containerPaddingTop": 0, + "containerPaddingBottom": 0, + "containerPaddingLeft": 1, + "containerPaddingRight": 1, + + // No gaps + "containerGap": 0, + "toolMarginTop": 0, + "agentInfoMarginTop": 0, + + // Minimal indentation + "textIndent": 2, + "toolIndent": 1, + + // Hide UI chrome + "showHeader": false, + "showFooter": false, + "forceSidebarHidden": true, + + // Ultra-compact input box + "showInputAgentInfo": false, + "showInputBorder": false, + "inputAgentInfoPaddingTop": 0, + "inputBoxPaddingTop": 0, + "inputBoxPaddingBottom": 0, + "inputAreaRightContent": "status", + }, +} +``` + +### Example: Comfortable Layout + +Create `~/.config/opencode/layout/comfortable.jsonc`: + +```jsonc +{ + "$schema": "https://opencode.ai/layout.json", + "name": "comfortable", + "description": "Extra breathing room for relaxed reading", + "config": { + // Extra spacing between messages + "messageSeparation": 2, + + // Generous padding + "userMessagePaddingTop": 2, + "userMessagePaddingBottom": 2, + "assistantMessagePaddingTop": 2, + "assistantMessagePaddingBottom": 2, + "messagePaddingLeft": 3, + + // Roomy containers + "containerPaddingTop": 2, + "containerPaddingBottom": 2, + "containerPaddingLeft": 3, + "containerPaddingRight": 3, + + // Generous gaps + "containerGap": 2, + "toolMarginTop": 2, + "agentInfoMarginTop": 2, + + // Clear indentation + "textIndent": 4, + "toolIndent": 3, + + // Show everything + "showHeader": true, + "showFooter": true, + "forceSidebarHidden": false, + + // Spacious input box + "showInputAgentInfo": true, + "showInputBorder": true, + "inputAgentInfoPaddingTop": 2, + "inputBoxPaddingTop": 2, + "inputBoxPaddingBottom": 1, + "inputAreaRightContent": "keybinds", + }, +} +``` + +## Configuration Reference + +### Message Spacing + +**`messageSeparation`** (number, default: 1) + +- Blank lines between consecutive messages (your questions and assistant replies) +- `0` = no spacing, `1` = one blank line, etc. + +**`userMessagePaddingTop`** (number, default: 1) + +- Blank lines above content inside user message boxes + +**`userMessagePaddingBottom`** (number, default: 0) + +- Blank lines below content inside user message boxes + +**`assistantMessagePaddingTop`** (number, default: 2) + +- Blank lines above content inside assistant message boxes + +**`assistantMessagePaddingBottom`** (number, default: 1) + +- Blank lines below content inside assistant message boxes + +**`messagePaddingLeft`** (number, default: 2) + +- Spaces of indentation inside message boxes (both user and assistant) + +### Container Spacing + +**`containerPaddingTop`** (number, default: 1) + +- Blank lines at top of session container + +**`containerPaddingBottom`** (number, default: 1) + +- Blank lines at bottom of session container + +**`containerPaddingLeft`** (number, default: 2) + +- Spaces of indentation at left edge + +**`containerPaddingRight`** (number, default: 2) + +- Spaces of indentation at right edge + +**`containerGap`** (number, default: 1) + +- Vertical spacing between container elements + +### Tool Output Spacing + +**`toolMarginTop`** (number, default: 1) + +- Blank lines above tool output blocks (like bash commands, file reads) + +**`agentInfoMarginTop`** (number, default: 1) + +- Blank lines above agent/model footer (e.g., "▣ Build · anthropic · claude-sonnet-4-5") + +### Text Indentation + +**`textIndent`** (number, default: 3) + +- Spaces to indent main message text + +**`toolIndent`** (number, default: 2) + +- Spaces to indent tool call/output text + +### UI Visibility + +**`showHeader`** (boolean, default: true) + +- Show/hide the session header at top + +**`showFooter`** (boolean, default: true) + +- Show/hide the status footer at bottom (LSP/MCP indicators) + +**`forceSidebarHidden`** (boolean, default: false) + +- Always hide the sidebar (useful for narrow terminals) + +### Input Box Styling + +**`showInputAgentInfo`** (boolean, default: true) + +- Show agent/model info below input box +- When `false`, info moves to status line + +**`showInputBorder`** (boolean, default: true) + +- Show decorative border below input box + +**`inputAgentInfoPaddingTop`** (number, default: 1) + +- Blank lines above agent info (when shown below input) + +**`inputBoxPaddingTop`** (number, default: 1) + +- Blank lines above cursor in input box +- `0` = cursor on first line, `1` = one blank line above cursor, etc. + +**`inputBoxPaddingBottom`** (number, default: 0) + +- Blank lines below cursor in input box + +**`inputAreaRightContent`** ("keybinds" | "status", default: "keybinds") + +- What to show on the right side of the input area +- `"keybinds"` = Key reminders (ctrl+t variants, tab agents, ctrl+p commands) +- `"status"` = LSP/MCP status indicators (• 1 LSP ⊙ 1 MCP) +- Dense layout uses `"status"` to show more useful info in less space + +## Understanding the TUI Elements + +The OpenCode TUI consists of several key elements you can customize: + +### Header (optional) + +- Location: Top of screen +- Content: Session title, navigation info +- Control: `showHeader` + +### Message History + +- Your messages: Gray background, left border in accent color +- Assistant messages: Transparent background, markdown-formatted text +- Tool outputs: Bordered boxes with command/file information +- Controls: `messageSeparation`, `messagePadding*`, `toolMarginTop` + +### Agent/Model Footer + +- Shows: "▣ Build · anthropic · claude-sonnet-4-5 · 2.3s" +- Location: Below each assistant message, or on status line +- Control: `agentInfoMarginTop`, `showInputAgentInfo` + +### Input Box + +- Where you type prompts +- Background: Gray box +- Optional elements: Agent info below, decorative border +- Controls: `inputBoxPadding*`, `showInputAgentInfo`, `showInputBorder` + +### Status Line + +- Shows spinner and status when assistant is thinking +- Shows agent/model info when input box doesn't +- Shows retry information when needed + +### Footer (optional) + +- Location: Bottom of screen +- Content: Directory, LSP count, MCP count +- Control: `showFooter` + +## Use Cases + +### Small Terminal / Screen Reader + +```jsonc +{ + "name": "compact", + "config": { + "messageSeparation": 0, + "userMessagePaddingTop": 0, + "userMessagePaddingBottom": 0, + "assistantMessagePaddingTop": 0, + "assistantMessagePaddingBottom": 0, + "toolMarginTop": 0, + "agentInfoMarginTop": 0, + "showHeader": false, + "showFooter": false, + "showInputAgentInfo": false, + "showInputBorder": false, + "inputBoxPaddingTop": 0, + "inputBoxPaddingBottom": 0, + "inputAreaRightContent": "status", + }, +} +``` + +**Result**: Maximum content, minimal chrome. Every row counts. + +### Ultrawide Terminal + +```jsonc +{ + "name": "ultrawide", + "config": { + "containerPaddingLeft": 20, + "containerPaddingRight": 20, + "messagePaddingLeft": 5, + "textIndent": 6, + "toolIndent": 4, + }, +} +``` + +**Result**: Content centered with generous margins, preventing eye strain from edge-to-edge text. + +### Presentation Mode + +```jsonc +{ + "name": "presentation", + "config": { + "messageSeparation": 3, + "userMessagePaddingTop": 2, + "userMessagePaddingBottom": 2, + "assistantMessagePaddingTop": 2, + "assistantMessagePaddingBottom": 2, + "containerPaddingLeft": 10, + "containerPaddingRight": 10, + "textIndent": 5, + "showFooter": false, + }, +} +``` + +**Result**: Large, clear spacing for demos and screen sharing. + +### Focused Coding + +```jsonc +{ + "name": "focused", + "config": { + "showHeader": false, + "showFooter": false, + "forceSidebarHidden": true, + "messageSeparation": 1, + "toolMarginTop": 0, + "agentInfoMarginTop": 0, + "showInputBorder": false, + }, +} +``` + +**Result**: Hide distractions, show only messages and code. + +## Tips + +### Start with a Built-in Layout + +1. Copy `~/.config/opencode/layout/` from the OpenCode source +2. Find `context/layout/default.jsonc` or `dense.jsonc` +3. Copy to your config directory and modify +4. The inline comments explain each field + +### Iterate Quickly + +1. Edit your layout file +2. Switch to a different layout and back (to reload) + - `/layout` → select different layout → `/layout` → select yours +3. See changes immediately +4. No need to restart OpenCode + +### Common Patterns + +**Want more vertical space?** + +- Set `messageSeparation: 0` +- Set all `*PaddingTop` and `*PaddingBottom` to `0` +- Set `showHeader: false` and `showFooter: false` + +**Want clearer separation?** + +- Increase `messageSeparation` to `2` or `3` +- Increase `toolMarginTop` to `2` +- Increase `agentInfoMarginTop` to `2` + +**Want less horizontal indentation?** + +- Reduce `textIndent` and `toolIndent` +- Reduce `messagePaddingLeft` +- Reduce `containerPaddingLeft` + +**Want centered input cursor?** + +- Set `inputBoxPaddingTop: 1` and `inputBoxPaddingBottom: 1` + +### Validation + +Layouts are validated when loaded. If you: + +- **Misspell a field name**: Warning logged, field ignored +- **Use wrong type** (string instead of number): Warning logged, default used +- **Omit a field**: Default value used +- **Add unknown fields** (future version features): Warning logged, field ignored + +This means layouts are forward and backward compatible - old layouts work with new versions, new layouts degrade gracefully on old versions. + +## Troubleshooting + +**Layout not showing up in `/layout` menu?** + +- Check filename ends in `.json` or `.jsonc` +- Check file is in `~/.config/opencode/layout/` +- Check JSON syntax is valid (use a JSON validator) + +**Layout loads but looks wrong?** + +- Check console for validation warnings +- Compare with built-in layouts in source code +- Try starting with a copy of `default.jsonc` and modifying incrementally + +**Changes not taking effect?** + +- Switch to a different layout and back to reload +- Or restart OpenCode +- Layouts reload when you open the `/layout` dialog + +**Want to reset to defaults?** + +- Use `/layout` and select `default` +- Or remove your custom layout file + +## Sharing Layouts + +If you create a layout others might find useful: + +- Share the `.jsonc` file (includes helpful comments) +- Document the use case and terminal size you optimized for +- Consider contributing to a community layouts repository (if one exists) + +## Advanced: Programmatic Layouts + +For very specific needs, you can: + +- Generate layouts programmatically +- Use shell scripts to switch layouts based on terminal size +- Create per-project layouts (place in `.opencode/layout/` in project root) + +Example bash script to auto-select layout based on terminal height: + +```bash +#!/bin/bash +ROWS=$(tput lines) +if [ $ROWS -lt 30 ]; then + # Small terminal, use dense + echo '{"layout": "dense"}' > ~/.config/opencode/config.json +else + # Normal terminal, use default + echo '{"layout": "default"}' > ~/.config/opencode/config.json +fi +``` + +## Accessibility Notes + +The layout system was designed with accessibility in mind: + +- **Screen readers**: Use minimal layouts to reduce non-content elements +- **Low vision**: Increase spacing and padding for clarity +- **Terminal limitations**: Optimize for your specific terminal size +- **Reduced motion**: No animations, instant layout changes +- **Customization**: Every spacing value is configurable + +If you have accessibility needs not addressed by the current system, please open an issue describing your use case. diff --git a/packages/opencode/src/bun/registry.ts b/packages/opencode/src/bun/registry.ts new file mode 100644 index 00000000000..c567668acd7 --- /dev/null +++ b/packages/opencode/src/bun/registry.ts @@ -0,0 +1,48 @@ +import { readableStreamToText, semver } from "bun" +import { Log } from "../util/log" + +export namespace PackageRegistry { + const log = Log.create({ service: "bun" }) + + function which() { + return process.execPath + } + + export async function info(pkg: string, field: string, cwd?: string): Promise { + const result = Bun.spawn([which(), "info", pkg, field], { + cwd, + stdout: "pipe", + stderr: "pipe", + env: { + ...process.env, + BUN_BE_BUN: "1", + }, + }) + + const code = await result.exited + const stdout = result.stdout ? await readableStreamToText(result.stdout) : "" + const stderr = result.stderr ? await readableStreamToText(result.stderr) : "" + + if (code !== 0) { + log.warn("bun info failed", { pkg, field, code, stderr }) + return null + } + + const value = stdout.trim() + if (!value) return null + return value + } + + export async function isOutdated(pkg: string, cachedVersion: string, cwd?: string): Promise { + const latestVersion = await info(pkg, "version", cwd) + if (!latestVersion) { + log.warn("Failed to resolve latest version, using cached", { pkg, cachedVersion }) + return false + } + + const isRange = /[\s^~*xX<>|=]/.test(cachedVersion) + if (isRange) return !semver.satisfies(latestVersion, cachedVersion) + + return semver.order(cachedVersion, latestVersion) === -1 + } +} diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 10d7a25f88f..e7e0bce8951 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -14,12 +14,14 @@ import { DialogModel, useConnected } from "@tui/component/dialog-model" import { DialogMcp } from "@tui/component/dialog-mcp" import { DialogStatus } from "@tui/component/dialog-status" import { DialogThemeList } from "@tui/component/dialog-theme-list" +import { DialogLayoutList } from "@tui/component/dialog-layout-list" import { DialogHelp } from "./ui/dialog-help" import { CommandProvider, useCommandDialog } from "@tui/component/dialog-command" import { DialogAgent } from "@tui/component/dialog-agent" import { DialogSessionList } from "@tui/component/dialog-session-list" import { KeybindProvider } from "@tui/context/keybind" import { ThemeProvider, useTheme } from "@tui/context/theme" +import { LayoutProvider } from "@tui/context/layout" import { Home } from "@tui/routes/home" import { Session } from "@tui/routes/session" import { PromptHistoryProvider } from "./component/prompt/history" @@ -134,23 +136,25 @@ export function tui(input: { > - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + @@ -459,6 +463,26 @@ function App() { }, category: "System", }, + { + title: "Switch layout", + value: "layout.switch", + slash: { + name: "layout", + aliases: ["layouts"], + }, + onSelect: () => { + dialog.replace(() => ) + }, + category: "System", + }, + { + title: "Connect provider", + value: "provider.connect", + onSelect: () => { + dialog.replace(() => ) + }, + category: "System", + }, { title: "Toggle appearance", value: "theme.switch_mode", diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-layout-list.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-layout-list.tsx new file mode 100644 index 00000000000..19e4eff30be --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-layout-list.tsx @@ -0,0 +1,61 @@ +import { DialogSelect, type DialogSelectRef } from "../ui/dialog-select" +import { useLayout } from "../context/layout" +import { useDialog } from "../ui/dialog" +import { createSignal, onCleanup, onMount } from "solid-js" + +export function DialogLayoutList() { + const layout = useLayout() + const [options, setOptions] = createSignal( + Object.keys(layout.all()).map((value) => ({ + title: value, + value: value, + })), + ) + const dialog = useDialog() + let confirmed = false + let ref: DialogSelectRef + const initial = layout.selected + + onMount(async () => { + // Reload layouts when dialog opens + await layout.reload() + setOptions( + Object.keys(layout.all()).map((value) => ({ + title: value, + value: value, + })), + ) + }) + + onCleanup(() => { + if (!confirmed) layout.set(initial) + }) + + return ( + { + layout.set(opt.value) + }} + onSelect={(opt) => { + layout.set(opt.value) + confirmed = true + dialog.clear() + }} + ref={(r) => { + ref = r + }} + onFilter={(query) => { + if (query.length === 0) { + layout.set(initial) + return + } + + const first = ref.filtered[0] + if (first) layout.set(first.value) + }} + /> + ) +} diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-skill.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-skill.tsx new file mode 100644 index 00000000000..4bcd3c7bde4 --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-skill.tsx @@ -0,0 +1,36 @@ +import { DialogSelect, type DialogSelectOption } from "@tui/ui/dialog-select" +import { createResource, createMemo } from "solid-js" +import { useDialog } from "@tui/ui/dialog" +import { useSDK } from "@tui/context/sdk" + +export type DialogSkillProps = { + onSelect: (skill: string) => void +} + +export function DialogSkill(props: DialogSkillProps) { + const dialog = useDialog() + const sdk = useSDK() + dialog.setSize("large") + + const [skills] = createResource(async () => { + const result = await sdk.client.app.skills() + return result.data ?? [] + }) + + const options = createMemo[]>(() => { + const list = skills() ?? [] + const maxWidth = Math.max(0, ...list.map((s) => s.name.length)) + return list.map((skill) => ({ + title: skill.name.padEnd(maxWidth), + description: skill.description?.replace(/\s+/g, " ").trim(), + value: skill.name, + category: "Skills", + onSelect: () => { + props.onSelect(skill.name) + dialog.clear() + }, + })) + }) + + return +} diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx index caa13032292..ecb315fd977 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -3,6 +3,7 @@ import { createEffect, createMemo, type JSX, onMount, createSignal, onCleanup, S import "opentui-spinner/solid" import { useLocal } from "@tui/context/local" import { useTheme } from "@tui/context/theme" +import { useLayout } from "@tui/context/layout" import { EmptyBorder } from "@tui/component/border" import { useSDK } from "@tui/context/sdk" import { useRoute } from "@tui/context/route" @@ -72,8 +73,14 @@ export function Prompt(props: PromptProps) { const command = useCommandDialog() const renderer = useRenderer() const { theme, syntax } = useTheme() + const layout = useLayout() const kv = useKV() + // LSP/MCP status data (for status display option) + const mcp = createMemo(() => Object.values(sync.data.mcp).filter((x) => x.status === "connected").length) + const mcpError = createMemo(() => Object.values(sync.data.mcp).some((x) => x.status === "failed")) + const lsp = createMemo(() => Object.keys(sync.data.lsp)) + function promptModelWarning() { toast.show({ variant: "warning", @@ -768,7 +775,8 @@ export function Prompt(props: PromptProps) { - - - {store.mode === "shell" ? "Shell" : Locale.titlecase(local.agent.current().name)}{" "} - - - - - {local.model.parsed().model} - - {local.model.parsed().provider} - - · - - {local.model.variant.current()} + + + + {store.mode === "shell" ? "Shell" : Locale.titlecase(local.agent.current().name)}{" "} + + + + + {local.model.parsed().model} - - - - + {local.model.parsed().provider} + + · + + {local.model.variant.current()} + + + + + + - + - + border={["left"]} + borderColor={highlight()} + customBorderChars={{ + ...EmptyBorder, + vertical: theme.backgroundElement.a !== 0 ? "╹" : " ", + }} + > + + + - }> + + + + {Locale.titlecase(local.agent.current().name)} + + {local.model.parsed().model} + {local.model.parsed().provider} + + + } + > - - - - 0}> + + + + + + 0}> + + {keybind.print("variant_cycle")} variants + + + + {keybind.print("agent_cycle")} agents + + + {keybind.print("command_list")} commands + + + + + esc exit shell mode + + + + + + + + + 0 ? theme.success : theme.textMuted }}>• {lsp().length} LSP + + - {keybind.print("variant_cycle")} variants + + + + + + + + + {mcp()} MCP - - {keybind.print("agent_cycle")} agents - - - {keybind.print("command_list")} commands - - - - - esc exit shell mode - - - - + + + diff --git a/packages/opencode/src/cli/cmd/tui/component/spinner.tsx b/packages/opencode/src/cli/cmd/tui/component/spinner.tsx new file mode 100644 index 00000000000..8dc54555043 --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/component/spinner.tsx @@ -0,0 +1,24 @@ +import { Show } from "solid-js" +import { useTheme } from "../context/theme" +import { useKV } from "../context/kv" +import type { JSX } from "@opentui/solid" +import type { RGBA } from "@opentui/core" +import "opentui-spinner/solid" + +const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"] + +export function Spinner(props: { children?: JSX.Element; color?: RGBA }) { + const { theme } = useTheme() + const kv = useKV() + const color = () => props.color ?? theme.textMuted + return ( + ⋯ {props.children}}> + + + + {props.children} + + + + ) +} diff --git a/packages/opencode/src/cli/cmd/tui/context/layout.tsx b/packages/opencode/src/cli/cmd/tui/context/layout.tsx new file mode 100644 index 00000000000..f190531c2a3 --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/context/layout.tsx @@ -0,0 +1,189 @@ +import path from "path" +import { createEffect, createMemo } from "solid-js" +import { createStore, produce } from "solid-js/store" +import { useSync } from "@tui/context/sync" +import { createSimpleContext } from "./helper" +import { useKV } from "./kv" +import { Global } from "@/global" +import { Filesystem } from "@/util/filesystem" +import { parse as parseJsonc } from "jsonc-parser" +import defaultLayoutText from "./layout/default.jsonc" with { type: "text" } +import denseLayoutText from "./layout/dense.jsonc" with { type: "text" } + +export type LayoutConfig = { + messageSeparation: number + userMessagePaddingTop: number + userMessagePaddingBottom: number + assistantMessagePaddingTop: number + assistantMessagePaddingBottom: number + containerPaddingTop: number + containerPaddingBottom: number + containerGap: number + toolMarginTop: number + agentInfoMarginTop: number + containerPaddingLeft: number + containerPaddingRight: number + messagePaddingLeft: number + textIndent: number + toolIndent: number + showHeader: boolean + showFooter: boolean + forceSidebarHidden: boolean + showInputAgentInfo: boolean + showInputBorder: boolean + inputAgentInfoPaddingTop: number + inputBoxPaddingTop: number + inputBoxPaddingBottom: number + inputAreaRightContent: "keybinds" | "status" +} + +type LayoutInfo = { + name: string + description?: string + config: LayoutConfig +} + +const DEFAULT_LAYOUT_CONFIG: LayoutConfig = (parseJsonc(defaultLayoutText) as LayoutInfo).config + +const BUILTIN_LAYOUTS: Record = { + default: DEFAULT_LAYOUT_CONFIG, + dense: (parseJsonc(denseLayoutText) as LayoutInfo).config, +} + +const CUSTOM_LAYOUT_GLOB = new Bun.Glob("layout/*.{json,jsonc}") + +// Validate and merge layout config with defaults +function validateAndMergeLayout(config: Partial, name: string, source: string): LayoutConfig { + const result = { ...DEFAULT_LAYOUT_CONFIG } + const knownFields = new Set(Object.keys(DEFAULT_LAYOUT_CONFIG)) + const warnings: string[] = [] + + // Check for unknown fields + for (const key of Object.keys(config)) { + if (!knownFields.has(key)) { + warnings.push(`Unknown field '${key}' (will be ignored)`) + } + } + + // Merge known fields with type validation + for (const key of knownFields) { + const value = config[key as keyof LayoutConfig] + const defaultValue = DEFAULT_LAYOUT_CONFIG[key as keyof LayoutConfig] + const expectedType = typeof defaultValue + + if (value === undefined) { + warnings.push(`Missing field '${key}' (using default: ${defaultValue})`) + continue + } + + if (typeof value !== expectedType) { + warnings.push( + `Invalid type for '${key}': expected ${expectedType}, got ${typeof value} (using default: ${defaultValue})`, + ) + continue + } + + ;(result as any)[key] = value + } + + if (warnings.length > 0) { + console.warn(`Layout '${name}' from ${source}:`) + warnings.forEach((w) => console.warn(` - ${w}`)) + } + + return result +} + +async function getCustomLayouts() { + const directories = [ + Global.Path.config, + ...(await Array.fromAsync( + Filesystem.up({ + targets: [".opencode"], + start: process.cwd(), + }), + )), + ] + + const result: Record = {} + for (const dir of directories) { + for await (const item of CUSTOM_LAYOUT_GLOB.scan({ + absolute: true, + followSymlinks: true, + dot: true, + cwd: dir, + })) { + try { + const name = path.basename(item).replace(/\.(json|jsonc)$/, "") + const text = await Bun.file(item).text() + const data = parseJsonc(text) as LayoutInfo + + if (!data?.config) { + console.warn(`Layout '${name}' from ${item}: missing 'config' object`) + continue + } + + result[name] = validateAndMergeLayout(data.config, name, item) + } catch (err) { + console.error(`Failed to load layout from ${item}:`, err) + } + } + } + return result +} + +export const { use: useLayout, provider: LayoutProvider } = createSimpleContext({ + name: "Layout", + init: () => { + const sync = useSync() + const kv = useKV() + const [store, setStore] = createStore({ + layouts: BUILTIN_LAYOUTS, + active: kv.get("layout_mode", (sync.data.config.tui as any)?.layout ?? "default") as string, + ready: false, + }) + + createEffect(async () => { + const custom = await getCustomLayouts() + setStore( + produce((draft) => { + Object.assign(draft.layouts, custom) + draft.ready = true + }), + ) + }) + + const current = createMemo(() => { + return store.layouts[store.active] ?? store.layouts.default + }) + + return { + get current() { + return current() + }, + all() { + return store.layouts + }, + get selected() { + return store.active + }, + set(name: string) { + setStore("active", name) + kv.set("layout_mode", name) + }, + get ready() { + return store.ready + }, + async reload() { + const custom = await getCustomLayouts() + setStore( + produce((draft) => { + // Reset to built-ins, then merge custom + draft.layouts = { ...BUILTIN_LAYOUTS } + Object.assign(draft.layouts, custom) + }), + ) + }, + } + }, +}) diff --git a/packages/opencode/src/cli/cmd/tui/context/layout/default.jsonc b/packages/opencode/src/cli/cmd/tui/context/layout/default.jsonc new file mode 100644 index 00000000000..7fd95c32469 --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/context/layout/default.jsonc @@ -0,0 +1,52 @@ +{ + "$schema": "https://opencode.ai/layout.json", + "name": "default", + "description": "Comfortable spacing with headers and sidebars", + "config": { + // Vertical spacing between consecutive messages + "messageSeparation": 1, + + // Padding inside user message containers + "userMessagePaddingTop": 1, + "userMessagePaddingBottom": 0, + + // Padding inside assistant message containers (tool outputs, text, etc.) + "assistantMessagePaddingTop": 2, + "assistantMessagePaddingBottom": 1, + + // Left padding for message text (shared by user and assistant) + "messagePaddingLeft": 2, + + // Padding around the entire session container + "containerPaddingTop": 1, + "containerPaddingBottom": 1, + "containerPaddingLeft": 2, + "containerPaddingRight": 2, + + // Vertical gap between elements within the container + "containerGap": 1, + + // Spacing above tool output blocks + "toolMarginTop": 1, + + // Spacing above agent info footer (model/duration line) + "agentInfoMarginTop": 1, + + // Horizontal indentation for message text and tool output + "textIndent": 3, // Main message text indent + "toolIndent": 2, // Tool call/output indent + + // UI visibility toggles + "showHeader": true, // Show session header + "showFooter": true, // Show status footer + "forceSidebarHidden": false, // Force sidebar off (useful for narrow terminals) + + // Input box styling + "showInputAgentInfo": true, // Show agent/model info below input box + "showInputBorder": true, // Show decorative border below input + "inputAgentInfoPaddingTop": 1, // Padding above agent info line + "inputBoxPaddingTop": 1, // Blank lines above cursor in input box + "inputBoxPaddingBottom": 0, // Blank lines below cursor in input box + "inputAreaRightContent": "keybinds", // What to show on right: "keybinds" or "status" + }, +} diff --git a/packages/opencode/src/cli/cmd/tui/context/layout/dense.jsonc b/packages/opencode/src/cli/cmd/tui/context/layout/dense.jsonc new file mode 100644 index 00000000000..819d3a35e39 --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/context/layout/dense.jsonc @@ -0,0 +1,52 @@ +{ + "$schema": "https://opencode.ai/layout.json", + "name": "dense", + "description": "Minimal spacing for small terminals - no headers or sidebars", + "config": { + // Spacing between messages + "messageSeparation": 1, + + // Minimal padding inside user message containers + "userMessagePaddingTop": 0, + "userMessagePaddingBottom": 0, + + // Minimal padding inside assistant message containers + "assistantMessagePaddingTop": 1, + "assistantMessagePaddingBottom": 0, + + // Left padding for message text + "messagePaddingLeft": 1, + + // Minimal container padding + "containerPaddingTop": 0, + "containerPaddingBottom": 0, + "containerPaddingLeft": 1, + "containerPaddingRight": 1, + + // No gap between container elements + "containerGap": 0, + + // No spacing above tools + "toolMarginTop": 0, + + // No spacing above agent info footer + "agentInfoMarginTop": 0, + + // Reduced indentation to save horizontal space + "textIndent": 2, // Minimal text indent + "toolIndent": 1, // Minimal tool indent + + // Hide UI chrome to maximize content area + "showHeader": false, // No header + "showFooter": false, // No footer + "forceSidebarHidden": true, // Always hide sidebar + + // Compact input box + "showInputAgentInfo": false, // Move agent/model to status line + "showInputBorder": false, // No decorative border + "inputAgentInfoPaddingTop": 0, // No padding (not shown anyway) + "inputBoxPaddingTop": 1, // One blank line above cursor + "inputBoxPaddingBottom": 1, // One blank line below cursor + "inputAreaRightContent": "status", // Show LSP/MCP status instead of keybind hints + }, +} diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/footer.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/footer.tsx index 8ace2fff372..ff7861e4190 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/footer.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/footer.tsx @@ -5,11 +5,13 @@ import { useDirectory } from "../../context/directory" import { useConnected } from "../../component/dialog-model" import { createStore } from "solid-js/store" import { useRoute } from "../../context/route" +import { useLayout } from "../../context/layout" export function Footer() { const { theme } = useTheme() const sync = useSync() const route = useRoute() + const layout = useLayout() const mcp = createMemo(() => Object.values(sync.data.mcp).filter((x) => x.status === "connected").length) const mcpError = createMemo(() => Object.values(sync.data.mcp).some((x) => x.status === "failed")) const lsp = createMemo(() => Object.keys(sync.data.lsp)) @@ -66,21 +68,23 @@ export function Footer() { {permissions().length > 1 ? "s" : ""} - - 0 ? theme.success : theme.textMuted }}>• {lsp().length} LSP - - + - - - - - - - - - {mcp()} MCP + 0 ? theme.success : theme.textMuted }}>• {lsp().length} LSP + + + + + + + + + + + {mcp()} MCP + + /status diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index d36a7d20994..bf38edb451d 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -17,6 +17,7 @@ import { useRoute, useRouteData } from "@tui/context/route" import { useSync } from "@tui/context/sync" import { SplitBorder } from "@tui/component/border" import { useTheme } from "@tui/context/theme" +import { useLayout, type LayoutConfig } from "@tui/context/layout" import { BoxRenderable, ScrollBoxRenderable, @@ -90,6 +91,7 @@ class CustomSpeedScroll implements ScrollAcceleration { const context = createContext<{ width: number + layout: () => LayoutConfig sessionID: string conceal: () => boolean showThinking: () => boolean @@ -148,9 +150,12 @@ export function Session() { const [showScrollbar, setShowScrollbar] = kv.signal("scrollbar_visible", false) const [diffWrapMode] = kv.signal<"word" | "none">("diff_wrap_mode", "word") const [animationsEnabled, setAnimationsEnabled] = kv.signal("animations_enabled", true) + const layoutCtx = useLayout() + const layout = createMemo(() => layoutCtx.current) const wide = createMemo(() => dimensions().width > 120) const sidebarVisible = createMemo(() => { + if (layout().forceSidebarHidden) return false if (session()?.parentID) return false if (sidebarOpen()) return true if (sidebar() === "auto" && wide()) return true @@ -929,6 +934,7 @@ export function Session() { get width() { return contentWidth() }, + layout, sessionID: route.sessionID, conceal, showThinking, @@ -939,9 +945,16 @@ export function Session() { }} > - + - +
+ +
+ @@ -1148,7 +1164,7 @@ function UserMessage(props: { border={["left"]} borderColor={color()} customBorderChars={SplitBorder.customBorderChars} - marginTop={props.index === 0 ? 0 : 1} + marginTop={props.index === 0 ? 0 : ctx.layout().messageSeparation} > { @@ -1158,10 +1174,10 @@ function UserMessage(props: { setHover(false) }} onMouseUp={props.onMouseUp} - paddingTop={1} - paddingBottom={1} - paddingLeft={2} - backgroundColor={hover() ? theme.backgroundElement : theme.backgroundPanel} + paddingTop={ctx.layout().userMessagePaddingTop} + paddingBottom={ctx.layout().userMessagePaddingBottom} + paddingLeft={ctx.layout().messagePaddingLeft} + backgroundColor={theme.backgroundElement} flexShrink={0} > {text()?.text} @@ -1252,43 +1268,53 @@ function AssistantMessage(props: { message: AssistantMessage; parts: Part[]; las }} - - {props.message.error?.data.message} - + {(function () { + const ctx = use() + return ( + + {props.message.error?.data.message} + + ) + })()} - - - - ▣{" "} - {" "} - {Locale.titlecase(props.message.mode)} - · {props.message.modelID} - - · {Locale.duration(duration())} - - - · interrupted - - - + {(function () { + const ctx = use() + return ( + + + + ▣{" "} + {" "} + {Locale.titlecase(props.message.mode)} + · {props.message.modelID} + + · {Locale.duration(duration())} + + + · interrupted + + + + ) + })()} @@ -1339,7 +1365,14 @@ function TextPart(props: { last: boolean; part: TextPart; message: AssistantMess const { theme, syntax } = useTheme() return ( - + p.test(message))) return true + + // Providers/status patterns handled outside of regex list: + // - Cerebras: often returns "400 (no body)" / "413 (no body)" + // - Mistral: often returns "400 (no body)" / "413 (no body)" + return /^4(00|13)\s*(status code)?\s*\(no body\)/i.test(message) + } + + function error(providerID: string, error: APICallError) { + if (providerID.includes("github-copilot") && error.statusCode === 403) { + return "Please reauthenticate with the copilot provider to ensure your credentials work properly with OpenCode." + } + + return error.message + } + + function message(providerID: string, e: APICallError) { + return iife(() => { + const msg = e.message + if (msg === "") { + if (e.responseBody) return e.responseBody + if (e.statusCode) { + const err = STATUS_CODES[e.statusCode] + if (err) return err + } + return "Unknown error" + } + + const transformed = error(providerID, e) + if (transformed !== msg) { + return transformed + } + if (!e.responseBody || (e.statusCode && msg !== STATUS_CODES[e.statusCode])) { + return msg + } + + try { + const body = JSON.parse(e.responseBody) + // try to extract common error message fields + const errMsg = body.message || body.error || body.error?.message + if (errMsg && typeof errMsg === "string") { + return `${msg}: ${errMsg}` + } + } catch {} + + return `${msg}: ${e.responseBody}` + }).trim() + } + + function json(input: unknown) { + if (typeof input === "string") { + try { + const result = JSON.parse(input) + if (result && typeof result === "object") return result + return undefined + } catch { + return undefined + } + } + if (typeof input === "object" && input !== null) { + return input + } + return undefined + } + + export type ParsedStreamError = + | { + type: "context_overflow" + message: string + responseBody: string + } + | { + type: "api_error" + message: string + isRetryable: false + responseBody: string + } + + export function parseStreamError(input: unknown): ParsedStreamError | undefined { + const body = json(input) + if (!body) return + + const responseBody = JSON.stringify(body) + if (body.type !== "error") return + + switch (body?.error?.code) { + case "context_length_exceeded": + return { + type: "context_overflow", + message: "Input exceeds context window of this model", + responseBody, + } + case "insufficient_quota": + return { + type: "api_error", + message: "Quota exceeded. Check your plan and billing details.", + isRetryable: false, + responseBody, + } + case "usage_not_included": + return { + type: "api_error", + message: "To use Codex with your ChatGPT plan, upgrade to Plus: https://chatgpt.com/explore/plus.", + isRetryable: false, + responseBody, + } + case "invalid_prompt": + return { + type: "api_error", + message: typeof body?.error?.message === "string" ? body?.error?.message : "Invalid prompt.", + isRetryable: false, + responseBody, + } + } + } + + export type ParsedAPICallError = + | { + type: "context_overflow" + message: string + responseBody?: string + } + | { + type: "api_error" + message: string + statusCode?: number + isRetryable: boolean + responseHeaders?: Record + responseBody?: string + metadata?: Record + } + + export function parseAPICallError(input: { providerID: string; error: APICallError }): ParsedAPICallError { + const m = message(input.providerID, input.error) + if (isOverflow(m)) { + return { + type: "context_overflow", + message: m, + responseBody: input.error.responseBody, + } + } + + const metadata = input.error.url ? { url: input.error.url } : undefined + return { + type: "api_error", + message: m, + statusCode: input.error.statusCode, + isRetryable: input.providerID.startsWith("openai") + ? isOpenAiErrorRetryable(input.error) + : input.error.isRetryable, + responseHeaders: input.error.responseHeaders, + responseBody: input.error.responseBody, + metadata, + } + } +} diff --git a/packages/opencode/src/provider/sdk/copilot/README.md b/packages/opencode/src/provider/sdk/copilot/README.md new file mode 100644 index 00000000000..8ce03d61407 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/README.md @@ -0,0 +1,5 @@ +This is a temporary package used primarily for GitHub Copilot compatibility. + +Avoid making changes to these files unless you only want to affect the Copilot provider. + +Also, this should ONLY be used for the Copilot provider. diff --git a/packages/opencode/src/provider/sdk/copilot/chat/convert-to-openai-compatible-chat-messages.ts b/packages/opencode/src/provider/sdk/copilot/chat/convert-to-openai-compatible-chat-messages.ts new file mode 100644 index 00000000000..e1e3ed4c201 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/chat/convert-to-openai-compatible-chat-messages.ts @@ -0,0 +1,164 @@ +import { + type LanguageModelV2Prompt, + type SharedV2ProviderMetadata, + UnsupportedFunctionalityError, +} from "@ai-sdk/provider" +import type { OpenAICompatibleChatPrompt } from "./openai-compatible-api-types" +import { convertToBase64 } from "@ai-sdk/provider-utils" + +function getOpenAIMetadata(message: { providerOptions?: SharedV2ProviderMetadata }) { + return message?.providerOptions?.copilot ?? {} +} + +export function convertToOpenAICompatibleChatMessages(prompt: LanguageModelV2Prompt): OpenAICompatibleChatPrompt { + const messages: OpenAICompatibleChatPrompt = [] + for (const { role, content, ...message } of prompt) { + const metadata = getOpenAIMetadata({ ...message }) + switch (role) { + case "system": { + messages.push({ + role: "system", + content: content, + ...metadata, + }) + break + } + + case "user": { + if (content.length === 1 && content[0].type === "text") { + messages.push({ + role: "user", + content: content[0].text, + ...getOpenAIMetadata(content[0]), + }) + break + } + + messages.push({ + role: "user", + content: content.map((part) => { + const partMetadata = getOpenAIMetadata(part) + switch (part.type) { + case "text": { + return { type: "text", text: part.text, ...partMetadata } + } + case "file": { + if (part.mediaType.startsWith("image/")) { + const mediaType = part.mediaType === "image/*" ? "image/jpeg" : part.mediaType + + return { + type: "image_url", + image_url: { + url: + part.data instanceof URL + ? part.data.toString() + : `data:${mediaType};base64,${convertToBase64(part.data)}`, + }, + ...partMetadata, + } + } else { + throw new UnsupportedFunctionalityError({ + functionality: `file part media type ${part.mediaType}`, + }) + } + } + } + }), + ...metadata, + }) + + break + } + + case "assistant": { + let text = "" + let reasoningText: string | undefined + let reasoningOpaque: string | undefined + const toolCalls: Array<{ + id: string + type: "function" + function: { name: string; arguments: string } + }> = [] + + for (const part of content) { + const partMetadata = getOpenAIMetadata(part) + // Check for reasoningOpaque on any part (may be attached to text/tool-call) + const partOpaque = (part.providerOptions as { copilot?: { reasoningOpaque?: string } })?.copilot + ?.reasoningOpaque + if (partOpaque && !reasoningOpaque) { + reasoningOpaque = partOpaque + } + + switch (part.type) { + case "text": { + text += part.text + break + } + case "reasoning": { + if (part.text) reasoningText = part.text + break + } + case "tool-call": { + toolCalls.push({ + id: part.toolCallId, + type: "function", + function: { + name: part.toolName, + arguments: JSON.stringify(part.input), + }, + ...partMetadata, + }) + break + } + } + } + + messages.push({ + role: "assistant", + content: text || null, + tool_calls: toolCalls.length > 0 ? toolCalls : undefined, + reasoning_text: reasoningOpaque ? reasoningText : undefined, + reasoning_opaque: reasoningOpaque, + ...metadata, + }) + + break + } + + case "tool": { + for (const toolResponse of content) { + const output = toolResponse.output + + let contentValue: string + switch (output.type) { + case "text": + case "error-text": + contentValue = output.value + break + case "content": + case "json": + case "error-json": + contentValue = JSON.stringify(output.value) + break + } + + const toolResponseMetadata = getOpenAIMetadata(toolResponse) + messages.push({ + role: "tool", + tool_call_id: toolResponse.toolCallId, + content: contentValue, + ...toolResponseMetadata, + }) + } + break + } + + default: { + const _exhaustiveCheck: never = role + throw new Error(`Unsupported role: ${_exhaustiveCheck}`) + } + } + } + + return messages +} diff --git a/packages/opencode/src/provider/sdk/copilot/chat/get-response-metadata.ts b/packages/opencode/src/provider/sdk/copilot/chat/get-response-metadata.ts new file mode 100644 index 00000000000..708fd968e3a --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/chat/get-response-metadata.ts @@ -0,0 +1,15 @@ +export function getResponseMetadata({ + id, + model, + created, +}: { + id?: string | undefined | null + created?: number | undefined | null + model?: string | undefined | null +}) { + return { + id: id ?? undefined, + modelId: model ?? undefined, + timestamp: created != null ? new Date(created * 1000) : undefined, + } +} diff --git a/packages/opencode/src/provider/sdk/copilot/chat/map-openai-compatible-finish-reason.ts b/packages/opencode/src/provider/sdk/copilot/chat/map-openai-compatible-finish-reason.ts new file mode 100644 index 00000000000..82e2ca02e98 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/chat/map-openai-compatible-finish-reason.ts @@ -0,0 +1,17 @@ +import type { LanguageModelV2FinishReason } from "@ai-sdk/provider" + +export function mapOpenAICompatibleFinishReason(finishReason: string | null | undefined): LanguageModelV2FinishReason { + switch (finishReason) { + case "stop": + return "stop" + case "length": + return "length" + case "content_filter": + return "content-filter" + case "function_call": + case "tool_calls": + return "tool-calls" + default: + return "unknown" + } +} diff --git a/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-api-types.ts b/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-api-types.ts new file mode 100644 index 00000000000..c127b05b17e --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-api-types.ts @@ -0,0 +1,64 @@ +import type { JSONValue } from "@ai-sdk/provider" + +export type OpenAICompatibleChatPrompt = Array + +export type OpenAICompatibleMessage = + | OpenAICompatibleSystemMessage + | OpenAICompatibleUserMessage + | OpenAICompatibleAssistantMessage + | OpenAICompatibleToolMessage + +// Allow for arbitrary additional properties for general purpose +// provider-metadata-specific extensibility. +type JsonRecord = Record + +export interface OpenAICompatibleSystemMessage extends JsonRecord { + role: "system" + content: string | Array +} + +export interface OpenAICompatibleSystemContentPart extends JsonRecord { + type: "text" + text: string +} + +export interface OpenAICompatibleUserMessage extends JsonRecord { + role: "user" + content: string | Array +} + +export type OpenAICompatibleContentPart = OpenAICompatibleContentPartText | OpenAICompatibleContentPartImage + +export interface OpenAICompatibleContentPartImage extends JsonRecord { + type: "image_url" + image_url: { url: string } +} + +export interface OpenAICompatibleContentPartText extends JsonRecord { + type: "text" + text: string +} + +export interface OpenAICompatibleAssistantMessage extends JsonRecord { + role: "assistant" + content?: string | null + tool_calls?: Array + // Copilot-specific reasoning fields + reasoning_text?: string + reasoning_opaque?: string +} + +export interface OpenAICompatibleMessageToolCall extends JsonRecord { + type: "function" + id: string + function: { + arguments: string + name: string + } +} + +export interface OpenAICompatibleToolMessage extends JsonRecord { + role: "tool" + content: string + tool_call_id: string +} diff --git a/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-chat-language-model.ts b/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-chat-language-model.ts new file mode 100644 index 00000000000..c85d3f3d178 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-chat-language-model.ts @@ -0,0 +1,780 @@ +import { + APICallError, + InvalidResponseDataError, + type LanguageModelV2, + type LanguageModelV2CallWarning, + type LanguageModelV2Content, + type LanguageModelV2FinishReason, + type LanguageModelV2StreamPart, + type SharedV2ProviderMetadata, +} from "@ai-sdk/provider" +import { + combineHeaders, + createEventSourceResponseHandler, + createJsonErrorResponseHandler, + createJsonResponseHandler, + type FetchFunction, + generateId, + isParsableJson, + parseProviderOptions, + type ParseResult, + postJsonToApi, + type ResponseHandler, +} from "@ai-sdk/provider-utils" +import { z } from "zod/v4" +import { convertToOpenAICompatibleChatMessages } from "./convert-to-openai-compatible-chat-messages" +import { getResponseMetadata } from "./get-response-metadata" +import { mapOpenAICompatibleFinishReason } from "./map-openai-compatible-finish-reason" +import { type OpenAICompatibleChatModelId, openaiCompatibleProviderOptions } from "./openai-compatible-chat-options" +import { defaultOpenAICompatibleErrorStructure, type ProviderErrorStructure } from "../openai-compatible-error" +import type { MetadataExtractor } from "./openai-compatible-metadata-extractor" +import { prepareTools } from "./openai-compatible-prepare-tools" + +export type OpenAICompatibleChatConfig = { + provider: string + headers: () => Record + url: (options: { modelId: string; path: string }) => string + fetch?: FetchFunction + includeUsage?: boolean + errorStructure?: ProviderErrorStructure + metadataExtractor?: MetadataExtractor + + /** + * Whether the model supports structured outputs. + */ + supportsStructuredOutputs?: boolean + + /** + * The supported URLs for the model. + */ + supportedUrls?: () => LanguageModelV2["supportedUrls"] +} + +export class OpenAICompatibleChatLanguageModel implements LanguageModelV2 { + readonly specificationVersion = "v2" + + readonly supportsStructuredOutputs: boolean + + readonly modelId: OpenAICompatibleChatModelId + private readonly config: OpenAICompatibleChatConfig + private readonly failedResponseHandler: ResponseHandler + private readonly chunkSchema // type inferred via constructor + + constructor(modelId: OpenAICompatibleChatModelId, config: OpenAICompatibleChatConfig) { + this.modelId = modelId + this.config = config + + // initialize error handling: + const errorStructure = config.errorStructure ?? defaultOpenAICompatibleErrorStructure + this.chunkSchema = createOpenAICompatibleChatChunkSchema(errorStructure.errorSchema) + this.failedResponseHandler = createJsonErrorResponseHandler(errorStructure) + + this.supportsStructuredOutputs = config.supportsStructuredOutputs ?? false + } + + get provider(): string { + return this.config.provider + } + + private get providerOptionsName(): string { + return this.config.provider.split(".")[0].trim() + } + + get supportedUrls() { + return this.config.supportedUrls?.() ?? {} + } + + private async getArgs({ + prompt, + maxOutputTokens, + temperature, + topP, + topK, + frequencyPenalty, + presencePenalty, + providerOptions, + stopSequences, + responseFormat, + seed, + toolChoice, + tools, + }: Parameters[0]) { + const warnings: LanguageModelV2CallWarning[] = [] + + // Parse provider options + const compatibleOptions = Object.assign( + (await parseProviderOptions({ + provider: "copilot", + providerOptions, + schema: openaiCompatibleProviderOptions, + })) ?? {}, + (await parseProviderOptions({ + provider: this.providerOptionsName, + providerOptions, + schema: openaiCompatibleProviderOptions, + })) ?? {}, + ) + + if (topK != null) { + warnings.push({ type: "unsupported-setting", setting: "topK" }) + } + + if (responseFormat?.type === "json" && responseFormat.schema != null && !this.supportsStructuredOutputs) { + warnings.push({ + type: "unsupported-setting", + setting: "responseFormat", + details: "JSON response format schema is only supported with structuredOutputs", + }) + } + + const { + tools: openaiTools, + toolChoice: openaiToolChoice, + toolWarnings, + } = prepareTools({ + tools, + toolChoice, + }) + + return { + args: { + // model id: + model: this.modelId, + + // model specific settings: + user: compatibleOptions.user, + + // standardized settings: + max_tokens: maxOutputTokens, + temperature, + top_p: topP, + frequency_penalty: frequencyPenalty, + presence_penalty: presencePenalty, + response_format: + responseFormat?.type === "json" + ? this.supportsStructuredOutputs === true && responseFormat.schema != null + ? { + type: "json_schema", + json_schema: { + schema: responseFormat.schema, + name: responseFormat.name ?? "response", + description: responseFormat.description, + }, + } + : { type: "json_object" } + : undefined, + + stop: stopSequences, + seed, + ...Object.fromEntries( + Object.entries(providerOptions?.[this.providerOptionsName] ?? {}).filter( + ([key]) => !Object.keys(openaiCompatibleProviderOptions.shape).includes(key), + ), + ), + + reasoning_effort: compatibleOptions.reasoningEffort, + verbosity: compatibleOptions.textVerbosity, + + // messages: + messages: convertToOpenAICompatibleChatMessages(prompt), + + // tools: + tools: openaiTools, + tool_choice: openaiToolChoice, + + // thinking_budget + thinking_budget: compatibleOptions.thinking_budget, + }, + warnings: [...warnings, ...toolWarnings], + } + } + + async doGenerate( + options: Parameters[0], + ): Promise>> { + const { args, warnings } = await this.getArgs({ ...options }) + + const body = JSON.stringify(args) + + const { + responseHeaders, + value: responseBody, + rawValue: rawResponse, + } = await postJsonToApi({ + url: this.config.url({ + path: "/chat/completions", + modelId: this.modelId, + }), + headers: combineHeaders(this.config.headers(), options.headers), + body: args, + failedResponseHandler: this.failedResponseHandler, + successfulResponseHandler: createJsonResponseHandler(OpenAICompatibleChatResponseSchema), + abortSignal: options.abortSignal, + fetch: this.config.fetch, + }) + + const choice = responseBody.choices[0] + const content: Array = [] + + // text content: + const text = choice.message.content + if (text != null && text.length > 0) { + content.push({ + type: "text", + text, + providerMetadata: choice.message.reasoning_opaque + ? { copilot: { reasoningOpaque: choice.message.reasoning_opaque } } + : undefined, + }) + } + + // reasoning content (Copilot uses reasoning_text): + const reasoning = choice.message.reasoning_text + if (reasoning != null && reasoning.length > 0) { + content.push({ + type: "reasoning", + text: reasoning, + // Include reasoning_opaque for Copilot multi-turn reasoning + providerMetadata: choice.message.reasoning_opaque + ? { copilot: { reasoningOpaque: choice.message.reasoning_opaque } } + : undefined, + }) + } + + // tool calls: + if (choice.message.tool_calls != null) { + for (const toolCall of choice.message.tool_calls) { + content.push({ + type: "tool-call", + toolCallId: toolCall.id ?? generateId(), + toolName: toolCall.function.name, + input: toolCall.function.arguments!, + providerMetadata: choice.message.reasoning_opaque + ? { copilot: { reasoningOpaque: choice.message.reasoning_opaque } } + : undefined, + }) + } + } + + // provider metadata: + const providerMetadata: SharedV2ProviderMetadata = { + [this.providerOptionsName]: {}, + ...(await this.config.metadataExtractor?.extractMetadata?.({ + parsedBody: rawResponse, + })), + } + const completionTokenDetails = responseBody.usage?.completion_tokens_details + if (completionTokenDetails?.accepted_prediction_tokens != null) { + providerMetadata[this.providerOptionsName].acceptedPredictionTokens = + completionTokenDetails?.accepted_prediction_tokens + } + if (completionTokenDetails?.rejected_prediction_tokens != null) { + providerMetadata[this.providerOptionsName].rejectedPredictionTokens = + completionTokenDetails?.rejected_prediction_tokens + } + + return { + content, + finishReason: mapOpenAICompatibleFinishReason(choice.finish_reason), + usage: { + inputTokens: responseBody.usage?.prompt_tokens ?? undefined, + outputTokens: responseBody.usage?.completion_tokens ?? undefined, + totalTokens: responseBody.usage?.total_tokens ?? undefined, + reasoningTokens: responseBody.usage?.completion_tokens_details?.reasoning_tokens ?? undefined, + cachedInputTokens: responseBody.usage?.prompt_tokens_details?.cached_tokens ?? undefined, + }, + providerMetadata, + request: { body }, + response: { + ...getResponseMetadata(responseBody), + headers: responseHeaders, + body: rawResponse, + }, + warnings, + } + } + + async doStream( + options: Parameters[0], + ): Promise>> { + const { args, warnings } = await this.getArgs({ ...options }) + + const body = { + ...args, + stream: true, + + // only include stream_options when in strict compatibility mode: + stream_options: this.config.includeUsage ? { include_usage: true } : undefined, + } + + const metadataExtractor = this.config.metadataExtractor?.createStreamExtractor() + + const { responseHeaders, value: response } = await postJsonToApi({ + url: this.config.url({ + path: "/chat/completions", + modelId: this.modelId, + }), + headers: combineHeaders(this.config.headers(), options.headers), + body, + failedResponseHandler: this.failedResponseHandler, + successfulResponseHandler: createEventSourceResponseHandler(this.chunkSchema), + abortSignal: options.abortSignal, + fetch: this.config.fetch, + }) + + const toolCalls: Array<{ + id: string + type: "function" + function: { + name: string + arguments: string + } + hasFinished: boolean + }> = [] + + let finishReason: LanguageModelV2FinishReason = "unknown" + const usage: { + completionTokens: number | undefined + completionTokensDetails: { + reasoningTokens: number | undefined + acceptedPredictionTokens: number | undefined + rejectedPredictionTokens: number | undefined + } + promptTokens: number | undefined + promptTokensDetails: { + cachedTokens: number | undefined + } + totalTokens: number | undefined + } = { + completionTokens: undefined, + completionTokensDetails: { + reasoningTokens: undefined, + acceptedPredictionTokens: undefined, + rejectedPredictionTokens: undefined, + }, + promptTokens: undefined, + promptTokensDetails: { + cachedTokens: undefined, + }, + totalTokens: undefined, + } + let isFirstChunk = true + const providerOptionsName = this.providerOptionsName + let isActiveReasoning = false + let isActiveText = false + let reasoningOpaque: string | undefined + + return { + stream: response.pipeThrough( + new TransformStream>, LanguageModelV2StreamPart>({ + start(controller) { + controller.enqueue({ type: "stream-start", warnings }) + }, + + // TODO we lost type safety on Chunk, most likely due to the error schema. MUST FIX + transform(chunk, controller) { + // Emit raw chunk if requested (before anything else) + if (options.includeRawChunks) { + controller.enqueue({ type: "raw", rawValue: chunk.rawValue }) + } + + // handle failed chunk parsing / validation: + if (!chunk.success) { + finishReason = "error" + controller.enqueue({ type: "error", error: chunk.error }) + return + } + const value = chunk.value + + metadataExtractor?.processChunk(chunk.rawValue) + + // handle error chunks: + if ("error" in value) { + finishReason = "error" + controller.enqueue({ type: "error", error: value.error.message }) + return + } + + if (isFirstChunk) { + isFirstChunk = false + + controller.enqueue({ + type: "response-metadata", + ...getResponseMetadata(value), + }) + } + + if (value.usage != null) { + const { + prompt_tokens, + completion_tokens, + total_tokens, + prompt_tokens_details, + completion_tokens_details, + } = value.usage + + usage.promptTokens = prompt_tokens ?? undefined + usage.completionTokens = completion_tokens ?? undefined + usage.totalTokens = total_tokens ?? undefined + if (completion_tokens_details?.reasoning_tokens != null) { + usage.completionTokensDetails.reasoningTokens = completion_tokens_details?.reasoning_tokens + } + if (completion_tokens_details?.accepted_prediction_tokens != null) { + usage.completionTokensDetails.acceptedPredictionTokens = + completion_tokens_details?.accepted_prediction_tokens + } + if (completion_tokens_details?.rejected_prediction_tokens != null) { + usage.completionTokensDetails.rejectedPredictionTokens = + completion_tokens_details?.rejected_prediction_tokens + } + if (prompt_tokens_details?.cached_tokens != null) { + usage.promptTokensDetails.cachedTokens = prompt_tokens_details?.cached_tokens + } + } + + const choice = value.choices[0] + + if (choice?.finish_reason != null) { + finishReason = mapOpenAICompatibleFinishReason(choice.finish_reason) + } + + if (choice?.delta == null) { + return + } + + const delta = choice.delta + + // Capture reasoning_opaque for Copilot multi-turn reasoning + if (delta.reasoning_opaque) { + if (reasoningOpaque != null) { + throw new InvalidResponseDataError({ + data: delta, + message: + "Multiple reasoning_opaque values received in a single response. Only one thinking part per response is supported.", + }) + } + reasoningOpaque = delta.reasoning_opaque + } + + // enqueue reasoning before text deltas (Copilot uses reasoning_text): + const reasoningContent = delta.reasoning_text + if (reasoningContent) { + if (!isActiveReasoning) { + controller.enqueue({ + type: "reasoning-start", + id: "reasoning-0", + }) + isActiveReasoning = true + } + + controller.enqueue({ + type: "reasoning-delta", + id: "reasoning-0", + delta: reasoningContent, + }) + } + + if (delta.content) { + // If reasoning was active and we're starting text, end reasoning first + // This handles the case where reasoning_opaque and content come in the same chunk + if (isActiveReasoning && !isActiveText) { + controller.enqueue({ + type: "reasoning-end", + id: "reasoning-0", + providerMetadata: reasoningOpaque ? { copilot: { reasoningOpaque } } : undefined, + }) + isActiveReasoning = false + } + + if (!isActiveText) { + controller.enqueue({ + type: "text-start", + id: "txt-0", + providerMetadata: reasoningOpaque ? { copilot: { reasoningOpaque } } : undefined, + }) + isActiveText = true + } + + controller.enqueue({ + type: "text-delta", + id: "txt-0", + delta: delta.content, + }) + } + + if (delta.tool_calls != null) { + // If reasoning was active and we're starting tool calls, end reasoning first + // This handles the case where reasoning goes directly to tool calls with no content + if (isActiveReasoning) { + controller.enqueue({ + type: "reasoning-end", + id: "reasoning-0", + providerMetadata: reasoningOpaque ? { copilot: { reasoningOpaque } } : undefined, + }) + isActiveReasoning = false + } + for (const toolCallDelta of delta.tool_calls) { + const index = toolCallDelta.index + + if (toolCalls[index] == null) { + if (toolCallDelta.id == null) { + throw new InvalidResponseDataError({ + data: toolCallDelta, + message: `Expected 'id' to be a string.`, + }) + } + + if (toolCallDelta.function?.name == null) { + throw new InvalidResponseDataError({ + data: toolCallDelta, + message: `Expected 'function.name' to be a string.`, + }) + } + + controller.enqueue({ + type: "tool-input-start", + id: toolCallDelta.id, + toolName: toolCallDelta.function.name, + }) + + toolCalls[index] = { + id: toolCallDelta.id, + type: "function", + function: { + name: toolCallDelta.function.name, + arguments: toolCallDelta.function.arguments ?? "", + }, + hasFinished: false, + } + + const toolCall = toolCalls[index] + + if (toolCall.function?.name != null && toolCall.function?.arguments != null) { + // send delta if the argument text has already started: + if (toolCall.function.arguments.length > 0) { + controller.enqueue({ + type: "tool-input-delta", + id: toolCall.id, + delta: toolCall.function.arguments, + }) + } + + // check if tool call is complete + // (some providers send the full tool call in one chunk): + if (isParsableJson(toolCall.function.arguments)) { + controller.enqueue({ + type: "tool-input-end", + id: toolCall.id, + }) + + controller.enqueue({ + type: "tool-call", + toolCallId: toolCall.id ?? generateId(), + toolName: toolCall.function.name, + input: toolCall.function.arguments, + providerMetadata: reasoningOpaque ? { copilot: { reasoningOpaque } } : undefined, + }) + toolCall.hasFinished = true + } + } + + continue + } + + // existing tool call, merge if not finished + const toolCall = toolCalls[index] + + if (toolCall.hasFinished) { + continue + } + + if (toolCallDelta.function?.arguments != null) { + toolCall.function!.arguments += toolCallDelta.function?.arguments ?? "" + } + + // send delta + controller.enqueue({ + type: "tool-input-delta", + id: toolCall.id, + delta: toolCallDelta.function.arguments ?? "", + }) + + // check if tool call is complete + if ( + toolCall.function?.name != null && + toolCall.function?.arguments != null && + isParsableJson(toolCall.function.arguments) + ) { + controller.enqueue({ + type: "tool-input-end", + id: toolCall.id, + }) + + controller.enqueue({ + type: "tool-call", + toolCallId: toolCall.id ?? generateId(), + toolName: toolCall.function.name, + input: toolCall.function.arguments, + providerMetadata: reasoningOpaque ? { copilot: { reasoningOpaque } } : undefined, + }) + toolCall.hasFinished = true + } + } + } + }, + + flush(controller) { + if (isActiveReasoning) { + controller.enqueue({ + type: "reasoning-end", + id: "reasoning-0", + // Include reasoning_opaque for Copilot multi-turn reasoning + providerMetadata: reasoningOpaque ? { copilot: { reasoningOpaque } } : undefined, + }) + } + + if (isActiveText) { + controller.enqueue({ type: "text-end", id: "txt-0" }) + } + + // go through all tool calls and send the ones that are not finished + for (const toolCall of toolCalls.filter((toolCall) => !toolCall.hasFinished)) { + controller.enqueue({ + type: "tool-input-end", + id: toolCall.id, + }) + + controller.enqueue({ + type: "tool-call", + toolCallId: toolCall.id ?? generateId(), + toolName: toolCall.function.name, + input: toolCall.function.arguments, + }) + } + + const providerMetadata: SharedV2ProviderMetadata = { + [providerOptionsName]: {}, + // Include reasoning_opaque for Copilot multi-turn reasoning + ...(reasoningOpaque ? { copilot: { reasoningOpaque } } : {}), + ...metadataExtractor?.buildMetadata(), + } + if (usage.completionTokensDetails.acceptedPredictionTokens != null) { + providerMetadata[providerOptionsName].acceptedPredictionTokens = + usage.completionTokensDetails.acceptedPredictionTokens + } + if (usage.completionTokensDetails.rejectedPredictionTokens != null) { + providerMetadata[providerOptionsName].rejectedPredictionTokens = + usage.completionTokensDetails.rejectedPredictionTokens + } + + controller.enqueue({ + type: "finish", + finishReason, + usage: { + inputTokens: usage.promptTokens ?? undefined, + outputTokens: usage.completionTokens ?? undefined, + totalTokens: usage.totalTokens ?? undefined, + reasoningTokens: usage.completionTokensDetails.reasoningTokens ?? undefined, + cachedInputTokens: usage.promptTokensDetails.cachedTokens ?? undefined, + }, + providerMetadata, + }) + }, + }), + ), + request: { body }, + response: { headers: responseHeaders }, + } + } +} + +const openaiCompatibleTokenUsageSchema = z + .object({ + prompt_tokens: z.number().nullish(), + completion_tokens: z.number().nullish(), + total_tokens: z.number().nullish(), + prompt_tokens_details: z + .object({ + cached_tokens: z.number().nullish(), + }) + .nullish(), + completion_tokens_details: z + .object({ + reasoning_tokens: z.number().nullish(), + accepted_prediction_tokens: z.number().nullish(), + rejected_prediction_tokens: z.number().nullish(), + }) + .nullish(), + }) + .nullish() + +// limited version of the schema, focussed on what is needed for the implementation +// this approach limits breakages when the API changes and increases efficiency +const OpenAICompatibleChatResponseSchema = z.object({ + id: z.string().nullish(), + created: z.number().nullish(), + model: z.string().nullish(), + choices: z.array( + z.object({ + message: z.object({ + role: z.literal("assistant").nullish(), + content: z.string().nullish(), + // Copilot-specific reasoning fields + reasoning_text: z.string().nullish(), + reasoning_opaque: z.string().nullish(), + tool_calls: z + .array( + z.object({ + id: z.string().nullish(), + function: z.object({ + name: z.string(), + arguments: z.string(), + }), + }), + ) + .nullish(), + }), + finish_reason: z.string().nullish(), + }), + ), + usage: openaiCompatibleTokenUsageSchema, +}) + +// limited version of the schema, focussed on what is needed for the implementation +// this approach limits breakages when the API changes and increases efficiency +const createOpenAICompatibleChatChunkSchema = (errorSchema: ERROR_SCHEMA) => + z.union([ + z.object({ + id: z.string().nullish(), + created: z.number().nullish(), + model: z.string().nullish(), + choices: z.array( + z.object({ + delta: z + .object({ + role: z.enum(["assistant"]).nullish(), + content: z.string().nullish(), + // Copilot-specific reasoning fields + reasoning_text: z.string().nullish(), + reasoning_opaque: z.string().nullish(), + tool_calls: z + .array( + z.object({ + index: z.number(), + id: z.string().nullish(), + function: z.object({ + name: z.string().nullish(), + arguments: z.string().nullish(), + }), + }), + ) + .nullish(), + }) + .nullish(), + finish_reason: z.string().nullish(), + }), + ), + usage: openaiCompatibleTokenUsageSchema, + }), + errorSchema, + ]) diff --git a/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-chat-options.ts b/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-chat-options.ts new file mode 100644 index 00000000000..ec5d53fbf9a --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-chat-options.ts @@ -0,0 +1,28 @@ +import { z } from "zod/v4" + +export type OpenAICompatibleChatModelId = string + +export const openaiCompatibleProviderOptions = z.object({ + /** + * A unique identifier representing your end-user, which can help the provider to + * monitor and detect abuse. + */ + user: z.string().optional(), + + /** + * Reasoning effort for reasoning models. Defaults to `medium`. + */ + reasoningEffort: z.string().optional(), + + /** + * Controls the verbosity of the generated text. Defaults to `medium`. + */ + textVerbosity: z.string().optional(), + + /** + * Copilot thinking_budget used for Anthropic models. + */ + thinking_budget: z.number().optional(), +}) + +export type OpenAICompatibleProviderOptions = z.infer diff --git a/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-metadata-extractor.ts b/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-metadata-extractor.ts new file mode 100644 index 00000000000..ba233fbc1b3 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-metadata-extractor.ts @@ -0,0 +1,44 @@ +import type { SharedV2ProviderMetadata } from "@ai-sdk/provider" + +/** +Extracts provider-specific metadata from API responses. +Used to standardize metadata handling across different LLM providers while allowing +provider-specific metadata to be captured. +*/ +export type MetadataExtractor = { + /** + * Extracts provider metadata from a complete, non-streaming response. + * + * @param parsedBody - The parsed response JSON body from the provider's API. + * + * @returns Provider-specific metadata or undefined if no metadata is available. + * The metadata should be under a key indicating the provider id. + */ + extractMetadata: ({ parsedBody }: { parsedBody: unknown }) => Promise + + /** + * Creates an extractor for handling streaming responses. The returned object provides + * methods to process individual chunks and build the final metadata from the accumulated + * stream data. + * + * @returns An object with methods to process chunks and build metadata from a stream + */ + createStreamExtractor: () => { + /** + * Process an individual chunk from the stream. Called for each chunk in the response stream + * to accumulate metadata throughout the streaming process. + * + * @param parsedChunk - The parsed JSON response chunk from the provider's API + */ + processChunk(parsedChunk: unknown): void + + /** + * Builds the metadata object after all chunks have been processed. + * Called at the end of the stream to generate the complete provider metadata. + * + * @returns Provider-specific metadata or undefined if no metadata is available. + * The metadata should be under a key indicating the provider id. + */ + buildMetadata(): SharedV2ProviderMetadata | undefined + } +} diff --git a/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-prepare-tools.ts b/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-prepare-tools.ts new file mode 100644 index 00000000000..8879d6481b3 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/chat/openai-compatible-prepare-tools.ts @@ -0,0 +1,87 @@ +import { + type LanguageModelV2CallOptions, + type LanguageModelV2CallWarning, + UnsupportedFunctionalityError, +} from "@ai-sdk/provider" + +export function prepareTools({ + tools, + toolChoice, +}: { + tools: LanguageModelV2CallOptions["tools"] + toolChoice?: LanguageModelV2CallOptions["toolChoice"] +}): { + tools: + | undefined + | Array<{ + type: "function" + function: { + name: string + description: string | undefined + parameters: unknown + } + }> + toolChoice: { type: "function"; function: { name: string } } | "auto" | "none" | "required" | undefined + toolWarnings: LanguageModelV2CallWarning[] +} { + // when the tools array is empty, change it to undefined to prevent errors: + tools = tools?.length ? tools : undefined + + const toolWarnings: LanguageModelV2CallWarning[] = [] + + if (tools == null) { + return { tools: undefined, toolChoice: undefined, toolWarnings } + } + + const openaiCompatTools: Array<{ + type: "function" + function: { + name: string + description: string | undefined + parameters: unknown + } + }> = [] + + for (const tool of tools) { + if (tool.type === "provider-defined") { + toolWarnings.push({ type: "unsupported-tool", tool }) + } else { + openaiCompatTools.push({ + type: "function", + function: { + name: tool.name, + description: tool.description, + parameters: tool.inputSchema, + }, + }) + } + } + + if (toolChoice == null) { + return { tools: openaiCompatTools, toolChoice: undefined, toolWarnings } + } + + const type = toolChoice.type + + switch (type) { + case "auto": + case "none": + case "required": + return { tools: openaiCompatTools, toolChoice: type, toolWarnings } + case "tool": + return { + tools: openaiCompatTools, + toolChoice: { + type: "function", + function: { name: toolChoice.toolName }, + }, + toolWarnings, + } + default: { + const _exhaustiveCheck: never = type + throw new UnsupportedFunctionalityError({ + functionality: `tool choice type: ${_exhaustiveCheck}`, + }) + } + } +} diff --git a/packages/opencode/src/provider/sdk/copilot/copilot-provider.ts b/packages/opencode/src/provider/sdk/copilot/copilot-provider.ts new file mode 100644 index 00000000000..1dc373ff3c7 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/copilot-provider.ts @@ -0,0 +1,100 @@ +import type { LanguageModelV2 } from "@ai-sdk/provider" +import { type FetchFunction, withoutTrailingSlash, withUserAgentSuffix } from "@ai-sdk/provider-utils" +import { OpenAICompatibleChatLanguageModel } from "./chat/openai-compatible-chat-language-model" +import { OpenAIResponsesLanguageModel } from "./responses/openai-responses-language-model" + +// Import the version or define it +const VERSION = "0.1.0" + +export type OpenaiCompatibleModelId = string + +export interface OpenaiCompatibleProviderSettings { + /** + * API key for authenticating requests. + */ + apiKey?: string + + /** + * Base URL for the OpenAI Compatible API calls. + */ + baseURL?: string + + /** + * Name of the provider. + */ + name?: string + + /** + * Custom headers to include in the requests. + */ + headers?: Record + + /** + * Custom fetch implementation. + */ + fetch?: FetchFunction +} + +export interface OpenaiCompatibleProvider { + (modelId: OpenaiCompatibleModelId): LanguageModelV2 + chat(modelId: OpenaiCompatibleModelId): LanguageModelV2 + responses(modelId: OpenaiCompatibleModelId): LanguageModelV2 + languageModel(modelId: OpenaiCompatibleModelId): LanguageModelV2 + + // embeddingModel(modelId: any): EmbeddingModelV2 + + // imageModel(modelId: any): ImageModelV2 +} + +/** + * Create an OpenAI Compatible provider instance. + */ +export function createOpenaiCompatible(options: OpenaiCompatibleProviderSettings = {}): OpenaiCompatibleProvider { + const baseURL = withoutTrailingSlash(options.baseURL ?? "https://api.openai.com/v1") + + if (!baseURL) { + throw new Error("baseURL is required") + } + + // Merge headers: defaults first, then user overrides + const headers = { + // Default OpenAI Compatible headers (can be overridden by user) + ...(options.apiKey && { Authorization: `Bearer ${options.apiKey}` }), + ...options.headers, + } + + const getHeaders = () => withUserAgentSuffix(headers, `ai-sdk/openai-compatible/${VERSION}`) + + const createChatModel = (modelId: OpenaiCompatibleModelId) => { + return new OpenAICompatibleChatLanguageModel(modelId, { + provider: `${options.name ?? "openai-compatible"}.chat`, + headers: getHeaders, + url: ({ path }) => `${baseURL}${path}`, + fetch: options.fetch, + }) + } + + const createResponsesModel = (modelId: OpenaiCompatibleModelId) => { + return new OpenAIResponsesLanguageModel(modelId, { + provider: `${options.name ?? "openai-compatible"}.responses`, + headers: getHeaders, + url: ({ path }) => `${baseURL}${path}`, + fetch: options.fetch, + }) + } + + const createLanguageModel = (modelId: OpenaiCompatibleModelId) => createChatModel(modelId) + + const provider = function (modelId: OpenaiCompatibleModelId) { + return createChatModel(modelId) + } + + provider.languageModel = createLanguageModel + provider.chat = createChatModel + provider.responses = createResponsesModel + + return provider as OpenaiCompatibleProvider +} + +// Default OpenAI Compatible provider instance +export const openaiCompatible = createOpenaiCompatible() diff --git a/packages/opencode/src/provider/sdk/copilot/index.ts b/packages/opencode/src/provider/sdk/copilot/index.ts new file mode 100644 index 00000000000..4da9cc21f4a --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/index.ts @@ -0,0 +1,2 @@ +export { createOpenaiCompatible, openaiCompatible } from "./copilot-provider" +export type { OpenaiCompatibleProvider, OpenaiCompatibleProviderSettings } from "./copilot-provider" diff --git a/packages/opencode/src/provider/sdk/copilot/openai-compatible-error.ts b/packages/opencode/src/provider/sdk/copilot/openai-compatible-error.ts new file mode 100644 index 00000000000..054c694dd30 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/openai-compatible-error.ts @@ -0,0 +1,27 @@ +import { z, type ZodType } from "zod/v4" + +export const openaiCompatibleErrorDataSchema = z.object({ + error: z.object({ + message: z.string(), + + // The additional information below is handled loosely to support + // OpenAI-compatible providers that have slightly different error + // responses: + type: z.string().nullish(), + param: z.any().nullish(), + code: z.union([z.string(), z.number()]).nullish(), + }), +}) + +export type OpenAICompatibleErrorData = z.infer + +export type ProviderErrorStructure = { + errorSchema: ZodType + errorToMessage: (error: T) => string + isRetryable?: (response: Response, error?: T) => boolean +} + +export const defaultOpenAICompatibleErrorStructure: ProviderErrorStructure = { + errorSchema: openaiCompatibleErrorDataSchema, + errorToMessage: (data) => data.error.message, +} diff --git a/packages/opencode/src/provider/sdk/copilot/responses/convert-to-openai-responses-input.ts b/packages/opencode/src/provider/sdk/copilot/responses/convert-to-openai-responses-input.ts new file mode 100644 index 00000000000..807f6ea57cd --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/convert-to-openai-responses-input.ts @@ -0,0 +1,303 @@ +import { + type LanguageModelV2CallWarning, + type LanguageModelV2Prompt, + type LanguageModelV2ToolCallPart, + UnsupportedFunctionalityError, +} from "@ai-sdk/provider" +import { convertToBase64, parseProviderOptions } from "@ai-sdk/provider-utils" +import { z } from "zod/v4" +import type { OpenAIResponsesInput, OpenAIResponsesReasoning } from "./openai-responses-api-types" +import { localShellInputSchema, localShellOutputSchema } from "./tool/local-shell" + +/** + * Check if a string is a file ID based on the given prefixes + * Returns false if prefixes is undefined (disables file ID detection) + */ +function isFileId(data: string, prefixes?: readonly string[]): boolean { + if (!prefixes) return false + return prefixes.some((prefix) => data.startsWith(prefix)) +} + +export async function convertToOpenAIResponsesInput({ + prompt, + systemMessageMode, + fileIdPrefixes, + store, + hasLocalShellTool = false, +}: { + prompt: LanguageModelV2Prompt + systemMessageMode: "system" | "developer" | "remove" + fileIdPrefixes?: readonly string[] + store: boolean + hasLocalShellTool?: boolean +}): Promise<{ + input: OpenAIResponsesInput + warnings: Array +}> { + const input: OpenAIResponsesInput = [] + const warnings: Array = [] + + for (const { role, content } of prompt) { + switch (role) { + case "system": { + switch (systemMessageMode) { + case "system": { + input.push({ role: "system", content }) + break + } + case "developer": { + input.push({ role: "developer", content }) + break + } + case "remove": { + warnings.push({ + type: "other", + message: "system messages are removed for this model", + }) + break + } + default: { + const _exhaustiveCheck: never = systemMessageMode + throw new Error(`Unsupported system message mode: ${_exhaustiveCheck}`) + } + } + break + } + + case "user": { + input.push({ + role: "user", + content: content.map((part, index) => { + switch (part.type) { + case "text": { + return { type: "input_text", text: part.text } + } + case "file": { + if (part.mediaType.startsWith("image/")) { + const mediaType = part.mediaType === "image/*" ? "image/jpeg" : part.mediaType + + return { + type: "input_image", + ...(part.data instanceof URL + ? { image_url: part.data.toString() } + : typeof part.data === "string" && isFileId(part.data, fileIdPrefixes) + ? { file_id: part.data } + : { + image_url: `data:${mediaType};base64,${convertToBase64(part.data)}`, + }), + detail: part.providerOptions?.openai?.imageDetail, + } + } else if (part.mediaType === "application/pdf") { + if (part.data instanceof URL) { + return { + type: "input_file", + file_url: part.data.toString(), + } + } + return { + type: "input_file", + ...(typeof part.data === "string" && isFileId(part.data, fileIdPrefixes) + ? { file_id: part.data } + : { + filename: part.filename ?? `part-${index}.pdf`, + file_data: `data:application/pdf;base64,${convertToBase64(part.data)}`, + }), + } + } else { + throw new UnsupportedFunctionalityError({ + functionality: `file part media type ${part.mediaType}`, + }) + } + } + } + }), + }) + + break + } + + case "assistant": { + const reasoningMessages: Record = {} + const toolCallParts: Record = {} + + for (const part of content) { + switch (part.type) { + case "text": { + input.push({ + role: "assistant", + content: [{ type: "output_text", text: part.text }], + id: (part.providerOptions?.openai?.itemId as string) ?? undefined, + }) + break + } + case "tool-call": { + toolCallParts[part.toolCallId] = part + + if (part.providerExecuted) { + break + } + + if (hasLocalShellTool && part.toolName === "local_shell") { + const parsedInput = localShellInputSchema.parse(part.input) + input.push({ + type: "local_shell_call", + call_id: part.toolCallId, + id: (part.providerOptions?.openai?.itemId as string) ?? undefined, + action: { + type: "exec", + command: parsedInput.action.command, + timeout_ms: parsedInput.action.timeoutMs, + user: parsedInput.action.user, + working_directory: parsedInput.action.workingDirectory, + env: parsedInput.action.env, + }, + }) + + break + } + + input.push({ + type: "function_call", + call_id: part.toolCallId, + name: part.toolName, + arguments: JSON.stringify(part.input), + id: (part.providerOptions?.openai?.itemId as string) ?? undefined, + }) + break + } + + // assistant tool result parts are from provider-executed tools: + case "tool-result": { + if (store) { + // use item references to refer to tool results from built-in tools + input.push({ type: "item_reference", id: part.toolCallId }) + } else { + warnings.push({ + type: "other", + message: `Results for OpenAI tool ${part.toolName} are not sent to the API when store is false`, + }) + } + + break + } + + case "reasoning": { + const providerOptions = await parseProviderOptions({ + provider: "copilot", + providerOptions: part.providerOptions, + schema: openaiResponsesReasoningProviderOptionsSchema, + }) + + const reasoningId = providerOptions?.itemId + + if (reasoningId != null) { + const reasoningMessage = reasoningMessages[reasoningId] + + if (store) { + if (reasoningMessage === undefined) { + // use item references to refer to reasoning (single reference) + input.push({ type: "item_reference", id: reasoningId }) + + // store unused reasoning message to mark id as used + reasoningMessages[reasoningId] = { + type: "reasoning", + id: reasoningId, + summary: [], + } + } + } else { + const summaryParts: Array<{ + type: "summary_text" + text: string + }> = [] + + if (part.text.length > 0) { + summaryParts.push({ + type: "summary_text", + text: part.text, + }) + } else if (reasoningMessage !== undefined) { + warnings.push({ + type: "other", + message: `Cannot append empty reasoning part to existing reasoning sequence. Skipping reasoning part: ${JSON.stringify(part)}.`, + }) + } + + if (reasoningMessage === undefined) { + reasoningMessages[reasoningId] = { + type: "reasoning", + id: reasoningId, + encrypted_content: providerOptions?.reasoningEncryptedContent, + summary: summaryParts, + } + input.push(reasoningMessages[reasoningId]) + } else { + reasoningMessage.summary.push(...summaryParts) + } + } + } else { + warnings.push({ + type: "other", + message: `Non-OpenAI reasoning parts are not supported. Skipping reasoning part: ${JSON.stringify(part)}.`, + }) + } + break + } + } + } + + break + } + + case "tool": { + for (const part of content) { + const output = part.output + + if (hasLocalShellTool && part.toolName === "local_shell" && output.type === "json") { + input.push({ + type: "local_shell_call_output", + call_id: part.toolCallId, + output: localShellOutputSchema.parse(output.value).output, + }) + break + } + + let contentValue: string + switch (output.type) { + case "text": + case "error-text": + contentValue = output.value + break + case "content": + case "json": + case "error-json": + contentValue = JSON.stringify(output.value) + break + } + + input.push({ + type: "function_call_output", + call_id: part.toolCallId, + output: contentValue, + }) + } + + break + } + + default: { + const _exhaustiveCheck: never = role + throw new Error(`Unsupported role: ${_exhaustiveCheck}`) + } + } + } + + return { input, warnings } +} + +const openaiResponsesReasoningProviderOptionsSchema = z.object({ + itemId: z.string().nullish(), + reasoningEncryptedContent: z.string().nullish(), +}) + +export type OpenAIResponsesReasoningProviderOptions = z.infer diff --git a/packages/opencode/src/provider/sdk/copilot/responses/map-openai-responses-finish-reason.ts b/packages/opencode/src/provider/sdk/copilot/responses/map-openai-responses-finish-reason.ts new file mode 100644 index 00000000000..54bb9056d79 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/map-openai-responses-finish-reason.ts @@ -0,0 +1,22 @@ +import type { LanguageModelV2FinishReason } from "@ai-sdk/provider" + +export function mapOpenAIResponseFinishReason({ + finishReason, + hasFunctionCall, +}: { + finishReason: string | null | undefined + // flag that checks if there have been client-side tool calls (not executed by openai) + hasFunctionCall: boolean +}): LanguageModelV2FinishReason { + switch (finishReason) { + case undefined: + case null: + return hasFunctionCall ? "tool-calls" : "stop" + case "max_output_tokens": + return "length" + case "content_filter": + return "content-filter" + default: + return hasFunctionCall ? "tool-calls" : "unknown" + } +} diff --git a/packages/opencode/src/provider/sdk/copilot/responses/openai-config.ts b/packages/opencode/src/provider/sdk/copilot/responses/openai-config.ts new file mode 100644 index 00000000000..2241dbb5249 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/openai-config.ts @@ -0,0 +1,18 @@ +import type { FetchFunction } from "@ai-sdk/provider-utils" + +export type OpenAIConfig = { + provider: string + url: (options: { modelId: string; path: string }) => string + headers: () => Record + fetch?: FetchFunction + generateId?: () => string + /** + * File ID prefixes used to identify file IDs in Responses API. + * When undefined, all file data is treated as base64 content. + * + * Examples: + * - OpenAI: ['file-'] for IDs like 'file-abc123' + * - Azure OpenAI: ['assistant-'] for IDs like 'assistant-abc123' + */ + fileIdPrefixes?: readonly string[] +} diff --git a/packages/opencode/src/provider/sdk/copilot/responses/openai-error.ts b/packages/opencode/src/provider/sdk/copilot/responses/openai-error.ts new file mode 100644 index 00000000000..e78824d3641 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/openai-error.ts @@ -0,0 +1,22 @@ +import { z } from "zod/v4" +import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils" + +export const openaiErrorDataSchema = z.object({ + error: z.object({ + message: z.string(), + + // The additional information below is handled loosely to support + // OpenAI-compatible providers that have slightly different error + // responses: + type: z.string().nullish(), + param: z.any().nullish(), + code: z.union([z.string(), z.number()]).nullish(), + }), +}) + +export type OpenAIErrorData = z.infer + +export const openaiFailedResponseHandler: any = createJsonErrorResponseHandler({ + errorSchema: openaiErrorDataSchema, + errorToMessage: (data) => data.error.message, +}) diff --git a/packages/opencode/src/provider/sdk/copilot/responses/openai-responses-api-types.ts b/packages/opencode/src/provider/sdk/copilot/responses/openai-responses-api-types.ts new file mode 100644 index 00000000000..cf1a3ba2fbf --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/openai-responses-api-types.ts @@ -0,0 +1,207 @@ +import type { JSONSchema7 } from "@ai-sdk/provider" + +export type OpenAIResponsesInput = Array + +export type OpenAIResponsesInputItem = + | OpenAIResponsesSystemMessage + | OpenAIResponsesUserMessage + | OpenAIResponsesAssistantMessage + | OpenAIResponsesFunctionCall + | OpenAIResponsesFunctionCallOutput + | OpenAIResponsesComputerCall + | OpenAIResponsesLocalShellCall + | OpenAIResponsesLocalShellCallOutput + | OpenAIResponsesReasoning + | OpenAIResponsesItemReference + +export type OpenAIResponsesIncludeValue = + | "web_search_call.action.sources" + | "code_interpreter_call.outputs" + | "computer_call_output.output.image_url" + | "file_search_call.results" + | "message.input_image.image_url" + | "message.output_text.logprobs" + | "reasoning.encrypted_content" + +export type OpenAIResponsesIncludeOptions = Array | undefined | null + +export type OpenAIResponsesSystemMessage = { + role: "system" | "developer" + content: string +} + +export type OpenAIResponsesUserMessage = { + role: "user" + content: Array< + | { type: "input_text"; text: string } + | { type: "input_image"; image_url: string } + | { type: "input_image"; file_id: string } + | { type: "input_file"; file_url: string } + | { type: "input_file"; filename: string; file_data: string } + | { type: "input_file"; file_id: string } + > +} + +export type OpenAIResponsesAssistantMessage = { + role: "assistant" + content: Array<{ type: "output_text"; text: string }> + id?: string +} + +export type OpenAIResponsesFunctionCall = { + type: "function_call" + call_id: string + name: string + arguments: string + id?: string +} + +export type OpenAIResponsesFunctionCallOutput = { + type: "function_call_output" + call_id: string + output: string +} + +export type OpenAIResponsesComputerCall = { + type: "computer_call" + id: string + status?: string +} + +export type OpenAIResponsesLocalShellCall = { + type: "local_shell_call" + id: string + call_id: string + action: { + type: "exec" + command: string[] + timeout_ms?: number + user?: string + working_directory?: string + env?: Record + } +} + +export type OpenAIResponsesLocalShellCallOutput = { + type: "local_shell_call_output" + call_id: string + output: string +} + +export type OpenAIResponsesItemReference = { + type: "item_reference" + id: string +} + +/** + * A filter used to compare a specified attribute key to a given value using a defined comparison operation. + */ +export type OpenAIResponsesFileSearchToolComparisonFilter = { + /** + * The key to compare against the value. + */ + key: string + + /** + * Specifies the comparison operator: eq, ne, gt, gte, lt, lte. + */ + type: "eq" | "ne" | "gt" | "gte" | "lt" | "lte" + + /** + * The value to compare against the attribute key; supports string, number, or boolean types. + */ + value: string | number | boolean +} + +/** + * Combine multiple filters using and or or. + */ +export type OpenAIResponsesFileSearchToolCompoundFilter = { + /** + * Type of operation: and or or. + */ + type: "and" | "or" + + /** + * Array of filters to combine. Items can be ComparisonFilter or CompoundFilter. + */ + filters: Array +} + +export type OpenAIResponsesTool = + | { + type: "function" + name: string + description: string | undefined + parameters: JSONSchema7 + strict: boolean | undefined + } + | { + type: "web_search" + filters: { allowed_domains: string[] | undefined } | undefined + search_context_size: "low" | "medium" | "high" | undefined + user_location: + | { + type: "approximate" + city?: string + country?: string + region?: string + timezone?: string + } + | undefined + } + | { + type: "web_search_preview" + search_context_size: "low" | "medium" | "high" | undefined + user_location: + | { + type: "approximate" + city?: string + country?: string + region?: string + timezone?: string + } + | undefined + } + | { + type: "code_interpreter" + container: string | { type: "auto"; file_ids: string[] | undefined } + } + | { + type: "file_search" + vector_store_ids: string[] + max_num_results: number | undefined + ranking_options: { ranker?: string; score_threshold?: number } | undefined + filters: OpenAIResponsesFileSearchToolComparisonFilter | OpenAIResponsesFileSearchToolCompoundFilter | undefined + } + | { + type: "image_generation" + background: "auto" | "opaque" | "transparent" | undefined + input_fidelity: "low" | "high" | undefined + input_image_mask: + | { + file_id: string | undefined + image_url: string | undefined + } + | undefined + model: string | undefined + moderation: "auto" | undefined + output_compression: number | undefined + output_format: "png" | "jpeg" | "webp" | undefined + partial_images: number | undefined + quality: "auto" | "low" | "medium" | "high" | undefined + size: "auto" | "1024x1024" | "1024x1536" | "1536x1024" | undefined + } + | { + type: "local_shell" + } + +export type OpenAIResponsesReasoning = { + type: "reasoning" + id: string + encrypted_content?: string | null + summary: Array<{ + type: "summary_text" + text: string + }> +} diff --git a/packages/opencode/src/provider/sdk/copilot/responses/openai-responses-language-model.ts b/packages/opencode/src/provider/sdk/copilot/responses/openai-responses-language-model.ts new file mode 100644 index 00000000000..0a575bc02bb --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/openai-responses-language-model.ts @@ -0,0 +1,1732 @@ +import { + APICallError, + type LanguageModelV2, + type LanguageModelV2CallWarning, + type LanguageModelV2Content, + type LanguageModelV2FinishReason, + type LanguageModelV2ProviderDefinedTool, + type LanguageModelV2StreamPart, + type LanguageModelV2Usage, + type SharedV2ProviderMetadata, +} from "@ai-sdk/provider" +import { + combineHeaders, + createEventSourceResponseHandler, + createJsonResponseHandler, + generateId, + parseProviderOptions, + type ParseResult, + postJsonToApi, +} from "@ai-sdk/provider-utils" +import { z } from "zod/v4" +import type { OpenAIConfig } from "./openai-config" +import { openaiFailedResponseHandler } from "./openai-error" +import { codeInterpreterInputSchema, codeInterpreterOutputSchema } from "./tool/code-interpreter" +import { fileSearchOutputSchema } from "./tool/file-search" +import { imageGenerationOutputSchema } from "./tool/image-generation" +import { convertToOpenAIResponsesInput } from "./convert-to-openai-responses-input" +import { mapOpenAIResponseFinishReason } from "./map-openai-responses-finish-reason" +import type { OpenAIResponsesIncludeOptions, OpenAIResponsesIncludeValue } from "./openai-responses-api-types" +import { prepareResponsesTools } from "./openai-responses-prepare-tools" +import type { OpenAIResponsesModelId } from "./openai-responses-settings" +import { localShellInputSchema } from "./tool/local-shell" + +const webSearchCallItem = z.object({ + type: z.literal("web_search_call"), + id: z.string(), + status: z.string(), + action: z + .discriminatedUnion("type", [ + z.object({ + type: z.literal("search"), + query: z.string().nullish(), + }), + z.object({ + type: z.literal("open_page"), + url: z.string(), + }), + z.object({ + type: z.literal("find"), + url: z.string(), + pattern: z.string(), + }), + ]) + .nullish(), +}) + +const fileSearchCallItem = z.object({ + type: z.literal("file_search_call"), + id: z.string(), + queries: z.array(z.string()), + results: z + .array( + z.object({ + attributes: z.record(z.string(), z.unknown()), + file_id: z.string(), + filename: z.string(), + score: z.number(), + text: z.string(), + }), + ) + .nullish(), +}) + +const codeInterpreterCallItem = z.object({ + type: z.literal("code_interpreter_call"), + id: z.string(), + code: z.string().nullable(), + container_id: z.string(), + outputs: z + .array( + z.discriminatedUnion("type", [ + z.object({ type: z.literal("logs"), logs: z.string() }), + z.object({ type: z.literal("image"), url: z.string() }), + ]), + ) + .nullable(), +}) + +const localShellCallItem = z.object({ + type: z.literal("local_shell_call"), + id: z.string(), + call_id: z.string(), + action: z.object({ + type: z.literal("exec"), + command: z.array(z.string()), + timeout_ms: z.number().optional(), + user: z.string().optional(), + working_directory: z.string().optional(), + env: z.record(z.string(), z.string()).optional(), + }), +}) + +const imageGenerationCallItem = z.object({ + type: z.literal("image_generation_call"), + id: z.string(), + result: z.string(), +}) + +/** + * `top_logprobs` request body argument can be set to an integer between + * 0 and 20 specifying the number of most likely tokens to return at each + * token position, each with an associated log probability. + * + * @see https://platform.openai.com/docs/api-reference/responses/create#responses_create-top_logprobs + */ +const TOP_LOGPROBS_MAX = 20 + +const LOGPROBS_SCHEMA = z.array( + z.object({ + token: z.string(), + logprob: z.number(), + top_logprobs: z.array( + z.object({ + token: z.string(), + logprob: z.number(), + }), + ), + }), +) + +export class OpenAIResponsesLanguageModel implements LanguageModelV2 { + readonly specificationVersion = "v2" + + readonly modelId: OpenAIResponsesModelId + + private readonly config: OpenAIConfig + + constructor(modelId: OpenAIResponsesModelId, config: OpenAIConfig) { + this.modelId = modelId + this.config = config + } + + readonly supportedUrls: Record = { + "image/*": [/^https?:\/\/.*$/], + "application/pdf": [/^https?:\/\/.*$/], + } + + get provider(): string { + return this.config.provider + } + + private async getArgs({ + maxOutputTokens, + temperature, + stopSequences, + topP, + topK, + presencePenalty, + frequencyPenalty, + seed, + prompt, + providerOptions, + tools, + toolChoice, + responseFormat, + }: Parameters[0]) { + const warnings: LanguageModelV2CallWarning[] = [] + const modelConfig = getResponsesModelConfig(this.modelId) + + if (topK != null) { + warnings.push({ type: "unsupported-setting", setting: "topK" }) + } + + if (seed != null) { + warnings.push({ type: "unsupported-setting", setting: "seed" }) + } + + if (presencePenalty != null) { + warnings.push({ + type: "unsupported-setting", + setting: "presencePenalty", + }) + } + + if (frequencyPenalty != null) { + warnings.push({ + type: "unsupported-setting", + setting: "frequencyPenalty", + }) + } + + if (stopSequences != null) { + warnings.push({ type: "unsupported-setting", setting: "stopSequences" }) + } + + const openaiOptions = await parseProviderOptions({ + provider: "copilot", + providerOptions, + schema: openaiResponsesProviderOptionsSchema, + }) + + const { input, warnings: inputWarnings } = await convertToOpenAIResponsesInput({ + prompt, + systemMessageMode: modelConfig.systemMessageMode, + fileIdPrefixes: this.config.fileIdPrefixes, + store: openaiOptions?.store ?? true, + hasLocalShellTool: hasOpenAITool("openai.local_shell"), + }) + + warnings.push(...inputWarnings) + + const strictJsonSchema = openaiOptions?.strictJsonSchema ?? false + + let include: OpenAIResponsesIncludeOptions = openaiOptions?.include + + function addInclude(key: OpenAIResponsesIncludeValue) { + include = include != null ? [...include, key] : [key] + } + + function hasOpenAITool(id: string) { + return tools?.find((tool) => tool.type === "provider-defined" && tool.id === id) != null + } + + // when logprobs are requested, automatically include them: + const topLogprobs = + typeof openaiOptions?.logprobs === "number" + ? openaiOptions?.logprobs + : openaiOptions?.logprobs === true + ? TOP_LOGPROBS_MAX + : undefined + + if (topLogprobs) { + addInclude("message.output_text.logprobs") + } + + // when a web search tool is present, automatically include the sources: + const webSearchToolName = ( + tools?.find( + (tool) => + tool.type === "provider-defined" && + (tool.id === "openai.web_search" || tool.id === "openai.web_search_preview"), + ) as LanguageModelV2ProviderDefinedTool | undefined + )?.name + + if (webSearchToolName) { + addInclude("web_search_call.action.sources") + } + + // when a code interpreter tool is present, automatically include the outputs: + if (hasOpenAITool("openai.code_interpreter")) { + addInclude("code_interpreter_call.outputs") + } + + const baseArgs = { + model: this.modelId, + input, + temperature, + top_p: topP, + max_output_tokens: maxOutputTokens, + + ...((responseFormat?.type === "json" || openaiOptions?.textVerbosity) && { + text: { + ...(responseFormat?.type === "json" && { + format: + responseFormat.schema != null + ? { + type: "json_schema", + strict: strictJsonSchema, + name: responseFormat.name ?? "response", + description: responseFormat.description, + schema: responseFormat.schema, + } + : { type: "json_object" }, + }), + ...(openaiOptions?.textVerbosity && { + verbosity: openaiOptions.textVerbosity, + }), + }, + }), + + // provider options: + max_tool_calls: openaiOptions?.maxToolCalls, + metadata: openaiOptions?.metadata, + parallel_tool_calls: openaiOptions?.parallelToolCalls, + previous_response_id: openaiOptions?.previousResponseId, + store: openaiOptions?.store, + user: openaiOptions?.user, + instructions: openaiOptions?.instructions, + service_tier: openaiOptions?.serviceTier, + include, + prompt_cache_key: openaiOptions?.promptCacheKey, + safety_identifier: openaiOptions?.safetyIdentifier, + top_logprobs: topLogprobs, + + // model-specific settings: + ...(modelConfig.isReasoningModel && + (openaiOptions?.reasoningEffort != null || openaiOptions?.reasoningSummary != null) && { + reasoning: { + ...(openaiOptions?.reasoningEffort != null && { + effort: openaiOptions.reasoningEffort, + }), + ...(openaiOptions?.reasoningSummary != null && { + summary: openaiOptions.reasoningSummary, + }), + }, + }), + ...(modelConfig.requiredAutoTruncation && { + truncation: "auto", + }), + } + + if (modelConfig.isReasoningModel) { + // remove unsupported settings for reasoning models + // see https://platform.openai.com/docs/guides/reasoning#limitations + if (baseArgs.temperature != null) { + baseArgs.temperature = undefined + warnings.push({ + type: "unsupported-setting", + setting: "temperature", + details: "temperature is not supported for reasoning models", + }) + } + + if (baseArgs.top_p != null) { + baseArgs.top_p = undefined + warnings.push({ + type: "unsupported-setting", + setting: "topP", + details: "topP is not supported for reasoning models", + }) + } + } else { + if (openaiOptions?.reasoningEffort != null) { + warnings.push({ + type: "unsupported-setting", + setting: "reasoningEffort", + details: "reasoningEffort is not supported for non-reasoning models", + }) + } + + if (openaiOptions?.reasoningSummary != null) { + warnings.push({ + type: "unsupported-setting", + setting: "reasoningSummary", + details: "reasoningSummary is not supported for non-reasoning models", + }) + } + } + + // Validate flex processing support + if (openaiOptions?.serviceTier === "flex" && !modelConfig.supportsFlexProcessing) { + warnings.push({ + type: "unsupported-setting", + setting: "serviceTier", + details: "flex processing is only available for o3, o4-mini, and gpt-5 models", + }) + // Remove from args if not supported + delete (baseArgs as any).service_tier + } + + // Validate priority processing support + if (openaiOptions?.serviceTier === "priority" && !modelConfig.supportsPriorityProcessing) { + warnings.push({ + type: "unsupported-setting", + setting: "serviceTier", + details: + "priority processing is only available for supported models (gpt-4, gpt-5, gpt-5-mini, o3, o4-mini) and requires Enterprise access. gpt-5-nano is not supported", + }) + // Remove from args if not supported + delete (baseArgs as any).service_tier + } + + const { + tools: openaiTools, + toolChoice: openaiToolChoice, + toolWarnings, + } = prepareResponsesTools({ + tools, + toolChoice, + strictJsonSchema, + }) + + return { + webSearchToolName, + args: { + ...baseArgs, + tools: openaiTools, + tool_choice: openaiToolChoice, + }, + warnings: [...warnings, ...toolWarnings], + } + } + + async doGenerate( + options: Parameters[0], + ): Promise>> { + const { args: body, warnings, webSearchToolName } = await this.getArgs(options) + const url = this.config.url({ + path: "/responses", + modelId: this.modelId, + }) + + const { + responseHeaders, + value: response, + rawValue: rawResponse, + } = await postJsonToApi({ + url, + headers: combineHeaders(this.config.headers(), options.headers), + body, + failedResponseHandler: openaiFailedResponseHandler, + successfulResponseHandler: createJsonResponseHandler( + z.object({ + id: z.string(), + created_at: z.number(), + error: z + .object({ + code: z.string(), + message: z.string(), + }) + .nullish(), + model: z.string(), + output: z.array( + z.discriminatedUnion("type", [ + z.object({ + type: z.literal("message"), + role: z.literal("assistant"), + id: z.string(), + content: z.array( + z.object({ + type: z.literal("output_text"), + text: z.string(), + logprobs: LOGPROBS_SCHEMA.nullish(), + annotations: z.array( + z.discriminatedUnion("type", [ + z.object({ + type: z.literal("url_citation"), + start_index: z.number(), + end_index: z.number(), + url: z.string(), + title: z.string(), + }), + z.object({ + type: z.literal("file_citation"), + file_id: z.string(), + filename: z.string().nullish(), + index: z.number().nullish(), + start_index: z.number().nullish(), + end_index: z.number().nullish(), + quote: z.string().nullish(), + }), + z.object({ + type: z.literal("container_file_citation"), + }), + ]), + ), + }), + ), + }), + webSearchCallItem, + fileSearchCallItem, + codeInterpreterCallItem, + imageGenerationCallItem, + localShellCallItem, + z.object({ + type: z.literal("function_call"), + call_id: z.string(), + name: z.string(), + arguments: z.string(), + id: z.string(), + }), + z.object({ + type: z.literal("computer_call"), + id: z.string(), + status: z.string().optional(), + }), + z.object({ + type: z.literal("reasoning"), + id: z.string(), + encrypted_content: z.string().nullish(), + summary: z.array( + z.object({ + type: z.literal("summary_text"), + text: z.string(), + }), + ), + }), + ]), + ), + service_tier: z.string().nullish(), + incomplete_details: z.object({ reason: z.string() }).nullish(), + usage: usageSchema, + }), + ), + abortSignal: options.abortSignal, + fetch: this.config.fetch, + }) + + if (response.error) { + throw new APICallError({ + message: response.error.message, + url, + requestBodyValues: body, + statusCode: 400, + responseHeaders, + responseBody: rawResponse as string, + isRetryable: false, + }) + } + + const content: Array = [] + const logprobs: Array> = [] + + // flag that checks if there have been client-side tool calls (not executed by openai) + let hasFunctionCall = false + + // map response content to content array + for (const part of response.output) { + switch (part.type) { + case "reasoning": { + // when there are no summary parts, we need to add an empty reasoning part: + if (part.summary.length === 0) { + part.summary.push({ type: "summary_text", text: "" }) + } + + for (const summary of part.summary) { + content.push({ + type: "reasoning" as const, + text: summary.text, + providerMetadata: { + openai: { + itemId: part.id, + reasoningEncryptedContent: part.encrypted_content ?? null, + }, + }, + }) + } + break + } + + case "image_generation_call": { + content.push({ + type: "tool-call", + toolCallId: part.id, + toolName: "image_generation", + input: "{}", + providerExecuted: true, + }) + + content.push({ + type: "tool-result", + toolCallId: part.id, + toolName: "image_generation", + result: { + result: part.result, + } satisfies z.infer, + providerExecuted: true, + }) + + break + } + + case "local_shell_call": { + content.push({ + type: "tool-call", + toolCallId: part.call_id, + toolName: "local_shell", + input: JSON.stringify({ action: part.action } satisfies z.infer), + providerMetadata: { + openai: { + itemId: part.id, + }, + }, + }) + + break + } + + case "message": { + for (const contentPart of part.content) { + if (options.providerOptions?.openai?.logprobs && contentPart.logprobs) { + logprobs.push(contentPart.logprobs) + } + + content.push({ + type: "text", + text: contentPart.text, + providerMetadata: { + openai: { + itemId: part.id, + }, + }, + }) + + for (const annotation of contentPart.annotations) { + if (annotation.type === "url_citation") { + content.push({ + type: "source", + sourceType: "url", + id: this.config.generateId?.() ?? generateId(), + url: annotation.url, + title: annotation.title, + }) + } else if (annotation.type === "file_citation") { + content.push({ + type: "source", + sourceType: "document", + id: this.config.generateId?.() ?? generateId(), + mediaType: "text/plain", + title: annotation.quote ?? annotation.filename ?? "Document", + filename: annotation.filename ?? annotation.file_id, + }) + } + } + } + + break + } + + case "function_call": { + hasFunctionCall = true + + content.push({ + type: "tool-call", + toolCallId: part.call_id, + toolName: part.name, + input: part.arguments, + providerMetadata: { + openai: { + itemId: part.id, + }, + }, + }) + break + } + + case "web_search_call": { + content.push({ + type: "tool-call", + toolCallId: part.id, + toolName: webSearchToolName ?? "web_search", + input: JSON.stringify({ action: part.action }), + providerExecuted: true, + }) + + content.push({ + type: "tool-result", + toolCallId: part.id, + toolName: webSearchToolName ?? "web_search", + result: { status: part.status }, + providerExecuted: true, + }) + + break + } + + case "computer_call": { + content.push({ + type: "tool-call", + toolCallId: part.id, + toolName: "computer_use", + input: "", + providerExecuted: true, + }) + + content.push({ + type: "tool-result", + toolCallId: part.id, + toolName: "computer_use", + result: { + type: "computer_use_tool_result", + status: part.status || "completed", + }, + providerExecuted: true, + }) + break + } + + case "file_search_call": { + content.push({ + type: "tool-call", + toolCallId: part.id, + toolName: "file_search", + input: "{}", + providerExecuted: true, + }) + + content.push({ + type: "tool-result", + toolCallId: part.id, + toolName: "file_search", + result: { + queries: part.queries, + results: + part.results?.map((result) => ({ + attributes: result.attributes, + fileId: result.file_id, + filename: result.filename, + score: result.score, + text: result.text, + })) ?? null, + } satisfies z.infer, + providerExecuted: true, + }) + break + } + + case "code_interpreter_call": { + content.push({ + type: "tool-call", + toolCallId: part.id, + toolName: "code_interpreter", + input: JSON.stringify({ + code: part.code, + containerId: part.container_id, + } satisfies z.infer), + providerExecuted: true, + }) + + content.push({ + type: "tool-result", + toolCallId: part.id, + toolName: "code_interpreter", + result: { + outputs: part.outputs, + } satisfies z.infer, + providerExecuted: true, + }) + break + } + } + } + + const providerMetadata: SharedV2ProviderMetadata = { + openai: { responseId: response.id }, + } + + if (logprobs.length > 0) { + providerMetadata.openai.logprobs = logprobs + } + + if (typeof response.service_tier === "string") { + providerMetadata.openai.serviceTier = response.service_tier + } + + return { + content, + finishReason: mapOpenAIResponseFinishReason({ + finishReason: response.incomplete_details?.reason, + hasFunctionCall, + }), + usage: { + inputTokens: response.usage.input_tokens, + outputTokens: response.usage.output_tokens, + totalTokens: response.usage.input_tokens + response.usage.output_tokens, + reasoningTokens: response.usage.output_tokens_details?.reasoning_tokens ?? undefined, + cachedInputTokens: response.usage.input_tokens_details?.cached_tokens ?? undefined, + }, + request: { body }, + response: { + id: response.id, + timestamp: new Date(response.created_at * 1000), + modelId: response.model, + headers: responseHeaders, + body: rawResponse, + }, + providerMetadata, + warnings, + } + } + + async doStream( + options: Parameters[0], + ): Promise>> { + const { args: body, warnings, webSearchToolName } = await this.getArgs(options) + + const { responseHeaders, value: response } = await postJsonToApi({ + url: this.config.url({ + path: "/responses", + modelId: this.modelId, + }), + headers: combineHeaders(this.config.headers(), options.headers), + body: { + ...body, + stream: true, + }, + failedResponseHandler: openaiFailedResponseHandler, + successfulResponseHandler: createEventSourceResponseHandler(openaiResponsesChunkSchema), + abortSignal: options.abortSignal, + fetch: this.config.fetch, + }) + + const self = this + + let finishReason: LanguageModelV2FinishReason = "unknown" + const usage: LanguageModelV2Usage = { + inputTokens: undefined, + outputTokens: undefined, + totalTokens: undefined, + } + const logprobs: Array> = [] + let responseId: string | null = null + const ongoingToolCalls: Record< + number, + | { + toolName: string + toolCallId: string + codeInterpreter?: { + containerId: string + } + } + | undefined + > = {} + + // flag that checks if there have been client-side tool calls (not executed by openai) + let hasFunctionCall = false + + // Track reasoning by output_index instead of item_id + // GitHub Copilot rotates encrypted item IDs on every event + const activeReasoning: Record< + number, + { + canonicalId: string // the item.id from output_item.added + encryptedContent?: string | null + summaryParts: number[] + } + > = {} + + // Track current active reasoning output_index for correlating summary events + let currentReasoningOutputIndex: number | null = null + + // Track a stable text part id for the current assistant message. + // Copilot may change item_id across text deltas; normalize to one id. + let currentTextId: string | null = null + + let serviceTier: string | undefined + + return { + stream: response.pipeThrough( + new TransformStream>, LanguageModelV2StreamPart>({ + start(controller) { + controller.enqueue({ type: "stream-start", warnings }) + }, + + transform(chunk, controller) { + if (options.includeRawChunks) { + controller.enqueue({ type: "raw", rawValue: chunk.rawValue }) + } + + // handle failed chunk parsing / validation: + if (!chunk.success) { + finishReason = "error" + controller.enqueue({ type: "error", error: chunk.error }) + return + } + + const value = chunk.value + + if (isResponseOutputItemAddedChunk(value)) { + if (value.item.type === "function_call") { + ongoingToolCalls[value.output_index] = { + toolName: value.item.name, + toolCallId: value.item.call_id, + } + + controller.enqueue({ + type: "tool-input-start", + id: value.item.call_id, + toolName: value.item.name, + }) + } else if (value.item.type === "web_search_call") { + ongoingToolCalls[value.output_index] = { + toolName: webSearchToolName ?? "web_search", + toolCallId: value.item.id, + } + + controller.enqueue({ + type: "tool-input-start", + id: value.item.id, + toolName: webSearchToolName ?? "web_search", + }) + } else if (value.item.type === "computer_call") { + ongoingToolCalls[value.output_index] = { + toolName: "computer_use", + toolCallId: value.item.id, + } + + controller.enqueue({ + type: "tool-input-start", + id: value.item.id, + toolName: "computer_use", + }) + } else if (value.item.type === "code_interpreter_call") { + ongoingToolCalls[value.output_index] = { + toolName: "code_interpreter", + toolCallId: value.item.id, + codeInterpreter: { + containerId: value.item.container_id, + }, + } + + controller.enqueue({ + type: "tool-input-start", + id: value.item.id, + toolName: "code_interpreter", + }) + + controller.enqueue({ + type: "tool-input-delta", + id: value.item.id, + delta: `{"containerId":"${value.item.container_id}","code":"`, + }) + } else if (value.item.type === "file_search_call") { + controller.enqueue({ + type: "tool-call", + toolCallId: value.item.id, + toolName: "file_search", + input: "{}", + providerExecuted: true, + }) + } else if (value.item.type === "image_generation_call") { + controller.enqueue({ + type: "tool-call", + toolCallId: value.item.id, + toolName: "image_generation", + input: "{}", + providerExecuted: true, + }) + } else if (value.item.type === "message") { + // Start a stable text part for this assistant message + currentTextId = value.item.id + controller.enqueue({ + type: "text-start", + id: value.item.id, + providerMetadata: { + openai: { + itemId: value.item.id, + }, + }, + }) + } else if (isResponseOutputItemAddedReasoningChunk(value)) { + activeReasoning[value.output_index] = { + canonicalId: value.item.id, + encryptedContent: value.item.encrypted_content, + summaryParts: [0], + } + currentReasoningOutputIndex = value.output_index + + controller.enqueue({ + type: "reasoning-start", + id: `${value.item.id}:0`, + providerMetadata: { + openai: { + itemId: value.item.id, + reasoningEncryptedContent: value.item.encrypted_content ?? null, + }, + }, + }) + } + } else if (isResponseOutputItemDoneChunk(value)) { + if (value.item.type === "function_call") { + ongoingToolCalls[value.output_index] = undefined + hasFunctionCall = true + + controller.enqueue({ + type: "tool-input-end", + id: value.item.call_id, + }) + + controller.enqueue({ + type: "tool-call", + toolCallId: value.item.call_id, + toolName: value.item.name, + input: value.item.arguments, + providerMetadata: { + openai: { + itemId: value.item.id, + }, + }, + }) + } else if (value.item.type === "web_search_call") { + ongoingToolCalls[value.output_index] = undefined + + controller.enqueue({ + type: "tool-input-end", + id: value.item.id, + }) + + controller.enqueue({ + type: "tool-call", + toolCallId: value.item.id, + toolName: "web_search", + input: JSON.stringify({ action: value.item.action }), + providerExecuted: true, + }) + + controller.enqueue({ + type: "tool-result", + toolCallId: value.item.id, + toolName: "web_search", + result: { status: value.item.status }, + providerExecuted: true, + }) + } else if (value.item.type === "computer_call") { + ongoingToolCalls[value.output_index] = undefined + + controller.enqueue({ + type: "tool-input-end", + id: value.item.id, + }) + + controller.enqueue({ + type: "tool-call", + toolCallId: value.item.id, + toolName: "computer_use", + input: "", + providerExecuted: true, + }) + + controller.enqueue({ + type: "tool-result", + toolCallId: value.item.id, + toolName: "computer_use", + result: { + type: "computer_use_tool_result", + status: value.item.status || "completed", + }, + providerExecuted: true, + }) + } else if (value.item.type === "file_search_call") { + ongoingToolCalls[value.output_index] = undefined + + controller.enqueue({ + type: "tool-result", + toolCallId: value.item.id, + toolName: "file_search", + result: { + queries: value.item.queries, + results: + value.item.results?.map((result) => ({ + attributes: result.attributes, + fileId: result.file_id, + filename: result.filename, + score: result.score, + text: result.text, + })) ?? null, + } satisfies z.infer, + providerExecuted: true, + }) + } else if (value.item.type === "code_interpreter_call") { + ongoingToolCalls[value.output_index] = undefined + + controller.enqueue({ + type: "tool-result", + toolCallId: value.item.id, + toolName: "code_interpreter", + result: { + outputs: value.item.outputs, + } satisfies z.infer, + providerExecuted: true, + }) + } else if (value.item.type === "image_generation_call") { + controller.enqueue({ + type: "tool-result", + toolCallId: value.item.id, + toolName: "image_generation", + result: { + result: value.item.result, + } satisfies z.infer, + providerExecuted: true, + }) + } else if (value.item.type === "local_shell_call") { + ongoingToolCalls[value.output_index] = undefined + + controller.enqueue({ + type: "tool-call", + toolCallId: value.item.call_id, + toolName: "local_shell", + input: JSON.stringify({ + action: { + type: "exec", + command: value.item.action.command, + timeoutMs: value.item.action.timeout_ms, + user: value.item.action.user, + workingDirectory: value.item.action.working_directory, + env: value.item.action.env, + }, + } satisfies z.infer), + providerMetadata: { + openai: { itemId: value.item.id }, + }, + }) + } else if (value.item.type === "message") { + if (currentTextId) { + controller.enqueue({ + type: "text-end", + id: currentTextId, + }) + currentTextId = null + } + } else if (isResponseOutputItemDoneReasoningChunk(value)) { + const activeReasoningPart = activeReasoning[value.output_index] + if (activeReasoningPart) { + for (const summaryIndex of activeReasoningPart.summaryParts) { + controller.enqueue({ + type: "reasoning-end", + id: `${activeReasoningPart.canonicalId}:${summaryIndex}`, + providerMetadata: { + openai: { + itemId: activeReasoningPart.canonicalId, + reasoningEncryptedContent: value.item.encrypted_content ?? null, + }, + }, + }) + } + delete activeReasoning[value.output_index] + if (currentReasoningOutputIndex === value.output_index) { + currentReasoningOutputIndex = null + } + } + } + } else if (isResponseFunctionCallArgumentsDeltaChunk(value)) { + const toolCall = ongoingToolCalls[value.output_index] + + if (toolCall != null) { + controller.enqueue({ + type: "tool-input-delta", + id: toolCall.toolCallId, + delta: value.delta, + }) + } + } else if (isResponseImageGenerationCallPartialImageChunk(value)) { + controller.enqueue({ + type: "tool-result", + toolCallId: value.item_id, + toolName: "image_generation", + result: { + result: value.partial_image_b64, + } satisfies z.infer, + providerExecuted: true, + }) + } else if (isResponseCodeInterpreterCallCodeDeltaChunk(value)) { + const toolCall = ongoingToolCalls[value.output_index] + + if (toolCall != null) { + controller.enqueue({ + type: "tool-input-delta", + id: toolCall.toolCallId, + // The delta is code, which is embedding in a JSON string. + // To escape it, we use JSON.stringify and slice to remove the outer quotes. + delta: JSON.stringify(value.delta).slice(1, -1), + }) + } + } else if (isResponseCodeInterpreterCallCodeDoneChunk(value)) { + const toolCall = ongoingToolCalls[value.output_index] + + if (toolCall != null) { + controller.enqueue({ + type: "tool-input-delta", + id: toolCall.toolCallId, + delta: '"}', + }) + + controller.enqueue({ + type: "tool-input-end", + id: toolCall.toolCallId, + }) + + // immediately send the tool call after the input end: + controller.enqueue({ + type: "tool-call", + toolCallId: toolCall.toolCallId, + toolName: "code_interpreter", + input: JSON.stringify({ + code: value.code, + containerId: toolCall.codeInterpreter!.containerId, + } satisfies z.infer), + providerExecuted: true, + }) + } + } else if (isResponseCreatedChunk(value)) { + responseId = value.response.id + controller.enqueue({ + type: "response-metadata", + id: value.response.id, + timestamp: new Date(value.response.created_at * 1000), + modelId: value.response.model, + }) + } else if (isTextDeltaChunk(value)) { + // Ensure a text-start exists, and normalize deltas to a stable id + if (!currentTextId) { + currentTextId = value.item_id + controller.enqueue({ + type: "text-start", + id: currentTextId, + providerMetadata: { + openai: { itemId: value.item_id }, + }, + }) + } + + controller.enqueue({ + type: "text-delta", + id: currentTextId, + delta: value.delta, + }) + + if (options.providerOptions?.openai?.logprobs && value.logprobs) { + logprobs.push(value.logprobs) + } + } else if (isResponseReasoningSummaryPartAddedChunk(value)) { + const activeItem = + currentReasoningOutputIndex !== null ? activeReasoning[currentReasoningOutputIndex] : null + + // the first reasoning start is pushed in isResponseOutputItemAddedReasoningChunk. + if (activeItem && value.summary_index > 0) { + activeItem.summaryParts.push(value.summary_index) + + controller.enqueue({ + type: "reasoning-start", + id: `${activeItem.canonicalId}:${value.summary_index}`, + providerMetadata: { + openai: { + itemId: activeItem.canonicalId, + reasoningEncryptedContent: activeItem.encryptedContent ?? null, + }, + }, + }) + } + } else if (isResponseReasoningSummaryTextDeltaChunk(value)) { + const activeItem = + currentReasoningOutputIndex !== null ? activeReasoning[currentReasoningOutputIndex] : null + + if (activeItem) { + controller.enqueue({ + type: "reasoning-delta", + id: `${activeItem.canonicalId}:${value.summary_index}`, + delta: value.delta, + providerMetadata: { + openai: { + itemId: activeItem.canonicalId, + }, + }, + }) + } + } else if (isResponseFinishedChunk(value)) { + finishReason = mapOpenAIResponseFinishReason({ + finishReason: value.response.incomplete_details?.reason, + hasFunctionCall, + }) + usage.inputTokens = value.response.usage.input_tokens + usage.outputTokens = value.response.usage.output_tokens + usage.totalTokens = value.response.usage.input_tokens + value.response.usage.output_tokens + usage.reasoningTokens = value.response.usage.output_tokens_details?.reasoning_tokens ?? undefined + usage.cachedInputTokens = value.response.usage.input_tokens_details?.cached_tokens ?? undefined + if (typeof value.response.service_tier === "string") { + serviceTier = value.response.service_tier + } + } else if (isResponseAnnotationAddedChunk(value)) { + if (value.annotation.type === "url_citation") { + controller.enqueue({ + type: "source", + sourceType: "url", + id: self.config.generateId?.() ?? generateId(), + url: value.annotation.url, + title: value.annotation.title, + }) + } else if (value.annotation.type === "file_citation") { + controller.enqueue({ + type: "source", + sourceType: "document", + id: self.config.generateId?.() ?? generateId(), + mediaType: "text/plain", + title: value.annotation.quote ?? value.annotation.filename ?? "Document", + filename: value.annotation.filename ?? value.annotation.file_id, + }) + } + } else if (isErrorChunk(value)) { + controller.enqueue({ type: "error", error: value }) + } + }, + + flush(controller) { + // Close any dangling text part + if (currentTextId) { + controller.enqueue({ type: "text-end", id: currentTextId }) + currentTextId = null + } + + const providerMetadata: SharedV2ProviderMetadata = { + openai: { + responseId, + }, + } + + if (logprobs.length > 0) { + providerMetadata.openai.logprobs = logprobs + } + + if (serviceTier !== undefined) { + providerMetadata.openai.serviceTier = serviceTier + } + + controller.enqueue({ + type: "finish", + finishReason, + usage, + providerMetadata, + }) + }, + }), + ), + request: { body }, + response: { headers: responseHeaders }, + } + } +} + +const usageSchema = z.object({ + input_tokens: z.number(), + input_tokens_details: z.object({ cached_tokens: z.number().nullish() }).nullish(), + output_tokens: z.number(), + output_tokens_details: z.object({ reasoning_tokens: z.number().nullish() }).nullish(), +}) + +const textDeltaChunkSchema = z.object({ + type: z.literal("response.output_text.delta"), + item_id: z.string(), + delta: z.string(), + logprobs: LOGPROBS_SCHEMA.nullish(), +}) + +const errorChunkSchema = z.object({ + type: z.literal("error"), + code: z.string(), + message: z.string(), + param: z.string().nullish(), + sequence_number: z.number(), +}) + +const responseFinishedChunkSchema = z.object({ + type: z.enum(["response.completed", "response.incomplete"]), + response: z.object({ + incomplete_details: z.object({ reason: z.string() }).nullish(), + usage: usageSchema, + service_tier: z.string().nullish(), + }), +}) + +const responseCreatedChunkSchema = z.object({ + type: z.literal("response.created"), + response: z.object({ + id: z.string(), + created_at: z.number(), + model: z.string(), + service_tier: z.string().nullish(), + }), +}) + +const responseOutputItemAddedSchema = z.object({ + type: z.literal("response.output_item.added"), + output_index: z.number(), + item: z.discriminatedUnion("type", [ + z.object({ + type: z.literal("message"), + id: z.string(), + }), + z.object({ + type: z.literal("reasoning"), + id: z.string(), + encrypted_content: z.string().nullish(), + }), + z.object({ + type: z.literal("function_call"), + id: z.string(), + call_id: z.string(), + name: z.string(), + arguments: z.string(), + }), + z.object({ + type: z.literal("web_search_call"), + id: z.string(), + status: z.string(), + action: z + .object({ + type: z.literal("search"), + query: z.string().optional(), + }) + .nullish(), + }), + z.object({ + type: z.literal("computer_call"), + id: z.string(), + status: z.string(), + }), + z.object({ + type: z.literal("file_search_call"), + id: z.string(), + }), + z.object({ + type: z.literal("image_generation_call"), + id: z.string(), + }), + z.object({ + type: z.literal("code_interpreter_call"), + id: z.string(), + container_id: z.string(), + code: z.string().nullable(), + outputs: z + .array( + z.discriminatedUnion("type", [ + z.object({ type: z.literal("logs"), logs: z.string() }), + z.object({ type: z.literal("image"), url: z.string() }), + ]), + ) + .nullable(), + status: z.string(), + }), + ]), +}) + +const responseOutputItemDoneSchema = z.object({ + type: z.literal("response.output_item.done"), + output_index: z.number(), + item: z.discriminatedUnion("type", [ + z.object({ + type: z.literal("message"), + id: z.string(), + }), + z.object({ + type: z.literal("reasoning"), + id: z.string(), + encrypted_content: z.string().nullish(), + }), + z.object({ + type: z.literal("function_call"), + id: z.string(), + call_id: z.string(), + name: z.string(), + arguments: z.string(), + status: z.literal("completed"), + }), + codeInterpreterCallItem, + imageGenerationCallItem, + webSearchCallItem, + fileSearchCallItem, + localShellCallItem, + z.object({ + type: z.literal("computer_call"), + id: z.string(), + status: z.literal("completed"), + }), + ]), +}) + +const responseFunctionCallArgumentsDeltaSchema = z.object({ + type: z.literal("response.function_call_arguments.delta"), + item_id: z.string(), + output_index: z.number(), + delta: z.string(), +}) + +const responseImageGenerationCallPartialImageSchema = z.object({ + type: z.literal("response.image_generation_call.partial_image"), + item_id: z.string(), + output_index: z.number(), + partial_image_b64: z.string(), +}) + +const responseCodeInterpreterCallCodeDeltaSchema = z.object({ + type: z.literal("response.code_interpreter_call_code.delta"), + item_id: z.string(), + output_index: z.number(), + delta: z.string(), +}) + +const responseCodeInterpreterCallCodeDoneSchema = z.object({ + type: z.literal("response.code_interpreter_call_code.done"), + item_id: z.string(), + output_index: z.number(), + code: z.string(), +}) + +const responseAnnotationAddedSchema = z.object({ + type: z.literal("response.output_text.annotation.added"), + annotation: z.discriminatedUnion("type", [ + z.object({ + type: z.literal("url_citation"), + url: z.string(), + title: z.string(), + }), + z.object({ + type: z.literal("file_citation"), + file_id: z.string(), + filename: z.string().nullish(), + index: z.number().nullish(), + start_index: z.number().nullish(), + end_index: z.number().nullish(), + quote: z.string().nullish(), + }), + ]), +}) + +const responseReasoningSummaryPartAddedSchema = z.object({ + type: z.literal("response.reasoning_summary_part.added"), + item_id: z.string(), + summary_index: z.number(), +}) + +const responseReasoningSummaryTextDeltaSchema = z.object({ + type: z.literal("response.reasoning_summary_text.delta"), + item_id: z.string(), + summary_index: z.number(), + delta: z.string(), +}) + +const openaiResponsesChunkSchema = z.union([ + textDeltaChunkSchema, + responseFinishedChunkSchema, + responseCreatedChunkSchema, + responseOutputItemAddedSchema, + responseOutputItemDoneSchema, + responseFunctionCallArgumentsDeltaSchema, + responseImageGenerationCallPartialImageSchema, + responseCodeInterpreterCallCodeDeltaSchema, + responseCodeInterpreterCallCodeDoneSchema, + responseAnnotationAddedSchema, + responseReasoningSummaryPartAddedSchema, + responseReasoningSummaryTextDeltaSchema, + errorChunkSchema, + z.object({ type: z.string() }).loose(), // fallback for unknown chunks +]) + +type ExtractByType = T extends { type: K } ? T : never + +function isTextDeltaChunk( + chunk: z.infer, +): chunk is z.infer { + return chunk.type === "response.output_text.delta" +} + +function isResponseOutputItemDoneChunk( + chunk: z.infer, +): chunk is z.infer { + return chunk.type === "response.output_item.done" +} + +function isResponseOutputItemDoneReasoningChunk(chunk: z.infer): chunk is z.infer< + typeof responseOutputItemDoneSchema +> & { + item: ExtractByType["item"], "reasoning"> +} { + return isResponseOutputItemDoneChunk(chunk) && chunk.item.type === "reasoning" +} + +function isResponseFinishedChunk( + chunk: z.infer, +): chunk is z.infer { + return chunk.type === "response.completed" || chunk.type === "response.incomplete" +} + +function isResponseCreatedChunk( + chunk: z.infer, +): chunk is z.infer { + return chunk.type === "response.created" +} + +function isResponseFunctionCallArgumentsDeltaChunk( + chunk: z.infer, +): chunk is z.infer { + return chunk.type === "response.function_call_arguments.delta" +} +function isResponseImageGenerationCallPartialImageChunk( + chunk: z.infer, +): chunk is z.infer { + return chunk.type === "response.image_generation_call.partial_image" +} + +function isResponseCodeInterpreterCallCodeDeltaChunk( + chunk: z.infer, +): chunk is z.infer { + return chunk.type === "response.code_interpreter_call_code.delta" +} + +function isResponseCodeInterpreterCallCodeDoneChunk( + chunk: z.infer, +): chunk is z.infer { + return chunk.type === "response.code_interpreter_call_code.done" +} + +function isResponseOutputItemAddedChunk( + chunk: z.infer, +): chunk is z.infer { + return chunk.type === "response.output_item.added" +} + +function isResponseOutputItemAddedReasoningChunk(chunk: z.infer): chunk is z.infer< + typeof responseOutputItemAddedSchema +> & { + item: ExtractByType["item"], "reasoning"> +} { + return isResponseOutputItemAddedChunk(chunk) && chunk.item.type === "reasoning" +} + +function isResponseAnnotationAddedChunk( + chunk: z.infer, +): chunk is z.infer { + return chunk.type === "response.output_text.annotation.added" +} + +function isResponseReasoningSummaryPartAddedChunk( + chunk: z.infer, +): chunk is z.infer { + return chunk.type === "response.reasoning_summary_part.added" +} + +function isResponseReasoningSummaryTextDeltaChunk( + chunk: z.infer, +): chunk is z.infer { + return chunk.type === "response.reasoning_summary_text.delta" +} + +function isErrorChunk(chunk: z.infer): chunk is z.infer { + return chunk.type === "error" +} + +type ResponsesModelConfig = { + isReasoningModel: boolean + systemMessageMode: "remove" | "system" | "developer" + requiredAutoTruncation: boolean + supportsFlexProcessing: boolean + supportsPriorityProcessing: boolean +} + +function getResponsesModelConfig(modelId: string): ResponsesModelConfig { + const supportsFlexProcessing = + modelId.startsWith("o3") || + modelId.startsWith("o4-mini") || + (modelId.startsWith("gpt-5") && !modelId.startsWith("gpt-5-chat")) + const supportsPriorityProcessing = + modelId.startsWith("gpt-4") || + modelId.startsWith("gpt-5-mini") || + (modelId.startsWith("gpt-5") && !modelId.startsWith("gpt-5-nano") && !modelId.startsWith("gpt-5-chat")) || + modelId.startsWith("o3") || + modelId.startsWith("o4-mini") + const defaults = { + requiredAutoTruncation: false, + systemMessageMode: "system" as const, + supportsFlexProcessing, + supportsPriorityProcessing, + } + + // gpt-5-chat models are non-reasoning + if (modelId.startsWith("gpt-5-chat")) { + return { + ...defaults, + isReasoningModel: false, + } + } + + // o series reasoning models: + if ( + modelId.startsWith("o") || + modelId.startsWith("gpt-5") || + modelId.startsWith("codex-") || + modelId.startsWith("computer-use") + ) { + if (modelId.startsWith("o1-mini") || modelId.startsWith("o1-preview")) { + return { + ...defaults, + isReasoningModel: true, + systemMessageMode: "remove", + } + } + + return { + ...defaults, + isReasoningModel: true, + systemMessageMode: "developer", + } + } + + // gpt models: + return { + ...defaults, + isReasoningModel: false, + } +} + +// TODO AI SDK 6: use optional here instead of nullish +const openaiResponsesProviderOptionsSchema = z.object({ + include: z + .array(z.enum(["reasoning.encrypted_content", "file_search_call.results", "message.output_text.logprobs"])) + .nullish(), + instructions: z.string().nullish(), + + /** + * Return the log probabilities of the tokens. + * + * Setting to true will return the log probabilities of the tokens that + * were generated. + * + * Setting to a number will return the log probabilities of the top n + * tokens that were generated. + * + * @see https://platform.openai.com/docs/api-reference/responses/create + * @see https://cookbook.openai.com/examples/using_logprobs + */ + logprobs: z.union([z.boolean(), z.number().min(1).max(TOP_LOGPROBS_MAX)]).optional(), + + /** + * The maximum number of total calls to built-in tools that can be processed in a response. + * This maximum number applies across all built-in tool calls, not per individual tool. + * Any further attempts to call a tool by the model will be ignored. + */ + maxToolCalls: z.number().nullish(), + + metadata: z.any().nullish(), + parallelToolCalls: z.boolean().nullish(), + previousResponseId: z.string().nullish(), + promptCacheKey: z.string().nullish(), + reasoningEffort: z.string().nullish(), + reasoningSummary: z.string().nullish(), + safetyIdentifier: z.string().nullish(), + serviceTier: z.enum(["auto", "flex", "priority"]).nullish(), + store: z.boolean().nullish(), + strictJsonSchema: z.boolean().nullish(), + textVerbosity: z.enum(["low", "medium", "high"]).nullish(), + user: z.string().nullish(), +}) + +export type OpenAIResponsesProviderOptions = z.infer diff --git a/packages/opencode/src/provider/sdk/copilot/responses/openai-responses-prepare-tools.ts b/packages/opencode/src/provider/sdk/copilot/responses/openai-responses-prepare-tools.ts new file mode 100644 index 00000000000..791de3e7cfa --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/openai-responses-prepare-tools.ts @@ -0,0 +1,177 @@ +import { + type LanguageModelV2CallOptions, + type LanguageModelV2CallWarning, + UnsupportedFunctionalityError, +} from "@ai-sdk/provider" +import { codeInterpreterArgsSchema } from "./tool/code-interpreter" +import { fileSearchArgsSchema } from "./tool/file-search" +import { webSearchArgsSchema } from "./tool/web-search" +import { webSearchPreviewArgsSchema } from "./tool/web-search-preview" +import { imageGenerationArgsSchema } from "./tool/image-generation" +import type { OpenAIResponsesTool } from "./openai-responses-api-types" + +export function prepareResponsesTools({ + tools, + toolChoice, + strictJsonSchema, +}: { + tools: LanguageModelV2CallOptions["tools"] + toolChoice?: LanguageModelV2CallOptions["toolChoice"] + strictJsonSchema: boolean +}): { + tools?: Array + toolChoice?: + | "auto" + | "none" + | "required" + | { type: "file_search" } + | { type: "web_search_preview" } + | { type: "web_search" } + | { type: "function"; name: string } + | { type: "code_interpreter" } + | { type: "image_generation" } + toolWarnings: LanguageModelV2CallWarning[] +} { + // when the tools array is empty, change it to undefined to prevent errors: + tools = tools?.length ? tools : undefined + + const toolWarnings: LanguageModelV2CallWarning[] = [] + + if (tools == null) { + return { tools: undefined, toolChoice: undefined, toolWarnings } + } + + const openaiTools: Array = [] + + for (const tool of tools) { + switch (tool.type) { + case "function": + openaiTools.push({ + type: "function", + name: tool.name, + description: tool.description, + parameters: tool.inputSchema, + strict: strictJsonSchema, + }) + break + case "provider-defined": { + switch (tool.id) { + case "openai.file_search": { + const args = fileSearchArgsSchema.parse(tool.args) + + openaiTools.push({ + type: "file_search", + vector_store_ids: args.vectorStoreIds, + max_num_results: args.maxNumResults, + ranking_options: args.ranking + ? { + ranker: args.ranking.ranker, + score_threshold: args.ranking.scoreThreshold, + } + : undefined, + filters: args.filters, + }) + + break + } + case "openai.local_shell": { + openaiTools.push({ + type: "local_shell", + }) + break + } + case "openai.web_search_preview": { + const args = webSearchPreviewArgsSchema.parse(tool.args) + openaiTools.push({ + type: "web_search_preview", + search_context_size: args.searchContextSize, + user_location: args.userLocation, + }) + break + } + case "openai.web_search": { + const args = webSearchArgsSchema.parse(tool.args) + openaiTools.push({ + type: "web_search", + filters: args.filters != null ? { allowed_domains: args.filters.allowedDomains } : undefined, + search_context_size: args.searchContextSize, + user_location: args.userLocation, + }) + break + } + case "openai.code_interpreter": { + const args = codeInterpreterArgsSchema.parse(tool.args) + openaiTools.push({ + type: "code_interpreter", + container: + args.container == null + ? { type: "auto", file_ids: undefined } + : typeof args.container === "string" + ? args.container + : { type: "auto", file_ids: args.container.fileIds }, + }) + break + } + case "openai.image_generation": { + const args = imageGenerationArgsSchema.parse(tool.args) + openaiTools.push({ + type: "image_generation", + background: args.background, + input_fidelity: args.inputFidelity, + input_image_mask: args.inputImageMask + ? { + file_id: args.inputImageMask.fileId, + image_url: args.inputImageMask.imageUrl, + } + : undefined, + model: args.model, + moderation: args.moderation, + partial_images: args.partialImages, + quality: args.quality, + output_compression: args.outputCompression, + output_format: args.outputFormat, + size: args.size, + }) + break + } + } + break + } + default: + toolWarnings.push({ type: "unsupported-tool", tool }) + break + } + } + + if (toolChoice == null) { + return { tools: openaiTools, toolChoice: undefined, toolWarnings } + } + + const type = toolChoice.type + + switch (type) { + case "auto": + case "none": + case "required": + return { tools: openaiTools, toolChoice: type, toolWarnings } + case "tool": + return { + tools: openaiTools, + toolChoice: + toolChoice.toolName === "code_interpreter" || + toolChoice.toolName === "file_search" || + toolChoice.toolName === "image_generation" || + toolChoice.toolName === "web_search_preview" || + toolChoice.toolName === "web_search" + ? { type: toolChoice.toolName } + : { type: "function", name: toolChoice.toolName }, + toolWarnings, + } + default: { + const _exhaustiveCheck: never = type + throw new UnsupportedFunctionalityError({ + functionality: `tool choice type: ${_exhaustiveCheck}`, + }) + } + } +} diff --git a/packages/opencode/src/provider/sdk/copilot/responses/openai-responses-settings.ts b/packages/opencode/src/provider/sdk/copilot/responses/openai-responses-settings.ts new file mode 100644 index 00000000000..76c97346fa2 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/openai-responses-settings.ts @@ -0,0 +1 @@ +export type OpenAIResponsesModelId = string diff --git a/packages/opencode/src/provider/sdk/copilot/responses/tool/code-interpreter.ts b/packages/opencode/src/provider/sdk/copilot/responses/tool/code-interpreter.ts new file mode 100644 index 00000000000..2bb4bce778d --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/tool/code-interpreter.ts @@ -0,0 +1,88 @@ +import { createProviderDefinedToolFactoryWithOutputSchema } from "@ai-sdk/provider-utils" +import { z } from "zod/v4" + +export const codeInterpreterInputSchema = z.object({ + code: z.string().nullish(), + containerId: z.string(), +}) + +export const codeInterpreterOutputSchema = z.object({ + outputs: z + .array( + z.discriminatedUnion("type", [ + z.object({ type: z.literal("logs"), logs: z.string() }), + z.object({ type: z.literal("image"), url: z.string() }), + ]), + ) + .nullish(), +}) + +export const codeInterpreterArgsSchema = z.object({ + container: z + .union([ + z.string(), + z.object({ + fileIds: z.array(z.string()).optional(), + }), + ]) + .optional(), +}) + +type CodeInterpreterArgs = { + /** + * The code interpreter container. + * Can be a container ID + * or an object that specifies uploaded file IDs to make available to your code. + */ + container?: string | { fileIds?: string[] } +} + +export const codeInterpreterToolFactory = createProviderDefinedToolFactoryWithOutputSchema< + { + /** + * The code to run, or null if not available. + */ + code?: string | null + + /** + * The ID of the container used to run the code. + */ + containerId: string + }, + { + /** + * The outputs generated by the code interpreter, such as logs or images. + * Can be null if no outputs are available. + */ + outputs?: Array< + | { + type: "logs" + + /** + * The logs output from the code interpreter. + */ + logs: string + } + | { + type: "image" + + /** + * The URL of the image output from the code interpreter. + */ + url: string + } + > | null + }, + CodeInterpreterArgs +>({ + id: "openai.code_interpreter", + name: "code_interpreter", + inputSchema: codeInterpreterInputSchema, + outputSchema: codeInterpreterOutputSchema, +}) + +export const codeInterpreter = ( + args: CodeInterpreterArgs = {}, // default +) => { + return codeInterpreterToolFactory(args) +} diff --git a/packages/opencode/src/provider/sdk/copilot/responses/tool/file-search.ts b/packages/opencode/src/provider/sdk/copilot/responses/tool/file-search.ts new file mode 100644 index 00000000000..1fccddaf63b --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/tool/file-search.ts @@ -0,0 +1,128 @@ +import { createProviderDefinedToolFactoryWithOutputSchema } from "@ai-sdk/provider-utils" +import type { + OpenAIResponsesFileSearchToolComparisonFilter, + OpenAIResponsesFileSearchToolCompoundFilter, +} from "../openai-responses-api-types" +import { z } from "zod/v4" + +const comparisonFilterSchema = z.object({ + key: z.string(), + type: z.enum(["eq", "ne", "gt", "gte", "lt", "lte"]), + value: z.union([z.string(), z.number(), z.boolean()]), +}) + +const compoundFilterSchema: z.ZodType = z.object({ + type: z.enum(["and", "or"]), + filters: z.array(z.union([comparisonFilterSchema, z.lazy(() => compoundFilterSchema)])), +}) + +export const fileSearchArgsSchema = z.object({ + vectorStoreIds: z.array(z.string()), + maxNumResults: z.number().optional(), + ranking: z + .object({ + ranker: z.string().optional(), + scoreThreshold: z.number().optional(), + }) + .optional(), + filters: z.union([comparisonFilterSchema, compoundFilterSchema]).optional(), +}) + +export const fileSearchOutputSchema = z.object({ + queries: z.array(z.string()), + results: z + .array( + z.object({ + attributes: z.record(z.string(), z.unknown()), + fileId: z.string(), + filename: z.string(), + score: z.number(), + text: z.string(), + }), + ) + .nullable(), +}) + +export const fileSearch = createProviderDefinedToolFactoryWithOutputSchema< + {}, + { + /** + * The search query to execute. + */ + queries: string[] + + /** + * The results of the file search tool call. + */ + results: + | null + | { + /** + * Set of 16 key-value pairs that can be attached to an object. + * This can be useful for storing additional information about the object + * in a structured format, and querying for objects via API or the dashboard. + * Keys are strings with a maximum length of 64 characters. + * Values are strings with a maximum length of 512 characters, booleans, or numbers. + */ + attributes: Record + + /** + * The unique ID of the file. + */ + fileId: string + + /** + * The name of the file. + */ + filename: string + + /** + * The relevance score of the file - a value between 0 and 1. + */ + score: number + + /** + * The text that was retrieved from the file. + */ + text: string + }[] + }, + { + /** + * List of vector store IDs to search through. + */ + vectorStoreIds: string[] + + /** + * Maximum number of search results to return. Defaults to 10. + */ + maxNumResults?: number + + /** + * Ranking options for the search. + */ + ranking?: { + /** + * The ranker to use for the file search. + */ + ranker?: string + + /** + * The score threshold for the file search, a number between 0 and 1. + * Numbers closer to 1 will attempt to return only the most relevant results, + * but may return fewer results. + */ + scoreThreshold?: number + } + + /** + * A filter to apply. + */ + filters?: OpenAIResponsesFileSearchToolComparisonFilter | OpenAIResponsesFileSearchToolCompoundFilter + } +>({ + id: "openai.file_search", + name: "file_search", + inputSchema: z.object({}), + outputSchema: fileSearchOutputSchema, +}) diff --git a/packages/opencode/src/provider/sdk/copilot/responses/tool/image-generation.ts b/packages/opencode/src/provider/sdk/copilot/responses/tool/image-generation.ts new file mode 100644 index 00000000000..7367a4802b7 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/tool/image-generation.ts @@ -0,0 +1,115 @@ +import { createProviderDefinedToolFactoryWithOutputSchema } from "@ai-sdk/provider-utils" +import { z } from "zod/v4" + +export const imageGenerationArgsSchema = z + .object({ + background: z.enum(["auto", "opaque", "transparent"]).optional(), + inputFidelity: z.enum(["low", "high"]).optional(), + inputImageMask: z + .object({ + fileId: z.string().optional(), + imageUrl: z.string().optional(), + }) + .optional(), + model: z.string().optional(), + moderation: z.enum(["auto"]).optional(), + outputCompression: z.number().int().min(0).max(100).optional(), + outputFormat: z.enum(["png", "jpeg", "webp"]).optional(), + partialImages: z.number().int().min(0).max(3).optional(), + quality: z.enum(["auto", "low", "medium", "high"]).optional(), + size: z.enum(["1024x1024", "1024x1536", "1536x1024", "auto"]).optional(), + }) + .strict() + +export const imageGenerationOutputSchema = z.object({ + result: z.string(), +}) + +type ImageGenerationArgs = { + /** + * Background type for the generated image. Default is 'auto'. + */ + background?: "auto" | "opaque" | "transparent" + + /** + * Input fidelity for the generated image. Default is 'low'. + */ + inputFidelity?: "low" | "high" + + /** + * Optional mask for inpainting. + * Contains image_url (string, optional) and file_id (string, optional). + */ + inputImageMask?: { + /** + * File ID for the mask image. + */ + fileId?: string + + /** + * Base64-encoded mask image. + */ + imageUrl?: string + } + + /** + * The image generation model to use. Default: gpt-image-1. + */ + model?: string + + /** + * Moderation level for the generated image. Default: auto. + */ + moderation?: "auto" + + /** + * Compression level for the output image. Default: 100. + */ + outputCompression?: number + + /** + * The output format of the generated image. One of png, webp, or jpeg. + * Default: png + */ + outputFormat?: "png" | "jpeg" | "webp" + + /** + * Number of partial images to generate in streaming mode, from 0 (default value) to 3. + */ + partialImages?: number + + /** + * The quality of the generated image. + * One of low, medium, high, or auto. Default: auto. + */ + quality?: "auto" | "low" | "medium" | "high" + + /** + * The size of the generated image. + * One of 1024x1024, 1024x1536, 1536x1024, or auto. + * Default: auto. + */ + size?: "auto" | "1024x1024" | "1024x1536" | "1536x1024" +} + +const imageGenerationToolFactory = createProviderDefinedToolFactoryWithOutputSchema< + {}, + { + /** + * The generated image encoded in base64. + */ + result: string + }, + ImageGenerationArgs +>({ + id: "openai.image_generation", + name: "image_generation", + inputSchema: z.object({}), + outputSchema: imageGenerationOutputSchema, +}) + +export const imageGeneration = ( + args: ImageGenerationArgs = {}, // default +) => { + return imageGenerationToolFactory(args) +} diff --git a/packages/opencode/src/provider/sdk/copilot/responses/tool/local-shell.ts b/packages/opencode/src/provider/sdk/copilot/responses/tool/local-shell.ts new file mode 100644 index 00000000000..4ceca0d6cd8 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/tool/local-shell.ts @@ -0,0 +1,65 @@ +import { createProviderDefinedToolFactoryWithOutputSchema } from "@ai-sdk/provider-utils" +import { z } from "zod/v4" + +export const localShellInputSchema = z.object({ + action: z.object({ + type: z.literal("exec"), + command: z.array(z.string()), + timeoutMs: z.number().optional(), + user: z.string().optional(), + workingDirectory: z.string().optional(), + env: z.record(z.string(), z.string()).optional(), + }), +}) + +export const localShellOutputSchema = z.object({ + output: z.string(), +}) + +export const localShell = createProviderDefinedToolFactoryWithOutputSchema< + { + /** + * Execute a shell command on the server. + */ + action: { + type: "exec" + + /** + * The command to run. + */ + command: string[] + + /** + * Optional timeout in milliseconds for the command. + */ + timeoutMs?: number + + /** + * Optional user to run the command as. + */ + user?: string + + /** + * Optional working directory to run the command in. + */ + workingDirectory?: string + + /** + * Environment variables to set for the command. + */ + env?: Record + } + }, + { + /** + * The output of local shell tool call. + */ + output: string + }, + {} +>({ + id: "openai.local_shell", + name: "local_shell", + inputSchema: localShellInputSchema, + outputSchema: localShellOutputSchema, +}) diff --git a/packages/opencode/src/provider/sdk/copilot/responses/tool/web-search-preview.ts b/packages/opencode/src/provider/sdk/copilot/responses/tool/web-search-preview.ts new file mode 100644 index 00000000000..69ea65ef0e5 --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/tool/web-search-preview.ts @@ -0,0 +1,104 @@ +import { createProviderDefinedToolFactory } from "@ai-sdk/provider-utils" +import { z } from "zod/v4" + +// Args validation schema +export const webSearchPreviewArgsSchema = z.object({ + /** + * Search context size to use for the web search. + * - high: Most comprehensive context, highest cost, slower response + * - medium: Balanced context, cost, and latency (default) + * - low: Least context, lowest cost, fastest response + */ + searchContextSize: z.enum(["low", "medium", "high"]).optional(), + + /** + * User location information to provide geographically relevant search results. + */ + userLocation: z + .object({ + /** + * Type of location (always 'approximate') + */ + type: z.literal("approximate"), + /** + * Two-letter ISO country code (e.g., 'US', 'GB') + */ + country: z.string().optional(), + /** + * City name (free text, e.g., 'Minneapolis') + */ + city: z.string().optional(), + /** + * Region name (free text, e.g., 'Minnesota') + */ + region: z.string().optional(), + /** + * IANA timezone (e.g., 'America/Chicago') + */ + timezone: z.string().optional(), + }) + .optional(), +}) + +export const webSearchPreview = createProviderDefinedToolFactory< + { + // Web search doesn't take input parameters - it's controlled by the prompt + }, + { + /** + * Search context size to use for the web search. + * - high: Most comprehensive context, highest cost, slower response + * - medium: Balanced context, cost, and latency (default) + * - low: Least context, lowest cost, fastest response + */ + searchContextSize?: "low" | "medium" | "high" + + /** + * User location information to provide geographically relevant search results. + */ + userLocation?: { + /** + * Type of location (always 'approximate') + */ + type: "approximate" + /** + * Two-letter ISO country code (e.g., 'US', 'GB') + */ + country?: string + /** + * City name (free text, e.g., 'Minneapolis') + */ + city?: string + /** + * Region name (free text, e.g., 'Minnesota') + */ + region?: string + /** + * IANA timezone (e.g., 'America/Chicago') + */ + timezone?: string + } + } +>({ + id: "openai.web_search_preview", + name: "web_search_preview", + inputSchema: z.object({ + action: z + .discriminatedUnion("type", [ + z.object({ + type: z.literal("search"), + query: z.string().nullish(), + }), + z.object({ + type: z.literal("open_page"), + url: z.string(), + }), + z.object({ + type: z.literal("find"), + url: z.string(), + pattern: z.string(), + }), + ]) + .nullish(), + }), +}) diff --git a/packages/opencode/src/provider/sdk/copilot/responses/tool/web-search.ts b/packages/opencode/src/provider/sdk/copilot/responses/tool/web-search.ts new file mode 100644 index 00000000000..89622ad3cea --- /dev/null +++ b/packages/opencode/src/provider/sdk/copilot/responses/tool/web-search.ts @@ -0,0 +1,103 @@ +import { createProviderDefinedToolFactory } from "@ai-sdk/provider-utils" +import { z } from "zod/v4" + +export const webSearchArgsSchema = z.object({ + filters: z + .object({ + allowedDomains: z.array(z.string()).optional(), + }) + .optional(), + + searchContextSize: z.enum(["low", "medium", "high"]).optional(), + + userLocation: z + .object({ + type: z.literal("approximate"), + country: z.string().optional(), + city: z.string().optional(), + region: z.string().optional(), + timezone: z.string().optional(), + }) + .optional(), +}) + +export const webSearchToolFactory = createProviderDefinedToolFactory< + { + // Web search doesn't take input parameters - it's controlled by the prompt + }, + { + /** + * Filters for the search. + */ + filters?: { + /** + * Allowed domains for the search. + * If not provided, all domains are allowed. + * Subdomains of the provided domains are allowed as well. + */ + allowedDomains?: string[] + } + + /** + * Search context size to use for the web search. + * - high: Most comprehensive context, highest cost, slower response + * - medium: Balanced context, cost, and latency (default) + * - low: Least context, lowest cost, fastest response + */ + searchContextSize?: "low" | "medium" | "high" + + /** + * User location information to provide geographically relevant search results. + */ + userLocation?: { + /** + * Type of location (always 'approximate') + */ + type: "approximate" + /** + * Two-letter ISO country code (e.g., 'US', 'GB') + */ + country?: string + /** + * City name (free text, e.g., 'Minneapolis') + */ + city?: string + /** + * Region name (free text, e.g., 'Minnesota') + */ + region?: string + /** + * IANA timezone (e.g., 'America/Chicago') + */ + timezone?: string + } + } +>({ + id: "openai.web_search", + name: "web_search", + inputSchema: z.object({ + action: z + .discriminatedUnion("type", [ + z.object({ + type: z.literal("search"), + query: z.string().nullish(), + }), + z.object({ + type: z.literal("open_page"), + url: z.string(), + }), + z.object({ + type: z.literal("find"), + url: z.string(), + pattern: z.string(), + }), + ]) + .nullish(), + }), +}) + +export const webSearch = ( + args: Parameters[0] = {}, // default +) => { + return webSearchToolFactory(args) +} diff --git a/packages/opencode/src/session/prompt/trinity.txt b/packages/opencode/src/session/prompt/trinity.txt new file mode 100644 index 00000000000..28ee4c4f269 --- /dev/null +++ b/packages/opencode/src/session/prompt/trinity.txt @@ -0,0 +1,97 @@ +You are opencode, an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user. + +# Tone and style +You should be concise, direct, and to the point. When you run a non-trivial bash command, you should explain what the command does and why you are running it, to make sure the user understands what you are doing (this is especially important when you are running a command that will make changes to the user's system). +Remember that your output will be displayed on a command line interface. Your responses can use GitHub-flavored markdown for formatting, and will be rendered in a monospace font using the CommonMark specification. +Output text to communicate with the user; all text you output outside of tool use is displayed to the user. Only use tools to complete tasks. Never use tools like Bash or code comments as means to communicate with the user during the session. +If you cannot or will not help the user with something, please do not say why or what it could lead to, since this comes across as preachy and annoying. Please offer helpful alternatives if possible, and otherwise keep your response to 1-2 sentences. +Only use emojis if the user explicitly requests it. Avoid using emojis in all communication unless asked. +IMPORTANT: You should minimize output tokens as much as possible while maintaining helpfulness, quality, and accuracy. Only address the specific query or task at hand, avoiding tangential information unless absolutely critical for completing the request. If you can answer in 1-3 sentences or a short paragraph, please do. +IMPORTANT: You should NOT answer with unnecessary preamble or postamble (such as explaining your code or summarizing your action), unless the user asks you to. +IMPORTANT: Keep your responses short, since they will be displayed on a command line interface. You MUST answer concisely with fewer than 4 lines (not including tool use or code generation), unless user asks for detail. Answer the user's question directly, without elaboration, explanation, or details. One word answers are best. Avoid introductions, conclusions, and explanations. You MUST avoid text before/after your response, such as "The answer is .", "Here is the content of the file..." or "Based on the information provided, the answer is..." or "Here is what I will do next...". Here are some examples to demonstrate appropriate verbosity: + +user: 2 + 2 +assistant: 4 + + + +user: what is 2+2? +assistant: 4 + + + +user: is 11 a prime number? +assistant: Yes + + + +user: what command should I run to list files in the current directory? +assistant: ls + + + +user: what command should I run to watch files in the current directory? +assistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files] +npm run dev + + + +user: How many golf balls fit inside a jetta? +assistant: 150000 + + + +user: what files are in the directory src/? +assistant: [runs ls and sees foo.c, bar.c, baz.c] +user: which file contains the implementation of foo? +assistant: src/foo.c + + + +user: write tests for new feature +assistant: [uses grep or glob to find where similar tests are defined, then read relevant files one at a time (one tool per message, wait for each result), then edit or write to add tests] + + +# Proactiveness +You are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between: +1. Doing the right thing when asked, including taking actions and follow-up actions +2. Not surprising the user with actions you take without asking +For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions. +3. Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did. + +# Following conventions +When making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns. +- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language). +- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions. +- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic. +- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository. + +# Code style +- IMPORTANT: DO NOT ADD ***ANY*** COMMENTS unless asked + +# Doing tasks +The user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended: +- Use the available search tools to understand the codebase and the user's query. Use one tool per message; after each result, decide the next step and call one tool again. +- Implement the solution using all tools available to you +- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach. +- VERY IMPORTANT: When you have completed a task, you MUST run the lint and typecheck commands (e.g. npm run lint, npm run typecheck, ruff, etc.) with Bash if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to AGENTS.md so that you will know to run it next time. +NEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked, otherwise the user will feel that you are being too proactive. + +- Tool results and user messages may include tags. tags contain useful information and reminders. They are NOT part of the user's provided input or the tool result. + +# Tool usage policy +- When doing file search, prefer to use the Task tool in order to reduce context usage. +- Use exactly one tool per assistant message. After each tool call, wait for the result before continuing. +- When the user's request is vague, use the question tool to clarify before reading files or making changes. +- Avoid repeating the same tool with the same parameters once you have useful results. Use the result to take the next step (e.g. pick one match, read that file, then act); do not search again in a loop. + +You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail. + +# Code References + +When referencing specific functions or pieces of code include the pattern `file_path:line_number` to allow the user to easily navigate to the source code location. + + +user: Where are errors from the client handled? +assistant: Clients are marked as failed in the `connectToServer` function in src/services/process.ts:712. + diff --git a/packages/opencode/src/skill/discovery.ts b/packages/opencode/src/skill/discovery.ts new file mode 100644 index 00000000000..a4bf97d7a1b --- /dev/null +++ b/packages/opencode/src/skill/discovery.ts @@ -0,0 +1,97 @@ +import path from "path" +import { mkdir } from "fs/promises" +import { Log } from "../util/log" +import { Global } from "../global" + +export namespace Discovery { + const log = Log.create({ service: "skill-discovery" }) + + type Index = { + skills: Array<{ + name: string + description: string + files: string[] + }> + } + + export function dir() { + return path.join(Global.Path.cache, "skills") + } + + async function get(url: string, dest: string): Promise { + if (await Bun.file(dest).exists()) return true + return fetch(url) + .then(async (response) => { + if (!response.ok) { + log.error("failed to download", { url, status: response.status }) + return false + } + await Bun.write(dest, await response.text()) + return true + }) + .catch((err) => { + log.error("failed to download", { url, err }) + return false + }) + } + + export async function pull(url: string): Promise { + const result: string[] = [] + const base = url.endsWith("/") ? url : `${url}/` + const index = new URL("index.json", base).href + const cache = dir() + const host = base.slice(0, -1) + + log.info("fetching index", { url: index }) + const data = await fetch(index) + .then(async (response) => { + if (!response.ok) { + log.error("failed to fetch index", { url: index, status: response.status }) + return undefined + } + return response + .json() + .then((json) => json as Index) + .catch((err) => { + log.error("failed to parse index", { url: index, err }) + return undefined + }) + }) + .catch((err) => { + log.error("failed to fetch index", { url: index, err }) + return undefined + }) + + if (!data?.skills || !Array.isArray(data.skills)) { + log.warn("invalid index format", { url: index }) + return result + } + + const list = data.skills.filter((skill) => { + if (!skill?.name || !Array.isArray(skill.files)) { + log.warn("invalid skill entry", { url: index, skill }) + return false + } + return true + }) + + await Promise.all( + list.map(async (skill) => { + const root = path.join(cache, skill.name) + await Promise.all( + skill.files.map(async (file) => { + const link = new URL(file, `${host}/${skill.name}/`).href + const dest = path.join(root, file) + await mkdir(path.dirname(dest), { recursive: true }) + await get(link, dest) + }), + ) + + const md = path.join(root, "SKILL.md") + if (await Bun.file(md).exists()) result.push(root) + }), + ) + + return result + } +} diff --git a/packages/opencode/src/util/abort.ts b/packages/opencode/src/util/abort.ts new file mode 100644 index 00000000000..3e7cfd8b28b --- /dev/null +++ b/packages/opencode/src/util/abort.ts @@ -0,0 +1,35 @@ +/** + * Creates an AbortController that automatically aborts after a timeout. + * + * Uses bind() instead of arrow functions to avoid capturing the surrounding + * scope in closures. Arrow functions like `() => controller.abort()` capture + * request bodies and other large objects, preventing GC for the timer lifetime. + * + * @param ms Timeout in milliseconds + * @returns Object with controller, signal, and clearTimeout function + */ +export function abortAfter(ms: number) { + const controller = new AbortController() + const id = setTimeout(controller.abort.bind(controller), ms) + return { + controller, + signal: controller.signal, + clearTimeout: () => globalThis.clearTimeout(id), + } +} + +/** + * Combines multiple AbortSignals with a timeout. + * + * @param ms Timeout in milliseconds + * @param signals Additional signals to combine + * @returns Combined signal that aborts on timeout or when any input signal aborts + */ +export function abortAfterAny(ms: number, ...signals: AbortSignal[]) { + const timeout = abortAfter(ms) + const signal = AbortSignal.any([timeout.signal, ...signals]) + return { + signal, + clearTimeout: timeout.clearTimeout, + } +} diff --git a/packages/opencode/src/util/proxied.ts b/packages/opencode/src/util/proxied.ts new file mode 100644 index 00000000000..440a9cccedb --- /dev/null +++ b/packages/opencode/src/util/proxied.ts @@ -0,0 +1,3 @@ +export function proxied() { + return !!(process.env.HTTP_PROXY || process.env.HTTPS_PROXY || process.env.http_proxy || process.env.https_proxy) +} diff --git a/packages/opencode/test/cli/import.test.ts b/packages/opencode/test/cli/import.test.ts new file mode 100644 index 00000000000..a1a69dc0941 --- /dev/null +++ b/packages/opencode/test/cli/import.test.ts @@ -0,0 +1,38 @@ +import { test, expect } from "bun:test" +import { parseShareUrl, transformShareData, type ShareData } from "../../src/cli/cmd/import" + +// parseShareUrl tests +test("parses valid share URLs", () => { + expect(parseShareUrl("https://opncd.ai/share/Jsj3hNIW")).toBe("Jsj3hNIW") + expect(parseShareUrl("https://custom.example.com/share/abc123")).toBe("abc123") + expect(parseShareUrl("http://localhost:3000/share/test_id-123")).toBe("test_id-123") +}) + +test("rejects invalid URLs", () => { + expect(parseShareUrl("https://opncd.ai/s/Jsj3hNIW")).toBeNull() // legacy format + expect(parseShareUrl("https://opncd.ai/share/")).toBeNull() + expect(parseShareUrl("https://opncd.ai/share/id/extra")).toBeNull() + expect(parseShareUrl("not-a-url")).toBeNull() +}) + +// transformShareData tests +test("transforms share data to storage format", () => { + const data: ShareData[] = [ + { type: "session", data: { id: "sess-1", title: "Test" } as any }, + { type: "message", data: { id: "msg-1", sessionID: "sess-1" } as any }, + { type: "part", data: { id: "part-1", messageID: "msg-1" } as any }, + { type: "part", data: { id: "part-2", messageID: "msg-1" } as any }, + ] + + const result = transformShareData(data)! + + expect(result.info.id).toBe("sess-1") + expect(result.messages).toHaveLength(1) + expect(result.messages[0].parts).toHaveLength(2) +}) + +test("returns null for invalid share data", () => { + expect(transformShareData([])).toBeNull() + expect(transformShareData([{ type: "message", data: {} as any }])).toBeNull() + expect(transformShareData([{ type: "session", data: { id: "s" } as any }])).toBeNull() // no messages +}) diff --git a/packages/opencode/test/file/ripgrep.test.ts b/packages/opencode/test/file/ripgrep.test.ts new file mode 100644 index 00000000000..ac46f1131b0 --- /dev/null +++ b/packages/opencode/test/file/ripgrep.test.ts @@ -0,0 +1,39 @@ +import { describe, expect, test } from "bun:test" +import fs from "fs/promises" +import path from "path" +import { tmpdir } from "../fixture/fixture" +import { Ripgrep } from "../../src/file/ripgrep" + +describe("file.ripgrep", () => { + test("defaults to include hidden", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + await Bun.write(path.join(dir, "visible.txt"), "hello") + await fs.mkdir(path.join(dir, ".opencode"), { recursive: true }) + await Bun.write(path.join(dir, ".opencode", "thing.json"), "{}") + }, + }) + + const files = await Array.fromAsync(Ripgrep.files({ cwd: tmp.path })) + const hasVisible = files.includes("visible.txt") + const hasHidden = files.includes(path.join(".opencode", "thing.json")) + expect(hasVisible).toBe(true) + expect(hasHidden).toBe(true) + }) + + test("hidden false excludes hidden", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + await Bun.write(path.join(dir, "visible.txt"), "hello") + await fs.mkdir(path.join(dir, ".opencode"), { recursive: true }) + await Bun.write(path.join(dir, ".opencode", "thing.json"), "{}") + }, + }) + + const files = await Array.fromAsync(Ripgrep.files({ cwd: tmp.path, hidden: false })) + const hasVisible = files.includes("visible.txt") + const hasHidden = files.includes(path.join(".opencode", "thing.json")) + expect(hasVisible).toBe(true) + expect(hasHidden).toBe(false) + }) +}) diff --git a/packages/opencode/test/memory/abort-leak.test.ts b/packages/opencode/test/memory/abort-leak.test.ts new file mode 100644 index 00000000000..b202c9127a8 --- /dev/null +++ b/packages/opencode/test/memory/abort-leak.test.ts @@ -0,0 +1,136 @@ +import { describe, test, expect } from "bun:test" +import path from "path" +import { Instance } from "../../src/project/instance" +import { WebFetchTool } from "../../src/tool/webfetch" + +const projectRoot = path.join(__dirname, "../..") + +const ctx = { + sessionID: "test", + messageID: "", + callID: "", + agent: "build", + abort: new AbortController().signal, + messages: [], + metadata: () => {}, + ask: async () => {}, +} + +const MB = 1024 * 1024 +const ITERATIONS = 50 + +const getHeapMB = () => { + Bun.gc(true) + return process.memoryUsage().heapUsed / MB +} + +describe("memory: abort controller leak", () => { + test("webfetch does not leak memory over many invocations", async () => { + await Instance.provide({ + directory: projectRoot, + fn: async () => { + const tool = await WebFetchTool.init() + + // Warm up + await tool.execute({ url: "https://example.com", format: "text" }, ctx).catch(() => {}) + + Bun.gc(true) + const baseline = getHeapMB() + + // Run many fetches + for (let i = 0; i < ITERATIONS; i++) { + await tool.execute({ url: "https://example.com", format: "text" }, ctx).catch(() => {}) + } + + Bun.gc(true) + const after = getHeapMB() + const growth = after - baseline + + console.log(`Baseline: ${baseline.toFixed(2)} MB`) + console.log(`After ${ITERATIONS} fetches: ${after.toFixed(2)} MB`) + console.log(`Growth: ${growth.toFixed(2)} MB`) + + // Memory growth should be minimal - less than 1MB per 10 requests + // With the old closure pattern, this would grow ~0.5MB per request + expect(growth).toBeLessThan(ITERATIONS / 10) + }, + }) + }, 60000) + + test("compare closure vs bind pattern directly", async () => { + const ITERATIONS = 500 + + // Test OLD pattern: arrow function closure + // Store closures in a map keyed by content to force retention + const closureMap = new Map void>() + const timers: Timer[] = [] + const controllers: AbortController[] = [] + + Bun.gc(true) + Bun.sleepSync(100) + const baseline = getHeapMB() + + for (let i = 0; i < ITERATIONS; i++) { + // Simulate large response body like webfetch would have + const content = `${i}:${"x".repeat(50 * 1024)}` // 50KB unique per iteration + const controller = new AbortController() + controllers.push(controller) + + // OLD pattern - closure captures `content` + const handler = () => { + // Actually use content so it can't be optimized away + if (content.length > 1000000000) controller.abort() + } + closureMap.set(content, handler) + const timeoutId = setTimeout(handler, 30000) + timers.push(timeoutId) + } + + Bun.gc(true) + Bun.sleepSync(100) + const after = getHeapMB() + const oldGrowth = after - baseline + + console.log(`OLD pattern (closure): ${oldGrowth.toFixed(2)} MB growth (${closureMap.size} closures)`) + + // Cleanup after measuring + timers.forEach(clearTimeout) + controllers.forEach((c) => c.abort()) + closureMap.clear() + + // Test NEW pattern: bind + Bun.gc(true) + Bun.sleepSync(100) + const baseline2 = getHeapMB() + const handlers2: (() => void)[] = [] + const timers2: Timer[] = [] + const controllers2: AbortController[] = [] + + for (let i = 0; i < ITERATIONS; i++) { + const _content = `${i}:${"x".repeat(50 * 1024)}` // 50KB - won't be captured + const controller = new AbortController() + controllers2.push(controller) + + // NEW pattern - bind doesn't capture surrounding scope + const handler = controller.abort.bind(controller) + handlers2.push(handler) + const timeoutId = setTimeout(handler, 30000) + timers2.push(timeoutId) + } + + Bun.gc(true) + Bun.sleepSync(100) + const after2 = getHeapMB() + const newGrowth = after2 - baseline2 + + // Cleanup after measuring + timers2.forEach(clearTimeout) + controllers2.forEach((c) => c.abort()) + handlers2.length = 0 + + console.log(`NEW pattern (bind): ${newGrowth.toFixed(2)} MB growth`) + console.log(`Improvement: ${(oldGrowth - newGrowth).toFixed(2)} MB saved`) + + expect(newGrowth).toBeLessThanOrEqual(oldGrowth) + }) +}) diff --git a/packages/opencode/test/plugin/auth-override.test.ts b/packages/opencode/test/plugin/auth-override.test.ts new file mode 100644 index 00000000000..d8f8ea4551b --- /dev/null +++ b/packages/opencode/test/plugin/auth-override.test.ts @@ -0,0 +1,44 @@ +import { describe, expect, test } from "bun:test" +import path from "path" +import fs from "fs/promises" +import { tmpdir } from "../fixture/fixture" +import { Instance } from "../../src/project/instance" +import { ProviderAuth } from "../../src/provider/auth" + +describe("plugin.auth-override", () => { + test("user plugin overrides built-in github-copilot auth", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + const pluginDir = path.join(dir, ".opencode", "plugin") + await fs.mkdir(pluginDir, { recursive: true }) + + await Bun.write( + path.join(pluginDir, "custom-copilot-auth.ts"), + [ + "export default async () => ({", + " auth: {", + ' provider: "github-copilot",', + " methods: [", + ' { type: "api", label: "Test Override Auth" },', + " ],", + " loader: async () => ({ access: 'test-token' }),", + " },", + "})", + "", + ].join("\n"), + ) + }, + }) + + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const methods = await ProviderAuth.methods() + const copilot = methods["github-copilot"] + expect(copilot).toBeDefined() + expect(copilot.length).toBe(1) + expect(copilot[0].label).toBe("Test Override Auth") + }, + }) + }, 30000) // Increased timeout for plugin installation +}) diff --git a/packages/opencode/test/provider/copilot/convert-to-copilot-messages.test.ts b/packages/opencode/test/provider/copilot/convert-to-copilot-messages.test.ts new file mode 100644 index 00000000000..6f874db6d2e --- /dev/null +++ b/packages/opencode/test/provider/copilot/convert-to-copilot-messages.test.ts @@ -0,0 +1,523 @@ +import { convertToOpenAICompatibleChatMessages as convertToCopilotMessages } from "@/provider/sdk/copilot/chat/convert-to-openai-compatible-chat-messages" +import { describe, test, expect } from "bun:test" + +describe("system messages", () => { + test("should convert system message content to string", () => { + const result = convertToCopilotMessages([ + { + role: "system", + content: "You are a helpful assistant with AGENTS.md instructions.", + }, + ]) + + expect(result).toEqual([ + { + role: "system", + content: "You are a helpful assistant with AGENTS.md instructions.", + }, + ]) + }) +}) + +describe("user messages", () => { + test("should convert messages with only a text part to a string content", () => { + const result = convertToCopilotMessages([ + { + role: "user", + content: [{ type: "text", text: "Hello" }], + }, + ]) + + expect(result).toEqual([{ role: "user", content: "Hello" }]) + }) + + test("should convert messages with image parts", () => { + const result = convertToCopilotMessages([ + { + role: "user", + content: [ + { type: "text", text: "Hello" }, + { + type: "file", + data: Buffer.from([0, 1, 2, 3]).toString("base64"), + mediaType: "image/png", + }, + ], + }, + ]) + + expect(result).toEqual([ + { + role: "user", + content: [ + { type: "text", text: "Hello" }, + { + type: "image_url", + image_url: { url: "data:image/png;base64,AAECAw==" }, + }, + ], + }, + ]) + }) + + test("should convert messages with image parts from Uint8Array", () => { + const result = convertToCopilotMessages([ + { + role: "user", + content: [ + { type: "text", text: "Hi" }, + { + type: "file", + data: new Uint8Array([0, 1, 2, 3]), + mediaType: "image/png", + }, + ], + }, + ]) + + expect(result).toEqual([ + { + role: "user", + content: [ + { type: "text", text: "Hi" }, + { + type: "image_url", + image_url: { url: "data:image/png;base64,AAECAw==" }, + }, + ], + }, + ]) + }) + + test("should handle URL-based images", () => { + const result = convertToCopilotMessages([ + { + role: "user", + content: [ + { + type: "file", + data: new URL("https://example.com/image.jpg"), + mediaType: "image/*", + }, + ], + }, + ]) + + expect(result).toEqual([ + { + role: "user", + content: [ + { + type: "image_url", + image_url: { url: "https://example.com/image.jpg" }, + }, + ], + }, + ]) + }) + + test("should handle multiple text parts without flattening", () => { + const result = convertToCopilotMessages([ + { + role: "user", + content: [ + { type: "text", text: "Part 1" }, + { type: "text", text: "Part 2" }, + ], + }, + ]) + + expect(result).toEqual([ + { + role: "user", + content: [ + { type: "text", text: "Part 1" }, + { type: "text", text: "Part 2" }, + ], + }, + ]) + }) +}) + +describe("assistant messages", () => { + test("should convert assistant text messages", () => { + const result = convertToCopilotMessages([ + { + role: "assistant", + content: [{ type: "text", text: "Hello back!" }], + }, + ]) + + expect(result).toEqual([ + { + role: "assistant", + content: "Hello back!", + tool_calls: undefined, + reasoning_text: undefined, + reasoning_opaque: undefined, + }, + ]) + }) + + test("should handle assistant message with null content when only tool calls", () => { + const result = convertToCopilotMessages([ + { + role: "assistant", + content: [ + { + type: "tool-call", + toolCallId: "call1", + toolName: "calculator", + input: { a: 1, b: 2 }, + }, + ], + }, + ]) + + expect(result).toEqual([ + { + role: "assistant", + content: null, + tool_calls: [ + { + id: "call1", + type: "function", + function: { + name: "calculator", + arguments: JSON.stringify({ a: 1, b: 2 }), + }, + }, + ], + reasoning_text: undefined, + reasoning_opaque: undefined, + }, + ]) + }) + + test("should concatenate multiple text parts", () => { + const result = convertToCopilotMessages([ + { + role: "assistant", + content: [ + { type: "text", text: "First part. " }, + { type: "text", text: "Second part." }, + ], + }, + ]) + + expect(result[0].content).toBe("First part. Second part.") + }) +}) + +describe("tool calls", () => { + test("should stringify arguments to tool calls", () => { + const result = convertToCopilotMessages([ + { + role: "assistant", + content: [ + { + type: "tool-call", + input: { foo: "bar123" }, + toolCallId: "quux", + toolName: "thwomp", + }, + ], + }, + { + role: "tool", + content: [ + { + type: "tool-result", + toolCallId: "quux", + toolName: "thwomp", + output: { type: "json", value: { oof: "321rab" } }, + }, + ], + }, + ]) + + expect(result).toEqual([ + { + role: "assistant", + content: null, + tool_calls: [ + { + id: "quux", + type: "function", + function: { + name: "thwomp", + arguments: JSON.stringify({ foo: "bar123" }), + }, + }, + ], + reasoning_text: undefined, + reasoning_opaque: undefined, + }, + { + role: "tool", + tool_call_id: "quux", + content: JSON.stringify({ oof: "321rab" }), + }, + ]) + }) + + test("should handle text output type in tool results", () => { + const result = convertToCopilotMessages([ + { + role: "tool", + content: [ + { + type: "tool-result", + toolCallId: "call-1", + toolName: "getWeather", + output: { type: "text", value: "It is sunny today" }, + }, + ], + }, + ]) + + expect(result).toEqual([ + { + role: "tool", + tool_call_id: "call-1", + content: "It is sunny today", + }, + ]) + }) + + test("should handle multiple tool results as separate messages", () => { + const result = convertToCopilotMessages([ + { + role: "tool", + content: [ + { + type: "tool-result", + toolCallId: "call1", + toolName: "api1", + output: { type: "text", value: "Result 1" }, + }, + { + type: "tool-result", + toolCallId: "call2", + toolName: "api2", + output: { type: "text", value: "Result 2" }, + }, + ], + }, + ]) + + expect(result).toHaveLength(2) + expect(result[0]).toEqual({ + role: "tool", + tool_call_id: "call1", + content: "Result 1", + }) + expect(result[1]).toEqual({ + role: "tool", + tool_call_id: "call2", + content: "Result 2", + }) + }) + + test("should handle text plus multiple tool calls", () => { + const result = convertToCopilotMessages([ + { + role: "assistant", + content: [ + { type: "text", text: "Checking... " }, + { + type: "tool-call", + toolCallId: "call1", + toolName: "searchTool", + input: { query: "Weather" }, + }, + { type: "text", text: "Almost there..." }, + { + type: "tool-call", + toolCallId: "call2", + toolName: "mapsTool", + input: { location: "Paris" }, + }, + ], + }, + ]) + + expect(result).toEqual([ + { + role: "assistant", + content: "Checking... Almost there...", + tool_calls: [ + { + id: "call1", + type: "function", + function: { + name: "searchTool", + arguments: JSON.stringify({ query: "Weather" }), + }, + }, + { + id: "call2", + type: "function", + function: { + name: "mapsTool", + arguments: JSON.stringify({ location: "Paris" }), + }, + }, + ], + reasoning_text: undefined, + reasoning_opaque: undefined, + }, + ]) + }) +}) + +describe("reasoning (copilot-specific)", () => { + test("should omit reasoning_text without reasoning_opaque", () => { + const result = convertToCopilotMessages([ + { + role: "assistant", + content: [ + { type: "reasoning", text: "Let me think about this..." }, + { type: "text", text: "The answer is 42." }, + ], + }, + ]) + + expect(result).toEqual([ + { + role: "assistant", + content: "The answer is 42.", + tool_calls: undefined, + reasoning_text: undefined, + reasoning_opaque: undefined, + }, + ]) + }) + + test("should include reasoning_opaque from providerOptions", () => { + const result = convertToCopilotMessages([ + { + role: "assistant", + content: [ + { + type: "reasoning", + text: "Thinking...", + providerOptions: { + copilot: { reasoningOpaque: "opaque-signature-123" }, + }, + }, + { type: "text", text: "Done!" }, + ], + }, + ]) + + expect(result).toEqual([ + { + role: "assistant", + content: "Done!", + tool_calls: undefined, + reasoning_text: "Thinking...", + reasoning_opaque: "opaque-signature-123", + }, + ]) + }) + + test("should include reasoning_opaque from text part providerOptions", () => { + const result = convertToCopilotMessages([ + { + role: "assistant", + content: [ + { + type: "text", + text: "Done!", + providerOptions: { + copilot: { reasoningOpaque: "opaque-text-456" }, + }, + }, + ], + }, + ]) + + expect(result).toEqual([ + { + role: "assistant", + content: "Done!", + tool_calls: undefined, + reasoning_text: undefined, + reasoning_opaque: "opaque-text-456", + }, + ]) + }) + + test("should handle reasoning-only assistant message", () => { + const result = convertToCopilotMessages([ + { + role: "assistant", + content: [ + { + type: "reasoning", + text: "Just thinking, no response yet", + providerOptions: { + copilot: { reasoningOpaque: "sig-abc" }, + }, + }, + ], + }, + ]) + + expect(result).toEqual([ + { + role: "assistant", + content: null, + tool_calls: undefined, + reasoning_text: "Just thinking, no response yet", + reasoning_opaque: "sig-abc", + }, + ]) + }) +}) + +describe("full conversation", () => { + test("should convert a multi-turn conversation with reasoning", () => { + const result = convertToCopilotMessages([ + { + role: "system", + content: "You are a helpful assistant.", + }, + { + role: "user", + content: [{ type: "text", text: "What is 2+2?" }], + }, + { + role: "assistant", + content: [ + { + type: "reasoning", + text: "Let me calculate 2+2...", + providerOptions: { + copilot: { reasoningOpaque: "sig-abc" }, + }, + }, + { type: "text", text: "2+2 equals 4." }, + ], + }, + { + role: "user", + content: [{ type: "text", text: "What about 3+3?" }], + }, + ]) + + expect(result).toHaveLength(4) + + const systemMsg = result[0] + expect(systemMsg.role).toBe("system") + + // Assistant message should have reasoning fields + const assistantMsg = result[2] as { + reasoning_text?: string + reasoning_opaque?: string + } + expect(assistantMsg.reasoning_text).toBe("Let me calculate 2+2...") + expect(assistantMsg.reasoning_opaque).toBe("sig-abc") + }) +}) diff --git a/packages/opencode/test/provider/copilot/copilot-chat-model.test.ts b/packages/opencode/test/provider/copilot/copilot-chat-model.test.ts new file mode 100644 index 00000000000..562da4507d3 --- /dev/null +++ b/packages/opencode/test/provider/copilot/copilot-chat-model.test.ts @@ -0,0 +1,592 @@ +import { OpenAICompatibleChatLanguageModel } from "@/provider/sdk/copilot/chat/openai-compatible-chat-language-model" +import { describe, test, expect, mock } from "bun:test" +import type { LanguageModelV2Prompt } from "@ai-sdk/provider" + +async function convertReadableStreamToArray(stream: ReadableStream): Promise { + const reader = stream.getReader() + const result: T[] = [] + while (true) { + const { done, value } = await reader.read() + if (done) break + result.push(value) + } + return result +} + +const TEST_PROMPT: LanguageModelV2Prompt = [{ role: "user", content: [{ type: "text", text: "Hello" }] }] + +// Fixtures from copilot_test.exs +const FIXTURES = { + basicText: [ + `data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1677652288,"model":"gemini-2.0-flash-001","choices":[{"index":0,"delta":{"role":"assistant","content":"Hello"},"finish_reason":null}]}`, + `data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1677652288,"model":"gemini-2.0-flash-001","choices":[{"index":0,"delta":{"content":" world"},"finish_reason":null}]}`, + `data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1677652288,"model":"gemini-2.0-flash-001","choices":[{"index":0,"delta":{"content":"!"},"finish_reason":"stop"}]}`, + `data: [DONE]`, + ], + + reasoningWithToolCalls: [ + `data: {"choices":[{"index":0,"delta":{"content":null,"role":"assistant","reasoning_text":"**Understanding Dayzee's Purpose**\\n\\nI'm starting to get a better handle on \`dayzee\`.\\n\\n"}}],"created":1764940861,"id":"OdwyabKMI9yel7oPlbzgwQM","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-3-pro-preview"}`, + `data: {"choices":[{"index":0,"delta":{"content":null,"role":"assistant","reasoning_text":"**Assessing Dayzee's Functionality**\\n\\nI've reviewed the files.\\n\\n"}}],"created":1764940862,"id":"OdwyabKMI9yel7oPlbzgwQM","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-3-pro-preview"}`, + `data: {"choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\\"filePath\\":\\"/README.md\\"}","name":"read_file"},"id":"call_abc123","index":0,"type":"function"}],"reasoning_opaque":"4CUQ6696CwSXOdQ5rtvDimqA91tBzfmga4ieRbmZ5P67T2NLW3"}}],"created":1764940862,"id":"OdwyabKMI9yel7oPlbzgwQM","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-3-pro-preview"}`, + `data: {"choices":[{"finish_reason":"tool_calls","index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\\"filePath\\":\\"/mix.exs\\"}","name":"read_file"},"id":"call_def456","index":1,"type":"function"}]}}],"created":1764940862,"id":"OdwyabKMI9yel7oPlbzgwQM","usage":{"completion_tokens":53,"prompt_tokens":19581,"prompt_tokens_details":{"cached_tokens":17068},"total_tokens":19768,"reasoning_tokens":134},"model":"gemini-3-pro-preview"}`, + `data: [DONE]`, + ], + + reasoningWithOpaqueAtEnd: [ + `data: {"choices":[{"index":0,"delta":{"content":null,"role":"assistant","reasoning_text":"**Analyzing the Inquiry's Nature**\\n\\nI'm currently parsing the user's question.\\n\\n"}}],"created":1765201729,"id":"Ptc2afqsCIHqlOoP653UiAI","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-3-pro-preview"}`, + `data: {"choices":[{"index":0,"delta":{"content":null,"role":"assistant","reasoning_text":"**Reconciling User's Input**\\n\\nI'm grappling with the context.\\n\\n"}}],"created":1765201730,"id":"Ptc2afqsCIHqlOoP653UiAI","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-3-pro-preview"}`, + `data: {"choices":[{"index":0,"delta":{"content":"I am Tidewave, a highly skilled AI coding agent.\\n\\n","role":"assistant"}}],"created":1765201730,"id":"Ptc2afqsCIHqlOoP653UiAI","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-3-pro-preview"}`, + `data: {"choices":[{"finish_reason":"stop","index":0,"delta":{"content":"How can I help you?","role":"assistant","reasoning_opaque":"/PMlTqxqSJZnUBDHgnnJKLVI4eZQ"}}],"created":1765201730,"id":"Ptc2afqsCIHqlOoP653UiAI","usage":{"completion_tokens":59,"prompt_tokens":5778,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":5932,"reasoning_tokens":95},"model":"gemini-3-pro-preview"}`, + `data: [DONE]`, + ], + + // Case where reasoning_opaque and content come in the SAME chunk + reasoningWithOpaqueAndContentSameChunk: [ + `data: {"choices":[{"index":0,"delta":{"content":null,"role":"assistant","reasoning_text":"**Understanding the Query's Nature**\\n\\nI'm currently grappling with the user's philosophical query.\\n\\n"}}],"created":1766062103,"id":"FPhDacixL9zrlOoPqLSuyQ4","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-2.5-pro"}`, + `data: {"choices":[{"index":0,"delta":{"content":null,"role":"assistant","reasoning_text":"**Framing the Response's Core**\\n\\nNow, I'm structuring my response.\\n\\n"}}],"created":1766062103,"id":"FPhDacixL9zrlOoPqLSuyQ4","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-2.5-pro"}`, + `data: {"choices":[{"index":0,"delta":{"content":"Of course. I'm thinking right now.","role":"assistant","reasoning_opaque":"ExXaGwW7jBo39OXRe9EPoFGN1rOtLJBx"}}],"created":1766062103,"id":"FPhDacixL9zrlOoPqLSuyQ4","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-2.5-pro"}`, + `data: {"choices":[{"finish_reason":"stop","index":0,"delta":{"content":" What's on your mind?","role":"assistant"}}],"created":1766062103,"id":"FPhDacixL9zrlOoPqLSuyQ4","usage":{"completion_tokens":78,"prompt_tokens":3767,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":3915,"reasoning_tokens":70},"model":"gemini-2.5-pro"}`, + `data: [DONE]`, + ], + + // Case where reasoning_opaque and content come in same chunk, followed by tool calls + reasoningWithOpaqueContentAndToolCalls: [ + `data: {"choices":[{"index":0,"delta":{"content":null,"role":"assistant","reasoning_text":"**Analyzing the Structure**\\n\\nI'm currently trying to get a handle on the project's layout. My initial focus is on the file structure itself, specifically the directory organization. I'm hoping this will illuminate how different components interact. I'll need to identify the key modules and their dependencies.\\n\\n\\n"}}],"created":1766066995,"id":"MQtEafqbFYTZsbwPwuCVoAg","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-2.5-pro"}`, + `data: {"choices":[{"index":0,"delta":{"content":"Okay, I need to check out the project's file structure.","role":"assistant","reasoning_opaque":"WHOd3dYFnxEBOsKUXjbX6c2rJa0fS214FHbsj+A3Q+i63SFo7H/92RsownAzyo0h2qEy3cOcrvAatsMx51eCKiMSqt4dYWZhd5YVSgF0CehkpDbWBP/SoRqLU1dhCmUJV/6b5uYFBOzKLBGNadyhI7T1gWFlXntwc6SNjH6DujnFPeVr+L8DdOoUJGJrw2aOfm9NtkXA6wZh9t7dt+831yIIImjD9MHczuXoXj8K7tyLpIJ9KlVXMhnO4IKSYNdKRtoHlGTmudAp5MgH/vLWb6oSsL+ZJl/OdF3WBOeanGhYNoByCRDSvR7anAR/9m5zf9yUax+u/nFg+gzmhFacnzZGtSmcvJ4/4HWKNtUkRASTKeN94DXB8j1ptB/i6ldaMAz2ZyU+sbjPWI8aI4fKJ2MuO01u3uE87xVwpWiM+0rahIzJsllI5edwOaOFtF4tnlCTQafbxHwCZR62uON2E+IjGzW80MzyfYrbLBJKS5zTeHCgPYQSNaKzPfpzkQvdwo3JUnJYcEHgGeKzkq5sbvS5qitCYI7Xue0V98S6/KnUSPnDQBjNnas2i6BqJV2vuCEU/Y3ucrlKVbuRIFCZXCyLzrsGeRLRKlrf5S/HDAQ04IOPQVQhBPvhX0nDjhZB"}}],"created":1766066995,"id":"MQtEafqbFYTZsbwPwuCVoAg","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-2.5-pro"}`, + `data: {"choices":[{"finish_reason":"tool_calls","index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{}","name":"list_project_files"},"id":"call_MHxqRDd5WVo3NU8wUXRaMmc0MFE","index":0,"type":"function"}]}}],"created":1766066995,"id":"MQtEafqbFYTZsbwPwuCVoAg","usage":{"completion_tokens":19,"prompt_tokens":3767,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":3797,"reasoning_tokens":11},"model":"gemini-2.5-pro"}`, + `data: [DONE]`, + ], + + // Case where reasoning goes directly to tool_calls with NO content + // reasoning_opaque and tool_calls come in the same chunk + reasoningDirectlyToToolCalls: [ + `data: {"choices":[{"index":0,"delta":{"content":null,"role":"assistant","reasoning_text":"**Executing and Analyzing HTML**\\n\\nI've successfully captured the HTML snapshot using the \`browser_eval\` tool, giving me a solid understanding of the page structure. Now, I'm shifting focus to Elixir code execution with \`project_eval\` to assess my ability to work within the project's environment.\\n\\n\\n"}}],"created":1766068643,"id":"oBFEaafzD9DVlOoPkY3l4Qs","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-3-pro-preview"}`, + `data: {"choices":[{"index":0,"delta":{"content":null,"role":"assistant","reasoning_text":"**Testing Project Contexts**\\n\\nI've got the HTML body snapshot from \`browser_eval\`, which is a helpful reference. Next, I'm testing my ability to run Elixir code in the project with \`project_eval\`. I'm starting with a simple sum: \`1 + 1\`. This will confirm I'm set up to interact with the project's codebase.\\n\\n\\n"}}],"created":1766068644,"id":"oBFEaafzD9DVlOoPkY3l4Qs","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-3-pro-preview"}`, + `data: {"choices":[{"finish_reason":"tool_calls","index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\\"code\\":\\"1 + 1\\"}","name":"project_eval"},"id":"call_MHw3RDhmT1J5Z3B6WlhpVjlveTc","index":0,"type":"function"}],"reasoning_opaque":"ytGNWFf2doK38peANDvm7whkLPKrd+Fv6/k34zEPBF6Qwitj4bTZT0FBXleydLb6"}}],"created":1766068644,"id":"oBFEaafzD9DVlOoPkY3l4Qs","usage":{"completion_tokens":12,"prompt_tokens":8677,"prompt_tokens_details":{"cached_tokens":3692},"total_tokens":8768,"reasoning_tokens":79},"model":"gemini-3-pro-preview"}`, + `data: [DONE]`, + ], + + reasoningOpaqueWithToolCallsNoReasoningText: [ + `data: {"choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{}","name":"read_file"},"id":"call_reasoning_only","index":0,"type":"function"}],"reasoning_opaque":"opaque-xyz"}}],"created":1769917420,"id":"opaque-only","usage":{"completion_tokens":0,"prompt_tokens":0,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":0,"reasoning_tokens":0},"model":"gemini-3-flash-preview"}`, + `data: {"choices":[{"finish_reason":"tool_calls","index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{}","name":"read_file"},"id":"call_reasoning_only_2","index":1,"type":"function"}]}}],"created":1769917420,"id":"opaque-only","usage":{"completion_tokens":12,"prompt_tokens":123,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":135,"reasoning_tokens":0},"model":"gemini-3-flash-preview"}`, + `data: [DONE]`, + ], +} + +function createMockFetch(chunks: string[]) { + return mock(async () => { + const body = new ReadableStream({ + start(controller) { + for (const chunk of chunks) { + controller.enqueue(new TextEncoder().encode(chunk + "\n\n")) + } + controller.close() + }, + }) + + return new Response(body, { + status: 200, + headers: { "Content-Type": "text/event-stream" }, + }) + }) +} + +function createModel(fetchFn: ReturnType) { + return new OpenAICompatibleChatLanguageModel("test-model", { + provider: "copilot.chat", + url: () => "https://api.test.com/chat/completions", + headers: () => ({ Authorization: "Bearer test-token" }), + fetch: fetchFn as any, + }) +} + +describe("doStream", () => { + test("should stream text deltas", async () => { + const mockFetch = createMockFetch(FIXTURES.basicText) + const model = createModel(mockFetch) + + const { stream } = await model.doStream({ + prompt: TEST_PROMPT, + includeRawChunks: false, + }) + + const parts = await convertReadableStreamToArray(stream) + + // Filter to just the key events + const textParts = parts.filter( + (p) => p.type === "text-start" || p.type === "text-delta" || p.type === "text-end" || p.type === "finish", + ) + + expect(textParts).toMatchObject([ + { type: "text-start", id: "txt-0" }, + { type: "text-delta", id: "txt-0", delta: "Hello" }, + { type: "text-delta", id: "txt-0", delta: " world" }, + { type: "text-delta", id: "txt-0", delta: "!" }, + { type: "text-end", id: "txt-0" }, + { type: "finish", finishReason: "stop" }, + ]) + }) + + test("should stream reasoning with tool calls and capture reasoning_opaque", async () => { + const mockFetch = createMockFetch(FIXTURES.reasoningWithToolCalls) + const model = createModel(mockFetch) + + const { stream } = await model.doStream({ + prompt: TEST_PROMPT, + includeRawChunks: false, + }) + + const parts = await convertReadableStreamToArray(stream) + + // Check reasoning parts + const reasoningParts = parts.filter( + (p) => p.type === "reasoning-start" || p.type === "reasoning-delta" || p.type === "reasoning-end", + ) + + expect(reasoningParts[0]).toEqual({ + type: "reasoning-start", + id: "reasoning-0", + }) + + expect(reasoningParts[1]).toMatchObject({ + type: "reasoning-delta", + id: "reasoning-0", + }) + expect((reasoningParts[1] as { delta: string }).delta).toContain("**Understanding Dayzee's Purpose**") + + expect(reasoningParts[2]).toMatchObject({ + type: "reasoning-delta", + id: "reasoning-0", + }) + expect((reasoningParts[2] as { delta: string }).delta).toContain("**Assessing Dayzee's Functionality**") + + // reasoning_opaque should be in reasoning-end providerMetadata + const reasoningEnd = reasoningParts.find((p) => p.type === "reasoning-end") + expect(reasoningEnd).toMatchObject({ + type: "reasoning-end", + id: "reasoning-0", + providerMetadata: { + copilot: { + reasoningOpaque: "4CUQ6696CwSXOdQ5rtvDimqA91tBzfmga4ieRbmZ5P67T2NLW3", + }, + }, + }) + + // Check tool calls + const toolParts = parts.filter( + (p) => p.type === "tool-input-start" || p.type === "tool-call" || p.type === "tool-input-end", + ) + + expect(toolParts).toContainEqual({ + type: "tool-input-start", + id: "call_abc123", + toolName: "read_file", + }) + + expect(toolParts).toContainEqual( + expect.objectContaining({ + type: "tool-call", + toolCallId: "call_abc123", + toolName: "read_file", + }), + ) + + expect(toolParts).toContainEqual({ + type: "tool-input-start", + id: "call_def456", + toolName: "read_file", + }) + + // Check finish + const finish = parts.find((p) => p.type === "finish") + expect(finish).toMatchObject({ + type: "finish", + finishReason: "tool-calls", + usage: { + inputTokens: 19581, + outputTokens: 53, + }, + }) + }) + + test("should handle reasoning_opaque that comes at end with text in between", async () => { + const mockFetch = createMockFetch(FIXTURES.reasoningWithOpaqueAtEnd) + const model = createModel(mockFetch) + + const { stream } = await model.doStream({ + prompt: TEST_PROMPT, + includeRawChunks: false, + }) + + const parts = await convertReadableStreamToArray(stream) + + // Check that reasoning comes first + const reasoningStart = parts.findIndex((p) => p.type === "reasoning-start") + const textStart = parts.findIndex((p) => p.type === "text-start") + expect(reasoningStart).toBeLessThan(textStart) + + // Check reasoning deltas + const reasoningDeltas = parts.filter((p) => p.type === "reasoning-delta") + expect(reasoningDeltas).toHaveLength(2) + expect((reasoningDeltas[0] as { delta: string }).delta).toContain("**Analyzing the Inquiry's Nature**") + expect((reasoningDeltas[1] as { delta: string }).delta).toContain("**Reconciling User's Input**") + + // Check text deltas + const textDeltas = parts.filter((p) => p.type === "text-delta") + expect(textDeltas).toHaveLength(2) + expect((textDeltas[0] as { delta: string }).delta).toContain("I am Tidewave") + expect((textDeltas[1] as { delta: string }).delta).toContain("How can I help you?") + + // reasoning-end should be emitted before text-start + const reasoningEndIndex = parts.findIndex((p) => p.type === "reasoning-end") + const textStartIndex = parts.findIndex((p) => p.type === "text-start") + expect(reasoningEndIndex).toBeGreaterThan(-1) + expect(reasoningEndIndex).toBeLessThan(textStartIndex) + + // In this fixture, reasoning_opaque comes AFTER content has started (in chunk 4) + // So it arrives too late to be attached to reasoning-end. But it should still + // be captured and included in the finish event's providerMetadata. + const reasoningEnd = parts.find((p) => p.type === "reasoning-end") + expect(reasoningEnd).toMatchObject({ + type: "reasoning-end", + id: "reasoning-0", + }) + + // reasoning_opaque should be in the finish event's providerMetadata + const finish = parts.find((p) => p.type === "finish") + expect(finish).toMatchObject({ + type: "finish", + finishReason: "stop", + usage: { + inputTokens: 5778, + outputTokens: 59, + }, + providerMetadata: { + copilot: { + reasoningOpaque: "/PMlTqxqSJZnUBDHgnnJKLVI4eZQ", + }, + }, + }) + }) + + test("should handle reasoning_opaque and content in the same chunk", async () => { + const mockFetch = createMockFetch(FIXTURES.reasoningWithOpaqueAndContentSameChunk) + const model = createModel(mockFetch) + + const { stream } = await model.doStream({ + prompt: TEST_PROMPT, + includeRawChunks: false, + }) + + const parts = await convertReadableStreamToArray(stream) + + // The critical test: reasoning-end should come BEFORE text-start + const reasoningEndIndex = parts.findIndex((p) => p.type === "reasoning-end") + const textStartIndex = parts.findIndex((p) => p.type === "text-start") + expect(reasoningEndIndex).toBeGreaterThan(-1) + expect(textStartIndex).toBeGreaterThan(-1) + expect(reasoningEndIndex).toBeLessThan(textStartIndex) + + // Check reasoning deltas + const reasoningDeltas = parts.filter((p) => p.type === "reasoning-delta") + expect(reasoningDeltas).toHaveLength(2) + expect((reasoningDeltas[0] as { delta: string }).delta).toContain("**Understanding the Query's Nature**") + expect((reasoningDeltas[1] as { delta: string }).delta).toContain("**Framing the Response's Core**") + + // reasoning_opaque should be in reasoning-end even though it came with content + const reasoningEnd = parts.find((p) => p.type === "reasoning-end") + expect(reasoningEnd).toMatchObject({ + type: "reasoning-end", + id: "reasoning-0", + providerMetadata: { + copilot: { + reasoningOpaque: "ExXaGwW7jBo39OXRe9EPoFGN1rOtLJBx", + }, + }, + }) + + // Check text deltas + const textDeltas = parts.filter((p) => p.type === "text-delta") + expect(textDeltas).toHaveLength(2) + expect((textDeltas[0] as { delta: string }).delta).toContain("Of course. I'm thinking right now.") + expect((textDeltas[1] as { delta: string }).delta).toContain("What's on your mind?") + + // Check finish + const finish = parts.find((p) => p.type === "finish") + expect(finish).toMatchObject({ + type: "finish", + finishReason: "stop", + }) + }) + + test("should handle reasoning_opaque and content followed by tool calls", async () => { + const mockFetch = createMockFetch(FIXTURES.reasoningWithOpaqueContentAndToolCalls) + const model = createModel(mockFetch) + + const { stream } = await model.doStream({ + prompt: TEST_PROMPT, + includeRawChunks: false, + }) + + const parts = await convertReadableStreamToArray(stream) + + // Check that reasoning comes first, then text, then tool calls + const reasoningEndIndex = parts.findIndex((p) => p.type === "reasoning-end") + const textStartIndex = parts.findIndex((p) => p.type === "text-start") + const toolStartIndex = parts.findIndex((p) => p.type === "tool-input-start") + + expect(reasoningEndIndex).toBeGreaterThan(-1) + expect(textStartIndex).toBeGreaterThan(-1) + expect(toolStartIndex).toBeGreaterThan(-1) + expect(reasoningEndIndex).toBeLessThan(textStartIndex) + expect(textStartIndex).toBeLessThan(toolStartIndex) + + // Check reasoning content + const reasoningDeltas = parts.filter((p) => p.type === "reasoning-delta") + expect(reasoningDeltas).toHaveLength(1) + expect((reasoningDeltas[0] as { delta: string }).delta).toContain("**Analyzing the Structure**") + + // reasoning_opaque should be in reasoning-end (comes with content in same chunk) + const reasoningEnd = parts.find((p) => p.type === "reasoning-end") + expect(reasoningEnd).toMatchObject({ + type: "reasoning-end", + id: "reasoning-0", + providerMetadata: { + copilot: { + reasoningOpaque: expect.stringContaining("WHOd3dYFnxEBOsKUXjbX6c2rJa0fS214"), + }, + }, + }) + + // Check text content + const textDeltas = parts.filter((p) => p.type === "text-delta") + expect(textDeltas).toHaveLength(1) + expect((textDeltas[0] as { delta: string }).delta).toContain( + "Okay, I need to check out the project's file structure.", + ) + + // Check tool call + const toolParts = parts.filter( + (p) => p.type === "tool-input-start" || p.type === "tool-call" || p.type === "tool-input-end", + ) + + expect(toolParts).toContainEqual({ + type: "tool-input-start", + id: "call_MHxqRDd5WVo3NU8wUXRaMmc0MFE", + toolName: "list_project_files", + }) + + expect(toolParts).toContainEqual( + expect.objectContaining({ + type: "tool-call", + toolCallId: "call_MHxqRDd5WVo3NU8wUXRaMmc0MFE", + toolName: "list_project_files", + }), + ) + + // Check finish + const finish = parts.find((p) => p.type === "finish") + expect(finish).toMatchObject({ + type: "finish", + finishReason: "tool-calls", + usage: { + inputTokens: 3767, + outputTokens: 19, + }, + }) + }) + + test("should emit reasoning-end before tool-input-start when reasoning goes directly to tool calls", async () => { + const mockFetch = createMockFetch(FIXTURES.reasoningDirectlyToToolCalls) + const model = createModel(mockFetch) + + const { stream } = await model.doStream({ + prompt: TEST_PROMPT, + includeRawChunks: false, + }) + + const parts = await convertReadableStreamToArray(stream) + + // Critical check: reasoning-end MUST come before tool-input-start + const reasoningEndIndex = parts.findIndex((p) => p.type === "reasoning-end") + const toolStartIndex = parts.findIndex((p) => p.type === "tool-input-start") + + expect(reasoningEndIndex).toBeGreaterThan(-1) + expect(toolStartIndex).toBeGreaterThan(-1) + expect(reasoningEndIndex).toBeLessThan(toolStartIndex) + + // Check reasoning parts + const reasoningDeltas = parts.filter((p) => p.type === "reasoning-delta") + expect(reasoningDeltas).toHaveLength(2) + expect((reasoningDeltas[0] as { delta: string }).delta).toContain("**Executing and Analyzing HTML**") + expect((reasoningDeltas[1] as { delta: string }).delta).toContain("**Testing Project Contexts**") + + // reasoning_opaque should be in reasoning-end providerMetadata + const reasoningEnd = parts.find((p) => p.type === "reasoning-end") + expect(reasoningEnd).toMatchObject({ + type: "reasoning-end", + id: "reasoning-0", + providerMetadata: { + copilot: { + reasoningOpaque: "ytGNWFf2doK38peANDvm7whkLPKrd+Fv6/k34zEPBF6Qwitj4bTZT0FBXleydLb6", + }, + }, + }) + + // No text parts should exist + const textParts = parts.filter((p) => p.type === "text-start" || p.type === "text-delta" || p.type === "text-end") + expect(textParts).toHaveLength(0) + + // Check tool call + const toolCall = parts.find((p) => p.type === "tool-call") + expect(toolCall).toMatchObject({ + type: "tool-call", + toolCallId: "call_MHw3RDhmT1J5Z3B6WlhpVjlveTc", + toolName: "project_eval", + }) + + // Check finish + const finish = parts.find((p) => p.type === "finish") + expect(finish).toMatchObject({ + type: "finish", + finishReason: "tool-calls", + }) + }) + + test("should attach reasoning_opaque to tool calls without reasoning_text", async () => { + const mockFetch = createMockFetch(FIXTURES.reasoningOpaqueWithToolCallsNoReasoningText) + const model = createModel(mockFetch) + + const { stream } = await model.doStream({ + prompt: TEST_PROMPT, + includeRawChunks: false, + }) + + const parts = await convertReadableStreamToArray(stream) + const reasoningParts = parts.filter( + (p) => p.type === "reasoning-start" || p.type === "reasoning-delta" || p.type === "reasoning-end", + ) + + expect(reasoningParts).toHaveLength(0) + + const toolCall = parts.find((p) => p.type === "tool-call" && p.toolCallId === "call_reasoning_only") + expect(toolCall).toMatchObject({ + type: "tool-call", + toolCallId: "call_reasoning_only", + toolName: "read_file", + providerMetadata: { + copilot: { + reasoningOpaque: "opaque-xyz", + }, + }, + }) + }) + + test("should include response metadata from first chunk", async () => { + const mockFetch = createMockFetch(FIXTURES.basicText) + const model = createModel(mockFetch) + + const { stream } = await model.doStream({ + prompt: TEST_PROMPT, + includeRawChunks: false, + }) + + const parts = await convertReadableStreamToArray(stream) + + const metadata = parts.find((p) => p.type === "response-metadata") + expect(metadata).toMatchObject({ + type: "response-metadata", + id: "chatcmpl-123", + modelId: "gemini-2.0-flash-001", + }) + }) + + test("should emit stream-start with warnings", async () => { + const mockFetch = createMockFetch(FIXTURES.basicText) + const model = createModel(mockFetch) + + const { stream } = await model.doStream({ + prompt: TEST_PROMPT, + includeRawChunks: false, + }) + + const parts = await convertReadableStreamToArray(stream) + + const streamStart = parts.find((p) => p.type === "stream-start") + expect(streamStart).toEqual({ + type: "stream-start", + warnings: [], + }) + }) + + test("should include raw chunks when requested", async () => { + const mockFetch = createMockFetch(FIXTURES.basicText) + const model = createModel(mockFetch) + + const { stream } = await model.doStream({ + prompt: TEST_PROMPT, + includeRawChunks: true, + }) + + const parts = await convertReadableStreamToArray(stream) + + const rawChunks = parts.filter((p) => p.type === "raw") + expect(rawChunks.length).toBeGreaterThan(0) + }) +}) + +describe("request body", () => { + test("should send tools in OpenAI format", async () => { + let capturedBody: unknown + const mockFetch = mock(async (_url: string, init?: RequestInit) => { + capturedBody = JSON.parse(init?.body as string) + return new Response( + new ReadableStream({ + start(controller) { + controller.enqueue(new TextEncoder().encode(`data: [DONE]\n\n`)) + controller.close() + }, + }), + { status: 200, headers: { "Content-Type": "text/event-stream" } }, + ) + }) + + const model = createModel(mockFetch) + + await model.doStream({ + prompt: TEST_PROMPT, + tools: [ + { + type: "function", + name: "get_weather", + description: "Get the weather for a location", + inputSchema: { + type: "object", + properties: { + location: { type: "string" }, + }, + required: ["location"], + }, + }, + ], + includeRawChunks: false, + }) + + expect((capturedBody as { tools: unknown[] }).tools).toEqual([ + { + type: "function", + function: { + name: "get_weather", + description: "Get the weather for a location", + parameters: { + type: "object", + properties: { + location: { type: "string" }, + }, + required: ["location"], + }, + }, + }, + ]) + }) +}) diff --git a/packages/opencode/test/session/prompt-missing-file.test.ts b/packages/opencode/test/session/prompt-missing-file.test.ts new file mode 100644 index 00000000000..081847c6792 --- /dev/null +++ b/packages/opencode/test/session/prompt-missing-file.test.ts @@ -0,0 +1,53 @@ +import path from "path" +import { describe, expect, test } from "bun:test" +import { Instance } from "../../src/project/instance" +import { Session } from "../../src/session" +import { SessionPrompt } from "../../src/session/prompt" +import { tmpdir } from "../fixture/fixture" + +describe("session.prompt missing file", () => { + test("does not fail the prompt when a file part is missing", async () => { + await using tmp = await tmpdir({ + git: true, + config: { + agent: { + build: { + model: "openai/gpt-5.2", + }, + }, + }, + }) + + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const session = await Session.create({}) + + const missing = path.join(tmp.path, "does-not-exist.ts") + const msg = await SessionPrompt.prompt({ + sessionID: session.id, + agent: "build", + noReply: true, + parts: [ + { type: "text", text: "please review @does-not-exist.ts" }, + { + type: "file", + mime: "text/plain", + url: `file://${missing}`, + filename: "does-not-exist.ts", + }, + ], + }) + + if (msg.info.role !== "user") throw new Error("expected user message") + + const hasFailure = msg.parts.some( + (part) => part.type === "text" && part.synthetic && part.text.includes("Read tool failed to read"), + ) + expect(hasFailure).toBe(true) + + await Session.remove(session.id) + }, + }) + }) +}) diff --git a/packages/opencode/test/session/prompt-special-chars.test.ts b/packages/opencode/test/session/prompt-special-chars.test.ts new file mode 100644 index 00000000000..dce0b004950 --- /dev/null +++ b/packages/opencode/test/session/prompt-special-chars.test.ts @@ -0,0 +1,56 @@ +import path from "path" +import { describe, expect, test } from "bun:test" +import { fileURLToPath } from "url" +import { Instance } from "../../src/project/instance" +import { Log } from "../../src/util/log" +import { Session } from "../../src/session" +import { SessionPrompt } from "../../src/session/prompt" +import { MessageV2 } from "../../src/session/message-v2" +import { tmpdir } from "../fixture/fixture" + +Log.init({ print: false }) + +describe("session.prompt special characters", () => { + test("handles filenames with # character", async () => { + await using tmp = await tmpdir({ + git: true, + init: async (dir) => { + await Bun.write(path.join(dir, "file#name.txt"), "special content\n") + }, + }) + + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const session = await Session.create({}) + const template = "Read @file#name.txt" + const parts = await SessionPrompt.resolvePromptParts(template) + const fileParts = parts.filter((part) => part.type === "file") + + expect(fileParts.length).toBe(1) + expect(fileParts[0].filename).toBe("file#name.txt") + + // Verify the URL is properly encoded (# should be %23) + expect(fileParts[0].url).toContain("%23") + + // Verify the URL can be correctly converted back to a file path + const decodedPath = fileURLToPath(fileParts[0].url) + expect(decodedPath).toBe(path.join(tmp.path, "file#name.txt")) + + const message = await SessionPrompt.prompt({ + sessionID: session.id, + parts, + noReply: true, + }) + const stored = await MessageV2.get({ sessionID: session.id, messageID: message.info.id }) + + // Verify the file content was read correctly + const textParts = stored.parts.filter((part) => part.type === "text") + const hasContent = textParts.some((part) => part.text.includes("special content")) + expect(hasContent).toBe(true) + + await Session.remove(session.id) + }, + }) + }) +}) diff --git a/packages/opencode/test/session/prompt-variant.test.ts b/packages/opencode/test/session/prompt-variant.test.ts new file mode 100644 index 00000000000..83ae175c6e1 --- /dev/null +++ b/packages/opencode/test/session/prompt-variant.test.ts @@ -0,0 +1,68 @@ +import { describe, expect, test } from "bun:test" +import { Instance } from "../../src/project/instance" +import { Session } from "../../src/session" +import { SessionPrompt } from "../../src/session/prompt" +import { tmpdir } from "../fixture/fixture" + +describe("session.prompt agent variant", () => { + test("applies agent variant only when using agent model", async () => { + const prev = process.env.OPENAI_API_KEY + process.env.OPENAI_API_KEY = "test-openai-key" + + try { + await using tmp = await tmpdir({ + git: true, + config: { + agent: { + build: { + model: "openai/gpt-5.2", + variant: "xhigh", + }, + }, + }, + }) + + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const session = await Session.create({}) + + const other = await SessionPrompt.prompt({ + sessionID: session.id, + agent: "build", + model: { providerID: "opencode", modelID: "kimi-k2.5-free" }, + noReply: true, + parts: [{ type: "text", text: "hello" }], + }) + if (other.info.role !== "user") throw new Error("expected user message") + expect(other.info.variant).toBeUndefined() + + const match = await SessionPrompt.prompt({ + sessionID: session.id, + agent: "build", + noReply: true, + parts: [{ type: "text", text: "hello again" }], + }) + if (match.info.role !== "user") throw new Error("expected user message") + expect(match.info.model).toEqual({ providerID: "openai", modelID: "gpt-5.2" }) + expect(match.info.variant).toBe("xhigh") + + const override = await SessionPrompt.prompt({ + sessionID: session.id, + agent: "build", + noReply: true, + variant: "high", + parts: [{ type: "text", text: "hello third" }], + }) + if (override.info.role !== "user") throw new Error("expected user message") + expect(override.info.variant).toBe("high") + + await Session.remove(session.id) + }, + }) + } finally { + if (prev === undefined) delete process.env.OPENAI_API_KEY + else process.env.OPENAI_API_KEY = prev + } + }) +}) diff --git a/packages/opencode/test/skill/discovery.test.ts b/packages/opencode/test/skill/discovery.test.ts new file mode 100644 index 00000000000..90759fa3c85 --- /dev/null +++ b/packages/opencode/test/skill/discovery.test.ts @@ -0,0 +1,60 @@ +import { describe, test, expect } from "bun:test" +import { Discovery } from "../../src/skill/discovery" +import path from "path" + +const CLOUDFLARE_SKILLS_URL = "https://developers.cloudflare.com/.well-known/skills/" + +describe("Discovery.pull", () => { + test("downloads skills from cloudflare url", async () => { + const dirs = await Discovery.pull(CLOUDFLARE_SKILLS_URL) + expect(dirs.length).toBeGreaterThan(0) + for (const dir of dirs) { + expect(dir).toStartWith(Discovery.dir()) + const md = path.join(dir, "SKILL.md") + expect(await Bun.file(md).exists()).toBe(true) + } + }, 30_000) + + test("url without trailing slash works", async () => { + const dirs = await Discovery.pull(CLOUDFLARE_SKILLS_URL.replace(/\/$/, "")) + expect(dirs.length).toBeGreaterThan(0) + for (const dir of dirs) { + const md = path.join(dir, "SKILL.md") + expect(await Bun.file(md).exists()).toBe(true) + } + }, 30_000) + + test("returns empty array for invalid url", async () => { + const dirs = await Discovery.pull("https://example.invalid/.well-known/skills/") + expect(dirs).toEqual([]) + }) + + test("returns empty array for non-json response", async () => { + const dirs = await Discovery.pull("https://example.com/") + expect(dirs).toEqual([]) + }) + + test("downloads reference files alongside SKILL.md", async () => { + const dirs = await Discovery.pull(CLOUDFLARE_SKILLS_URL) + // find a skill dir that should have reference files (e.g. agents-sdk) + const agentsSdk = dirs.find((d) => d.endsWith("/agents-sdk")) + if (agentsSdk) { + const refs = path.join(agentsSdk, "references") + expect(await Bun.file(path.join(agentsSdk, "SKILL.md")).exists()).toBe(true) + // agents-sdk has reference files per the index + const refDir = await Array.fromAsync(new Bun.Glob("**/*.md").scan({ cwd: refs, onlyFiles: true })) + expect(refDir.length).toBeGreaterThan(0) + } + }, 30_000) + + test("caches downloaded files on second pull", async () => { + // first pull to populate cache + const first = await Discovery.pull(CLOUDFLARE_SKILLS_URL) + expect(first.length).toBeGreaterThan(0) + + // second pull should return same results from cache + const second = await Discovery.pull(CLOUDFLARE_SKILLS_URL) + expect(second.length).toBe(first.length) + expect(second.sort()).toEqual(first.sort()) + }, 60_000) +}) diff --git a/packages/opencode/test/tool/skill.test.ts b/packages/opencode/test/tool/skill.test.ts new file mode 100644 index 00000000000..d5057ba9e7f --- /dev/null +++ b/packages/opencode/test/tool/skill.test.ts @@ -0,0 +1,112 @@ +import { describe, expect, test } from "bun:test" +import path from "path" +import { pathToFileURL } from "url" +import type { PermissionNext } from "../../src/permission/next" +import type { Tool } from "../../src/tool/tool" +import { Instance } from "../../src/project/instance" +import { SkillTool } from "../../src/tool/skill" +import { tmpdir } from "../fixture/fixture" + +const baseCtx: Omit = { + sessionID: "test", + messageID: "", + callID: "", + agent: "build", + abort: AbortSignal.any([]), + messages: [], + metadata: () => {}, +} + +describe("tool.skill", () => { + test("description lists skill location URL", async () => { + await using tmp = await tmpdir({ + git: true, + init: async (dir) => { + const skillDir = path.join(dir, ".opencode", "skill", "tool-skill") + await Bun.write( + path.join(skillDir, "SKILL.md"), + `--- +name: tool-skill +description: Skill for tool tests. +--- + +# Tool Skill +`, + ) + }, + }) + + const home = process.env.OPENCODE_TEST_HOME + process.env.OPENCODE_TEST_HOME = tmp.path + + try { + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const tool = await SkillTool.init() + const skillPath = path.join(tmp.path, ".opencode", "skill", "tool-skill", "SKILL.md") + expect(tool.description).toContain(`${pathToFileURL(skillPath).href}`) + }, + }) + } finally { + process.env.OPENCODE_TEST_HOME = home + } + }) + + test("execute returns skill content block with files", async () => { + await using tmp = await tmpdir({ + git: true, + init: async (dir) => { + const skillDir = path.join(dir, ".opencode", "skill", "tool-skill") + await Bun.write( + path.join(skillDir, "SKILL.md"), + `--- +name: tool-skill +description: Skill for tool tests. +--- + +# Tool Skill + +Use this skill. +`, + ) + await Bun.write(path.join(skillDir, "scripts", "demo.txt"), "demo") + }, + }) + + const home = process.env.OPENCODE_TEST_HOME + process.env.OPENCODE_TEST_HOME = tmp.path + + try { + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const tool = await SkillTool.init() + const requests: Array> = [] + const ctx: Tool.Context = { + ...baseCtx, + ask: async (req) => { + requests.push(req) + }, + } + + const result = await tool.execute({ name: "tool-skill" }, ctx) + const dir = path.join(tmp.path, ".opencode", "skill", "tool-skill") + const file = path.resolve(dir, "scripts", "demo.txt") + + expect(requests.length).toBe(1) + expect(requests[0].permission).toBe("skill") + expect(requests[0].patterns).toContain("tool-skill") + expect(requests[0].always).toContain("tool-skill") + + expect(result.metadata.dir).toBe(dir) + expect(result.output).toContain(``) + expect(result.output).toContain(`Base directory for this skill: ${pathToFileURL(dir).href}`) + expect(result.output).toContain(`${file}`) + }, + }) + } finally { + process.env.OPENCODE_TEST_HOME = home + } + }) +}) diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts index ca13e5e93cf..7065c694c9c 100644 --- a/packages/sdk/js/src/gen/types.gen.ts +++ b/packages/sdk/js/src/gen/types.gen.ts @@ -1207,6 +1207,10 @@ export type Config = { * Control diff rendering style: 'auto' adapts to terminal width, 'stacked' always shows single column */ diff_style?: "auto" | "stacked" + /** + * Layout mode (built-in: default, dense; or custom layouts from ~/.config/opencode/layout/) + */ + layout?: string } /** * Command configuration, see https://opencode.ai/docs/commands diff --git a/packages/ui/src/assets/icons/app/android-studio.svg b/packages/ui/src/assets/icons/app/android-studio.svg new file mode 100644 index 00000000000..6b545e27a30 --- /dev/null +++ b/packages/ui/src/assets/icons/app/android-studio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/ui/src/assets/icons/app/antigravity.svg b/packages/ui/src/assets/icons/app/antigravity.svg new file mode 100644 index 00000000000..3c3554af75f --- /dev/null +++ b/packages/ui/src/assets/icons/app/antigravity.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/ui/src/assets/icons/app/cursor.svg b/packages/ui/src/assets/icons/app/cursor.svg new file mode 100644 index 00000000000..5aa26e8e71f --- /dev/null +++ b/packages/ui/src/assets/icons/app/cursor.svg @@ -0,0 +1 @@ + diff --git a/packages/ui/src/assets/icons/app/file-explorer.svg b/packages/ui/src/assets/icons/app/file-explorer.svg new file mode 100644 index 00000000000..316cbab35da --- /dev/null +++ b/packages/ui/src/assets/icons/app/file-explorer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/ui/src/assets/icons/app/finder.png b/packages/ui/src/assets/icons/app/finder.png new file mode 100644 index 00000000000..2cff579e612 Binary files /dev/null and b/packages/ui/src/assets/icons/app/finder.png differ diff --git a/packages/ui/src/assets/icons/app/ghostty.svg b/packages/ui/src/assets/icons/app/ghostty.svg new file mode 100644 index 00000000000..1dc652aac5d --- /dev/null +++ b/packages/ui/src/assets/icons/app/ghostty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/ui/src/assets/icons/app/iterm2.svg b/packages/ui/src/assets/icons/app/iterm2.svg new file mode 100644 index 00000000000..0b00a1b7a7c --- /dev/null +++ b/packages/ui/src/assets/icons/app/iterm2.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/ui/src/assets/icons/app/powershell.svg b/packages/ui/src/assets/icons/app/powershell.svg new file mode 100644 index 00000000000..fa0c70f0b67 --- /dev/null +++ b/packages/ui/src/assets/icons/app/powershell.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/ui/src/assets/icons/app/sublimetext.svg b/packages/ui/src/assets/icons/app/sublimetext.svg new file mode 100644 index 00000000000..f482ec5bb9b --- /dev/null +++ b/packages/ui/src/assets/icons/app/sublimetext.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/ui/src/assets/icons/app/terminal.png b/packages/ui/src/assets/icons/app/terminal.png new file mode 100644 index 00000000000..43857b6323f Binary files /dev/null and b/packages/ui/src/assets/icons/app/terminal.png differ diff --git a/packages/ui/src/assets/icons/app/textmate.png b/packages/ui/src/assets/icons/app/textmate.png new file mode 100644 index 00000000000..1eee73c5ebe Binary files /dev/null and b/packages/ui/src/assets/icons/app/textmate.png differ diff --git a/packages/ui/src/assets/icons/app/vscode.svg b/packages/ui/src/assets/icons/app/vscode.svg new file mode 100644 index 00000000000..aba7e19f6b5 --- /dev/null +++ b/packages/ui/src/assets/icons/app/vscode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/ui/src/assets/icons/app/xcode.png b/packages/ui/src/assets/icons/app/xcode.png new file mode 100644 index 00000000000..c37d9f17620 Binary files /dev/null and b/packages/ui/src/assets/icons/app/xcode.png differ diff --git a/packages/ui/src/assets/icons/app/zed-dark.svg b/packages/ui/src/assets/icons/app/zed-dark.svg new file mode 100644 index 00000000000..67a99ae4a81 --- /dev/null +++ b/packages/ui/src/assets/icons/app/zed-dark.svg @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/packages/ui/src/assets/icons/app/zed.svg b/packages/ui/src/assets/icons/app/zed.svg new file mode 100644 index 00000000000..a845bf18157 --- /dev/null +++ b/packages/ui/src/assets/icons/app/zed.svg @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/packages/ui/src/components/app-icon.css b/packages/ui/src/components/app-icon.css new file mode 100644 index 00000000000..16cb0dcc1ce --- /dev/null +++ b/packages/ui/src/components/app-icon.css @@ -0,0 +1,5 @@ +img[data-component="app-icon"] { + display: block; + box-sizing: border-box; + object-fit: contain; +} diff --git a/packages/ui/src/components/app-icon.tsx b/packages/ui/src/components/app-icon.tsx new file mode 100644 index 00000000000..e91638b9893 --- /dev/null +++ b/packages/ui/src/components/app-icon.tsx @@ -0,0 +1,83 @@ +import type { Component, ComponentProps } from "solid-js" +import { createSignal, onCleanup, onMount, splitProps } from "solid-js" +import type { IconName } from "./app-icons/types" + +import androidStudio from "../assets/icons/app/android-studio.svg" +import antigravity from "../assets/icons/app/antigravity.svg" +import cursor from "../assets/icons/app/cursor.svg" +import fileExplorer from "../assets/icons/app/file-explorer.svg" +import finder from "../assets/icons/app/finder.png" +import ghostty from "../assets/icons/app/ghostty.svg" +import iterm2 from "../assets/icons/app/iterm2.svg" +import powershell from "../assets/icons/app/powershell.svg" +import terminal from "../assets/icons/app/terminal.png" +import textmate from "../assets/icons/app/textmate.png" +import vscode from "../assets/icons/app/vscode.svg" +import xcode from "../assets/icons/app/xcode.png" +import zed from "../assets/icons/app/zed.svg" +import zedDark from "../assets/icons/app/zed-dark.svg" +import sublimetext from "../assets/icons/app/sublimetext.svg" + +const icons = { + vscode, + cursor, + zed, + "file-explorer": fileExplorer, + finder, + terminal, + iterm2, + ghostty, + xcode, + "android-studio": androidStudio, + antigravity, + textmate, + powershell, + "sublime-text": sublimetext, +} satisfies Record + +const themed: Partial> = { + zed: { + light: zed, + dark: zedDark, + }, +} + +const scheme = () => { + if (typeof document !== "object") return "light" as const + if (document.documentElement.dataset.colorScheme === "dark") return "dark" as const + return "light" as const +} + +export type AppIconProps = Omit, "src"> & { + id: IconName +} + +export const AppIcon: Component = (props) => { + const [local, rest] = splitProps(props, ["id", "class", "classList", "alt", "draggable"]) + const [mode, setMode] = createSignal(scheme()) + + onMount(() => { + const sync = () => setMode(scheme()) + const observer = new MutationObserver(sync) + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ["data-color-scheme"], + }) + sync() + onCleanup(() => observer.disconnect()) + }) + + return ( + {local.alt + ) +} diff --git a/packages/ui/src/components/app-icons/sprite.svg b/packages/ui/src/components/app-icons/sprite.svg new file mode 100644 index 00000000000..68361f4137b --- /dev/null +++ b/packages/ui/src/components/app-icons/sprite.svg @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/ui/src/components/app-icons/types.ts b/packages/ui/src/components/app-icons/types.ts new file mode 100644 index 00000000000..a0343c25b7c --- /dev/null +++ b/packages/ui/src/components/app-icons/types.ts @@ -0,0 +1,20 @@ +// This file is generated by icon spritesheet generator + +export const iconNames = [ + "vscode", + "cursor", + "zed", + "file-explorer", + "finder", + "terminal", + "iterm2", + "ghostty", + "xcode", + "android-studio", + "antigravity", + "textmate", + "powershell", + "sublime-text", +] as const + +export type IconName = (typeof iconNames)[number] diff --git a/packages/ui/src/components/context-menu.css b/packages/ui/src/components/context-menu.css new file mode 100644 index 00000000000..1e366dccd42 --- /dev/null +++ b/packages/ui/src/components/context-menu.css @@ -0,0 +1,134 @@ +[data-component="context-menu-content"], +[data-component="context-menu-sub-content"] { + min-width: 8rem; + overflow: hidden; + border: none; + border-radius: var(--radius-md); + box-shadow: var(--shadow-xs-border); + background-clip: padding-box; + background-color: var(--surface-raised-stronger-non-alpha); + padding: 4px; + z-index: 100; + transform-origin: var(--kb-menu-content-transform-origin); + + &:focus-within, + &:focus { + outline: none; + } + + animation: contextMenuContentHide var(--transition-duration) var(--transition-easing) forwards; + + @starting-style { + animation: none; + } + + &[data-expanded] { + pointer-events: auto; + animation: contextMenuContentShow var(--transition-duration) var(--transition-easing) forwards; + } +} + +[data-component="context-menu-content"], +[data-component="context-menu-sub-content"] { + [data-slot="context-menu-item"], + [data-slot="context-menu-checkbox-item"], + [data-slot="context-menu-radio-item"], + [data-slot="context-menu-sub-trigger"] { + position: relative; + display: flex; + align-items: center; + gap: 8px; + padding: 4px 8px; + border-radius: var(--radius-sm); + cursor: default; + outline: none; + + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-strong); + + transition-property: background-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + user-select: none; + + &:hover { + background-color: var(--surface-raised-base-hover); + } + + &[data-disabled] { + color: var(--text-weak); + pointer-events: none; + } + } + + [data-slot="context-menu-sub-trigger"] { + &[data-expanded] { + background: var(--surface-raised-base-hover); + outline: none; + border: none; + } + } + + [data-slot="context-menu-item-indicator"] { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + } + + [data-slot="context-menu-item-label"] { + flex: 1; + } + + [data-slot="context-menu-item-description"] { + font-size: var(--font-size-x-small); + color: var(--text-weak); + } + + [data-slot="context-menu-separator"] { + height: 1px; + margin: 4px -4px; + border-top-color: var(--border-weak-base); + } + + [data-slot="context-menu-group-label"] { + padding: 4px 8px; + font-family: var(--font-family-sans); + font-size: var(--font-size-x-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-weak); + } + + [data-slot="context-menu-arrow"] { + fill: var(--surface-raised-stronger-non-alpha); + } +} + +@keyframes contextMenuContentShow { + from { + opacity: 0; + transform: scaleY(0.95); + } + to { + opacity: 1; + transform: scaleY(1); + } +} + +@keyframes contextMenuContentHide { + from { + opacity: 1; + transform: scaleY(1); + } + to { + opacity: 0; + transform: scaleY(0.95); + } +} diff --git a/packages/ui/src/components/context-menu.tsx b/packages/ui/src/components/context-menu.tsx new file mode 100644 index 00000000000..afdaff7b800 --- /dev/null +++ b/packages/ui/src/components/context-menu.tsx @@ -0,0 +1,308 @@ +import { ContextMenu as Kobalte } from "@kobalte/core/context-menu" +import { splitProps } from "solid-js" +import type { ComponentProps, ParentProps } from "solid-js" + +export interface ContextMenuProps extends ComponentProps {} +export interface ContextMenuTriggerProps extends ComponentProps {} +export interface ContextMenuIconProps extends ComponentProps {} +export interface ContextMenuPortalProps extends ComponentProps {} +export interface ContextMenuContentProps extends ComponentProps {} +export interface ContextMenuArrowProps extends ComponentProps {} +export interface ContextMenuSeparatorProps extends ComponentProps {} +export interface ContextMenuGroupProps extends ComponentProps {} +export interface ContextMenuGroupLabelProps extends ComponentProps {} +export interface ContextMenuItemProps extends ComponentProps {} +export interface ContextMenuItemLabelProps extends ComponentProps {} +export interface ContextMenuItemDescriptionProps extends ComponentProps {} +export interface ContextMenuItemIndicatorProps extends ComponentProps {} +export interface ContextMenuRadioGroupProps extends ComponentProps {} +export interface ContextMenuRadioItemProps extends ComponentProps {} +export interface ContextMenuCheckboxItemProps extends ComponentProps {} +export interface ContextMenuSubProps extends ComponentProps {} +export interface ContextMenuSubTriggerProps extends ComponentProps {} +export interface ContextMenuSubContentProps extends ComponentProps {} + +function ContextMenuRoot(props: ContextMenuProps) { + return +} + +function ContextMenuTrigger(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +function ContextMenuIcon(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +function ContextMenuPortal(props: ContextMenuPortalProps) { + return +} + +function ContextMenuContent(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +function ContextMenuArrow(props: ContextMenuArrowProps) { + const [local, rest] = splitProps(props, ["class", "classList"]) + return ( + + ) +} + +function ContextMenuSeparator(props: ContextMenuSeparatorProps) { + const [local, rest] = splitProps(props, ["class", "classList"]) + return ( + + ) +} + +function ContextMenuGroup(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +function ContextMenuGroupLabel(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +function ContextMenuItem(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +function ContextMenuItemLabel(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +function ContextMenuItemDescription(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +function ContextMenuItemIndicator(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +function ContextMenuRadioGroup(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +function ContextMenuRadioItem(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +function ContextMenuCheckboxItem(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +function ContextMenuSub(props: ContextMenuSubProps) { + return +} + +function ContextMenuSubTrigger(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +function ContextMenuSubContent(props: ParentProps) { + const [local, rest] = splitProps(props, ["class", "classList", "children"]) + return ( + + {local.children} + + ) +} + +export const ContextMenu = Object.assign(ContextMenuRoot, { + Trigger: ContextMenuTrigger, + Icon: ContextMenuIcon, + Portal: ContextMenuPortal, + Content: ContextMenuContent, + Arrow: ContextMenuArrow, + Separator: ContextMenuSeparator, + Group: ContextMenuGroup, + GroupLabel: ContextMenuGroupLabel, + Item: ContextMenuItem, + ItemLabel: ContextMenuItemLabel, + ItemDescription: ContextMenuItemDescription, + ItemIndicator: ContextMenuItemIndicator, + RadioGroup: ContextMenuRadioGroup, + RadioItem: ContextMenuRadioItem, + CheckboxItem: ContextMenuCheckboxItem, + Sub: ContextMenuSub, + SubTrigger: ContextMenuSubTrigger, + SubContent: ContextMenuSubContent, +}) diff --git a/packages/ui/src/i18n/bs.ts b/packages/ui/src/i18n/bs.ts new file mode 100644 index 00000000000..24e4c12068e --- /dev/null +++ b/packages/ui/src/i18n/bs.ts @@ -0,0 +1,109 @@ +import { dict as en } from "./en" + +type Keys = keyof typeof en + +export const dict = { + "ui.sessionReview.title": "Promjene sesije", + "ui.sessionReview.title.lastTurn": "Promjene u posljednjem potezu", + "ui.sessionReview.diffStyle.unified": "Ujedinjeno", + "ui.sessionReview.diffStyle.split": "Podijeljeno", + "ui.sessionReview.expandAll": "Proširi sve", + "ui.sessionReview.collapseAll": "Sažmi sve", + "ui.sessionReview.change.added": "Dodano", + "ui.sessionReview.change.removed": "Uklonjeno", + "ui.sessionReview.change.modified": "Izmijenjeno", + + "ui.lineComment.label.prefix": "Komentar na ", + "ui.lineComment.label.suffix": "", + "ui.lineComment.editorLabel.prefix": "Komentarišeš ", + "ui.lineComment.editorLabel.suffix": "", + "ui.lineComment.placeholder": "Dodaj komentar", + "ui.lineComment.submit": "Komentariši", + + "ui.sessionTurn.steps.show": "Prikaži korake", + "ui.sessionTurn.steps.hide": "Sakrij korake", + "ui.sessionTurn.summary.response": "Odgovor", + "ui.sessionTurn.diff.showMore": "Prikaži još izmjena ({{count}})", + + "ui.sessionTurn.retry.retrying": "ponovni pokušaj", + "ui.sessionTurn.retry.inSeconds": "za {{seconds}}s", + + "ui.sessionTurn.status.delegating": "Delegiranje posla", + "ui.sessionTurn.status.planning": "Planiranje sljedećih koraka", + "ui.sessionTurn.status.gatheringContext": "Prikupljanje konteksta", + "ui.sessionTurn.status.searchingCodebase": "Pretraživanje baze koda", + "ui.sessionTurn.status.searchingWeb": "Pretraživanje weba", + "ui.sessionTurn.status.makingEdits": "Pravljenje izmjena", + "ui.sessionTurn.status.runningCommands": "Pokretanje komandi", + "ui.sessionTurn.status.thinking": "Razmišljanje", + "ui.sessionTurn.status.thinkingWithTopic": "Razmišljanje - {{topic}}", + "ui.sessionTurn.status.gatheringThoughts": "Sređivanje misli", + "ui.sessionTurn.status.consideringNextSteps": "Razmatranje sljedećih koraka", + + "ui.messagePart.diagnostic.error": "Greška", + "ui.messagePart.title.edit": "Uredi", + "ui.messagePart.title.write": "Napiši", + "ui.messagePart.option.typeOwnAnswer": "Unesi svoj odgovor", + "ui.messagePart.review.title": "Pregledaj svoje odgovore", + + "ui.list.loading": "Učitavanje", + "ui.list.empty": "Nema rezultata", + "ui.list.clearFilter": "Očisti filter", + "ui.list.emptyWithFilter.prefix": "Nema rezultata za", + "ui.list.emptyWithFilter.suffix": "", + + "ui.messageNav.newMessage": "Nova poruka", + + "ui.textField.copyToClipboard": "Kopiraj u međuspremnik", + "ui.textField.copyLink": "Kopiraj link", + "ui.textField.copied": "Kopirano", + + "ui.imagePreview.alt": "Pregled slike", + + "ui.tool.read": "Čitanje", + "ui.tool.loaded": "Učitano", + "ui.tool.list": "Listanje", + "ui.tool.glob": "Glob", + "ui.tool.grep": "Grep", + "ui.tool.webfetch": "Web preuzimanje", + "ui.tool.shell": "Shell", + "ui.tool.patch": "Patch", + "ui.tool.todos": "Lista zadataka", + "ui.tool.todos.read": "Čitanje liste zadataka", + "ui.tool.questions": "Pitanja", + "ui.tool.agent": "{{type}} agent", + + "ui.common.file.one": "datoteka", + "ui.common.file.other": "datoteke", + "ui.common.question.one": "pitanje", + "ui.common.question.other": "pitanja", + + "ui.common.add": "Dodaj", + "ui.common.cancel": "Otkaži", + "ui.common.confirm": "Potvrdi", + "ui.common.dismiss": "Odbaci", + "ui.common.close": "Zatvori", + "ui.common.next": "Dalje", + "ui.common.submit": "Pošalji", + + "ui.permission.deny": "Zabrani", + "ui.permission.allowAlways": "Uvijek dozvoli", + "ui.permission.allowOnce": "Dozvoli jednom", + + "ui.message.expand": "Proširi poruku", + "ui.message.collapse": "Sažmi poruku", + "ui.message.copy": "Kopiraj", + "ui.message.copied": "Kopirano!", + "ui.message.attachment.alt": "prilog", + + "ui.patch.action.deleted": "Obrisano", + "ui.patch.action.created": "Kreirano", + "ui.patch.action.moved": "Premješteno", + "ui.patch.action.patched": "Primijenjeno", + + "ui.question.subtitle.answered": "{{count}} odgovoreno", + "ui.question.answer.none": "(nema odgovora)", + "ui.question.review.notAnswered": "(nije odgovoreno)", + "ui.question.multiHint": "(odaberi sve što važi)", + "ui.question.custom.placeholder": "Unesi svoj odgovor...", +} satisfies Partial> diff --git a/packages/web/src/components/Footer.astro b/packages/web/src/components/Footer.astro new file mode 100644 index 00000000000..0c66d7e63f7 --- /dev/null +++ b/packages/web/src/components/Footer.astro @@ -0,0 +1,125 @@ +--- +import config from "virtual:starlight/user-config" +import LanguageSelect from "@astrojs/starlight/components/LanguageSelect.astro" +import { Icon } from "@astrojs/starlight/components" + +const { lang, editUrl, lastUpdated, entry } = Astro.locals.starlightRoute +const template = entry.data.template +const issueLink = Astro.locals.t("app.footer.issueLink", "Found a bug? Open an issue") +const discordLink = Astro.locals.t("app.footer.discordLink", "Join our Discord community") + +const github = config.social?.find((item) => item.icon === "github") +const discord = config.social?.find((item) => item.icon === "discord") +--- + +{ + template === "doc" && ( + + ) +} + + diff --git a/packages/web/src/content/docs/ar/acp.mdx b/packages/web/src/content/docs/ar/acp.mdx new file mode 100644 index 00000000000..1919e426821 --- /dev/null +++ b/packages/web/src/content/docs/ar/acp.mdx @@ -0,0 +1,156 @@ +--- +title: دعم ACP +description: استخدم OpenCode في أي محرر متوافق مع ACP. +--- + +يدعم OpenCode بروتوكول [Agent Client Protocol](https://agentclientprotocol.com) أو (ACP)، مما يتيح لك استخدامه مباشرة في المحررات وبيئات التطوير المتكاملة (IDEs) المتوافقة. + +:::tip +للاطلاع على قائمة بالمحررات والأدوات التي تدعم ACP، راجع [ACP progress report](https://zed.dev/blog/acp-progress-report#available-now). +::: + +ACP بروتوكول مفتوح يوحّد آلية التواصل بين محررات الشيفرة ووكلاء البرمجة بالذكاء الاصطناعي. + +--- + +## الإعداد + +لاستخدام OpenCode عبر ACP، اضبط محررك ليشغّل الأمر `opencode acp`. + +يشغّل هذا الأمر OpenCode كعملية فرعية متوافقة مع ACP تتواصل مع محررك عبر JSON-RPC باستخدام stdio. + +فيما يلي أمثلة لمحررات شائعة تدعم ACP. + +--- + +### Zed + +أضف إلى إعدادات [Zed](https://zed.dev) (`~/.config/zed/settings.json`): + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +لفتحه، استخدم الإجراء `agent: new thread` في **Command Palette**. + +يمكنك أيضا ربط اختصار لوحة مفاتيح عبر تعديل `keymap.json`: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### JetBrains IDEs + +أضف إلى ملف acp.json الخاص بـ [JetBrains IDE](https://www.jetbrains.com/) وفقا لـ [documentation](https://www.jetbrains.com/help/ai-assistant/acp.html): + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +لفتحه، اختر الوكيل الجديد 'OpenCode' من محدد الوكلاء في AI Chat. + +--- + +### Avante.nvim + +أضف إلى إعدادات [Avante.nvim](https://github.com/yetone/avante.nvim): + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +إذا احتجت إلى تمرير متغيرات البيئة: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +لاستخدام OpenCode كوكيل ACP في [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim)، أضف التالي إلى إعدادات Neovim: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +يضبط هذا الإعداد CodeCompanion لاستخدام OpenCode كوكيل ACP للدردشة. + +إذا احتجت إلى تمرير متغيرات البيئة (مثل `OPENCODE_API_KEY`)، فارجع إلى [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) ضمن توثيق CodeCompanion.nvim للاطلاع على التفاصيل كاملة. + +## الدعم + +يعمل OpenCode عبر ACP بالطريقة نفسها التي يعمل بها في terminal. جميع الميزات مدعومة: + +:::note +بعض أوامر الشرطة المائلة المضمنة مثل `/undo` و`/redo` غير مدعومة حاليا. +::: + +- الأدوات المضمنة (عمليات الملفات، أوامر terminal، إلخ.) +- الأدوات المخصصة وأوامر الشرطة المائلة +- خوادم MCP المضبوطة في إعدادات OpenCode +- قواعد خاصة بالمشروع من `AGENTS.md` +- المنسقات (formatters) والمدققات (linters) المخصصة +- نظام الوكلاء والأذونات diff --git a/packages/web/src/content/docs/ar/agents.mdx b/packages/web/src/content/docs/ar/agents.mdx new file mode 100644 index 00000000000..01e13fda896 --- /dev/null +++ b/packages/web/src/content/docs/ar/agents.mdx @@ -0,0 +1,746 @@ +--- +title: الوكلاء +description: هيّئ الوكلاء المتخصصين واستخدمهم. +--- + +الوكلاء هم مساعدون متخصصون بالذكاء الاصطناعي يمكن تهيئتهم لمهام وسير عمل محدد. يتيحون لك إنشاء أدوات مركزة مع موجّهات مخصصة ونماذج وصلاحية وصول للأدوات. + +:::tip +استخدم وكيل plan لتحليل الشفرة ومراجعة الاقتراحات بدون إجراء أي تغييرات على الشفرة. +::: + +يمكنك التبديل بين الوكلاء أثناء الجلسة أو استدعاؤهم عبر الإشارة بـ `@`. + +--- + +## الأنواع + +يوجد نوعان من الوكلاء في OpenCode: وكلاء أساسيون ووكلاء فرعيون. + +--- + +### الوكلاء الأساسيون + +الوكلاء الأساسيون هم المساعدون الرئيسيون الذين تتفاعل معهم مباشرة. يمكنك التنقل بينهم باستخدام مفتاح **Tab** أو اختصار `switch_agent` الذي قمت بتهيئته. يتولى هؤلاء الوكلاء محادثتك الرئيسية. يتم ضبط وصول الأدوات عبر الأذونات — على سبيل المثال، يمتلك Build جميع الأدوات مفعلة بينما يكون Plan مقيّدا. + +:::tip +يمكنك استخدام مفتاح **Tab** للتبديل بين الوكلاء الأساسيين أثناء الجلسة. +::: + +يأتي OpenCode مع وكيلين أساسيين مدمجين: **Build** و **Plan**. سنلقي نظرة عليهما أدناه. + +--- + +### الوكلاء الفرعيون + +الوكلاء الفرعيون هم مساعدين متخصصين يمكن للوكلاء الأساسيين استدعاؤهم لمهام محددة. يمكنك أيضا استدعاؤهم يدويا عبر **الإشارة بـ @** في رسائلك. + +يأتي OpenCode مع وكيلين فرعيين مدمجين: **General** و **Explore**. سنلقي نظرة على ذلك أدناه. + +--- + +## المدمجة + +يأتي OpenCode مع وكيلين أساسيين مدمجين ووكيلين فرعيين مدمجين. + +--- + +### استخدام Build + +_الوضع_: `primary` + +Build هو الوكيل الأساسي **الافتراضي** مع تفعيل جميع الأدوات. هذا هو الوكيل القياسي لأعمال التطوير عندما تحتاج إلى وصول كامل لعمليات الملفات وأوامر النظام. + +--- + +### استخدام Plan + +_الوضع_: `primary` + +وكيل مقيّد صُمم للتخطيط والتحليل. نستخدم نظام أذونات لمنحك تحكما أكبر ومنع التغييرات غير المقصودة. +افتراضيا، يتم ضبط كل ما يلي على `ask`: + +- `file edits`: جميع عمليات الكتابة والتصحيح (patches) والتحرير +- `bash`: جميع أوامر bash + +يفيد هذا الوكيل عندما تريد من LLM تحليل الشفرة أو اقتراح تغييرات أو إنشاء خطط بدون إجراء أي تعديلات فعلية على قاعدة الشفرة. + +--- + +### استخدام General + +_الوضع_: `subagent` + +وكيل عام الغرض للبحث في أسئلة معقدة وتنفيذ مهام متعددة الخطوات. لديه وصول كامل للأدوات (باستثناء todo)، لذا يمكنه إجراء تغييرات على الملفات عند الحاجة. استخدمه لتشغيل عدة وحدات عمل بالتوازي. + +--- + +### استخدام Explore + +_الوضع_: `subagent` + +وكيل سريع للقراءة فقط لاستكشاف قواعد الشفرة. لا يستطيع تعديل الملفات. استخدمه عندما تحتاج إلى العثور بسرعة على ملفات عبر أنماط، أو البحث في الشفرة عن كلمات مفتاحية، أو الإجابة عن أسئلة حول قاعدة الشفرة. + +--- + +### استخدام Compaction + +_الوضع_: `primary` + +وكيل نظام مخفي يضغط السياق الطويل إلى ملخص أصغر. يعمل تلقائيا عند الحاجة ولا يمكن اختياره من واجهة المستخدم. + +--- + +### استخدام Title + +_الوضع_: `primary` + +وكيل نظام مخفي ينشئ عناوين قصيرة للجلسات. يعمل تلقائيا ولا يمكن اختياره من واجهة المستخدم. + +--- + +### استخدام Summary + +_الوضع_: `primary` + +وكيل نظام مخفي ينشئ ملخصات للجلسات. يعمل تلقائيا ولا يمكن اختياره من واجهة المستخدم. + +--- + +## الاستخدام + +1. للوكلاء الأساسيين، استخدم مفتاح **Tab** للتنقل بينهم أثناء الجلسة. يمكنك أيضا استخدام اختصار `switch_agent` الذي قمت بتهيئته. + +2. يمكن استدعاء الوكلاء الفرعيين: + - **تلقائيا** بواسطة الوكلاء الأساسيين لمهام متخصصة بناء على أوصافهم. + - يدويا عبر **الإشارة بـ @** إلى وكيل فرعي في رسالتك. على سبيل المثال: + + ```txt frame="none" + @general help me search for this function + ``` + +3. **التنقل بين الجلسات**: عندما ينشئ الوكلاء الفرعيون جلسات فرعية خاصة بهم، يمكنك التنقل بين الجلسة الأم وجميع الجلسات الفرعية باستخدام: + - **\+Right** (أو اختصار `session_child_cycle` الذي قمت بتهيئته) للتنقل للأمام عبر parent → child1 → child2 → ... → parent + - **\+Left** (أو اختصار `session_child_cycle_reverse` الذي قمت بتهيئته) للتنقل للخلف عبر parent ← child1 ← child2 ← ... ← parent + + يتيح لك ذلك التبديل بسلاسة بين المحادثة الرئيسية وعمل الوكلاء الفرعيين المتخصص. + +--- + +## التهيئة + +يمكنك تخصيص الوكلاء المدمجين أو إنشاء وكلائك عبر التهيئة. يمكن تهيئة الوكلاء بطريقتين: + +--- + +### JSON + +هيّئ الوكلاء في ملف إعدادات `opencode.json`: + +```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 + +يمكنك أيضا تعريف الوكلاء باستخدام ملفات Markdown. ضعها في: + +- عام: `~/.config/opencode/agents/` +- لكل مشروع: `.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 هو اسم الوكيل. على سبيل المثال، ينشئ `review.md` وكيلا باسم `review`. + +--- + +## الخيارات + +لنلق نظرة على خيارات التهيئة هذه بمزيد من التفصيل. + +--- + +### الوصف + +استخدم خيار `description` لتقديم وصف موجز لما يفعله الوكيل ومتى ينبغي استخدامه. + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +هذا خيار تهيئة **إلزامي**. + +--- + +### درجة الحرارة + +تحكم في العشوائية والإبداع في ردود LLM عبر إعداد `temperature`. + +القيم الأقل تجعل الردود أكثر تركيزا وحتمية، بينما تزيد القيم الأعلى من الإبداع والتنوع. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +عادة تتراوح قيم `temperature` بين 0.0 و 1.0: + +- **0.0-0.2**: ردود شديدة التركيز وحتمية، مثالية لتحليل الشفرة والتخطيط +- **0.3-0.5**: ردود متوازنة مع قدر من الإبداع، مناسبة لمهام التطوير العامة +- **0.6-1.0**: ردود أكثر إبداعا وتنوعا، مفيدة للعصف الذهني والاستكشاف + +```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}" + } + } +} +``` + +إذا لم يتم تحديد temperature، يستخدم OpenCode القيم الافتراضية الخاصة بالنموذج؛ عادة 0 لمعظم النماذج و 0.55 لنماذج Qwen. + +--- + +### الحد الأقصى للخطوات + +تحكم في الحد الأقصى لعدد التكرارات الوكيلة التي يمكن لوكيل تنفيذها قبل أن يُجبر على الرد بنص فقط. يتيح ذلك للمستخدمين الذين يرغبون في التحكم بالتكاليف وضع حد للإجراءات الوكيلة. + +إذا لم يتم ضبط هذا الخيار، سيستمر الوكيل بالتكرار حتى يقرر النموذج التوقف أو يقاطع المستخدم الجلسة. + +```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 + } + } +} +``` + +عند بلوغ الحد، يتلقى الوكيل موجّها نظاميا خاصا يطلب منه الرد بملخص لعمله والمهام المتبقية الموصى بها. + +:::caution +الحقل القديم `maxSteps` متقادم. استخدم `steps` بدلا منه. +::: + +--- + +### التعطيل + +اضبطه على `true` لتعطيل الوكيل. + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### الموجّه + +حدد ملف موجّه نظامي مخصص لهذا الوكيل عبر إعداد `prompt`. يجب أن يحتوي ملف الموجّه على تعليمات خاصة بهدف الوكيل. + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +هذا المسار نسبي لمكان وجود ملف الإعدادات. لذلك يعمل هذا لكل من إعدادات OpenCode العامة وإعدادات المشروع. + +--- + +### النموذج + +استخدم إعداد `model` لتجاوز (override) النموذج لهذا الوكيل. يفيد ذلك لاستخدام نماذج مختلفة مُحسّنة لمهام مختلفة. على سبيل المثال، نموذج أسرع للتخطيط ونموذج أقدر للتنفيذ. + +:::tip +إذا لم تحدد نموذجا، يستخدم الوكلاء الأساسيون [النموذج المُهيأ عالميا](/docs/config#models)، بينما يستخدم الوكلاء الفرعيون نموذج الوكيل الأساسي الذي استدعاهم. +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +يستخدم معرّف النموذج في إعدادات OpenCode الصيغة `provider/model-id`. على سبيل المثال، إذا كنت تستخدم [OpenCode Zen](/docs/zen)، فستستخدم `opencode/gpt-5.1-codex` لـ GPT 5.1 Codex. + +--- + +### الأدوات + +تحكم في الأدوات المتاحة لهذا الوكيل عبر إعداد `tools`. يمكنك تفعيل أو تعطيل أدوات محددة بضبطها على `true` أو `false`. + +```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 +إعدادات الوكيل الخاصة تتجاوز الإعدادات العامة. +::: + +يمكنك أيضا استخدام المحارف البديلة (wildcards) للتحكم في عدة أدوات دفعة واحدة. على سبيل المثال، لتعطيل جميع الأدوات القادمة من خادم MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[اعرف المزيد عن الأدوات](/docs/tools). + +--- + +### الأذونات + +يمكنك تهيئة الأذونات لإدارة الإجراءات التي يستطيع الوكيل تنفيذها. حاليا، يمكن تهيئة أذونات أدوات `edit` و `bash` و `webfetch` إلى: + +- `"ask"` — طلب الموافقة قبل تشغيل الأداة +- `"allow"` — السماح بكل العمليات بدون موافقة +- `"deny"` — تعطيل الأداة + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +يمكنك تجاوز هذه الأذونات لكل وكيل. + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +يمكنك أيضا ضبط الأذونات في وكلاء Markdown. + +```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. +``` + +يمكنك ضبط الأذونات لأوامر bash محددة. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +يمكن لهذا أن يقبل نمط glob. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +ويمكنك أيضا استخدام المحرف البديل `*` لإدارة الأذونات لكل الأوامر. +وبما أن آخر قاعدة مطابقة لها الأولوية، ضع قاعدة `*` أولا ثم القواعد الأكثر تخصيصا بعدها. + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[اعرف المزيد عن الأذونات](/docs/permissions). + +--- + +### الوضع + +تحكم في وضع الوكيل عبر إعداد `mode`. يُستخدم خيار `mode` لتحديد كيفية استخدام الوكيل. + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +يمكن ضبط خيار `mode` على `primary` أو `subagent` أو `all`. إذا لم يتم تحديد `mode`، فالقيمة الافتراضية هي `all`. + +--- + +### مخفي + +أخفِ وكيلا فرعيا من قائمة الإكمال التلقائي لـ `@` عبر `hidden: true`. يفيد ذلك للوكلاء الفرعيين الداخليين الذين ينبغي استدعاؤهم برمجيا فقط بواسطة وكلاء آخرين عبر أداة Task. + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +يؤثر هذا فقط على ظهور الوكيل للمستخدم في قائمة الإكمال التلقائي. لا يزال بإمكان النموذج استدعاء الوكلاء المخفيين عبر أداة Task إذا سمحت الأذونات. + +:::note +ينطبق فقط على الوكلاء ذوي `mode: subagent`. +::: + +--- + +### أذونات Task + +تحكم في أي الوكلاء الفرعيين يمكن لوكيل استدعاؤهم عبر أداة Task باستخدام `permission.task`. يستخدم أنماط glob لمطابقة مرنة. + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +عند ضبطها على `deny`، تتم إزالة الوكيل الفرعي بالكامل من وصف أداة Task، لذا لن يحاول النموذج استدعاءه. + +:::tip +تُقيّم القواعد بالترتيب، و **آخر قاعدة مطابقة هي التي تفوز**. في المثال أعلاه، يطابق `orchestrator-planner` كلا من `*` (deny) و `orchestrator-*` (allow)، ولكن بما أن `orchestrator-*` تأتي بعد `*` فالنتيجة هي `allow`. +::: + +:::tip +يمكن للمستخدمين دائما استدعاء أي وكيل فرعي مباشرة عبر قائمة الإكمال التلقائي لـ `@`، حتى لو كانت أذونات task للوكيل سترفض ذلك. +::: + +--- + +### اللون + +خصص المظهر البصري للوكيل في واجهة المستخدم عبر خيار `color`. يؤثر ذلك على كيفية ظهور الوكيل في الواجهة. + +استخدم لونا سداسيا صالحا (مثل `#FF5733`) أو لون سمة: `primary` و `secondary` و `accent` و `success` و `warning` و `error` و `info`. + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +تحكم في تنوع الردود عبر خيار `top_p`. بديل عن temperature للتحكم بالعشوائية. + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +تتراوح القيم من 0.0 إلى 1.0. القيم الأقل أكثر تركيزا، والقيم الأعلى أكثر تنوعا. + +--- + +### خيارات إضافية + +أي خيارات أخرى تحددها في تهيئة الوكيل سيتم **تمريرها مباشرة** إلى مزود النموذج كخيارات للنموذج. يتيح لك ذلك استخدام ميزات ومعاملات خاصة بالمزود. + +على سبيل المثال، مع نماذج الاستدلال من OpenAI يمكنك التحكم في مجهود الاستدلال: + +```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" + } + } +} +``` + +هذه الخيارات الإضافية تعتمد على النموذج والمزود. راجع توثيق مزودك لمعرفة المعاملات المتاحة. + +:::tip +شغّل `opencode models` لعرض قائمة بالنماذج المتاحة. +::: + +--- + +## إنشاء وكلاء + +يمكنك إنشاء وكلاء جدد باستخدام الأمر التالي: + +```bash +opencode agent create +``` + +سيقوم هذا الأمر التفاعلي بما يلي: + +1. سيسألك أين تريد حفظ الوكيل: عام (global) أو خاص بالمشروع. +2. سيطلب وصفا لما ينبغي أن يفعله الوكيل. +3. سيولّد موجّها نظاميا ومعرّفا مناسبا. +4. سيتيح لك اختيار الأدوات التي يمكن للوكيل الوصول إليها. +5. أخيرا، سينشئ ملف Markdown يحتوي تهيئة الوكيل. + +--- + +## حالات الاستخدام + +فيما يلي بعض حالات الاستخدام الشائعة لوكلاء مختلفين. + +- **Build agent**: أعمال تطوير كاملة مع تفعيل جميع الأدوات +- **Plan agent**: تحليل وتخطيط بدون إجراء تغييرات +- **Review agent**: مراجعة الشفرة مع وصول للقراءة فقط بالإضافة إلى أدوات التوثيق +- **Debug agent**: يركز على التحقيق مع تفعيل أدوات bash والقراءة +- **Docs agent**: كتابة التوثيق مع عمليات الملفات بدون أوامر النظام + +--- + +## أمثلة + +فيما يلي بعض أمثلة الوكلاء التي قد تجدها مفيدة. + +:::tip +هل لديك وكيل تود مشاركته؟ [قدّم PR](https://github.com/anomalyco/opencode). +::: + +--- + +### وكيل التوثيق + +```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 +``` + +--- + +### مدقق أمني + +```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/ar/cli.mdx b/packages/web/src/content/docs/ar/cli.mdx new file mode 100644 index 00000000000..33463de475e --- /dev/null +++ b/packages/web/src/content/docs/ar/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: أوامر وخيارات CLI في OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +يبدأ CLI الخاص بـ OpenCode افتراضيا واجهة [TUI](/docs/tui) عند تشغيله بدون أي معاملات. + +```bash +opencode +``` + +كما يدعم أيضا أوامر موثقة في هذه الصفحة، ما يتيح لك التفاعل مع OpenCode برمجيا. + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +بدء واجهة المستخدم terminal (TUI) الخاصة بـ OpenCode. + +```bash +opencode [project] +``` + +#### الخيارات + +| الخيار | المختصر | الوصف | +| ------------ | ------- | ----------------------------------------------------------------- | +| `--continue` | `-c` | متابعة الجلسة الأخيرة | +| `--session` | `-s` | معرّف الجلسة للمتابعة | +| `--fork` | | تفريع الجلسة عند المتابعة (يستخدم مع `--continue` أو `--session`) | +| `--prompt` | | الموجّه المراد استخدامه | +| `--model` | `-m` | النموذج المراد استخدامه بصيغة provider/model | +| `--agent` | | الوكيل المراد استخدامه | +| `--port` | | المنفذ الذي يتم الاستماع عليه | +| `--hostname` | | اسم المضيف الذي يتم الاستماع عليه | + +--- + +## الأوامر + +يتضمن CLI الخاص بـ OpenCode أيضا الأوامر التالية. + +--- + +### agent + +إدارة وكلاء OpenCode. + +```bash +opencode agent [command] +``` + +--- + +### attach + +إرفاق terminal بخادم الواجهة الخلفية لـ OpenCode قيد التشغيل بالفعل، والذي تم تشغيله عبر الأمرين `serve` أو `web`. + +```bash +opencode attach [url] +``` + +يتيح ذلك استخدام واجهة TUI مع واجهة خلفية لـ OpenCode تعمل عن بعد. على سبيل المثال: + +```bash +# ابدأ خادم الواجهة الخلفية للوصول عبر الويب/الجوال +opencode web --port 4096 --hostname 0.0.0.0 + +# في محطة طرفية (terminal) أخرى، اربط TUI بالواجهة الخلفية قيد التشغيل +opencode attach http://10.20.30.40:4096 +``` + +#### الرايات + +| الراية | المختصر | الوصف | +| ----------- | ------- | ----------------------------------- | +| `--dir` | | دليل العمل الذي ستبدأ منه واجهة TUI | +| `--session` | `-s` | معرّف الجلسة للمتابعة | + +--- + +#### create + +إنشاء وكيل جديد بإعدادات مخصصة. + +```bash +opencode agent create +``` + +سيرشدك هذا الأمر خلال إنشاء وكيل جديد مع موجه نظام مخصص وإعدادات الأدوات. + +--- + +#### list + +عرض جميع الوكلاء المتاحين. + +```bash +opencode agent list +``` + +--- + +### auth + +أمر لإدارة بيانات الاعتماد وتسجيل الدخول لمزودي الخدمة. + +```bash +opencode auth [command] +``` + +--- + +#### login + +يعتمد OpenCode على قائمة المزودين في [Models.dev](https://models.dev)، لذا يمكنك استخدام `opencode auth login` لتهيئة مفاتيح API لأي مزود ترغب باستخدامه. يتم حفظ ذلك في `~/.local/share/opencode/auth.json`. + +```bash +opencode auth login +``` + +عند تشغيل OpenCode يقوم بتحميل المزودين من ملف بيانات الاعتماد، وكذلك أي مفاتيح معرّفة في متغيرات البيئة لديك أو في ملف `.env` ضمن مشروعك. + +--- + +#### list + +يسرد جميع المزودين الذين تم توثيقهم كما هم محفوظون في ملف بيانات الاعتماد. + +```bash +opencode auth list +``` + +أو النسخة المختصرة. + +```bash +opencode auth ls +``` + +--- + +#### logout + +يسجلك خارج مزود عبر حذفه من ملف بيانات الاعتماد. + +```bash +opencode auth logout +``` + +--- + +### github + +إدارة وكيل GitHub لأتمتة المستودع. + +```bash +opencode github [command] +``` + +--- + +#### install + +تثبيت وكيل GitHub في مستودعك. + +```bash +opencode github install +``` + +يقوم ذلك بإعداد سير عمل GitHub Actions اللازم ويرشدك خلال عملية التهيئة. [اعرف المزيد](/docs/github). + +--- + +#### run + +تشغيل وكيل GitHub. يُستخدم هذا عادة ضمن GitHub Actions. + +```bash +opencode github run +``` + +##### الرايات + +| الراية | الوصف | +| --------- | ------------------------------------ | +| `--event` | حدث GitHub مُحاكى لتشغيل الوكيل عليه | +| `--token` | رمز وصول شخصي لـ GitHub | + +--- + +### mcp + +إدارة خوادم Model Context Protocol. + +```bash +opencode mcp [command] +``` + +--- + +#### add + +إضافة خادم MCP إلى تهيئتك. + +```bash +opencode mcp add +``` + +سيرشدك هذا الأمر خلال إضافة خادم MCP محلي أو بعيد. + +--- + +#### list + +عرض جميع خوادم MCP المُهيأة وحالة اتصالها. + +```bash +opencode mcp list +``` + +أو استخدم النسخة المختصرة. + +```bash +opencode mcp ls +``` + +--- + +#### auth + +إجراء المصادقة مع خادم MCP يدعم OAuth. + +```bash +opencode mcp auth [name] +``` + +إذا لم تُحدِّد اسم خادم، فسيُطلب منك الاختيار من الخوادم المتاحة الداعمة لـ OAuth. + +يمكنك أيضا عرض الخوادم الداعمة لـ OAuth وحالة المصادقة الخاصة بها. + +```bash +opencode mcp auth list +``` + +أو استخدم النسخة المختصرة. + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +إزالة بيانات اعتماد OAuth لخادم MCP. + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +تشخيص مشاكل اتصال OAuth لخادم MCP. + +```bash +opencode mcp debug +``` + +--- + +### models + +عرض جميع النماذج المتاحة من المزودين المُهيأين. + +```bash +opencode models [provider] +``` + +يعرض هذا الأمر جميع النماذج المتاحة عبر المزودين المُهيأين لديك بصيغة `provider/model`. + +هذا مفيد لتحديد اسم النموذج الدقيق الذي ستستخدمه في [تهيئتك](/docs/config/). + +يمكنك اختياريا تمرير معرّف مزود لتصفية النماذج حسب ذلك المزود. + +```bash +opencode models anthropic +``` + +#### الرايات + +| الراية | الوصف | +| ----------- | ------------------------------------------------------------- | +| `--refresh` | تحديث ذاكرة التخزين المؤقت للنماذج من models.dev | +| `--verbose` | استخدام مخرجات أكثر تفصيلا للنماذج (تشمل بيانات مثل التكاليف) | + +استخدم الراية `--refresh` لتحديث قائمة النماذج المخزنة مؤقتا. يفيد ذلك عند إضافة نماذج جديدة إلى مزود وتريد رؤيتها في OpenCode. + +```bash +opencode models --refresh +``` + +--- + +### run + +تشغيل opencode في وضع غير تفاعلي عبر تمرير موجه مباشرة. + +```bash +opencode run [message..] +``` + +هذا مفيد للبرمجة النصية والأتمتة، أو عندما تريد إجابة سريعة دون تشغيل واجهة TUI كاملة. على سبيل المثال. + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +يمكنك أيضا الإرفاق بمثيل `opencode serve` قيد التشغيل لتجنّب زمن الإقلاع البارد لخوادم MCP في كل تشغيل: + +```bash +# ابدأ خادمًا بلا واجهة في محطة طرفية واحدة +opencode serve + +# في محطة طرفية أخرى، شغّل الأوامر التي ترتبط به +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### الرايات + +| الراية | المختصر | الوصف | +| ------------ | ------- | ----------------------------------------------------------------- | +| `--command` | | الأمر المراد تشغيله؛ استخدم الرسالة كوسائط | +| `--continue` | `-c` | متابعة الجلسة الأخيرة | +| `--session` | `-s` | معرّف الجلسة للمتابعة | +| `--fork` | | تفريع الجلسة عند المتابعة (يستخدم مع `--continue` أو `--session`) | +| `--share` | | مشاركة الجلسة | +| `--model` | `-m` | النموذج المراد استخدامه بصيغة provider/model | +| `--agent` | | الوكيل المراد استخدامه | +| `--file` | `-f` | ملف/ملفات لإرفاقها بالرسالة | +| `--format` | | التنسيق: default (منسق) أو json (أحداث JSON خام) | +| `--title` | | عنوان للجلسة (يستخدم موجهًا مقتطعًا إن لم تُحدَّد قيمة) | +| `--attach` | | الإرفاق بخادم opencode قيد التشغيل (مثل http://localhost:4096) | +| `--port` | | منفذ الخادم المحلي (الافتراضي منفذ عشوائي) | + +--- + +### serve + +بدء خادم OpenCode بدون واجهة للوصول عبر API. راجع [توثيق الخادم](/docs/server) لواجهة HTTP الكاملة. + +```bash +opencode serve +``` + +يشغّل هذا خادم HTTP يوفّر وصولا عبر API لوظائف opencode دون واجهة TUI. اضبط `OPENCODE_SERVER_PASSWORD` لتفعيل مصادقة HTTP الأساسية (اسم المستخدم الافتراضي `opencode`). + +#### الرايات + +| الراية | الوصف | +| ------------ | ----------------------------------------- | +| `--port` | المنفذ الذي يتم الاستماع عليه | +| `--hostname` | اسم المضيف الذي يتم الاستماع عليه | +| `--mdns` | تفعيل اكتشاف mDNS | +| `--cors` | أصول/منشأات إضافية للمتصفح للسماح بـ CORS | + +--- + +### session + +إدارة جلسات OpenCode. + +```bash +opencode session [command] +``` + +--- + +#### list + +عرض جميع جلسات OpenCode. + +```bash +opencode session list +``` + +##### الرايات + +| الراية | المختصر | الوصف | +| ------------- | ------- | ------------------------------------- | +| `--max-count` | `-n` | حصر النتائج في أحدث N جلسات | +| `--format` | | تنسيق المخرجات: table أو json (table) | + +--- + +### stats + +عرض إحصاءات استخدام الرموز والتكلفة لجلسات OpenCode لديك. + +```bash +opencode stats +``` + +#### الرايات + +| الراية | الوصف | +| ----------- | ------------------------------------------------------------------------- | +| `--days` | عرض الإحصاءات لآخر N يومًا (الافتراضي: كل الوقت) | +| `--tools` | عدد الأدوات المطلوب عرضها (الافتراضي: الكل) | +| `--models` | عرض تفصيل استخدام النماذج (مخفي افتراضيا). مرّر رقمًا لعرض أعلى N | +| `--project` | التصفية حسب المشروع (الافتراضي: كل المشاريع، سلسلة فارغة: المشروع الحالي) | + +--- + +### export + +تصدير بيانات الجلسة بصيغة JSON. + +```bash +opencode export [sessionID] +``` + +إذا لم تُقدّم معرّف جلسة، فسيُطلب منك الاختيار من الجلسات المتاحة. + +--- + +### import + +استيراد بيانات الجلسة من ملف JSON أو رابط مشاركة OpenCode. + +```bash +opencode import +``` + +يمكنك الاستيراد من ملف محلي أو من رابط مشاركة OpenCode. + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +بدء خادم OpenCode بدون واجهة مع واجهة ويب. + +```bash +opencode web +``` + +يشغّل هذا خادم HTTP ويفتح متصفح ويب للوصول إلى OpenCode عبر واجهة ويب. اضبط `OPENCODE_SERVER_PASSWORD` لتفعيل مصادقة HTTP الأساسية (اسم المستخدم الافتراضي `opencode`). + +#### الرايات + +| الراية | الوصف | +| ------------ | ----------------------------------------- | +| `--port` | المنفذ الذي يتم الاستماع عليه | +| `--hostname` | اسم المضيف الذي يتم الاستماع عليه | +| `--mdns` | تفعيل اكتشاف mDNS | +| `--cors` | أصول/منشأات إضافية للمتصفح للسماح بـ CORS | + +--- + +### acp + +بدء خادم ACP (Agent Client Protocol). + +```bash +opencode acp +``` + +يشغّل هذا الأمر خادم ACP يتواصل عبر stdin/stdout باستخدام nd-JSON. + +#### الرايات + +| الراية | الوصف | +| ------------ | --------------------------------- | +| `--cwd` | دليل العمل | +| `--port` | المنفذ الذي يتم الاستماع عليه | +| `--hostname` | اسم المضيف الذي يتم الاستماع عليه | + +--- + +### uninstall + +إلغاء تثبيت OpenCode وإزالة جميع الملفات ذات الصلة. + +```bash +opencode uninstall +``` + +#### الرايات + +| الراية | المختصر | الوصف | +| --------------- | ------- | ----------------------------------- | +| `--keep-config` | `-c` | الإبقاء على ملفات التهيئة | +| `--keep-data` | `-d` | الإبقاء على بيانات الجلسات واللقطات | +| `--dry-run` | | عرض ما سيتم حذفه دون تنفيذ الحذف | +| `--force` | `-f` | تخطي مطالبات التأكيد | + +--- + +### upgrade + +تحديث opencode إلى أحدث إصدار أو إلى إصدار محدد. + +```bash +opencode upgrade [target] +``` + +للترقية إلى أحدث إصدار. + +```bash +opencode upgrade +``` + +للترقية إلى إصدار محدد. + +```bash +opencode upgrade v0.1.48 +``` + +#### الرايات + +| الراية | المختصر | الوصف | +| ---------- | ------- | ----------------------------------------------------------- | +| `--method` | `-m` | طريقة التثبيت المستخدمة: curl أو npm أو pnpm أو bun أو brew | + +--- + +## الخيارات العامة + +يدعم سطر أوامر opencode الخيارات العامة التالية. + +| الراية | المختصر | الوصف | +| -------------- | ------- | -------------------------------------- | +| `--help` | `-h` | عرض المساعدة | +| `--version` | `-v` | طباعة رقم الإصدار | +| `--print-logs` | | طباعة السجلات إلى stderr | +| `--log-level` | | مستوى السجل (DEBUG, INFO, WARN, ERROR) | + +--- + +## متغيرات البيئة + +يمكن تهيئة OpenCode باستخدام متغيرات البيئة. + +| المتغير | النوع | الوصف | +| ------------------------------------- | ------- | --------------------------------------------------------- | +| `OPENCODE_AUTO_SHARE` | boolean | مشاركة الجلسات تلقائيا | +| `OPENCODE_GIT_BASH_PATH` | string | مسار ملف Git Bash التنفيذي على Windows | +| `OPENCODE_CONFIG` | string | مسار ملف التهيئة | +| `OPENCODE_CONFIG_DIR` | string | مسار دليل التهيئة | +| `OPENCODE_CONFIG_CONTENT` | string | محتوى تهيئة JSON مُضمّن | +| `OPENCODE_DISABLE_AUTOUPDATE` | boolean | تعطيل التحقق التلقائي من التحديثات | +| `OPENCODE_DISABLE_PRUNE` | boolean | تعطيل تنقية البيانات القديمة | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | تعطيل تحديث عنوان terminal تلقائيا | +| `OPENCODE_PERMISSION` | string | تهيئة أذونات JSON مُضمّنة | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | تعطيل الإضافات الافتراضية | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | تعطيل تنزيل خوادم LSP تلقائيا | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | تفعيل النماذج التجريبية | +| `OPENCODE_DISABLE_AUTOCOMPACT` | boolean | تعطيل ضغط السياق تلقائيا | +| `OPENCODE_DISABLE_CLAUDE_CODE` | boolean | تعطيل القراءة من `.claude` (الموجه + المهارات) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | تعطيل قراءة `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | تعطيل تحميل `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | boolean | تعطيل جلب النماذج من مصادر بعيدة | +| `OPENCODE_FAKE_VCS` | string | مزود VCS وهمي لأغراض الاختبار | +| `OPENCODE_DISABLE_FILETIME_CHECK` | boolean | تعطيل التحقق من وقت الملف لتحسين الأداء | +| `OPENCODE_CLIENT` | string | معرّف العميل (الافتراضي `cli`) | +| `OPENCODE_ENABLE_EXA` | boolean | تفعيل أدوات بحث الويب من Exa | +| `OPENCODE_SERVER_PASSWORD` | string | تفعيل المصادقة الأساسية لخادمي `serve`/`web` | +| `OPENCODE_SERVER_USERNAME` | string | تجاوز اسم مستخدم المصادقة الأساسية (الافتراضي `opencode`) | +| `OPENCODE_MODELS_URL` | string | رابط مخصص لجلب تهيئة النماذج | + +--- + +### تجريبي + +تقوم متغيرات البيئة التالية بتفعيل ميزات تجريبية قد تتغير أو تتم إزالتها. + +| المتغير | النوع | الوصف | +| ----------------------------------------------- | ------- | ------------------------------------------- | +| `OPENCODE_EXPERIMENTAL` | boolean | تفعيل جميع الميزات التجريبية | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | تفعيل اكتشاف الأيقونات | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | تعطيل النسخ عند التحديد في TUI | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number | المهلة الافتراضية لأوامر bash بالميلي ثانية | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | number | الحد الأقصى لرموز المخرجات لاستجابات LLM | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolean | تفعيل مراقب الملفات لكامل الدليل | +| `OPENCODE_EXPERIMENTAL_OXFMT` | boolean | تفعيل مُنسّق oxfmt | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolean | تفعيل أداة LSP تجريبية | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | تعطيل مراقب الملفات | +| `OPENCODE_EXPERIMENTAL_EXA` | boolean | تفعيل ميزات Exa التجريبية | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolean | تفعيل تدقيق أنواع LSP تجريبي | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolean | تفعيل ميزات markdown تجريبية | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolean | تفعيل وضع الخطة | diff --git a/packages/web/src/content/docs/ar/commands.mdx b/packages/web/src/content/docs/ar/commands.mdx new file mode 100644 index 00000000000..da14065212d --- /dev/null +++ b/packages/web/src/content/docs/ar/commands.mdx @@ -0,0 +1,322 @@ +--- +title: الأوامر +description: أنشئ أوامر مخصصة للمهام المتكررة. +--- + +تتيح لك الأوامر المخصصة تحديد مُطالبة (prompt) تريد تشغيلها عند تنفيذ ذلك الأمر في واجهة TUI. + +```bash frame="none" +/my-command +``` + +تُعدّ الأوامر المخصصة إضافةً إلى الأوامر المضمنة مثل `/init` و`/undo` و`/redo` و`/share` و`/help`. [اعرف المزيد](/docs/tui#commands). + +--- + +## إنشاء ملفات الأوامر + +أنشئ ملفات Markdown داخل الدليل `commands/` لتعريف أوامر مخصصة. + +أنشئ الملف `.opencode/commands/test.md`: + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +تُعرِّف ترويسة Frontmatter خصائص الأمر، بينما يصبح المحتوى هو القالب. + +استخدم الأمر بكتابة `/` ثم اسم الأمر. + +```bash frame="none" +"/test" +``` + +--- + +## الإعداد + +يمكنك إضافة أوامر مخصصة عبر إعدادات OpenCode أو بإنشاء ملفات Markdown داخل الدليل `commands/`. + +--- + +### JSON + +استخدم خيار `command` في [config](/docs/config) الخاص بـ OpenCode: + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // يصبح هذا اسم الأمر + "test": { + // هذه هي المطالبة التي ستُرسل إلى LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // يظهر هذا كوصف في TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +يمكنك الآن تشغيل هذا الأمر في واجهة TUI: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +يمكنك أيضًا تعريف الأوامر باستخدام ملفات Markdown. ضعها في: + +- على مستوى النظام: `~/.config/opencode/commands/` +- لكل مشروع: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +يصبح اسم ملف Markdown هو اسم الأمر. على سبيل المثال، يتيح لك `test.md` تشغيل: + +```bash frame="none" +/test +``` + +--- + +## إعداد المُطالبة + +تدعم مُطالبات الأوامر المخصصة عدة عناصر نائبة (placeholders) وبنى خاصة. + +--- + +### الوسائط + +مرِّر وسائط إلى الأوامر باستخدام العنصر النائب `$ARGUMENTS`. + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +شغِّل الأمر مع وسائط: + +```bash frame="none" +/component Button +``` + +وسيُستبدل `$ARGUMENTS` بالقيمة `Button`. + +يمكنك أيضًا الوصول إلى كل وسيط على حدة باستخدام المعاملات الموضعية: + +- `$1` - الوسيط الأول +- `$2` - الوسيط الثاني +- `$3` - الوسيط الثالث +- وهكذا... + +على سبيل المثال: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +شغِّل الأمر: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +سيؤدي ذلك إلى استبدال: + +- `$1` بـ `config.json` +- `$2` بـ `src` +- `$3` بـ `{ "key": "value" }` + +--- + +### خرج shell + +استخدم _!`command`_ لحقن خرج [أمر bash](/docs/tui#bash-commands) داخل مُطالبتك. + +على سبيل المثال، لإنشاء أمر مخصص يُحلل تغطية الاختبارات: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +أو لمراجعة التغييرات الأخيرة: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +تُشغَّل الأوامر في دليل جذر مشروعك ويصبح خرجها جزءًا من المُطالبة. + +--- + +### مراجع الملفات + +ضمِّن الملفات في أمرك باستخدام `@` ثم اسم الملف. + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +يُدرج محتوى الملف في المُطالبة تلقائيًا. + +--- + +## الخيارات + +لنلقِ نظرةً على خيارات الإعداد بالتفصيل. + +--- + +### القالب (`template`) + +يُعرِّف خيار `template` المُطالبة التي ستُرسل إلى نموذج اللغة (LLM) عند تنفيذ الأمر. + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +هذا خيار إعداد **إلزامي**. + +--- + +### الوصف (`description`) + +استخدم خيار `description` لتقديم وصف موجز لما يفعله الأمر. + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +يظهر هذا الوصف في واجهة TUI عند كتابة الأمر. + +--- + +### الوكيل (`agent`) + +استخدم إعداد `agent` لتحديد أي [agent](/docs/agents) ينبغي أن ينفّذ هذا الأمر (اختياريًا). +إذا كان هذا [subagent](/docs/agents/#subagents)، فسيؤدي الأمر افتراضيًا إلى تشغيل استدعاء subagent. +لإيقاف هذا السلوك، عيِّن `subtask` إلى `false`. + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +هذا خيار إعداد **اختياري**. إن لم تُحدده، فسيُستخدم agent الحالي افتراضيًا. + +--- + +### مهمة فرعية (`subtask`) + +استخدم القيمة المنطقية `subtask` لفرض أن يُشغِّل الأمر استدعاء [subagent](/docs/agents/#subagents). +يفيد هذا إذا أردت ألا يلوّث الأمر السياق الأساسي لديك، إذ سيُجبر (**force**) الـ agent على العمل كـ subagent، +حتى لو كان `mode` مضبوطًا على `primary` في إعدادات [agent](/docs/agents). + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +هذا خيار إعداد **اختياري**. + +--- + +### النموذج (`model`) + +استخدم إعداد `model` لتجاوز النموذج الافتراضي لهذا الأمر. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +هذا خيار إعداد **اختياري**. + +--- + +## الأوامر المضمنة + +يتضمن opencode عدة أوامر مضمنة مثل `/init` و`/undo` و`/redo` و`/share` و`/help`؛ [اعرف المزيد](/docs/tui#commands). + +:::note +يمكن للأوامر المخصصة تجاوز الأوامر المضمنة. +::: + +إذا عرّفت أمرًا مخصصًا بالاسم نفسه، فسيستبدل الأمر المضمن. diff --git a/packages/web/src/content/docs/ar/config.mdx b/packages/web/src/content/docs/ar/config.mdx new file mode 100644 index 00000000000..d415969972d --- /dev/null +++ b/packages/web/src/content/docs/ar/config.mdx @@ -0,0 +1,684 @@ +--- +title: الإعدادات +description: استخدام ملف إعدادات OpenCode بصيغة JSON. +--- + +يمكنك ضبط OpenCode باستخدام ملف إعدادات بصيغة JSON. + +--- + +## التنسيق + +يدعم OpenCode تنسيقي **JSON** و**JSONC** (JSON مع تعليقات). + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + // إعدادات السمة + "theme": "opencode", + "model": "anthropic/claude-sonnet-4-5", + "autoupdate": true, +} +``` + +--- + +## المواقع + +يمكنك وضع ملف الإعدادات في عدة مواقع مختلفة، ولكل موقع +ترتيب أولوية مختلف. + +:::note +تُدمَج ملفات الإعدادات **معًا** ولا تُستبدَل. +::: + +تُدمَج ملفات الإعدادات معًا ولا تُستبدَل. يتم جمع الإعدادات من مواقع الإعدادات التالية. تتجاوز الإعدادات اللاحقة الإعدادات السابقة فقط عند تعارض المفاتيح. أما الإعدادات غير المتعارضة فتبقى محفوظة من جميع الملفات. + +على سبيل المثال، إذا كان الإعداد العام يضبط `theme: "opencode"` و`autoupdate: true`، وكان إعداد المشروع يضبط `model: "anthropic/claude-sonnet-4-5"`، فستتضمن الإعدادات النهائية الخيارات الثلاثة جميعها. + +--- + +### ترتيب الأولوية + +تُحمَّل مصادر الإعدادات بهذا الترتيب (المصادر اللاحقة تتجاوز السابقة): + +1. **الإعدادات البعيدة** (من `.well-known/opencode`) - الإعدادات الافتراضية على مستوى المؤسسة +2. **الإعدادات العامة** (`~/.config/opencode/opencode.json`) - تفضيلات المستخدم +3. **إعدادات مخصصة** (`OPENCODE_CONFIG` env var) - تجاوزات مخصصة +4. **إعدادات المشروع** (`opencode.json` داخل المشروع) - إعدادات خاصة بالمشروع +5. **أدلة `.opencode`** - الوكلاء، الأوامر، الإضافات +6. **إعدادات ضمنية** (`OPENCODE_CONFIG_CONTENT` env var) - تجاوزات وقت التشغيل + +هذا يعني أن إعدادات المشروع يمكنها تجاوز الإعدادات العامة، وأن الإعدادات العامة يمكنها تجاوز الإعدادات الافتراضية البعيدة على مستوى المؤسسة. + +:::note +يستخدم الدليلان `.opencode` و`~/.config/opencode` **أسماء جمع** للأدلة الفرعية: `agents/` و`commands/` و`modes/` و`plugins/` و`skills/` و`tools/` و`themes/`. كما تُدعَم أسماء المفرد (مثل `agent/`) للتوافق مع الإصدارات السابقة. +::: + +--- + +### عن بُعد + +يمكن للمؤسسات توفير إعدادات افتراضية عبر نقطة النهاية `.well-known/opencode`. يتم جلب ذلك تلقائيًا عندما تقوم بالمصادقة مع مزوّد يدعم هذه الميزة. + +تُحمَّل الإعدادات البعيدة أولًا لتكون طبقة الأساس. ويمكن لجميع مصادر الإعدادات الأخرى (العامة، وإعدادات المشروع) تجاوز هذه القيم الافتراضية. + +على سبيل المثال، إذا كانت مؤسستك توفر خوادم MCP معطّلة افتراضيًا: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +يمكنك تفعيل خوادم محددة في إعداداتك المحلية: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### عام + +ضع إعدادات OpenCode العامة في `~/.config/opencode/opencode.json`. استخدم الإعدادات العامة للتفضيلات على مستوى المستخدم مثل السمات، والمزوّدين، أو اختصارات المفاتيح. + +تتجاوز الإعدادات العامة القيم الافتراضية البعيدة الخاصة بالمؤسسة. + +--- + +### لكل مشروع + +أضف `opencode.json` في جذر مشروعك. تمتلك إعدادات المشروع أعلى أولوية بين ملفات الإعدادات القياسية، إذ تتجاوز الإعدادات العامة والبعيدة معًا. + +:::tip +ضع إعدادات المشروع الخاصة في جذر مشروعك. +::: + +عند تشغيل OpenCode، يبحث عن ملف إعدادات في الدليل الحالي أو يصعد حتى أقرب دليل Git. + +ومن الآمن أيضًا تضمينه في Git، كما يستخدم نفس المخطط الخاص بالإعدادات العامة. + +--- + +### مسار مخصص + +حدّد مسار ملف إعدادات مخصصًا باستخدام متغير البيئة `OPENCODE_CONFIG`. + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +تُحمَّل الإعدادات المخصصة بين الإعدادات العامة وإعدادات المشروع ضمن ترتيب الأولوية. + +--- + +### دليل مخصص + +حدّد دليل إعدادات مخصصًا باستخدام متغير البيئة `OPENCODE_CONFIG_DIR`. +سيتم البحث داخل هذا الدليل عن الوكلاء والأوامر والأوضاع والإضافات تمامًا مثل +الدليل القياسي `.opencode`، ويجب أن يتبع نفس البنية. + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +يُحمَّل الدليل المخصص بعد الإعدادات العامة وأدلة `.opencode`، لذلك **يمكنه تجاوز** إعداداتها. + +--- + +## المخطط + +يحتوي ملف الإعدادات على مخطط مُعرَّف في [**`opencode.ai/config.json`**](https://opencode.ai/config.json). + +يفترض أن يتمكن محررك من التحقق والإكمال التلقائي اعتمادًا على هذا المخطط. + +--- + +### TUI + +يمكنك ضبط الإعدادات الخاصة بـ TUI عبر الخيار `tui`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +الخيارات المتاحة: + +- `scroll_acceleration.enabled` - تفعيل تسارع التمرير بأسلوب macOS. **له أولوية على `scroll_speed`.** +- `scroll_speed` - مُضاعِف سرعة تمرير مخصص (الافتراضي: `3`، الحد الأدنى: `1`). يتم تجاهله إذا كان `scroll_acceleration.enabled` مساويًا لـ `true`. +- `diff_style` - التحكم في عرض `diff`. القيمة `"auto"` تتكيف مع عرض terminal، و`"stacked"` تعرض عمودًا واحدًا دائمًا. + +[تعرف على المزيد حول استخدام TUI هنا](/docs/tui). + +--- + +### الخادم + +يمكنك ضبط إعدادات الخادم لأوامر `opencode serve` و`opencode web` عبر الخيار `server`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +الخيارات المتاحة: + +- `port` - المنفذ الذي سيتم الاستماع عليه. +- `hostname` - اسم المضيف الذي سيتم الاستماع عليه. عند تفعيل `mdns` وعدم ضبط اسم مضيف، تكون القيمة الافتراضية `0.0.0.0`. +- `mdns` - تفعيل اكتشاف الخدمة عبر mDNS. يتيح ذلك للأجهزة الأخرى على الشبكة اكتشاف خادم OpenCode. +- `mdnsDomain` - اسم نطاق مخصص لخدمة mDNS. القيمة الافتراضية هي `opencode.local`. مفيد لتشغيل عدة نُسخ على نفس الشبكة. +- `cors` - أصول إضافية مسموح بها لـ CORS عند استخدام خادم HTTP من عميل يعتمد على المتصفح. يجب أن تكون القيم أصولًا كاملة (البروتوكول + المضيف + منفذ اختياري)، مثل `https://app.example.com`. + +[تعرف على المزيد حول الخادم هنا](/docs/server). + +--- + +### الأدوات + +يمكنك إدارة الأدوات التي يمكن لـ LLM استخدامها عبر الخيار `tools`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[تعرف على المزيد حول الأدوات هنا](/docs/tools). + +--- + +### النماذج + +يمكنك ضبط المزوّدين والنماذج التي تريد استخدامها في إعدادات OpenCode عبر الخيارات `provider` و`model` و`small_model`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +يضبط الخيار `small_model` نموذجًا منفصلًا للمهام الخفيفة مثل توليد العناوين. افتراضيًا يحاول OpenCode استخدام نموذج أقل تكلفة إذا كان متاحًا لدى مزوّدك، وإلا فسيعود إلى النموذج الرئيسي. + +قد تتضمن خيارات المزوّد `timeout` و`setCacheKey`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` - مهلة الطلب بالميلي ثانية (الافتراضي: 300000). اضبطه إلى `false` لتعطيله. +- `setCacheKey` - يضمن تعيين مفتاح التخزين المؤقت دائمًا للمزوّد المحدد. + +يمكنك أيضًا ضبط [النماذج المحلية](/docs/models#local). [تعرف على المزيد](/docs/models). + +--- + +#### خيارات خاصة بالمزوّد + +يدعم بعض المزوّدين خيارات إعداد إضافية تتجاوز الإعدادات العامة مثل `timeout` و`apiKey`. + +##### Amazon Bedrock + +يدعم Amazon Bedrock إعدادات خاصة بـ AWS: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` - منطقة AWS لـ Bedrock (الافتراضي: متغير البيئة `AWS_REGION` أو `us-east-1`) +- `profile` - ملف تعريف AWS المُسمّى من `~/.aws/credentials` (الافتراضي: متغير البيئة `AWS_PROFILE`) +- `endpoint` - عنوان URL لنقطة نهاية مخصصة لنقاط نهاية VPC. هذا اسم بديل للخيار العام `baseURL` باستخدام مصطلحات AWS. إذا تم تحديدهما معًا، تكون أولوية `endpoint` أعلى. + +:::note +لرموز Bearer (`AWS_BEARER_TOKEN_BEDROCK` أو `/connect`) أولوية أعلى من المصادقة القائمة على ملف التعريف. راجع [أولوية المصادقة](/docs/providers#authentication-precedence) للتفاصيل. +::: + +[تعرف على المزيد حول إعداد Amazon Bedrock](/docs/providers#amazon-bedrock). + +--- + +### السمات + +يمكنك ضبط السمة التي تريد استخدامها في إعدادات OpenCode عبر الخيار `theme`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[تعرف على المزيد هنا](/docs/themes). + +--- + +### الوكلاء + +يمكنك ضبط وكلاء متخصصين لمهام محددة عبر الخيار `agent`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // تعطيل أدوات تعديل الملفات لوكيل المراجعة فقط + "write": false, + "edit": false, + }, + }, + }, +} +``` + +يمكنك أيضًا تعريف الوكلاء باستخدام ملفات markdown في `~/.config/opencode/agents/` أو `.opencode/agents/`. [تعرف على المزيد هنا](/docs/agents). + +--- + +### الوكيل الافتراضي + +يمكنك تعيين الوكيل الافتراضي باستخدام الخيار `default_agent`. يحدد ذلك أي وكيل سيتم استخدامه عندما لا يتم تحديد وكيل صراحةً. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +يجب أن يكون الوكيل الافتراضي وكيلًا أساسيًا (وليس وكيلًا فرعيًا). يمكن أن يكون وكيلًا مدمجًا مثل `"build"` أو `"plan"`، أو [وكيلًا مخصصًا](/docs/agents) قمت بتعريفه. إذا لم يكن الوكيل المحدد موجودًا أو كان وكيلًا فرعيًا، فسيعود OpenCode إلى `"build"` مع تحذير. + +ينطبق هذا الإعداد على جميع الواجهات: TUI وCLI (`opencode run`) وتطبيق سطح المكتب وGitHub Action. + +--- + +### المشاركة + +يمكنك ضبط ميزة [share](/docs/share) عبر الخيار `share`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +يقبل هذا الإعداد القيم التالية: + +- `"manual"` - السماح بالمشاركة اليدوية عبر الأوامر (الافتراضي) +- `"auto"` - مشاركة المحادثات الجديدة تلقائيًا +- `"disabled"` - تعطيل المشاركة بالكامل + +افتراضيًا تكون المشاركة في الوضع اليدوي، حيث تحتاج إلى مشاركة المحادثات صراحةً باستخدام الأمر `/share`. + +--- + +### الأوامر + +يمكنك ضبط أوامر مخصصة للمهام المتكررة عبر الخيار `command`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +يمكنك أيضًا تعريف الأوامر باستخدام ملفات markdown في `~/.config/opencode/commands/` أو `.opencode/commands/`. [تعرف على المزيد هنا](/docs/commands). + +--- + +### اختصارات المفاتيح + +يمكنك تخصيص اختصارات المفاتيح عبر الخيار `keybinds`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[تعرف على المزيد هنا](/docs/keybinds). + +--- + +### التحديث التلقائي + +سيقوم OpenCode بتنزيل أي تحديثات جديدة تلقائيًا عند بدء التشغيل. يمكنك تعطيل ذلك عبر الخيار `autoupdate`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +إذا لم تكن تريد التحديثات لكنك تريد الإشعار عند توفر نسخة جديدة، فاضبط `autoupdate` على `"notify"`. +لاحظ أن هذا يعمل فقط إذا لم يتم تثبيته عبر مدير حزم مثل Homebrew. + +--- + +### المنسّقات + +يمكنك ضبط منسّقات الشفرة عبر الخيار `formatter`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[تعرف على المزيد حول المنسّقات هنا](/docs/formatters). + +--- + +### الأذونات + +افتراضيًا يسمح opencode **بجميع العمليات** دون الحاجة إلى موافقة صريحة. يمكنك تغيير ذلك عبر الخيار `permission`. + +على سبيل المثال، لضمان أن أداتي `edit` و`bash` تتطلبان موافقة المستخدم: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[تعرف على المزيد حول الأذونات هنا](/docs/permissions). + +--- + +### ضغط السياق + +يمكنك التحكم في سلوك ضغط السياق عبر الخيار `compaction`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto` - ضغط الجلسة تلقائيًا عند امتلاء السياق (الافتراضي: `true`). +- `prune` - إزالة مخرجات الأدوات القديمة لتوفير الرموز (tokens) (الافتراضي: `true`). + +--- + +### المراقِب + +يمكنك ضبط أنماط التجاهل لمراقِب الملفات عبر الخيار `watcher`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +تتبع الأنماط صياغة `glob`. استخدم ذلك لاستبعاد الأدلة المزدحمة من مراقبة الملفات. + +--- + +### خوادم MCP + +يمكنك ضبط خوادم MCP التي تريد استخدامها عبر الخيار `mcp`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[تعرف على المزيد هنا](/docs/mcp-servers). + +--- + +### الإضافات + +[الإضافات](/docs/plugins) توسّع OpenCode بأدوات وخُطافات وتكاملات مخصصة. + +ضع ملفات الإضافات في `.opencode/plugins/` أو `~/.config/opencode/plugins/`. يمكنك أيضًا تحميل إضافات من npm عبر الخيار `plugin`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[تعرف على المزيد هنا](/docs/plugins). + +--- + +### التعليمات + +يمكنك ضبط التعليمات الخاصة بالنموذج الذي تستخدمه عبر الخيار `instructions`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +يقبل هذا مصفوفة من المسارات وأنماط `glob` لملفات التعليمات. [تعرف على المزيد +حول القواعد هنا](/docs/rules). + +--- + +### المزوّدون المعطّلون + +يمكنك تعطيل المزوّدين الذين يتم تحميلهم تلقائيًا عبر الخيار `disabled_providers`. هذا مفيد عندما تريد منع تحميل مزوّدين معينين حتى لو كانت بيانات الاعتماد الخاصة بهم متاحة. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +الخيار `disabled_providers` له أولوية على `enabled_providers`. +::: + +يقبل الخيار `disabled_providers` مصفوفة من معرفات المزوّدين. عند تعطيل مزوّد: + +- لن يتم تحميله حتى لو كانت متغيرات البيئة مضبوطة. +- لن يتم تحميله حتى لو كانت مفاتيح API مضبوطة عبر الأمر `/connect`. +- لن تظهر نماذج هذا المزوّد في قائمة اختيار النموذج. + +--- + +### المزوّدون المفعّلون + +يمكنك تحديد قائمة سماح للمزوّدين عبر الخيار `enabled_providers`. عند ضبطه، سيتم تفعيل المزوّدين المحددين فقط وسيتم تجاهل البقية. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +هذا مفيد عندما تريد تقييد OpenCode لاستخدام مزوّدين محددين بدلًا من تعطيلهم واحدًا تلو الآخر. + +:::note +الخيار `disabled_providers` له أولوية على `enabled_providers`. +::: + +إذا ظهر مزوّد ضمن كل من `enabled_providers` و`disabled_providers`، تكون أولوية `disabled_providers` أعلى للتوافق مع الإصدارات السابقة. + +--- + +### تجريبي + +يحتوي المفتاح `experimental` على خيارات قيد التطوير النشط. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +الخيارات التجريبية غير مستقرة. قد تتغير أو تُزال دون إشعار. +::: + +--- + +## المتغيرات + +يمكنك استخدام استبدال المتغيرات في ملفات الإعدادات للإشارة إلى متغيرات البيئة ومحتويات الملفات. + +--- + +### متغيرات البيئة + +استخدم `{env:VARIABLE_NAME}` لاستبدال متغيرات البيئة: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +إذا لم يكن متغير البيئة مضبوطًا، فسيتم استبداله بسلسلة فارغة. + +--- + +### الملفات + +استخدم `{file:path/to/file}` لاستبدال محتويات ملف: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +يمكن أن تكون مسارات الملفات: + +- نسبية إلى دليل ملف الإعدادات +- أو مسارات مطلقة تبدأ بـ `/` أو `~` + +يُفيد ذلك في: + +- الاحتفاظ بالبيانات الحساسة مثل مفاتيح API في ملفات منفصلة. +- تضمين ملفات تعليمات كبيرة دون تشويش ملف الإعدادات. +- مشاركة مقتطفات إعدادات مشتركة عبر عدة ملفات إعدادات. diff --git a/packages/web/src/content/docs/ar/custom-tools.mdx b/packages/web/src/content/docs/ar/custom-tools.mdx new file mode 100644 index 00000000000..9382627fab6 --- /dev/null +++ b/packages/web/src/content/docs/ar/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: الأدوات المخصصة +description: أنشئ أدوات يمكن لـ LLM استدعاؤها في opencode. +--- + +الأدوات المخصصة هي دوال تنشئها يمكن لـ LLM استدعاؤها أثناء المحادثات. تعمل جنبا إلى جنب مع [الأدوات المدمجة](/docs/tools) في opencode مثل `read` و`write` و`bash`. + +--- + +## إنشاء أداة + +تُعرّف الأدوات كملفات **TypeScript** أو **JavaScript**. لكن تعريف الأداة يمكنه استدعاء سكربتات مكتوبة **بأي لغة** — إذ تُستخدم TypeScript أو JavaScript فقط لتعريف الأداة نفسه. + +--- + +### الموقع + +يمكن تعريفها: + +- محليا بوضعها في مجلد `.opencode/tools/` داخل مشروعك. +- أو عالميا بوضعها في `~/.config/opencode/tools/`. + +--- + +### البنية + +أسهل طريقة لإنشاء أدوات هي استخدام المساعد `tool()` الذي يوفر أمان الأنواع والتحقق. + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +يصبح **اسم الملف** هو **اسم الأداة**. المثال أعلاه ينشئ أداة باسم `database`. + +--- + +#### عدة أدوات في ملف واحد + +يمكنك أيضا تصدير عدة أدوات من ملف واحد. يصبح كل تصدير **أداة مستقلة** باسم **`_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +ينشئ هذا أداتين: `math_add` و`math_multiply`. + +--- + +### الوسائط + +يمكنك استخدام `tool.schema`، وهو في الأساس [Zod](https://zod.dev)، لتعريف أنواع الوسائط. + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +يمكنك أيضا استيراد [Zod](https://zod.dev) مباشرة وإرجاع كائن عادي: + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### السياق + +تستقبل الأدوات سياقا حول الجلسة الحالية: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +استخدم `context.directory` لدليل العمل الخاص بالجلسة. +استخدم `context.worktree` لجذر شجرة العمل (worktree) في git. + +--- + +## أمثلة + +### كتابة أداة بلغة Python + +يمكنك كتابة أدواتك بأي لغة تريدها. إليك مثالا يجمع رقمين باستخدام Python. + +أولا، أنشئ الأداة كسكربت Python: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +ثم أنشئ تعريف الأداة الذي يستدعيه: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +هنا نستخدم أداة [`Bun.$`](https://bun.com/docs/runtime/shell) لتشغيل سكربت Python. diff --git a/packages/web/src/content/docs/ar/ecosystem.mdx b/packages/web/src/content/docs/ar/ecosystem.mdx new file mode 100644 index 00000000000..df3a4c7ddb5 --- /dev/null +++ b/packages/web/src/content/docs/ar/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: النظام البيئي +description: مشاريع وتكاملات مبنية باستخدام OpenCode. +--- + +مجموعة من مشاريع المجتمع المبنية على OpenCode. + +:::note +هل تريد إضافة مشروع مرتبط بـ OpenCode إلى هذه القائمة؟ قدّم PR. +::: + +يمكنك أيضا الاطلاع على [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) و [opencode.cafe](https://opencode.cafe)؛ وهو مجتمع يجمع روابط النظام البيئي والمجتمع. + +--- + +## الإضافات + +| الاسم | الوصف | +| --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | تشغيل جلسات OpenCode تلقائيا داخل بيئات Daytona معزولة مع مزامنة git ومعاينات حية | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | حقن ترويسات جلسة Helicone تلقائيا لتجميع الطلبات | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | حقن أنواع TypeScript/Svelte تلقائيا في قراءات الملفات باستخدام أدوات البحث | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | استخدام اشتراك ChatGPT Plus/Pro بدلا من أرصدة واجهة API | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | استخدام خطة Gemini الحالية بدلا من فوترة API | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | استخدام نماذج Antigravity المجانية بدلا من فوترة API | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | عزل devcontainer متعدد الفروع مع استنساخات shallow ومنافذ تُعيَّن تلقائيا | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | ملحق Google Antigravity OAuth مع دعم Google Search ومعالجة API أكثر متانة | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | تحسين استخدام الرموز (tokens) عبر تقليم مخرجات الأدوات القديمة | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | إضافة دعم websearch أصلي للمزوّدين المدعومين بأسلوب مستند إلى Google | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | تمكين وكلاء الذكاء الاصطناعي من تشغيل عمليات بالخلفية داخل PTY وإرسال إدخال تفاعلي إليها. | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | إرشادات لأوامر shell غير التفاعلية - تمنع التعليق الناتج عن عمليات تعتمد على TTY | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | تتبع استخدام OpenCode عبر Wakatime | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | تنظيف جداول Markdown التي تنتجها نماذج LLM | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | تحرير الشيفرة أسرع بـ 10x باستخدام Morph Fast Apply API وعلامات تعديل كسولة | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | وكلاء خلفية وأدوات LSP/AST/MCP جاهزة ووكلاء منتقون وتوافق مع Claude Code | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | إشعارات سطح المكتب وتنبيهات صوتية لجلسات OpenCode | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | إشعارات سطح المكتب وتنبيهات صوتية لأحداث الأذونات والإكمال والأخطاء | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | تسمية جلسات Zellij تلقائيا بالاعتماد على سياق OpenCode وبمساعدة الذكاء الاصطناعي | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | تمكين وكلاء OpenCode من تحميل الموجهات عند الطلب عبر اكتشاف المهارات وحقنها | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | ذاكرة مستمرة عبر الجلسات باستخدام Supermemory | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | مراجعة تفاعلية للخطة مع تعليقات توضيحية مرئية ومشاركة خاصة/دون اتصال | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | توسيع /commands في opencode إلى نظام تنسيق قوي مع تحكم دقيق في التدفق | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | جدولة مهام متكررة باستخدام launchd (Mac) أو systemd (Linux) بصياغة cron | +| [micode](https://github.com/vtemian/micode) | سير عمل منظم: عصف ذهني → خطة → تنفيذ مع استمرارية الجلسة | +| [octto](https://github.com/vtemian/octto) | واجهة متصفح تفاعلية للعصف الذهني بالذكاء الاصطناعي مع نماذج متعددة الأسئلة | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | وكلاء خلفية على نمط Claude Code مع تفويض غير متزامن واستمرارية للسياق | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | إشعارات نظام تشغيل أصلية لـ OpenCode - اعرف متى تكتمل المهام | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | حزمة تنسيق متعددة الوكلاء - 16 مكوّنا، تثبيت واحد | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | git worktrees بلا تعقيد لـ OpenCode | + +--- + +## المشاريع + +| الاسم | الوصف | +| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------ | +| [kimaki](https://github.com/remorses/kimaki) | بوت Discord للتحكم بجلسات OpenCode، مبني على SDK | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | ملحق Neovim لموجهات تراعي المحرر، مبني على API | +| [portal](https://github.com/hosenur/portal) | واجهة ويب تركز على الجوال لـ OpenCode عبر Tailscale/VPN | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | قالب لبناء ملحقات OpenCode | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | واجهة Neovim لـ opencode - وكيل برمجة بالذكاء الاصطناعي يعمل في terminal | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | موفر Vercel AI SDK لاستخدام OpenCode عبر @opencode-ai/sdk | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | تطبيق ويب/سطح مكتب وامتداد VS Code لـ OpenCode | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | ملحق Obsidian يدمج OpenCode داخل واجهة Obsidian | +| [OpenWork](https://github.com/different-ai/openwork) | بديل مفتوح المصدر لـ Claude Cowork، مدعوم بـ OpenCode | +| [ocx](https://github.com/kdcokenny/ocx) | مدير امتدادات OpenCode مع ملفات تعريف محمولة ومعزولة. | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | تطبيق عميل لسطح المكتب والويب والجوال وعن بُعد لـ OpenCode | + +--- + +## الوكلاء + +| الاسم | الوصف | +| ----------------------------------------------------------------- | --------------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | وكلاء وأوامر ذكاء اصطناعي معيارية لتطوير منظم | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | إعدادات وموجهات ووكلاء وملحقات لسير عمل محسّن | diff --git a/packages/web/src/content/docs/ar/enterprise.mdx b/packages/web/src/content/docs/ar/enterprise.mdx new file mode 100644 index 00000000000..b7b188edeb3 --- /dev/null +++ b/packages/web/src/content/docs/ar/enterprise.mdx @@ -0,0 +1,165 @@ +--- +title: المؤسسات +description: استخدام OpenCode بأمان داخل مؤسستك. +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +OpenCode Enterprise مخصص للمؤسسات التي تريد التأكد من أن الشيفرة والبيانات لا تغادر بنيتها التحتية مطلقا. ويمكن تحقيق ذلك عبر استخدام إعدادات مركزية تتكامل مع SSO وبوابة AI الداخلية لديك. + +:::note +لا يقوم OpenCode بتخزين أي من شيفرتك أو بيانات السياق. +::: + +لبدء استخدام OpenCode Enterprise: + +1. أجرِ تجربة داخلية مع فريقك. +2. **اتصل بنا** لمناقشة التسعير وخيارات التنفيذ. + +--- + +## تجربة + +OpenCode مفتوح المصدر ولا يخزن أي من شيفرتك أو بيانات السياق، لذا يمكن للمطورين لديك ببساطة [البدء](/docs/) وإجراء تجربة. + +--- + +### التعامل مع البيانات + +**لا يقوم OpenCode بتخزين شيفرتك أو بيانات السياق.** تتم جميع المعالجة محليا أو عبر استدعاءات API مباشرة إلى مزود AI لديك. + +وهذا يعني أنه طالما أنك تستخدم مزودا تثق به، أو بوابة AI داخلية، يمكنك استخدام OpenCode بأمان. + +الاستثناء الوحيد هنا هو ميزة `/share` الاختيارية. + +--- + +#### مشاركة المحادثات + +إذا فعّل المستخدم ميزة `/share`، فسيتم إرسال المحادثة والبيانات المرتبطة بها إلى الخدمة التي نستخدمها لاستضافة صفحات المشاركة هذه على opencode.ai. + +يتم تقديم البيانات حاليا عبر شبكة الحافة الخاصة بـ CDN لدينا، وتُخزّن مؤقتا على الحافة بالقرب من مستخدميك. + +نوصي بتعطيل ذلك أثناء التجربة. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[تعرّف على المزيد حول المشاركة](/docs/share). + +--- + +### ملكية الشيفرة + +**أنت تملك كل الشيفرة التي ينتجها OpenCode.** لا توجد قيود ترخيص أو مطالبات بالملكية. + +--- + +## التسعير + +نستخدم نموذج تسعير لكل مقعد في OpenCode Enterprise. إذا كانت لديك بوابة LLM خاصة بك، فلن نفرض رسوما على الرموز (tokens) المستخدمة. لمزيد من التفاصيل حول التسعير وخيارات التنفيذ، **اتصل بنا**. + +--- + +## النشر + +بعد إكمال التجربة وعندما تكون جاهزا لاستخدام OpenCode داخل مؤسستك، يمكنك **الاتصال بنا** لمناقشة التسعير وخيارات التنفيذ. + +--- + +### الإعدادات المركزية + +يمكننا إعداد OpenCode لاستخدام إعدادات مركزية واحدة لكامل مؤسستك. + +يمكن لهذه الإعدادات المركزية أن تتكامل مع مزود SSO لديك، وتضمن أن جميع المستخدمين يصلون فقط إلى بوابة AI الداخلية لديك. + +--- + +### تكامل SSO + +عبر الإعدادات المركزية، يمكن لـ OpenCode التكامل مع مزود SSO في مؤسستك لأغراض المصادقة. + +يتيح ذلك لـ OpenCode الحصول على بيانات الاعتماد لبوابة AI الداخلية لديك عبر نظام إدارة الهوية الحالي لديك. + +--- + +### بوابة AI الداخلية + +مع الإعدادات المركزية، يمكن أيضا تهيئة OpenCode لاستخدام بوابة AI الداخلية لديك فقط. + +يمكنك أيضا تعطيل جميع مزودي AI الآخرين، لضمان مرور جميع الطلبات عبر البنية التحتية المعتمدة في مؤسستك. + +--- + +### الاستضافة الذاتية + +بينما نوصي بتعطيل صفحات المشاركة لضمان ألا تغادر بياناتك مؤسستك مطلقا، يمكننا أيضا مساعدتك على استضافتها ذاتيا على بنيتك التحتية. + +هذا موجود حاليا على خارطة طريقنا. إذا كنت مهتما، **أخبرنا**. + +--- + +## الأسئلة الشائعة + +
+ما هو OpenCode Enterprise؟ + +OpenCode Enterprise مخصص للمؤسسات التي تريد التأكد من أن الشيفرة والبيانات لا تغادر بنيتها التحتية مطلقا. ويمكن تحقيق ذلك عبر استخدام إعدادات مركزية تتكامل مع SSO وبوابة AI الداخلية لديك. + +
+ +
+كيف أبدأ باستخدام OpenCode Enterprise؟ + +ابدأ ببساطة بتجربة داخلية مع فريقك. لا يقوم OpenCode افتراضيا بتخزين شيفرتك أو بيانات السياق، مما يجعل البدء سهلا. + +ثم **اتصل بنا** لمناقشة التسعير وخيارات التنفيذ. + +
+ +
+كيف يعمل تسعير المؤسسات؟ + +نقدم تسعيرا للمؤسسات لكل مقعد. إذا كانت لديك بوابة LLM خاصة بك، فلن نفرض رسوما على الرموز (tokens) المستخدمة. لمزيد من التفاصيل، **اتصل بنا** للحصول على عرض سعر مخصص بناء على احتياجات مؤسستك. + +
+ +
+هل بياناتي آمنة مع OpenCode Enterprise؟ + +نعم. لا يقوم OpenCode بتخزين شيفرتك أو بيانات السياق. تتم جميع المعالجة محليا أو عبر استدعاءات API مباشرة إلى مزود AI لديك. ومع الإعدادات المركزية وتكامل SSO، تظل بياناتك آمنة داخل البنية التحتية لمؤسستك. + +
+ +
+هل يمكننا استخدام سجل NPM خاص بنا؟ + +يدعم OpenCode سجلات npm الخاصة عبر دعم Bun الأصلي لملف `.npmrc`. إذا كانت مؤسستك تستخدم سجلا خاصا مثل JFrog Artifactory أو Nexus أو ما شابه ذلك، فتأكد من مصادقة المطورين قبل تشغيل OpenCode. + +لإعداد المصادقة مع السجل الخاص بك: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +سيؤدي ذلك إلى إنشاء `~/.npmrc` مع تفاصيل المصادقة. سيلتقط OpenCode هذا تلقائيا. + +:::caution +يجب أن تكون مسجلا الدخول إلى السجل الخاص قبل تشغيل OpenCode. +::: + +بدلا من ذلك، يمكنك تهيئة ملف `.npmrc` يدويا: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +يجب أن يكون المطورون مسجلين الدخول إلى السجل الخاص قبل تشغيل OpenCode لضمان إمكانية تثبيت الحزم من سجل مؤسستك. + +
diff --git a/packages/web/src/content/docs/ar/formatters.mdx b/packages/web/src/content/docs/ar/formatters.mdx new file mode 100644 index 00000000000..a1d5478af3a --- /dev/null +++ b/packages/web/src/content/docs/ar/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: المُنسِّقات +description: يستخدم OpenCode مُنسِّقات خاصة بكل لغة. +--- + +يُنسِّق OpenCode الملفات تلقائيا بعد كتابتها أو تعديلها باستخدام مُنسِّقات خاصة بكل لغة. يضمن ذلك أن الشيفرة التي يتم توليدها تتبع أساليب التنسيق المعتمدة في مشروعك. + +--- + +## مُضمَّنة + +يأتي OpenCode مع عدة مُنسِّقات مُضمَّنة للغات وأطر العمل الشائعة. فيما يلي قائمة بالمُنسِّقات وامتدادات الملفات المدعومة والأوامر أو خيارات الإعداد التي تحتاجها. + +| المُنسِّق | الامتدادات | المتطلبات | +| -------------------- | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | +| gofmt | .go | يتوفر أمر `gofmt` | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | يتوفر أمر `mix` | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml، و[غير ذلك](https://prettier.io/docs/en/index.html) | وجود اعتماد `prettier` في `package.json` | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml، و[غير ذلك](https://biomejs.dev/) | ملف إعداد `biome.json(c)` | +| zig | .zig, .zon | يتوفر أمر `zig` | +| clang-format | .c, .cpp, .h, .hpp, .ino، و[غير ذلك](https://clang.llvm.org/docs/ClangFormat.html) | ملف إعداد `.clang-format` | +| ktlint | .kt, .kts | يتوفر أمر `ktlint` | +| ruff | .py, .pyi | يتوفر أمر `ruff` مع إعداد | +| rustfmt | .rs | يتوفر أمر `rustfmt` | +| cargofmt | .rs | يتوفر أمر `cargo fmt` | +| uv | .py, .pyi | يتوفر أمر `uv` | +| rubocop | .rb, .rake, .gemspec, .ru | يتوفر أمر `rubocop` | +| standardrb | .rb, .rake, .gemspec, .ru | يتوفر أمر `standardrb` | +| htmlbeautifier | .erb, .html.erb | يتوفر أمر `htmlbeautifier` | +| air | .R | يتوفر أمر `air` | +| dart | .dart | يتوفر أمر `dart` | +| ocamlformat | .ml, .mli | يتوفر أمر `ocamlformat` وملف إعداد `.ocamlformat` | +| terraform | .tf, .tfvars | يتوفر أمر `terraform` | +| gleam | .gleam | يتوفر أمر `gleam` | +| nixfmt | .nix | يتوفر أمر `nixfmt` | +| shfmt | .sh, .bash | يتوفر أمر `shfmt` | +| pint | .php | وجود اعتماد `laravel/pint` في `composer.json` | +| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | وجود اعتماد `oxfmt` في `package.json` و[علم متغير بيئة تجريبي](/docs/cli/#experimental) | +| ormolu | .hs | يتوفر أمر `ormolu` | + +لذا إذا كان مشروعك يتضمن `prettier` ضمن `package.json`، فسيستخدمه OpenCode تلقائيا. + +--- + +## كيف يعمل + +عندما يكتب OpenCode ملفا أو يحرره، فإنه: + +1. يتحقق من امتداد الملف مقابل جميع المُنسِّقات المفعّلة. +2. يشغّل أمر المُنسِّق المناسب على الملف. +3. يطبق تغييرات التنسيق تلقائيا. + +تتم هذه العملية في الخلفية لضمان الحفاظ على أساليب تنسيق الشيفرة دون أي خطوات يدوية. + +--- + +## الإعداد + +يمكنك تخصيص المُنسِّقات عبر قسم `formatter` في إعدادات OpenCode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +يدعم إعداد كل مُنسِّق ما يلي: + +| الخاصية | النوع | الوصف | +| ------------- | -------- | ------------------------------------------------------ | +| `disabled` | boolean | اضبطها على `true` لتعطيل المُنسِّق | +| `command` | string[] | الأمر الذي سيتم تشغيله للتنسيق | +| `environment` | object | متغيرات البيئة التي يتم ضبطها عند تشغيل المُنسِّق | +| `extensions` | string[] | امتدادات الملفات التي يجب أن يتعامل معها هذا المُنسِّق | + +لنلقِ نظرة على بعض الأمثلة. + +--- + +### تعطيل المُنسِّقات + +لتعطيل **جميع** المُنسِّقات على مستوى عام، اضبط `formatter` على `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +لتعطيل مُنسِّق **محدد**، اضبط `disabled` على `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### مُنسِّقات مخصّصة + +يمكنك تجاوز المُنسِّقات المُضمَّنة أو إضافة مُنسِّقات جديدة عبر تحديد الأمر ومتغيرات البيئة وامتدادات الملفات: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +سيتم استبدال **العنصر النائب `$FILE`** في الأمر بمسار الملف الذي يجري تنسيقه. diff --git a/packages/web/src/content/docs/ar/github.mdx b/packages/web/src/content/docs/ar/github.mdx new file mode 100644 index 00000000000..1365b74e537 --- /dev/null +++ b/packages/web/src/content/docs/ar/github.mdx @@ -0,0 +1,321 @@ +--- +title: GitHub +description: استخدم OpenCode في GitHub Issues وPull Requests. +--- + +يتكامل OpenCode مع سير عمل GitHub لديك. اذكر `/opencode` أو `/oc` في تعليقك، وسيقوم OpenCode بتنفيذ المهام داخل GitHub Actions runner لديك. + +--- + +## الميزات + +- **فرز Issues**: اطلب من OpenCode الاطلاع على Issue وشرحها لك. +- **إصلاح وتنفيذ**: اطلب من OpenCode إصلاح Issue أو تنفيذ ميزة. وسيعمل على فرع جديد ويقدّم PR يضم كل التغييرات. +- **آمن**: يعمل OpenCode داخل GitHub runners لديك. + +--- + +## التثبيت + +شغّل الأمر التالي داخل مشروع موجود في مستودع GitHub: + +```bash +opencode github install +``` + +سيأخذك هذا خلال تثبيت GitHub app، وإنشاء workflow، وإعداد secrets. + +--- + +### الإعداد اليدوي + +أو يمكنك إعداده يدويًا. + +1. **تثبيت GitHub app** + + انتقل إلى [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). تأكد من تثبيته على المستودع الهدف. + +2. **إضافة الـworkflow** + + أضف ملف الـworkflow التالي إلى `.github/workflows/opencode.yml` في مستودعك. تأكد من ضبط `model` المناسب ومفاتيح API المطلوبة ضمن `env`. + + ```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx + ``` + +3. **تخزين مفاتيح API ضمن secrets** + + في **settings** الخاصة بالمؤسسة أو المشروع، وسّع **Secrets and variables** في الشريط الجانبي الأيسر ثم اختر **Actions**، وأضف مفاتيح API المطلوبة. + +--- + +## الإعدادات + +- `model`: النموذج الذي سيستخدمه OpenCode. يأخذ الصيغة `provider/model`. هذا **مطلوب**. +- `agent`: الـagent الذي سيتم استخدامه. يجب أن يكون agent أساسيًا. يعود افتراضيًا إلى `default_agent` من الإعدادات أو `"build"` إذا لم يُعثر عليه. +- `share`: هل تتم مشاركة جلسة OpenCode. القيمة الافتراضية **true** للمستودعات العامة. +- `prompt`: موجه مخصص اختياري لتجاوز السلوك الافتراضي. استخدمه لتخصيص كيفية معالجة OpenCode للطلبات. +- `token`: GitHub access token اختياري لتنفيذ عمليات مثل إنشاء التعليقات، وcommit للتغييرات، وفتح Pull Requests. افتراضيًا يستخدم OpenCode installation access token الخاص بـOpenCode GitHub App، لذا تظهر commits والتعليقات وPull Requests وكأنها صادرة من التطبيق. + + بدلًا من ذلك، يمكنك استخدام [`GITHUB_TOKEN` المدمج](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) في GitHub Action runner دون تثبيت OpenCode GitHub App. فقط تأكد من منح الأذونات المطلوبة في الـworkflow: + + ```yaml + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + ``` + + يمكنك أيضًا استخدام [رموز الوصول الشخصية](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) إن فضّلت ذلك. + +--- + +## الأحداث المدعومة + +يمكن تشغيل OpenCode عبر أحداث GitHub التالية: + +| نوع الحدث | يتم تشغيله عبر | التفاصيل | +| ----------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------- | +| `issue_comment` | تعليق على Issue أو PR | اذكر `/opencode` أو `/oc` في تعليقك. يقرأ OpenCode السياق ويمكنه إنشاء فروع، وفتح PRs، أو الرد. | +| `pull_request_review_comment` | تعليق على أسطر كود محددة في PR | اذكر `/opencode` أو `/oc` أثناء مراجعة الكود. يستلم OpenCode مسار الملف وأرقام الأسطر وسياق الـdiff. | +| `issues` | فتح Issue أو تعديلها | تشغيل OpenCode تلقائيًا عند إنشاء Issues أو تعديلها. يتطلب إدخال `prompt`. | +| `pull_request` | فتح PR أو تحديثه | تشغيل OpenCode تلقائيًا عند فتح PRs أو مزامنتها أو إعادة فتحها. مفيد للمراجعات الآلية. | +| `schedule` | جدول يعتمد على Cron | تشغيل OpenCode وفق جدول. يتطلب إدخال `prompt`. يذهب الناتج إلى logs وPRs (لا يوجد Issue للتعليق عليها). | +| `workflow_dispatch` | تشغيل يدوي من واجهة GitHub | تشغيل OpenCode عند الطلب عبر Actions tab. يتطلب إدخال `prompt`. يذهب الناتج إلى logs وPRs. | + +### مثال للجدولة + +شغّل OpenCode وفق جدول لتنفيذ مهام آلية: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +بالنسبة لأحداث `schedule`، يكون إدخال `prompt` **مطلوبًا** لعدم وجود تعليق لاستخراج التعليمات منه. تعمل عمليات الـworkflow المجدولة دون سياق مستخدم للتحقق من الأذونات، لذا يجب أن يمنح الـworkflow صلاحيات `contents: write` و`pull-requests: write` إذا كنت تتوقع أن ينشئ OpenCode فروعًا أو PRs. + +--- + +### مثال Pull Request + +راجع PRs تلقائيًا عند فتحها أو تحديثها: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +بالنسبة لأحداث `pull_request`، إذا لم يتم توفير `prompt`، فإن OpenCode يراجع Pull Request افتراضيًا. + +--- + +### مثال فرز Issues + +قم بفرز Issues الجديدة تلقائيًا. يقوم هذا المثال بتصفية الحسابات الأقدم من 30 يومًا لتقليل الرسائل المزعجة: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +بالنسبة لأحداث `issues`، يكون إدخال `prompt` **مطلوبًا** لعدم وجود تعليق لاستخراج التعليمات منه. + +--- + +## الموجهات المخصصة + +قم بتجاوز الموجه الافتراضي لتخصيص سلوك OpenCode ضمن الـworkflow لديك. + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +يفيد ذلك في فرض معايير مراجعة محددة، أو معايير كتابة الكود، أو مجالات تركيز تناسب مشروعك. + +--- + +## أمثلة + +إليك بعض الأمثلة على كيفية استخدام OpenCode في GitHub. + +- **شرح Issue** + + أضف هذا التعليق داخل GitHub Issue. + + ``` + /opencode explain this issue + ``` + + سيقرأ OpenCode كامل النقاش، بما في ذلك جميع التعليقات، ويرد بشرح واضح. + +- **إصلاح Issue** + + داخل GitHub Issue، اكتب: + + ``` + /opencode fix this + ``` + + وسيُنشئ OpenCode فرعًا جديدًا، وينفّذ التغييرات، ويفتح PR يتضمنها. + +- **مراجعة PRs وإجراء تغييرات** + + اترك التعليق التالي على GitHub PR. + + ``` + Delete the attachment from S3 when the note is removed /oc + ``` + + سينفّذ OpenCode التغيير المطلوب ويعمل له commit إلى نفس PR. + +- **مراجعة أسطر كود محددة** + + اترك تعليقًا مباشرة على أسطر الكود في تبويب "Files" داخل PR. يكتشف OpenCode تلقائيًا الملف وأرقام الأسطر وسياق الـdiff لتقديم ردود دقيقة. + + ``` + [Comment on specific lines in Files tab] + /oc add error handling here + ``` + + عند التعليق على أسطر محددة، يستلم OpenCode: + - الملف الدقيق الذي تتم مراجعته + - أسطر الكود المحددة + - سياق الـdiff المحيط + - معلومات أرقام الأسطر + + يسمح ذلك بطلبات أكثر تحديدًا دون الحاجة لذكر مسارات الملفات أو أرقام الأسطر يدويًا. diff --git a/packages/web/src/content/docs/ar/gitlab.mdx b/packages/web/src/content/docs/ar/gitlab.mdx new file mode 100644 index 00000000000..12e36de108b --- /dev/null +++ b/packages/web/src/content/docs/ar/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: استخدم OpenCode في مشكلات GitLab وطلبات الدمج. +--- + +يتكامل OpenCode مع سير عمل GitLab لديك عبر خط أنابيب GitLab CI/CD أو عبر GitLab Duo. + +في كلتا الحالتين، سيعمل OpenCode على مشغّلات GitLab لديك. + +--- + +## GitLab CI + +يعمل OpenCode ضمن خط أنابيب GitLab عادي. يمكنك دمجه في الخط كمكوّن [CI](https://docs.gitlab.com/ee/ci/components/). + +هنا نستخدم مكوّن CI/CD أنشأه المجتمع لـ OpenCode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### الميزات + +- **استخدام إعدادات مخصّصة لكل مهمة**: يمكنك إعداد OpenCode باستخدام دليل إعدادات مخصّص، مثل `./config/#custom-directory`، لتفعيل الوظائف أو تعطيلها في كل تشغيل لـ OpenCode. +- **إعداد بسيط**: يقوم مكوّن CI بإعداد OpenCode في الخلفية؛ كل ما عليك هو إنشاء إعدادات OpenCode والمطالبة (prompt) الأولية. +- **مرن**: يدعم مكوّن CI عدة مُدخلات لتخصيص سلوكه. + +--- + +### الإعداد + +1. احفظ JSON مصادقة OpenCode كمتغيرات بيئة CI من نوع File ضمن **Settings** > **CI/CD** > **Variables**. تأكد من تعيينها على "Masked and hidden". +2. أضف ما يلي إلى ملف `.gitlab-ci.yml`. + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +لمزيد من المُدخلات وحالات الاستخدام، [اطّلع على الوثائق](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) الخاصة بهذا المكوّن. + +--- + +## GitLab Duo + +يتكامل OpenCode مع سير عمل GitLab لديك. +اذكر `@opencode` في تعليق، وسينفّذ OpenCode المهام ضمن خط أنابيب GitLab CI لديك. + +--- + +### الميزات + +- **فرز المشكلات**: اطلب من OpenCode النظر في مشكلة وشرحها لك. +- **الإصلاح والتنفيذ**: اطلب من OpenCode إصلاح مشكلة أو تنفيذ ميزة. + سيُنشئ فرعًا جديدًا ويرفع طلب دمج بالتغييرات. +- **آمن**: يعمل OpenCode على مشغّلات GitLab لديك. + +--- + +### الإعداد + +يعمل OpenCode ضمن خط أنابيب GitLab CI/CD لديك، وإليك ما ستحتاجه لإعداده: + +:::tip +اطّلع على [**وثائق GitLab**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) للحصول على تعليمات محدّثة. +::: + +1. قم بتهيئة بيئة GitLab لديك +2. أعد إعداد CI/CD +3. احصل على مفتاح API من مزوّد نموذج ذكاء اصطناعي +4. أنشئ حساب خدمة +5. اضبط متغيرات CI/CD +6. أنشئ ملف إعداد للتدفق، وإليك مثالًا: + +
+ + إعدادات التدفق + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +يمكنك الرجوع إلى [وثائق GitLab CLI agents](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) للحصول على تعليمات مفصلة. + +--- + +### أمثلة + +فيما يلي بعض الأمثلة على كيفية استخدام OpenCode في GitLab. + +:::tip +يمكنك ضبطه لاستخدام عبارة تشغيل مختلفة عن `@opencode`. +::: + +- **شرح مشكلة** + + أضف هذا التعليق في مشكلة على GitLab. + + ``` + @opencode explain this issue + ``` + + سيقرأ OpenCode المشكلة ويرد بشرح واضح. + +- **إصلاح مشكلة** + + في مشكلة على GitLab، قل: + + ``` + @opencode fix this + ``` + + سيُنشئ OpenCode فرعًا جديدًا، وينفّذ التغييرات، ويفتح طلب دمج بالتغييرات. + +- **مراجعة طلبات الدمج** + + اترك التعليق التالي على طلب دمج في GitLab. + + ``` + @opencode review this merge request + ``` + + سيُراجع OpenCode طلب الدمج ويقدّم ملاحظات. diff --git a/packages/web/src/content/docs/ar/ide.mdx b/packages/web/src/content/docs/ar/ide.mdx new file mode 100644 index 00000000000..354d95a07d3 --- /dev/null +++ b/packages/web/src/content/docs/ar/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: امتداد OpenCode لـ VS Code و Cursor وغيرها من بيئات التطوير +--- + +يتكامل OpenCode مع VS Code و Cursor أو أي IDE يدعم terminal. ما عليك سوى تشغيل `opencode` في terminal للبدء. + +--- + +## الاستخدام + +- **تشغيل سريع**: استخدم `Cmd+Esc` (Mac) أو `Ctrl+Esc` (Windows/Linux) لفتح OpenCode في عرض terminal مقسّم، أو للتركيز على جلسة terminal موجودة إذا كانت قيد التشغيل بالفعل. +- **جلسة جديدة**: استخدم `Cmd+Shift+Esc` (Mac) أو `Ctrl+Shift+Esc` (Windows/Linux) لبدء جلسة terminal جديدة لـ OpenCode حتى لو كانت هناك جلسة مفتوحة. يمكنك أيضا النقر على زر OpenCode في واجهة المستخدم. +- **وعي بالسياق**: شارك تلقائيا تحديدك الحالي أو تبويبك مع OpenCode. +- **اختصارات الإشارة إلى الملفات**: استخدم `Cmd+Option+K` (Mac) أو `Alt+Ctrl+K` (Linux/Windows) لإدراج مراجع الملفات. مثلا: `@File#L37-42`. + +--- + +## التثبيت + +لتثبيت OpenCode على VS Code والتفرعات الشائعة مثل Cursor و Windsurf و VSCodium: + +1. افتح VS Code +2. افتح terminal المدمجة +3. شغّل `opencode` - سيتم تثبيت الامتداد تلقائيا + +أما إذا كنت تريد استخدام IDE الخاص بك عند تشغيل `/editor` أو `/export` من واجهة TUI، فستحتاج إلى ضبط `export EDITOR="code --wait"`. [اعرف المزيد](/docs/tui/#editor-setup). + +--- + +### التثبيت اليدوي + +ابحث عن **OpenCode** في Extension Marketplace وانقر **Install**. + +--- + +### استكشاف الأخطاء وإصلاحها + +إذا فشل تثبيت الامتداد تلقائيا: + +- تأكد من أنك تشغّل `opencode` داخل terminal المدمجة. +- تأكد من تثبيت CLI الخاصة بـ IDE لديك: + - لـ VS Code: أمر `code` + - لـ Cursor: أمر `cursor` + - لـ Windsurf: أمر `windsurf` + - لـ VSCodium: أمر `codium` + - إذا لم تكن مثبتة، شغّل `Cmd+Shift+P` (Mac) أو `Ctrl+Shift+P` (Windows/Linux) وابحث عن "Shell Command: Install 'code' command in PATH" (أو ما يعادله في IDE لديك) +- تأكد من أن VS Code لديه الصلاحية لتثبيت الامتدادات diff --git a/packages/web/src/content/docs/ar/index.mdx b/packages/web/src/content/docs/ar/index.mdx new file mode 100644 index 00000000000..fef8844dc09 --- /dev/null +++ b/packages/web/src/content/docs/ar/index.mdx @@ -0,0 +1,343 @@ +--- +title: مقدمة +description: ابدأ باستخدام OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**OpenCode**](/) هو وكيل ترميز بالذكاء الاصطناعي مفتوح المصدر. يتوفر كواجهة terminal، وتطبيق لسطح المكتب، أو إضافة لبيئة تطوير متكاملة (IDE). + +![واجهة OpenCode في terminal مع سمة opencode](../../../assets/lander/screenshot.png) + +لنبدأ. + +--- + +#### المتطلبات + +لاستخدام OpenCode في terminal، ستحتاج إلى: + +1. محاكي terminal حديث مثل: + - [WezTerm](https://wezterm.org) متعدد المنصات + - [Alacritty](https://alacritty.org) متعدد المنصات + - [Ghostty](https://ghostty.org) على Linux وmacOS + - [Kitty](https://sw.kovidgoyal.net/kitty/) على Linux وmacOS + +2. مفاتيح API لمزوّدي نماذج اللغة (LLM) الذين تريد استخدامهم. + +--- + +## التثبيت + +أسهل طريقة لتثبيت OpenCode هي عبر سكربت التثبيت. + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +يمكنك أيضا تثبيته عبر الأوامر التالية: + +- **باستخدام Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **باستخدام Homebrew على macOS وLinux** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > نوصي باستخدام tap الخاص بـ OpenCode للحصول على أحدث الإصدارات. صيغة `brew install opencode` الرسمية تُدار بواسطة فريق Homebrew ويتم تحديثها بوتيرة أقل. + +- **باستخدام Paru على Arch Linux** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[موصى به: استخدم WSL] +لأفضل تجربة على Windows، نوصي باستخدام [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). يوفر أداء أفضل وتوافقا كاملا مع ميزات OpenCode. +::: + +- **باستخدام Chocolatey** + + ```bash + choco install opencode + ``` + +- **باستخدام Scoop** + + ```bash + scoop install opencode + ``` + +- **باستخدام NPM** + + ```bash + npm install -g opencode-ai + ``` + +- **باستخدام Mise** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **باستخدام Docker** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +دعم تثبيت OpenCode على Windows باستخدام Bun قيد العمل حاليا. + +يمكنك أيضا تنزيل الملف التنفيذي من صفحة [Releases](https://github.com/anomalyco/opencode/releases). + +--- + +## الإعداد + +مع OpenCode يمكنك استخدام أي مزود LLM عبر إعداد مفاتيح API الخاصة به. + +إذا كنت جديدا على استخدام مزوّدي LLM، فنوصي باستخدام [OpenCode Zen](/docs/zen). +إنها قائمة منتقاة من النماذج تم اختبارها والتحقق منها بواسطة فريق OpenCode. + +1. شغّل الأمر `/connect` في واجهة TUI، واختر opencode، ثم انتقل إلى [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. سجّل الدخول، وأضف تفاصيل الدفع، ثم انسخ مفتاح API. + +3. الصق مفتاح API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +بدلا من ذلك يمكنك اختيار أحد المزوّدين الآخرين. [اعرف المزيد](/docs/providers#directory). + +--- + +## التهيئة + +بعد أن قمت بإعداد مزوّد، يمكنك الانتقال إلى المشروع الذي تريد العمل عليه. + +```bash +cd /path/to/project +``` + +ثم شغّل OpenCode. + +```bash +opencode +``` + +بعد ذلك، هيّئ OpenCode للمشروع عبر تشغيل الأمر التالي. + +```bash frame="none" +/init +``` + +سيجعل هذا OpenCode يحلل مشروعك ويُنشئ ملف `AGENTS.md` في جذر المشروع. + +:::tip +يستحسن أن تقوم بعمل commit لملف `AGENTS.md` الخاص بمشروعك إلى Git. +::: + +يساعد هذا OpenCode على فهم بنية المشروع وأنماط الترميز المستخدمة. + +--- + +## الاستخدام + +أصبحت الآن جاهزا لاستخدام OpenCode للعمل على مشروعك. لا تتردد في سؤاله أي شيء! + +إذا كنت جديدا على استخدام وكيل ترميز بالذكاء الاصطناعي، فإليك بعض الأمثلة التي قد تساعد. + +--- + +### اطرح أسئلة + +يمكنك أن تطلب من OpenCode شرح قاعدة الشيفرة لك. + +:::tip +استخدم المفتاح `@` للبحث التقريبي عن الملفات داخل المشروع. +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +يفيد هذا عندما تكون هناك أجزاء من قاعدة الشيفرة لم تعمل عليها. + +--- + +### أضف ميزات + +يمكنك أن تطلب من OpenCode إضافة ميزات جديدة إلى مشروعك، لكننا نوصي أولا بطلب إنشاء خطة. + +1. **أنشئ خطة** + + لدى OpenCode _وضع Plan_ يعطل قدرته على إجراء التغييرات، ويقترح بدلا من ذلك _كيف_ سينفّذ الميزة. + + انتقل إليه باستخدام مفتاح **Tab**. سترى مؤشرا لذلك في الزاوية السفلية اليمنى. + + ```bash frame="none" title="التبديل إلى وضع Plan" + + ``` + + الآن لنصف ما نريده أن يفعله. + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + احرص على تزويد OpenCode بتفاصيل كافية ليفهم ما تريد. يساعد أن تتحدث إليه كما لو كنت تتحدث إلى مطور مبتدئ ضمن فريقك. + + :::tip + أعطِ OpenCode سياقا وأمثلة كافية لمساعدته على فهم ما تريد. + ::: + +2. **حسّن الخطة** + + بعد أن يقدم لك خطة، يمكنك إعطاؤه ملاحظات أو إضافة تفاصيل أكثر. + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + + :::tip + اسحب الصور وأفلِتها داخل terminal لإضافتها إلى الطلب. + ::: + + يستطيع OpenCode فحص أي صور تزوده بها وإضافتها إلى الطلب. يمكنك فعل ذلك عبر سحب الصورة وإفلاتها داخل terminal. + +3. **ابنِ الميزة** + + عندما تشعر بالارتياح للخطة، عد إلى _وضع Build_ بالضغط على مفتاح **Tab** مرة أخرى. + + ```bash frame="none" + + ``` + + ثم اطلب منه تنفيذ التغييرات. + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### نفّذ تغييرات + +للتغييرات الأبسط، يمكنك أن تطلب من OpenCode تنفيذها مباشرة دون الحاجة لمراجعة خطة أولا. + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +تأكد من تقديم قدر مناسب من التفاصيل لكي يجري OpenCode التغييرات الصحيحة. + +--- + +### تراجع عن التغييرات + +لنفترض أنك طلبت من OpenCode إجراء بعض التغييرات. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +لكن تتضح لك لاحقا أنها ليست ما تريده. يمكنك **التراجع** عن التغييرات باستخدام الأمر `/undo`. + +```bash frame="none" +/undo +``` + +سيقوم OpenCode الآن بعكس التغييرات التي أُجريت ويعرض رسالتك الأصلية مجددا. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +من هنا يمكنك تعديل الطلب وطلب المحاولة مرة أخرى. + +:::tip +يمكنك تشغيل `/undo` عدة مرات للتراجع عن عدة تغييرات. +::: + +أو يمكنك **إعادة تنفيذ** التغييرات باستخدام الأمر `/redo`. + +```bash frame="none" +/redo +``` + +--- + +## المشاركة + +يمكن [مشاركة المحادثات](/docs/share) التي تجريها مع OpenCode مع فريقك. + +```bash frame="none" +/share +``` + +سيقوم هذا بإنشاء رابط للمحادثة الحالية ونسخه إلى الحافظة. + +:::note +لا تتم مشاركة المحادثات افتراضيا. +::: + +إليك [مثالا لمحادثة](https://opencode.ai/s/4XP1fce5) مع OpenCode. + +--- + +## التخصيص + +وهذا كل شيء! أصبحت الآن محترفا في استخدام OpenCode. + +لتجعله مناسبا لك، نوصي بـ [اختيار سمة](/docs/themes)، و[تخصيص اختصارات لوحة المفاتيح](/docs/keybinds)، و[إعداد منسقات الشيفرة](/docs/formatters)، و[إنشاء أوامر مخصصة](/docs/commands)، أو التجربة مع [إعدادات OpenCode](/docs/config). diff --git a/packages/web/src/content/docs/ar/keybinds.mdx b/packages/web/src/content/docs/ar/keybinds.mdx new file mode 100644 index 00000000000..f07eaed37b4 --- /dev/null +++ b/packages/web/src/content/docs/ar/keybinds.mdx @@ -0,0 +1,192 @@ +--- +title: اختصارات لوحة المفاتيح +description: خصّص اختصارات لوحة المفاتيح. +--- + +يوفّر OpenCode قائمة باختصارات لوحة المفاتيح يمكنك تخصيصها عبر إعدادات OpenCode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## مفتاح القائد + +يستخدم OpenCode مفتاح `leader` لمعظم اختصارات لوحة المفاتيح. يساعد ذلك على تجنّب التعارضات في terminal لديك. + +افتراضيا، يكون `ctrl+x` هو مفتاح القائد، وتتطلّب معظم الإجراءات أن تضغط أولا مفتاح القائد ثم الاختصار. على سبيل المثال، لبدء جلسة جديدة اضغط `ctrl+x` أولا ثم اضغط `n`. + +لا يلزم استخدام مفتاح قائد لاختصاراتك، لكننا نوصي بذلك. + +--- + +## تعطيل اختصار + +يمكنك تعطيل أي اختصار بإضافة معرّف الاختصار إلى ملف الإعدادات بقيمة "none". + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## اختصارات موجّه سطح المكتب + +يدعم حقل إدخال الموجّه في تطبيق OpenCode لسطح المكتب اختصارات شائعة لتحرير النص على نمط Readline/Emacs. هذه الاختصارات مدمجة حاليا ولا يمكن تخصيصها عبر `opencode.json`. + +| الاختصار | الإجراء | +| -------- | ------------------------------------------ | +| `ctrl+a` | الانتقال إلى بداية السطر الحالي | +| `ctrl+e` | الانتقال إلى نهاية السطر الحالي | +| `ctrl+b` | تحريك المؤشر للخلف حرفا واحدا | +| `ctrl+f` | تحريك المؤشر للأمام حرفا واحدا | +| `alt+b` | تحريك المؤشر للخلف كلمة واحدة | +| `alt+f` | تحريك المؤشر للأمام كلمة واحدة | +| `ctrl+d` | حذف الحرف الموجود تحت المؤشر | +| `ctrl+k` | حذف حتى نهاية السطر | +| `ctrl+u` | حذف حتى بداية السطر | +| `ctrl+w` | حذف الكلمة السابقة | +| `alt+d` | حذف الكلمة التالية | +| `ctrl+t` | تبديل موضعي حرفين | +| `ctrl+g` | إلغاء النوافذ المنبثقة / إيقاف الرد الجاري | + +--- + +## مفتاح Shift+Enter + +بعض تطبيقات terminal لا ترسل مفاتيح التعديل مع Enter افتراضيا. قد تحتاج إلى ضبط terminal لإرسال `Shift+Enter` كسلسلة هروب. + +### Windows Terminal + +افتح ملف `settings.json` الموجود في: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +أضف هذا إلى مصفوفة `actions` على مستوى الجذر: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +أضف هذا إلى مصفوفة `keybindings` على مستوى الجذر: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +احفظ الملف ثم أعد تشغيل Windows Terminal أو افتح علامة تبويب جديدة. diff --git a/packages/web/src/content/docs/ar/lsp.mdx b/packages/web/src/content/docs/ar/lsp.mdx new file mode 100644 index 00000000000..541b48ecc9b --- /dev/null +++ b/packages/web/src/content/docs/ar/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: خوادم LSP +description: يتكامل OpenCode مع خوادم LSP لديك. +--- + +يتكامل OpenCode مع بروتوكول خادم اللغة (LSP) لمساعدة LLM على التفاعل مع قاعدة الشيفرة لديك. ويستخدم التشخيصات لتزويد LLM بتغذية راجعة. + +--- + +## المدمجة + +يأتي OpenCode مع عدة خوادم LSP مدمجة للغات الشائعة: + +| خادم 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+)` | +| 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` (على macOS عبر `xcode`) | +| 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 | يثبت `yaml-language-server` من Red Hat تلقائيا | +| zls | .zig, .zon | توفر أمر `zig` | + +تُفعَّل خوادم LSP تلقائيا عند اكتشاف أحد امتدادات الملفات المذكورة أعلاه واستيفاء المتطلبات. + +:::note +يمكنك تعطيل تنزيلات خوادم LSP التلقائية عبر ضبط متغير البيئة `OPENCODE_DISABLE_LSP_DOWNLOAD` على `true`. +::: + +--- + +## كيف يعمل + +عندما يفتح opencode ملفا، فإنه: + +1. يفحص امتداد الملف مقابل جميع خوادم LSP المفعّلة. +2. يشغّل خادم LSP المناسب إذا لم يكن قيد التشغيل بالفعل. + +--- + +## الإعداد + +يمكنك تخصيص خوادم LSP عبر قسم `lsp` في إعدادات opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +يدعم كل خادم LSP ما يلي: + +| الخاصية | النوع | الوصف | +| ---------------- | -------- | ------------------------------------------------- | +| `disabled` | boolean | اضبطها على `true` لتعطيل خادم LSP | +| `command` | string[] | الأمر المستخدم لتشغيل خادم LSP | +| `extensions` | string[] | امتدادات الملفات التي يجب أن يعالجها خادم LSP هذا | +| `env` | object | متغيرات البيئة التي تُضبط عند تشغيل الخادم | +| `initialization` | object | خيارات التهيئة التي تُرسل إلى خادم LSP | + +لنلق نظرة على بعض الأمثلة. + +--- + +### متغيرات البيئة + +استخدم الخاصية `env` لضبط متغيرات البيئة عند تشغيل خادم LSP: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### خيارات التهيئة + +استخدم الخاصية `initialization` لتمرير خيارات التهيئة إلى خادم LSP. هذه إعدادات خاصة بالخادم تُرسل أثناء طلب LSP `initialize`: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +تختلف خيارات التهيئة بحسب خادم LSP. راجع توثيق خادم LSP لديك لمعرفة الخيارات المتاحة. +::: + +--- + +### تعطيل خوادم LSP + +لتعطيل **جميع** خوادم LSP على مستوى التطبيق، اضبط `lsp` على `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +لتعطيل خادم LSP **بعينه**، اضبط `disabled` على `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### خوادم LSP مخصصة + +يمكنك إضافة خوادم LSP مخصصة عبر تحديد الأمر وامتدادات الملفات: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## معلومات إضافية + +### PHP Intelephense + +يوفر PHP Intelephense ميزات مدفوعة عبر مفتاح ترخيص. يمكنك تزويده بمفتاح الترخيص عبر وضع (فقط) المفتاح داخل ملف نصي في: + +- على macOS/Linux: `$HOME/intelephense/licence.txt` +- على Windows: `%USERPROFILE%/intelephense/licence.txt` + +يجب أن يحتوي الملف على مفتاح الترخيص فقط دون أي محتوى إضافي. diff --git a/packages/web/src/content/docs/ar/mcp-servers.mdx b/packages/web/src/content/docs/ar/mcp-servers.mdx new file mode 100644 index 00000000000..dacdb9490bf --- /dev/null +++ b/packages/web/src/content/docs/ar/mcp-servers.mdx @@ -0,0 +1,511 @@ +--- +title: خوادم MCP +description: أضف أدوات MCP محلية وبعيدة. +--- + +يمكنك إضافة أدوات خارجية إلى OpenCode باستخدام _Model Context Protocol_، أو MCP. يدعم OpenCode خوادم محلية وبعيدة. + +بعد إضافتها، تصبح أدوات MCP متاحة تلقائيا للـ LLM إلى جانب الأدوات المضمنة. + +--- + +#### تنبيهات + +عند استخدام خادم MCP فإنه يضيف إلى السياق. وقد يتراكم ذلك بسرعة إذا كان لديك الكثير من الأدوات. لذلك نوصي بالتحلّي بالحذر عند اختيار خوادم MCP التي تستخدمها. + +:::tip +تضيف خوادم MCP إلى سياقك، لذا احرص على اختيار ما تفعّله منها بعناية. +::: + +تميل بعض خوادم MCP، مثل خادم GitHub MCP، إلى إضافة الكثير من الرموز (tokens) وقد تتجاوز حد السياق بسهولة. + +--- + +## التمكين + +يمكنك تعريف خوادم MCP في [إعدادات OpenCode](https://opencode.ai/docs/config/) ضمن `mcp`. أضف كل خادم MCP باسم فريد. ويمكنك الإشارة إلى ذلك الخادم بالاسم عند توجيه الطلب إلى الـ LLM. + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +يمكنك أيضا تعطيل خادم عبر ضبط `enabled` على `false`. يفيد ذلك إذا أردت تعطيله مؤقتا دون إزالته من إعداداتك. + +--- + +### تجاوز القيم الافتراضية البعيدة + +يمكن للمنظمات توفير خوادم MCP الافتراضية عبر نقطة النهاية `.well-known/opencode` الخاصة بها. قد تكون هذه الخوادم معطّلة افتراضيا، مما يتيح للمستخدمين تفعيل ما يحتاجونه فقط. + +لتفعيل خادم معيّن من الإعدادات البعيدة الخاصة بمؤسستك، أضفه إلى إعداداتك المحلية مع `enabled: true`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +تتغلب قيم إعداداتك المحلية على القيم الافتراضية البعيدة. راجع [أولوية الإعدادات](/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", + }, + }, + }, +} +``` + +الأمر `command` هو الطريقة التي يتم بها تشغيل خادم MCP المحلي. ويمكنك أيضا تمرير قائمة بمتغيرات البيئة. + +على سبيل المثال، إليك كيفية إضافة خادم MCP التجريبي [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything). + +```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` | String | Y | نوع اتصال خادم MCP، ويجب أن يكون `"local"`. | +| `command` | Array | Y | الأمر والوسائط اللازمة لتشغيل خادم MCP. | +| `environment` | Object | | متغيرات البيئة التي يتم تعيينها عند تشغيل الخادم. | +| `enabled` | Boolean | | تفعيل خادم MCP أو تعطيله عند بدء التشغيل. | +| `timeout` | Number | | المهلة بالمللي ثانية لجلب الأدوات من خادم MCP. القيمة الافتراضية 5000 (5 ثوانٍ). | + +--- + +## بعيد + +أضف خوادم MCP البعيدة عبر ضبط `type` على `"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" + } + } + } +} +``` + +يمثل `url` عنوان URL لخادم MCP البعيد، وباستخدام خيار `headers` يمكنك تمرير قائمة من الرؤوس (headers). + +--- + +#### الخيارات + +| الخيار | النوع | مطلوب | الوصف | +| --------- | ------- | ----- | -------------------------------------------------------------------------------- | +| `type` | String | Y | نوع اتصال خادم MCP، ويجب أن يكون `"remote"`. | +| `url` | String | Y | عنوان URL لخادم MCP البعيد. | +| `enabled` | Boolean | | تفعيل خادم MCP أو تعطيله عند بدء التشغيل. | +| `headers` | Object | | الرؤوس التي يتم إرسالها مع الطلب. | +| `oauth` | Object | | إعدادات مصادقة OAuth. راجع قسم [OAuth](#oauth) أدناه. | +| `timeout` | Number | | المهلة بالمللي ثانية لجلب الأدوات من خادم MCP. القيمة الافتراضية 5000 (5 ثوانٍ). | + +--- + +## OAuth + +يتولى OpenCode تلقائيا معالجة مصادقة OAuth لخوادم MCP البعيدة. عندما يتطلب خادم ما المصادقة، سيقوم OpenCode بما يلي: + +1. اكتشاف استجابة 401 وبدء تدفق OAuth +2. استخدام **Dynamic Client Registration (RFC 7591)** إذا كان الخادم يدعمه +3. تخزين الرموز (tokens) بشكل آمن للطلبات المستقبلية + +--- + +### تلقائي + +بالنسبة لمعظم خوادم MCP التي تدعم OAuth، لا تحتاج إلى إعدادات خاصة. ما عليك سوى تهيئة الخادم البعيد: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "my-oauth-server": { + "type": "remote", + "url": "https://mcp.example.com/mcp" + } + } +} +``` + +إذا كان الخادم يتطلب المصادقة، فسيطلب منك OpenCode المصادقة عند أول محاولة لاستخدامه. وإذا لم يحدث ذلك، يمكنك [تشغيل التدفق يدويا](#authenticating) باستخدام `opencode mcp auth `. + +--- + +### مُسجَّل مسبقا + +إذا كانت لديك بيانات اعتماد العميل من موفّر خادم 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 + +إذا أردت تعطيل OAuth التلقائي لخادم ما (على سبيل المثال، للخوادم التي تستخدم مفاتيح API بدلا من ذلك)، فاضبط `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، أو `false` لتعطيل الاكتشاف التلقائي لـ OAuth. | +| `clientId` | String | معرّف عميل OAuth. إذا لم يُحدَّد، ستتم محاولة التسجيل الديناميكي للعميل. | +| `clientSecret` | String | سرّ عميل OAuth، إذا كان مطلوبا من خادم التفويض. | +| `scope` | String | نطاقات OAuth المطلوبة أثناء التفويض. | + +#### تصحيح الأخطاء + +إذا فشل خادم MCP بعيد في المصادقة، يمكنك تشخيص المشكلة باستخدام: + +```bash +# عرض حالة المصادقة لجميع الخوادم القادرة على OAuth +opencode mcp auth list + +# تصحيح الاتصال وتدفق OAuth لخادم محدد +opencode mcp debug my-oauth-server +``` + +يعرض أمر `mcp debug` حالة المصادقة الحالية، ويختبر اتصال HTTP، ويحاول تنفيذ تدفق اكتشاف OAuth. + +--- + +## الإدارة + +تتوفر خوادم MCP لديك كأدوات داخل OpenCode إلى جانب الأدوات المضمنة. لذا يمكنك إدارتها عبر إعدادات OpenCode مثل أي أداة أخرى. + +--- + +### عام + +هذا يعني أنه يمكنك تفعيلها أو تعطيلها على مستوى عام. + +```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 + } +} +``` + +يمكننا أيضا استخدام نمط glob لتعطيل جميع خوادم 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 + } +} +``` + +هنا نستخدم نمط glob `my-mcp*` لتعطيل جميع خوادم MCP. + +--- + +### لكل وكيل + +إذا كان لديك عدد كبير من خوادم MCP فقد ترغب في تفعيلها لكل وكيل على حدة وتعطيلها على المستوى العام. للقيام بذلك: + +1. عطّلها كأداة على المستوى العام. +2. في [إعدادات الوكيل](/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 + } + } + } +} +``` + +--- + +#### أنماط Glob + +يستخدم نمط glob أنماطا بسيطة من مطابقة glob: + +- `*` يطابق صفرا أو أكثر من أي محرف (على سبيل المثال، `"my-mcp*"` يطابق `my-mcp_search` و`my-mcp_list` وغيرها.) +- `?` يطابق محرفا واحدا بالضبط +- جميع المحارف الأخرى تُطابق حرفيا + +:::note +تُسجَّل أدوات خادم MCP مع اسم الخادم كبادئة، لذا لتعطيل جميع أدوات خادم ما استخدم ببساطة: + +``` +"mymcpservername_*": false +``` + +::: + +--- + +## أمثلة + +فيما يلي أمثلة لبعض خوادم MCP الشائعة. يمكنك إرسال PR إذا أردت توثيق خوادم أخرى. + +--- + +### Sentry + +أضف [خادم MCP الخاص بـ Sentry](https://mcp.sentry.dev) للتفاعل مع مشاريع Sentry والقضايا (issues) الخاصة بك. + +```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 + +أضف [خادم MCP الخاص بـ Context7](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`. + +أضف `use context7` إلى طلباتك لاستخدام خادم MCP الخاص بـ 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 + +أضف خادم MCP الخاص بـ [Grep by Vercel](https://grep.app) للبحث في مقتطفات الشيفرة على GitHub. + +```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/ar/models.mdx b/packages/web/src/content/docs/ar/models.mdx new file mode 100644 index 00000000000..dcb6aa519e6 --- /dev/null +++ b/packages/web/src/content/docs/ar/models.mdx @@ -0,0 +1,222 @@ +--- +title: النماذج +description: تهيئة مزوّد LLM والنموذج. +--- + +يستخدم OpenCode كلاً من [AI SDK](https://ai-sdk.dev/) و[Models.dev](https://models.dev) لدعم **أكثر من 75 مزوّداً لنماذج LLM**، كما يدعم تشغيل النماذج محلياً. + +--- + +## المزوّدون + +أكثر المزوّدين شيوعاً مُحمَّلون مسبقاً افتراضياً. إذا أضفت بيانات اعتماد أحد المزوّدين عبر الأمر `/connect` فستكون متاحة عند تشغيل OpenCode. + +تعرّف على المزيد حول [المزوّدين](/docs/providers). + +--- + +## اختر نموذجاً + +بعد تهيئة المزوّد يمكنك اختيار النموذج الذي تريده بكتابة: + +```bash frame="none" +/models +``` + +--- + +## النماذج الموصى بها + +هناك الكثير من النماذج المتاحة، وتظهر نماذج جديدة كل أسبوع. + +:::tip +ننصح باستخدام أحد النماذج التي نوصي بها. +::: + +لكن القليل منها فقط يكون جيداً في كلٍ من توليد الشيفرة واستدعاء الأدوات. + +فيما يلي عدة نماذج تعمل جيداً مع OpenCode، دون ترتيب معيّن. (هذه ليست قائمة شاملة وقد لا تكون محدَّثة دائماً): + +- GPT 5.2 +- GPT 5.1 Codex +- Claude Opus 4.5 +- Claude Sonnet 4.5 +- Minimax M2.1 +- Gemini 3 Pro + +--- + +## تعيين الافتراضي + +لتعيين أحد هذه النماذج كنموذج افتراضي، يمكنك ضبط المفتاح `model` في ملف إعدادات OpenCode. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +المعرّف الكامل هنا يكون بالشكل `provider_id/model_id`. على سبيل المثال، إذا كنت تستخدم [OpenCode Zen](/docs/zen) فستستخدم `opencode/gpt-5.1-codex` لنموذج GPT 5.1 Codex. + +إذا كنت قد هيّأت [مزوّداً مخصّصاً](/docs/providers#custom)، فإن `provider_id` هو المفتاح الموجود ضمن قسم `provider` في إعداداتك، و`model_id` هو المفتاح الموجود ضمن `provider.models`. + +--- + +## إعداد النماذج + +يمكنك ضبط خيارات النموذج على مستوى عام عبر ملف الإعدادات. + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +هنا نقوم بضبط إعدادات عامة لنموذجين مدمجين: `gpt-5` عند الوصول إليه عبر مزوّد `openai`، و`claude-sonnet-4-20250514` عند الوصول إليه عبر مزوّد `anthropic`. +يمكن العثور على أسماء المزوّدين والنماذج المدمجة على [Models.dev](https://models.dev). + +يمكنك أيضاً ضبط هذه الخيارات لأي وكلاء تستخدمهم. تتجاوز إعدادات الوكيل أي خيارات عامة هنا. [اعرف المزيد](/docs/agents/#additional). + +كما يمكنك تعريف متغيّرات مخصّصة تُوسّع المتغيّرات المدمجة. تتيح لك المتغيّرات ضبط إعدادات مختلفة للنموذج نفسه دون إنشاء إدخالات مكرّرة: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## المتغيّرات + +تدعم العديد من النماذج عدة متغيّرات بإعدادات مختلفة. يأتي OpenCode مع متغيّرات افتراضية مدمجة للمزوّدين الشائعين. + +### المتغيّرات المدمجة + +يأتي OpenCode مع متغيّرات افتراضية لعدد كبير من المزوّدين: + +**Anthropic**: + +- `high` - ميزانية تفكير مرتفعة (الافتراضي) +- `max` - أقصى ميزانية تفكير + +**OpenAI**: + +تختلف حسب النموذج، لكن بشكل عام: + +- `none` - بدون استدلال +- `minimal` - أقل جهد للاستدلال +- `low` - جهد استدلال منخفض +- `medium` - جهد استدلال متوسط +- `high` - جهد استدلال مرتفع +- `xhigh` - جهد استدلال مرتفع جداً + +**Google**: + +- `low` - جهد/ميزانية رموز أقل +- `high` - جهد/ميزانية رموز أعلى + +:::tip +هذه القائمة ليست شاملة. لدى العديد من المزوّدين الآخرين إعدادات افتراضية مدمجة أيضاً. +::: + +### متغيّرات مخصّصة + +يمكنك تجاوز المتغيّرات الموجودة أو إضافة متغيّراتك الخاصة: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### التبديل بين المتغيّرات + +استخدم اختصار لوحة المفاتيح `variant_cycle` للتبديل بسرعة بين المتغيّرات. [اعرف المزيد](/docs/keybinds). + +--- + +## تحميل النماذج + +عند بدء تشغيل OpenCode، يتحقق من النماذج وفق ترتيب الأولوية التالي: + +1. خيار CLI `--model` أو `-m`. الصيغة هي نفسها الموجودة في ملف الإعدادات: `provider_id/model_id`. + +2. قائمة النماذج في إعدادات OpenCode. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + + الصيغة هنا هي `provider/model`. + +3. آخر نموذج تم استخدامه. + +4. أول نموذج وفق أولوية داخلية. diff --git a/packages/web/src/content/docs/ar/modes.mdx b/packages/web/src/content/docs/ar/modes.mdx new file mode 100644 index 00000000000..f4889819aa7 --- /dev/null +++ b/packages/web/src/content/docs/ar/modes.mdx @@ -0,0 +1,331 @@ +--- +title: الأوضاع +description: أوضاع مختلفة لحالات استخدام مختلفة. +--- + +:::caution +يتم الآن ضبط الأوضاع عبر خيار `agent` في إعدادات opencode. أصبح خيار +`mode` مُهمَلًا الآن. [اعرف المزيد](/docs/agents). +::: + +تتيح لك الأوضاع في opencode تخصيص السلوك والأدوات والمطالبات لحالات استخدام مختلفة. + +يأتي مع وضعين مدمجين: **build** و **plan**. يمكنك تخصيصهما أو إعداد +أوضاعك الخاصة عبر إعدادات opencode. + +يمكنك التبديل بين الأوضاع أثناء الجلسة أو إعدادها في ملف الإعدادات لديك. + +--- + +## الأوضاع المدمجة + +يأتي opencode مع وضعين مدمجين. + +--- + +### Build + +وضع Build هو الوضع **الافتراضي** مع تفعيل جميع الأدوات. هذا هو الوضع القياسي لأعمال التطوير عندما تحتاج إلى وصول كامل لعمليات الملفات وأوامر النظام. + +--- + +### Plan + +وضع مقيَّد مُصمَّم للتخطيط والتحليل. في وضع plan، تكون الأدوات التالية مُعطَّلة افتراضيًا: + +- `write` - لا يمكن إنشاء ملفات جديدة +- `edit` - لا يمكن تعديل الملفات الموجودة، باستثناء الملفات الموجودة في `.opencode/plans/*.md` لتفصيل الخطة نفسها +- `patch` - لا يمكن تطبيق التصحيحات +- `bash` - لا يمكن تنفيذ أوامر shell + +يكون هذا الوضع مفيدًا عندما تريد من الذكاء الاصطناعي تحليل الشيفرة، أو اقتراح تغييرات، أو إنشاء خطط دون إجراء أي تعديلات فعلية على قاعدة الشيفرة لديك. + +--- + +## التبديل + +يمكنك التبديل بين الأوضاع أثناء الجلسة باستخدام مفتاح _Tab_، أو اختصار `switch_mode` الذي قمت بإعداده. + +انظر أيضًا: [Formatters](/docs/formatters) لمعلومات حول إعدادات تنسيق الشيفرة. + +--- + +## الإعداد + +يمكنك تخصيص الأوضاع المدمجة أو إنشاء أوضاعك الخاصة عبر الإعدادات. يمكن إعداد الأوضاع بطريقتين: + +### إعدادات JSON + +قم بإعداد الأوضاع في ملف الإعدادات `opencode.json` لديك: + +```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 + +يمكنك أيضًا تعريف الأوضاع باستخدام ملفات markdown. ضعها في: + +- عالمي: `~/.config/opencode/modes/` +- للمشروع: `.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. +``` + +يصبح اسم ملف markdown هو اسم الوضع (على سبيل المثال، `review.md` ينشئ وضعًا باسم `review`). + +لنلقِ نظرة على خيارات الإعداد هذه بمزيد من التفصيل. + +--- + +### النموذج + +استخدم إعداد `model` لتجاوز النموذج الافتراضي لهذا الوضع. يفيد ذلك عند استخدام نماذج مختلفة مُحسَّنة لمهام مختلفة؛ مثل نموذج أسرع للتخطيط ونموذج أكثر قدرة للتنفيذ. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### درجة الحرارة + +تحكَّم في العشوائية والإبداع في ردود الذكاء الاصطناعي عبر إعداد `temperature`. القيم الأقل تجعل الردود أكثر تركيزًا وحتمية، بينما تزيد القيم الأعلى الإبداع والتنوّع. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +تتراوح قيم درجة الحرارة عادةً بين 0.0 و 1.0: + +- **0.0-0.2**: ردود شديدة التركيز وحتمية، مثالية لتحليل الشيفرة والتخطيط +- **0.3-0.5**: ردود متوازنة مع قدر من الإبداع، مناسبة لمهام التطوير العامة +- **0.6-1.0**: ردود أكثر إبداعًا وتنوّعًا، مفيدة للعصف الذهني والاستكشاف + +```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}" + } + } +} +``` + +إذا لم يتم تحديد درجة الحرارة، يستخدم opencode القيم الافتراضية الخاصة بكل نموذج (عادةً 0 لمعظم النماذج و 0.55 لنماذج Qwen). + +--- + +### الموجّه + +حدِّد ملف موجّه نظام (system prompt) مخصص لهذا الوضع عبر إعداد `prompt`. ينبغي أن يحتوي ملف الموجّه على تعليمات مرتبطة بهدف هذا الوضع. + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +هذا المسار نسبي بالنسبة لموقع ملف الإعدادات. لذلك يعمل مع +إعدادات opencode العالمية وكذلك إعدادات المشروع. + +--- + +### الأدوات + +تحكَّم في الأدوات المتاحة في هذا الوضع عبر إعداد `tools`. يمكنك تفعيل أدوات محددة أو تعطيلها بضبطها على `true` أو `false`. + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +إذا لم يتم تحديد أدوات، فستكون جميع الأدوات مفعّلة افتراضيًا. + +--- + +#### الأدوات المتاحة + +فيما يلي جميع الأدوات التي يمكن التحكم بها عبر إعدادات الوضع. + +| الأداة | الوصف | +| ----------- | -------------------------- | +| `bash` | تنفيذ أوامر shell | +| `edit` | تعديل الملفات الموجودة | +| `write` | إنشاء ملفات جديدة | +| `read` | قراءة محتويات الملفات | +| `grep` | البحث في محتويات الملفات | +| `glob` | العثور على الملفات حسب نمط | +| `list` | سرد محتويات الدليل | +| `patch` | تطبيق تصحيحات على الملفات | +| `todowrite` | إدارة قوائم المهام | +| `todoread` | قراءة قوائم المهام | +| `webfetch` | جلب محتوى الويب | + +--- + +## أوضاع مخصصة + +يمكنك إنشاء أوضاعك المخصصة بإضافتها إلى الإعدادات. فيما يلي أمثلة باستخدام كلا الأسلوبين: + +### باستخدام إعدادات JSON + +```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 + } + } + } +} +``` + +### باستخدام ملفات markdown + +أنشئ ملفات الأوضاع في `.opencode/modes/` لأوضاع خاصة بالمشروع أو في `~/.config/opencode/modes/` لأوضاع عالمية: + +```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 +``` + +--- + +### حالات الاستخدام + +فيما يلي بعض حالات الاستخدام الشائعة لأوضاع مختلفة. + +- **Build mode**: أعمال تطوير كاملة مع تفعيل جميع الأدوات +- **Plan mode**: التحليل والتخطيط دون إجراء تغييرات +- **Review mode**: مراجعة الشيفرة مع وصول للقراءة فقط بالإضافة إلى أدوات التوثيق +- **Debug mode**: تركيز على الاستقصاء مع تفعيل أدوات `bash` و `read` +- **Docs mode**: كتابة التوثيق مع عمليات الملفات لكن دون أوامر النظام + +قد تجد أيضًا أن نماذج مختلفة تكون أنسب لحالات استخدام مختلفة. diff --git a/packages/web/src/content/docs/ar/network.mdx b/packages/web/src/content/docs/ar/network.mdx new file mode 100644 index 00000000000..62f9b94a88a --- /dev/null +++ b/packages/web/src/content/docs/ar/network.mdx @@ -0,0 +1,57 @@ +--- +title: الشبكة +description: إعداد الوكلاء والشهادات المخصصة. +--- + +يدعم OpenCode متغيرات بيئة الوكيل (proxy) القياسية والشهادات المخصصة لبيئات الشبكات المؤسسية. + +--- + +## الوكيل + +يتبع OpenCode متغيرات بيئة الوكيل القياسية. + +```bash +# وكيل HTTPS (موصى به) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# وكيل HTTP (إذا لم يتوفر HTTPS) +export HTTP_PROXY=http://proxy.example.com:8080 + +# تجاوز الوكيل للخادم المحلي (مطلوب) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +تتواصل واجهة TUI مع خادم HTTP محلي. يجب تجاوز الوكيل لهذا الاتصال لمنع حلقات التوجيه. +::: + +يمكنك إعداد منفذ الخادم واسم المضيف باستخدام [أعلام CLI](/docs/cli#run). + +--- + +### المصادقة + +إذا كان الوكيل يتطلب مصادقة أساسية، فأدرج بيانات الاعتماد في عنوان URL. + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +تجنّب تضمين كلمات المرور بشكل ثابت. استخدم متغيرات البيئة أو تخزين بيانات اعتماد آمن. +::: + +بالنسبة للوكلاء الذين يتطلبون مصادقة متقدمة مثل NTLM أو Kerberos، فكّر في استخدام بوابة LLM تدعم طريقة المصادقة لديك. + +--- + +## الشهادات المخصصة + +إذا كانت مؤسستك تستخدم سلطات تصديق (CA) مخصصة لاتصالات HTTPS، فقم بإعداد OpenCode ليثق بها. + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +يعمل ذلك لكل من اتصالات الوكيل والوصول المباشر إلى APIs. diff --git a/packages/web/src/content/docs/ar/permissions.mdx b/packages/web/src/content/docs/ar/permissions.mdx new file mode 100644 index 00000000000..ee22c951d47 --- /dev/null +++ b/packages/web/src/content/docs/ar/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: الأذونات +description: تحكّم في الإجراءات التي تتطلب موافقة قبل تنفيذها. +--- + +يستخدم OpenCode إعداد `permission` لتحديد ما إذا كان إجراءٌ ما سيُنفّذ تلقائيًا، أو سيطلب موافقتك، أو سيتم حظره. + +اعتبارًا من `v1.1.1`، تم إهمال إعداد `tools` القديم (المنطقي) ودمجه ضمن `permission`. ولا يزال إعداد `tools` القديم مدعومًا للتوافق مع الإصدارات السابقة. + +--- + +## الإجراءات + +يؤول كل حكم أذونات إلى إحدى القيم التالية: + +- `"allow"` — تشغيل دون موافقة +- `"ask"` — طلب الموافقة +- `"deny"` — حظر الإجراء + +--- + +## الإعداد + +يمكنك تعيين الأذونات بشكل عام (باستخدام `*`) ثم تجاوزها لأدوات محددة. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +يمكنك أيضًا تعيين جميع الأذونات دفعة واحدة: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## قواعد دقيقة (صيغة الكائن) + +في معظم الأذونات، يمكنك استخدام كائن لتطبيق إجراءات مختلفة بناءً على مُدخلات الأداة. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +تُقيَّم القواعد عبر مطابقة الأنماط، مع كون **آخر قاعدة مطابقة هي التي تُطبَّق**. من الشائع وضع قاعدة الشمول `"*"` أولًا ثم القواعد الأكثر تحديدًا بعدها. + +### أحرف البدل + +تستخدم أنماط الأذونات مطابقة بسيطة لأحرف البدل: + +- `*` يطابق صفرًا أو أكثر من أي حرف +- `?` يطابق حرفًا واحدًا بالضبط +- جميع الأحرف الأخرى تُطابق حرفيًا + +### توسيع مجلد المنزل + +يمكنك استخدام `~` أو `$HOME` في بداية النمط للإشارة إلى مجلد المنزل. هذا مفيد خصوصًا لقواعد [`external_directory`](#external-directories). + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### الأدلة الخارجية + +استخدم `external_directory` للسماح باستدعاءات الأدوات التي تلمس مسارات خارج دليل العمل الذي بدأ منه OpenCode. ينطبق ذلك على أي أداة تأخذ مسارًا كمدخل (مثل `read` و`edit` و`list` و`glob` و`grep` والعديد من أوامر `bash`). + +توسيع المنزل (مثل `~/...`) يؤثر فقط على طريقة كتابة النمط. لا يجعل ذلك المسار الخارجي جزءًا من مساحة العمل الحالية، لذا يجب السماح بالمسارات خارج دليل العمل عبر `external_directory` أيضًا. + +على سبيل المثال، يتيح هذا الوصول إلى كل ما يقع تحت `~/projects/personal/`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +أي دليل مسموح به هنا يرث نفس القيم الافتراضية لمساحة العمل الحالية. وبما أن [`read` افتراضيًا هو `allow`](#defaults)، فإن عمليات القراءة تكون مسموحة أيضًا للعناصر ضمن `external_directory` ما لم يتم تجاوز ذلك. أضِف قواعد صريحة عندما يجب تقييد أداة ما في هذه المسارات، مثل حظر التعديلات مع الإبقاء على القراءة: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +اجعل القائمة مقتصرة على المسارات الموثوقة، ثم أضِف طبقات إضافية من قواعد `allow` أو `deny` حسب الحاجة لأدوات أخرى (مثل `bash`). + +--- + +## الأذونات المتاحة + +تُعرَّف أذونات OpenCode بأسماء الأدوات، بالإضافة إلى بعض حواجز الأمان: + +- `read` — قراءة ملف (يطابق مسار الملف) +- `edit` — جميع تعديلات الملفات (يشمل `edit` و`write` و`patch` و`multiedit`) +- `glob` — مطابقة أسماء الملفات (يطابق نمط الـ glob) +- `grep` — البحث في المحتوى (يطابق نمط regex) +- `list` — سرد الملفات في دليل (يطابق مسار الدليل) +- `bash` — تشغيل أوامر shell (يطابق الأوامر المُحلَّلة مثل `git status --porcelain`) +- `task` — تشغيل وكلاء فرعيين (يطابق نوع الوكيل الفرعي) +- `skill` — تحميل مهارة (يطابق اسم المهارة) +- `lsp` — تشغيل استعلامات LSP (حاليًا دون قواعد دقيقة) +- `todoread`, `todowrite` — قراءة/تحديث قائمة المهام +- `webfetch` — جلب عنوان URL (يطابق الـ URL) +- `websearch`, `codesearch` — بحث الويب/الكود (يطابق الاستعلام) +- `external_directory` — يُفعَّل عندما تلمس أداة مسارات خارج دليل عمل المشروع +- `doom_loop` — يُفعَّل عندما يتكرر نفس استدعاء الأداة 3 مرات مع نفس المُدخلات + +--- + +## القيم الافتراضية + +إذا لم تحدد شيئًا، يبدأ OpenCode بقيم افتراضية متساهلة: + +- معظم الأذونات افتراضيًا تكون `"allow"`. +- `doom_loop` و`external_directory` افتراضيًا تكون `"ask"`. +- `read` هو `"allow"`، لكن ملفات `.env` تكون مرفوضة افتراضيًا: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## ماذا تفعل `"ask"` + +عندما يطلب OpenCode الموافقة، تعرض الواجهة ثلاث نتائج ممكنة: + +- `once` — الموافقة على هذا الطلب فقط +- `always` — الموافقة على الطلبات المستقبلية المطابقة للأنماط المقترحة (لباقي جلسة OpenCode الحالية) +- `reject` — رفض الطلب + +مجموعة الأنماط التي ستوافق عليها `always` تُوفَّر من الأداة نفسها (على سبيل المثال، موافقات `bash` عادةً ما تُدرج بادئة أمر آمنة في القائمة البيضاء مثل `git status*`). + +--- + +## الوكلاء + +يمكنك تجاوز الأذونات لكل وكيل. تُدمَج أذونات الوكلاء مع الإعداد العام، وتكون قواعد الوكيل هي ذات الأولوية. [تعرّف أكثر](/docs/agents#permissions) على أذونات الوكلاء. + +:::note +ارجع إلى قسم [قواعد دقيقة (صيغة الكائن)](#granular-rules-object-syntax) للحصول على أمثلة أكثر تفصيلًا حول مطابقة الأنماط. +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +يمكنك أيضًا ضبط أذونات الوكيل في Markdown: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +استخدم مطابقة الأنماط للأوامر التي تحتوي على معاملات. يسمح `"grep *"` بتنفيذ `grep pattern file.txt`، بينما سيحظر `"grep"` وحده ذلك. تعمل أوامر مثل `git status` للسلوك الافتراضي، لكنها تتطلب إذنًا صريحًا (مثل `"git status *"`) عند تمرير معاملات. +::: diff --git a/packages/web/src/content/docs/ar/plugins.mdx b/packages/web/src/content/docs/ar/plugins.mdx new file mode 100644 index 00000000000..d7c025bbc31 --- /dev/null +++ b/packages/web/src/content/docs/ar/plugins.mdx @@ -0,0 +1,385 @@ +--- +title: الإضافات +description: اكتب إضافاتك الخاصة لتوسيع OpenCode. +--- + +تتيح لك الإضافات توسيع OpenCode عبر ربطها بأحداث مختلفة وتخصيص السلوك. يمكنك إنشاء إضافات لإضافة ميزات جديدة، أو التكامل مع خدمات خارجية، أو تعديل السلوك الافتراضي لـ OpenCode. + +للاطلاع على أمثلة، راجع [الإضافات](/docs/ecosystem#plugins) التي أنشأها المجتمع. + +--- + +## استخدام إضافة + +هناك طريقتان لتحميل الإضافات. + +--- + +### من ملفات محلية + +ضع ملفات JavaScript أو TypeScript في دليل الإضافات. + +- `.opencode/plugins/` - إضافات على مستوى المشروع +- `~/.config/opencode/plugins/` - إضافات عامة + +تُحمَّل الملفات في هذه الأدلة تلقائيا عند بدء التشغيل. + +--- + +### من npm + +حدّد حزم npm في ملف الإعدادات. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +يتم دعم حزم npm العادية والحزم ذات النطاق (scoped). + +تصفّح الإضافات المتاحة في [النظام البيئي](/docs/ecosystem#plugins). + +--- + +### كيفية تثبيت الإضافات + +**إضافات npm** تُثبَّت تلقائيا باستخدام Bun عند بدء التشغيل. تُخزَّن الحزم واعتمادياتها مؤقتا في `~/.cache/opencode/node_modules/`. + +**الإضافات المحلية** تُحمَّل مباشرة من دليل الإضافات. لاستخدام حزم خارجية، يجب إنشاء `package.json` داخل دليل الإعدادات لديك (راجع [الاعتماديات](#dependencies))، أو نشر الإضافة على npm ثم [إضافتها إلى إعداداتك](/docs/config#plugins). + +--- + +### ترتيب التحميل + +تُحمَّل الإضافات من جميع المصادر وتعمل جميع الخطافات بالتتابع. ترتيب التحميل هو: + +1. إعدادات عامة (`~/.config/opencode/opencode.json`) +2. إعدادات المشروع (`opencode.json`) +3. دليل الإضافات العام (`~/.config/opencode/plugins/`) +4. دليل إضافات المشروع (`.opencode/plugins/`) + +تُحمَّل حزم npm المكررة ذات الاسم والإصدار نفسيهما مرة واحدة. ومع ذلك، تُحمَّل الإضافة المحلية وإضافة npm ذات الاسم المشابه كلتاهما بشكل مستقل. + +--- + +## إنشاء إضافة + +الإضافة هي **وحدة JavaScript/TypeScript** تصدّر دالة إضافة واحدة أو أكثر. +تستقبل كل دالة كائنا للسياق وتعيد كائنا للخطافات. + +--- + +### الاعتماديات + +يمكن للإضافات المحلية والأدوات المخصصة استخدام حزم npm خارجية. أضف `package.json` إلى دليل الإعدادات لديك متضمنا الاعتماديات التي تحتاجها. + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +يشغّل OpenCode الأمر `bun install` عند بدء التشغيل لتثبيتها. بعد ذلك يمكن لإضافاتك وأدواتك استيرادها. + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### البنية الأساسية + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +تستقبل دالة الإضافة ما يلي: + +- `project`: معلومات المشروع الحالي. +- `directory`: دليل العمل الحالي. +- `worktree`: مسار git worktree. +- `client`: عميل SDK لـ opencode للتفاعل مع الذكاء الاصطناعي. +- `$`: واجهة [shell API](https://bun.com/docs/runtime/shell) الخاصة بـ Bun لتنفيذ الأوامر. + +--- + +### دعم TypeScript + +بالنسبة لإضافات TypeScript، يمكنك استيراد الأنواع من حزمة الإضافة: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### الأحداث + +يمكن للإضافات الاشتراك في الأحداث كما هو موضح أدناه في قسم الأمثلة. فيما يلي قائمة بالأحداث المتاحة. + +#### أحداث الأوامر + +- `command.executed` + +#### أحداث الملفات + +- `file.edited` +- `file.watcher.updated` + +#### أحداث التثبيت + +- `installation.updated` + +#### أحداث LSP + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### أحداث الرسائل + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### أحداث الأذونات + +- `permission.asked` +- `permission.replied` + +#### أحداث الخادم + +- `server.connected` + +#### أحداث الجلسة + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### أحداث Todo + +- `todo.updated` + +#### أحداث shell + +- `shell.env` + +#### أحداث الأدوات + +- `tool.execute.after` +- `tool.execute.before` + +#### أحداث واجهة TUI + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## أمثلة + +فيما يلي بعض أمثلة الإضافات التي يمكنك استخدامها لتوسيع opencode. + +--- + +### إرسال إشعارات + +أرسل إشعارات عند وقوع أحداث معينة: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +نستخدم `osascript` لتشغيل AppleScript على macOS. هنا نستخدمه لإرسال إشعارات. + +:::note +إذا كنت تستخدم تطبيق OpenCode لسطح المكتب، فيمكنه إرسال إشعارات النظام تلقائيا عند جاهزية الرد أو عند حدوث خطأ في جلسة. +::: + +--- + +### حماية .env + +امنع opencode من قراءة ملفات `.env`: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### حقن متغيرات البيئة + +احقن متغيرات البيئة في جميع عمليات تنفيذ shell (أدوات الذكاء الاصطناعي وterminal المستخدم): + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### أدوات مخصصة + +يمكن للإضافات أيضا إضافة أدوات مخصصة إلى opencode: + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +تقوم الدالة المساعدة `tool` بإنشاء أداة مخصصة يمكن لـ opencode استدعاؤها. تأخذ دالة مخطط Zod وتعيد تعريف أداة يتضمن: + +- `description`: ما الذي تفعله الأداة +- `args`: مخطط Zod لوسائط الأداة +- `execute`: الدالة التي تُشغَّل عند استدعاء الأداة + +ستكون أدواتك المخصصة متاحة لـ opencode إلى جانب الأدوات المضمنة. + +--- + +### التسجيل + +استخدم `client.app.log()` بدلا من `console.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` في هذه الحالة. diff --git a/packages/web/src/content/docs/ar/providers.mdx b/packages/web/src/content/docs/ar/providers.mdx new file mode 100644 index 00000000000..1d448986f31 --- /dev/null +++ b/packages/web/src/content/docs/ar/providers.mdx @@ -0,0 +1,1885 @@ +--- +title: المزوّدون +description: استخدام أي موفّر LLM في OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console + +يستخدم OpenCode ‏[AI SDK](https://ai-sdk.dev/) و[Models.dev](https://models.dev) لدعم **أكثر من 75 موفّر LLM**، كما يدعم تشغيل النماذج المحلية. + +لإضافة مزوّد تحتاج إلى: + +1. أضف مفاتيح API الخاصة بالمزوّد باستخدام الأمر `/connect`. +2. اضبط المزوّد في ملف إعدادات OpenCode. + +--- + +### بيانات الاعتماد + +عند إضافة مفاتيح API الخاصة بمزوّد عبر الأمر `/connect`، يتم تخزينها +في `~/.local/share/opencode/auth.json`. + +--- + +### الإعدادات + +يمكنك تخصيص المزوّدات عبر قسم `provider` في ملف إعدادات OpenCode. + +--- + +#### عنوان URL الأساسي + +يمكنك تخصيص عنوان URL الأساسي لأي مزوّد عبر خيار `baseURL`. يفيد ذلك عند استخدام خدمات وسيطة (proxy) أو نقاط نهاية مخصّصة. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen هي قائمة نماذج يوفّرها فريق OpenCode وقد تم +اختبارها والتحقق من أنها تعمل بشكل جيد مع OpenCode. [اعرف المزيد](/docs/zen). + +:::tip +إذا كنت جديدا، فننصح بالبدء مع OpenCode Zen. +::: + +1. شغّل الأمر `/connect` في TUI، واختر opencode، ثم انتقل إلى [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. سجّل الدخول، وأضف تفاصيل الفوترة، ثم انسخ مفتاح API الخاص بك. + +3. الصق مفتاح API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل `/models` في TUI لعرض قائمة النماذج التي نوصي بها. + + ```txt + /models + ``` + +يعمل مثل أي مزوّد آخر في OpenCode واستخدامه اختياري بالكامل. + +--- + +## الدليل + +لنلقِ نظرة على بعض المزوّدات بالتفصيل. إذا رغبت في إضافة مزوّد إلى القائمة، +فلا تتردد في فتح PR. + +:::note +لم تجد المزوّد الذي تبحث عنه؟ أرسل PR. +::: + +--- + +### 302.AI + +1. توجّه إلى [302.AI console](https://302.ai/)، وأنشئ حسابا، ثم أنشئ مفتاح API. + +2. شغّل الأمر `/connect` وابحث عن **302.AI**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ 302.AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار نموذج. + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +لاستخدام Amazon Bedrock مع OpenCode: + +1. توجّه إلى **Model catalog** في Amazon Bedrock console واطلب + الوصول إلى النماذج التي تريدها. + + :::tip + يجب أن يكون لديك وصول إلى النموذج الذي تريده في Amazon Bedrock. + ::: + +2. **اضبط المصادقة** باستخدام إحدى الطرق التالية: + + #### متغيرات البيئة (بدء سريع) + + عيّن أحد متغيرات البيئة التالية أثناء تشغيل opencode: + + ```bash + # الخيار 1: استخدام مفاتيح وصول AWS + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # الخيار 2: استخدام ملف تعريف AWS مسمّى + AWS_PROFILE=my-profile opencode + + # الخيار 3: استخدام رمز Bedrock المميز (bearer token) + AWS_BEARER_TOKEN_BEDROCK=XXX opencode + ``` + + أو أضفها إلى 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" + } + } + } + } + ``` + + **الخيارات المتاحة:** + - `region` - منطقة AWS (مثل `us-east-1`، `eu-west-1`) + - `profile` - ملف تعريف AWS المسمّى من `~/.aws/credentials` + - `endpoint` - عنوان URL لنقطة نهاية مخصّصة لنقاط نهاية VPC (اسم بديل لخيار `baseURL` العام) + + :::tip + خيارات ملف الإعدادات لها أولوية على متغيرات البيئة. + ::: + + #### متقدم: نقاط نهاية VPC + + إذا كنت تستخدم نقاط نهاية VPC لـ Bedrock: + + ```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` العام باستخدام مصطلحات AWS. إذا تم تحديد كل من `endpoint` و`baseURL`، فستكون الأولوية لـ `endpoint`. + ::: + + #### طرق المصادقة - **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: أنشئ مستخدم IAM وأنشئ مفاتيح وصول من AWS Console + - **`AWS_PROFILE`**: استخدم ملفات تعريف مسمّاة من `~/.aws/credentials`. اضبط أولا عبر `aws configure --profile my-profile` أو `aws sso login` + - **`AWS_BEARER_TOKEN_BEDROCK`**: أنشئ مفاتيح API طويلة الأجل من Amazon Bedrock console + - **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: لـ EKS IRSA (IAM Roles for Service Accounts) أو بيئات Kubernetes أخرى مع اتحاد OIDC. يتم حقن متغيرات البيئة هذه تلقائيا بواسطة Kubernetes عند استخدام تعليقات حساب الخدمة. + + #### أولوية المصادقة + + يستخدم Amazon Bedrock أولوية المصادقة التالية: + 1. **Bearer Token** - متغير البيئة `AWS_BEARER_TOKEN_BEDROCK` أو الرمز من الأمر `/connect` + 2. **AWS Credential Chain** - الملف الشخصي، مفاتيح الوصول، بيانات الاعتماد المشتركة، أدوار IAM، رموز Web Identity (EKS IRSA)، بيانات تعريف المثيل + + :::note + عند تعيين bearer token (عبر `/connect` أو `AWS_BEARER_TOKEN_BEDROCK`)، ستكون له أولوية على جميع طرق بيانات اعتماد AWS بما في ذلك ملفات التعريف المضبوطة. + ::: + +3. شغّل الأمر `/models` لاختيار النموذج الذي تريده. + + ```txt + /models + ``` + +:::note +بالنسبة إلى ملفات تعريف الاستدلال المخصّصة، استخدم اسم النموذج واسم المزوّد في المفتاح وعيّن الخاصية `id` إلى arn. يضمن ذلك التخزين المؤقت الصحيح: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. بعد إنشاء حسابك، شغّل الأمر `/connect` واختر Anthropic. + + ```txt + /connect + ``` + +2. هنا يمكنك اختيار خيار **Claude Pro/Max** وسيتم فتح المتصفح + وسيطلب منك المصادقة. + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. الآن يجب أن تكون جميع نماذج Anthropic متاحة عند استخدام الأمر `/models`. + + ```txt + /models + ``` + +:::info +استخدام اشتراك Claude Pro/Max داخل OpenCode غير مدعوم رسميا من [Anthropic](https://anthropic.com). +::: + +##### استخدام مفاتيح API + +يمكنك أيضا اختيار **Create an API Key** إذا لم يكن لديك اشتراك Pro/Max. سيفتح ذلك المتصفح أيضا ويطلب منك تسجيل الدخول إلى Anthropic ويعطيك رمزا يمكنك لصقه في terminal. + +أو إذا كان لديك مفتاح API بالفعل، يمكنك اختيار **Manually enter API Key** ولصقه في terminal. + +--- + +### Azure OpenAI + +:::note +إذا واجهت أخطاء "I'm sorry, but I cannot assist with that request"، فجرّب تغيير مرشح المحتوى من **DefaultV2** إلى **Default** في مورد Azure الخاص بك. +::: + +1. توجّه إلى [Azure portal](https://portal.azure.com/) وأنشئ موردا من نوع **Azure OpenAI**. ستحتاج إلى: + - **Resource name**: يصبح جزءا من نقطة نهاية API لديك (`https://RESOURCE_NAME.openai.azure.com/`) + - **API key**: إما `KEY 1` أو `KEY 2` من موردك + +2. اذهب إلى [Azure AI Foundry](https://ai.azure.com/) وانشر نموذجا. + + :::note + يجب أن يطابق اسم النشر اسم النموذج كي يعمل opencode بشكل صحيح. + ::: + +3. شغّل الأمر `/connect` وابحث عن **Azure**. + + ```txt + /connect + ``` + +4. أدخل مفتاح API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. عيّن اسم المورد كمتغير بيئة: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + أو أضفه إلى bash profile: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. شغّل الأمر `/models` لاختيار النموذج الذي قمت بنشره. + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. توجّه إلى [Azure portal](https://portal.azure.com/) وأنشئ موردا من نوع **Azure OpenAI**. ستحتاج إلى: + - **Resource name**: يصبح جزءا من نقطة نهاية API لديك (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) + - **API key**: إما `KEY 1` أو `KEY 2` من موردك + +2. اذهب إلى [Azure AI Foundry](https://ai.azure.com/) وانشر نموذجا. + + :::note + يجب أن يطابق اسم النشر اسم النموذج كي يعمل opencode بشكل صحيح. + ::: + +3. شغّل الأمر `/connect` وابحث عن **Azure Cognitive Services**. + + ```txt + /connect + ``` + +4. أدخل مفتاح API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. عيّن اسم المورد كمتغير بيئة: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + أو أضفه إلى bash profile: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. شغّل الأمر `/models` لاختيار النموذج الذي قمت بنشره. + + ```txt + /models + ``` + +--- + +### Baseten + +1. توجّه إلى [Baseten](https://app.baseten.co/)، وأنشئ حسابا، ثم أنشئ مفتاح API. + +2. شغّل الأمر `/connect` وابحث عن **Baseten**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ Baseten. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار نموذج. + + ```txt + /models + ``` + +--- + +### Cerebras + +1. توجّه إلى [Cerebras console](https://inference.cerebras.ai/)، وأنشئ حسابا، ثم أنشئ مفتاح API. + +2. شغّل الأمر `/connect` وابحث عن **Cerebras**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ Cerebras. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار نموذج مثل _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +تتيح Cloudflare AI Gateway الوصول إلى نماذج من OpenAI وAnthropic وWorkers AI وغيرها عبر نقطة نهاية موحّدة. مع [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) لن تحتاج إلى مفاتيح API منفصلة لكل مزوّد. + +1. توجّه إلى [Cloudflare dashboard](https://dash.cloudflare.com/)، وانتقل إلى **AI** > **AI Gateway**، وأنشئ بوابة جديدة. + +2. عيّن Account ID وGateway ID كمتغيرات بيئة. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. شغّل الأمر `/connect` وابحث عن **Cloudflare AI Gateway**. + + ```txt + /connect + ``` + +4. أدخل Cloudflare API token. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + أو عيّنه كمتغير بيئة. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. شغّل الأمر `/models` لاختيار نموذج. + + ```txt + /models + ``` + + يمكنك أيضا إضافة نماذج عبر إعدادات opencode. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +### Cortecs + +1. توجّه إلى [Cortecs console](https://cortecs.ai/)، وأنشئ حسابا، ثم أنشئ مفتاح API. + +2. شغّل الأمر `/connect` وابحث عن **Cortecs**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ Cortecs. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار نموذج مثل _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. توجّه إلى [DeepSeek console](https://platform.deepseek.com/)، وأنشئ حسابا، ثم انقر **Create new API key**. + +2. شغّل الأمر `/connect` وابحث عن **DeepSeek**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ DeepSeek. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار نموذج من DeepSeek مثل _DeepSeek Reasoner_. + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. توجّه إلى [Deep Infra dashboard](https://deepinfra.com/dash)، وأنشئ حسابا، ثم أنشئ مفتاح API. + +2. شغّل الأمر `/connect` وابحث عن **Deep Infra**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ Deep Infra. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار نموذج. + + ```txt + /models + ``` + +--- + +### Firmware + +1. توجّه إلى [Firmware dashboard](https://app.firmware.ai/signup)، وأنشئ حسابا، ثم أنشئ مفتاح API. + +2. شغّل الأمر `/connect` وابحث عن **Firmware**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ Firmware. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار نموذج. + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. توجّه إلى [Fireworks AI console](https://app.fireworks.ai/)، وأنشئ حسابا، ثم انقر **Create API Key**. + +2. شغّل الأمر `/connect` وابحث عن **Fireworks AI**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ Fireworks AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار نموذج مثل _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### GitLab Duo + +يوفّر GitLab Duo دردشة وكيلة (agentic) مدعومة بالذكاء الاصطناعي مع قدرات استدعاء أدوات بشكل مدمج عبر Anthropic proxy الخاصة بـ GitLab. + +1. شغّل الأمر `/connect` واختر GitLab. + + ```txt + /connect + ``` + +2. اختر طريقة المصادقة: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ + ``` + + #### استخدام OAuth (موصى به) + + اختر **OAuth** وسيفتح المتصفح لإتمام التفويض. + + #### استخدام Personal Access Token 1. اذهب إلى [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens) + 2. انقر **Add new token** + 3. Name: `OpenCode`، Scopes: `api` + 4. انسخ الرمز (يبدأ بـ `glpat-`) + 5. أدخله في terminal + +3. شغّل الأمر `/models` لعرض النماذج المتاحة. + + ```txt + /models + ``` + + تتوفر ثلاثة نماذج مبنية على Claude: + - **duo-chat-haiku-4-5** (Default) - استجابات سريعة للمهام السريعة + - **duo-chat-sonnet-4-5** - أداء متوازن لمعظم سير العمل + - **duo-chat-opus-4-5** - الأكثر قدرة للتحليل المعقّد + +:::note +يمكنك أيضا تعيين متغير البيئة 'GITLAB_TOKEN' إذا لم تكن تريد +تخزين الرمز في مساحة تخزين مصادقة opencode. +::: + +##### GitLab مستضاف ذاتيا + +:::note[ملاحظة امتثال] +يستخدم OpenCode نموذجا صغيرا لبعض مهام الذكاء الاصطناعي مثل إنشاء عنوان الجلسة. +تم ضبطه لاستخدام gpt-5-nano افتراضيا، مستضافا عبر Zen. لحصر OpenCode +على استخدام مثيل GitLab المستضاف لديك فقط، أضف ما يلي إلى ملف +`opencode.json` لديك. يوصى أيضا بتعطيل مشاركة الجلسات. + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +لمثيلات GitLab المستضافة ذاتيا: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +إذا كان مثيلك يشغّل AI Gateway مخصّصة: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +أو أضفها إلى bash profile: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +يجب على مدير GitLab لديك تفعيل ما يلي: + +1. [Duo Agent Platform](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) للمستخدم أو المجموعة أو المثيل +2. Feature flags (عبر Rails console): + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: + +##### OAuth للمثيلات المستضافة ذاتيا + +لكي يعمل Oauth مع مثيلك المستضاف ذاتيا، تحتاج إلى إنشاء +تطبيق جديد (Settings → Applications) مع +callback URL ‏`http://127.0.0.1:8080/callback` ونطاقات الصلاحيات التالية: + +- api (Access the API on your behalf) +- read_user (Read your personal information) +- read_repository (Allows read-only access to the repository) + +ثم عرّض application ID كمتغير بيئة: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +مزيد من التوثيق على صفحة [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth). + +##### التهيئة + +خصّص عبر `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### أدوات GitLab API (اختياري، لكن موصى به بشدة) + +للوصول إلى أدوات GitLab (merge requests وissues وpipelines وCI/CD وغيرها): + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +يوفّر هذا الملحق قدرات شاملة لإدارة مستودعات GitLab بما في ذلك مراجعات MR وتتبع issues ومراقبة pipelines وغير ذلك. + +--- + +### GitHub Copilot + +لاستخدام اشتراك GitHub Copilot مع opencode: + +:::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). +::: + +1. شغّل الأمر `/connect` وابحث عن GitHub Copilot. + + ```txt + /connect + ``` + +2. انتقل إلى [github.com/login/device](https://github.com/login/device) وأدخل الرمز. + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + └ Waiting for authorization... + ``` + +3. الآن شغّل الأمر `/models` لاختيار النموذج الذي تريده. + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +لاستخدام Google Vertex AI مع OpenCode: + +1. توجّه إلى **Model Garden** في Google Cloud Console وتحقق من + النماذج المتاحة في منطقتك. + + :::note + تحتاج إلى مشروع Google Cloud مع تفعيل Vertex AI API. + ::: + +2. عيّن متغيرات البيئة المطلوبة: + - `GOOGLE_CLOUD_PROJECT`: معرّف مشروع Google Cloud لديك + - `VERTEX_LOCATION` (اختياري): منطقة Vertex AI (الافتراضي `global`) + - المصادقة (اختر واحدا): + - `GOOGLE_APPLICATION_CREDENTIALS`: مسار ملف مفتاح حساب الخدمة بصيغة JSON + - المصادقة عبر gcloud CLI: ‏`gcloud auth application-default login` + + عيّنها أثناء تشغيل opencode. + + ```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode + ``` + + أو أضفها إلى 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` على تحسين التوفر وتقليل الأخطاء دون تكلفة إضافية. استخدم نقاط نهاية إقليمية (مثل `us-central1`) لمتطلبات موضع البيانات. [اعرف المزيد](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. شغّل الأمر `/models` لاختيار النموذج الذي تريده. + + ```txt + /models + ``` + +--- + +### Groq + +1. توجّه إلى [Groq console](https://console.groq.com/)، وانقر **Create API Key**، ثم انسخ المفتاح. + +2. شغّل الأمر `/connect` وابحث عن Groq. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بالمزوّد. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار ما تريده. + + ```txt + /models + ``` + +--- + +### Hugging Face + +توفّر [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) لإنشاء رمز (token) بصلاحية إجراء طلبات إلى Inference Providers. + +2. شغّل الأمر `/connect` وابحث عن **Hugging Face**. + + ```txt + /connect + ``` + +3. أدخل token الخاص بـ Hugging Face. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار نموذج مثل _Kimi-K2-Instruct_ أو _GLM-4.6_. + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) منصة لملاحظة LLM (observability) توفّر التسجيل والمراقبة والتحليلات لتطبيقات الذكاء الاصطناعي لديك. تقوم Helicone AI Gateway بتوجيه طلباتك تلقائيا إلى المزوّد المناسب بناء على النموذج. + +1. توجّه إلى [Helicone](https://helicone.ai)، وأنشئ حسابا، ثم أنشئ مفتاح API من لوحة التحكم. + +2. شغّل الأمر `/connect` وابحث عن **Helicone**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ Helicone. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار نموذج. + + ```txt + /models + ``` + +لمزيد من المزوّدات والميزات المتقدمة مثل التخزين المؤقت (caching) وتحديد المعدّل (rate limiting)، راجع [توثيق Helicone](https://docs.helicone.ai). + +#### إعدادات اختيارية + +إذا رأيت ميزة أو نموذجا في Helicone لم يتم ضبطه تلقائيا عبر opencode، فيمكنك دائما ضبطه بنفسك. + +هذه هي [Helicone's Model Directory](https://helicone.ai/models)، وستحتاجها للحصول على IDs الخاصة بالنماذج التي تريد إضافتها. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### ترويسات مخصّصة + +تدعم Helicone ترويسات مخصّصة لميزات مثل التخزين المؤقت وتتبع المستخدم وإدارة الجلسات. أضفها إلى إعداد المزوّد عبر `options.headers`: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### تتبع الجلسات + +تتيح ميزة [Sessions](https://docs.helicone.ai/features/sessions) في Helicone تجميع طلبات LLM المرتبطة معا. استخدم ملحق [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) لتسجيل كل محادثة OpenCode تلقائيا كجلسة في Helicone. + +```bash +npm install -g opencode-helicone-session +``` + +أضفه إلى إعداداتك. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +يقوم الملحق بحقن ترويسات `Helicone-Session-Id` و`Helicone-Session-Name` ضمن طلباتك. في صفحة Sessions داخل Helicone، سترى كل محادثة OpenCode مدرجة كجلسة مستقلة. + +##### ترويسات Helicone الشائعة + +| Header | الوصف | +| -------------------------- | -------------------------------------------------------- | +| `Helicone-Cache-Enabled` | تفعيل التخزين المؤقت للاستجابات (`true`/`false`) | +| `Helicone-User-Id` | تتبع المقاييس حسب المستخدم | +| `Helicone-Property-[Name]` | إضافة خصائص مخصّصة (مثل `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | ربط الطلبات بإصدارات prompt | + +راجع [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory) لعرض جميع الترويسات المتاحة. + +--- + +### llama.cpp + +يمكنك ضبط opencode لاستخدام نماذج محلية عبر أداة llama-server ضمن [llama.cpp](https://github.com/ggml-org/llama.cpp) + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +في هذا المثال: + +- `llama.cpp` هو ID مزوّد مخصّص. يمكن أن يكون أي سلسلة نصية تريدها. +- `npm` يحدد الحزمة المستخدمة لهذا المزوّد. هنا يتم استخدام `@ai-sdk/openai-compatible` لأي API متوافق مع OpenAI. +- `name` هو اسم العرض للمزوّد في واجهة المستخدم. +- `options.baseURL` هو نقطة نهاية الخادم المحلي. +- `models` هو خريطة من IDs النماذج إلى إعداداتها. سيتم عرض اسم النموذج ضمن قائمة اختيار النماذج. + +--- + +### IO.NET + +تقدّم IO.NET ‏17 نموذجا محسّنا لاستخدامات متعددة: + +1. توجّه إلى [IO.NET console](https://ai.io.net/)، وأنشئ حسابا، ثم أنشئ مفتاح API. + +2. شغّل الأمر `/connect` وابحث عن **IO.NET**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ IO.NET. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار نموذج. + + ```txt + /models + ``` + +--- + +### LM Studio + +يمكنك ضبط opencode لاستخدام نماذج محلية عبر LM Studio. + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +في هذا المثال: + +- `lmstudio` هو ID مزوّد مخصّص. يمكن أن يكون أي سلسلة نصية تريدها. +- `npm` يحدد الحزمة المستخدمة لهذا المزوّد. هنا يتم استخدام `@ai-sdk/openai-compatible` لأي API متوافق مع OpenAI. +- `name` هو اسم العرض للمزوّد في واجهة المستخدم. +- `options.baseURL` هو نقطة نهاية الخادم المحلي. +- `models` هو خريطة من IDs النماذج إلى إعداداتها. سيتم عرض اسم النموذج ضمن قائمة اختيار النماذج. + +--- + +### Moonshot AI + +لاستخدام Kimi K2 من Moonshot AI: + +1. توجّه إلى [Moonshot AI console](https://platform.moonshot.ai/console)، وأنشئ حسابا، ثم انقر **Create API key**. + +2. شغّل الأمر `/connect` وابحث عن **Moonshot AI**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ Moonshot. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار _Kimi K2_. + + ```txt + /models + ``` + +--- + +### MiniMax + +1. توجّه إلى [MiniMax API Console](https://platform.minimax.io/login)، وأنشئ حسابا، ثم أنشئ مفتاح API. + +2. شغّل الأمر `/connect` وابحث عن **MiniMax**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ MiniMax. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار نموذج مثل _M2.1_. + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. توجّه إلى [Nebius Token Factory console](https://tokenfactory.nebius.com/)، وأنشئ حسابا، ثم انقر **Add Key**. + +2. شغّل الأمر `/connect` وابحث عن **Nebius Token Factory**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ Nebius Token Factory. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` لاختيار نموذج مثل _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Ollama + +يمكنك ضبط opencode لاستخدام نماذج محلية عبر Ollama. + +:::tip +يمكن لـ Ollama ضبط نفسه تلقائيا للعمل مع OpenCode. راجع [توثيق تكامل Ollama](https://docs.ollama.com/integrations/opencode) للتفاصيل. +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +في هذا المثال: + +- `ollama` هو ID مزوّد مخصّص. يمكن أن يكون أي سلسلة نصية تريدها. +- `npm` يحدد الحزمة المستخدمة لهذا المزوّد. هنا يتم استخدام `@ai-sdk/openai-compatible` لأي API متوافق مع OpenAI. +- `name` هو اسم العرض للمزوّد في واجهة المستخدم. +- `options.baseURL` هو نقطة نهاية الخادم المحلي. +- `models` هو خريطة من IDs النماذج إلى إعداداتها. سيتم عرض اسم النموذج ضمن قائمة اختيار النماذج. + +:::tip +إذا لم تكن tool calls تعمل، جرّب زيادة `num_ctx` في Ollama. ابدأ بنحو 16k - 32k. +::: + +--- + +### Ollama Cloud + +لاستخدام Ollama Cloud مع OpenCode: + +1. توجّه إلى [https://ollama.com/](https://ollama.com/) وسجّل الدخول أو أنشئ حسابا. + +2. انتقل إلى **Settings** > **Keys** وانقر **Add API Key** لإنشاء مفتاح API جديد. + +3. انسخ مفتاح API لاستخدامه في OpenCode. + +4. شغّل الأمر `/connect` وابحث عن **Ollama Cloud**. + + ```txt + /connect + ``` + +5. أدخل مفتاح API الخاص بـ Ollama Cloud. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **مهم**: قبل استخدام نماذج السحابة في OpenCode، يجب سحب معلومات النموذج محليا: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. شغّل الأمر `/models` لاختيار نموذج Ollama Cloud. + + ```txt + /models + ``` + +--- + +### OpenAI + +نوصي بالاشتراك في [ChatGPT Plus أو Pro](https://chatgpt.com/pricing). + +1. بعد الاشتراك، شغّل الأمر `/connect` واختر OpenAI. + + ```txt + /connect + ``` + +2. هنا يمكنك اختيار خيار **ChatGPT Plus/Pro** وسيتم فتح المتصفح + وسيطلب منك المصادقة. + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. الآن يجب أن تكون جميع نماذج OpenAI متاحة عند استخدام الأمر `/models`. + + ```txt + /models + ``` + +##### استخدام مفاتيح API + +إذا كان لديك مفتاح API بالفعل، يمكنك اختيار **Manually enter API Key** ولصقه في terminal. + +--- + +### OpenCode Zen + +OpenCode Zen هي قائمة من النماذج التي تم اختبارها والتحقق منها مقدّمة من فريق OpenCode. [اعرف المزيد](/docs/zen). + +1. سجّل الدخول إلى **OpenCode Zen** وانقر **Create API Key**. + +2. شغّل الأمر `/connect` وابحث عن **OpenCode Zen**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ OpenCode. + + ```txt + ┌ API key + │ + │ + └ 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 لديك، ثم أنشئ service key. + + :::tip + service key هو كائن 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 الخاص بـ service key. + + ```txt + ┌ Service key + │ + │ + └ enter + ``` + + أو عيّن متغير البيئة `AICORE_SERVICE_KEY`: + + ```bash + AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode + ``` + + أو أضفه إلى bash profile: + + ```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' + ``` + +4. اختياريا، عيّن deployment ID وresource group: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + هذه الإعدادات اختيارية ويجب ضبطها وفقا لإعداد SAP AI Core لديك. + ::: + +5. شغّل الأمر `/models` للاختيار من بين أكثر من 40 نموذجا متاحا. + + ```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. أدخل مفتاح API الخاص بـ Scaleway. + + ```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. أدخل مفتاح API الخاص بـ Together AI. + + ```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. أدخل مفتاح API الخاص بـ Venice AI. + + ```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. أدخل مفتاح API الخاص بـ Vercel AI Gateway. + + ```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"] + } + } + } + } + } +} +``` + +بعض خيارات التوجيه المفيدة: + +| Option | الوصف | +| ------------------- | ----------------------------------------------- | +| `order` | تسلسل المزوّدات التي سيتم تجربتها | +| `only` | تقييد الاستخدام على مزوّدات محددة | +| `zeroDataRetention` | استخدام مزوّدات بسياسات احتفاظ بيانات صفرية فقط | + +--- + +### xAI + +1. توجّه إلى [xAI console](https://console.x.ai/)، وأنشئ حسابا، ثم أنشئ مفتاح API. + +2. شغّل الأمر `/connect` وابحث عن **xAI**. + + ```txt + /connect + ``` + +3. أدخل مفتاح API الخاص بـ xAI. + + ```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. أدخل مفتاح API الخاص بـ Z.AI. + + ```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-compatible** غير موجود ضمن الأمر `/connect`: + +:::tip +يمكنك استخدام أي مزوّد OpenAI-compatible مع opencode. معظم مزوّدي الذكاء الاصطناعي الحديثة يقدّمون APIs متوافقة مع OpenAI. +::: + +1. شغّل الأمر `/connect` ومرّر للأسفل حتى **Other**. + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. أدخل ID فريدا للمزوّد. + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::note + اختر 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-compatible + - **name**: اسم العرض في واجهة المستخدم. + - **models**: النماذج المتاحة. + - **options.baseURL**: عنوان URL لنقطة نهاية API. + - **options.apiKey**: تعيين مفتاح API اختياريا إذا لم تكن تستخدم auth. + - **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. **تحقق من إعداد auth**: شغّل `opencode auth list` لمعرفة ما إذا كانت بيانات الاعتماد + الخاصة بالمزوّد قد أضيفت إلى إعداداتك. + + لا ينطبق هذا على مزوّدات مثل Amazon Bedrock التي تعتمد على متغيرات البيئة لـ auth. + +2. للمزوّدات المخصّصة، راجع إعدادات opencode وتأكد من: + - أن provider ID المستخدم في الأمر `/connect` يطابق الـ ID في إعدادات opencode. + - استخدام حزمة npm الصحيحة للمزوّد. على سبيل المثال استخدم `@ai-sdk/cerebras` لـ Cerebras. ولكل المزوّدات الأخرى المتوافقة مع OpenAI استخدم `@ai-sdk/openai-compatible`. + - استخدام نقطة نهاية API الصحيحة في الحقل `options.baseURL`. diff --git a/packages/web/src/content/docs/ar/rules.mdx b/packages/web/src/content/docs/ar/rules.mdx new file mode 100644 index 00000000000..8e3d9886d4d --- /dev/null +++ b/packages/web/src/content/docs/ar/rules.mdx @@ -0,0 +1,180 @@ +--- +title: القواعد +description: اضبط تعليمات مخصصة لـ opencode. +--- + +يمكنك تزويد opencode بتعليمات مخصصة عبر إنشاء ملف `AGENTS.md`. هذا مشابه لقواعد Cursor. يحتوي هذا الملف على تعليمات تُضاف إلى سياق نموذج اللغة (LLM) لتخصيص سلوكه لمشروعك المحدد. + +--- + +## التهيئة + +لإنشاء ملف `AGENTS.md` جديد، يمكنك تشغيل الأمر `/init` في opencode. + +:::tip +يُستحسن عمل commit لملف `AGENTS.md` الخاص بمشروعك إلى Git. +::: + +سيقوم ذلك بفحص مشروعك وكل محتوياته لفهم طبيعة المشروع وتوليد ملف `AGENTS.md` بناءً على ذلك. يساعد هذا opencode على التنقّل داخل المشروع بشكل أفضل. + +إذا كان لديك ملف `AGENTS.md` موجود بالفعل، فسيحاول هذا إضافة محتوى إليه. + +--- + +## مثال + +يمكنك أيضًا إنشاء هذا الملف يدويًا. إليك مثالًا على بعض الأمور التي يمكنك وضعها في ملف `AGENTS.md`. + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +نضيف هنا تعليمات خاصة بالمشروع، وسيتم مشاركتها عبر فريقك. + +--- + +## الأنواع + +يدعم opencode أيضًا قراءة ملف `AGENTS.md` من مواقع متعددة، ولكل موقع غرض مختلف. + +### المشروع + +ضع ملف `AGENTS.md` في جذر مشروعك للقواعد الخاصة بالمشروع. لا تُطبَّق هذه القواعد إلا عند العمل داخل هذا المجلد أو مجلداته الفرعية. + +### عام + +يمكنك أيضًا وضع قواعد عامة في ملف `~/.config/opencode/AGENTS.md`. تُطبَّق هذه القواعد على جميع جلسات opencode. + +وبما أن هذا الملف لا يتم عمل commit له إلى Git ولا تتم مشاركته مع فريقك، نوصي باستخدامه لتحديد أي قواعد شخصية يجب أن يلتزم بها نموذج اللغة. + +### التوافق مع Claude Code + +للمستخدمين الذين ينتقلون من Claude Code، يدعم OpenCode اصطلاحات ملفات Claude Code كبدائل احتياطية: + +- **قواعد المشروع**: `CLAUDE.md` في دليل مشروعك (يُستخدم إذا لم يوجد `AGENTS.md`) +- **قواعد عامة**: `~/.claude/CLAUDE.md` (يُستخدم إذا لم يوجد `~/.config/opencode/AGENTS.md`) +- **المهارات**: `~/.claude/skills/` — راجع [مهارات الوكيل](/docs/skills/) للتفاصيل + +لإيقاف التوافق مع Claude Code، عيّن أحد متغيرات البيئة التالية: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## الأولوية + +عند بدء opencode، يبحث عن ملفات القواعد بهذا الترتيب: + +1. **ملفات محلية** عبر التنقّل صعودًا من الدليل الحالي (`AGENTS.md`, `CLAUDE.md`) +2. **ملف عام** في `~/.config/opencode/AGENTS.md` +3. **ملف Claude Code** في `~/.claude/CLAUDE.md` (ما لم يتم تعطيله) + +يتم اعتماد أول ملف مطابق ضمن كل فئة. على سبيل المثال، إذا كان لديك كل من `AGENTS.md` و`CLAUDE.md` فسيتم استخدام `AGENTS.md` فقط. وبالمثل، تكون الأولوية لملف `~/.config/opencode/AGENTS.md` على `~/.claude/CLAUDE.md`. + +--- + +## تعليمات مخصصة + +يمكنك تحديد ملفات تعليمات مخصصة في `opencode.json` أو في الملف العام `~/.config/opencode/opencode.json`. يتيح ذلك لك ولفريقك إعادة استخدام القواعد الموجودة بدلًا من تكرارها داخل AGENTS.md. + +مثال: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +يمكنك أيضًا استخدام عناوين URL بعيدة لتحميل التعليمات من الويب. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +يتم جلب التعليمات البعيدة بمهلة قدرها 5 ثوانٍ. + +تُدمَج جميع ملفات التعليمات مع ملفات `AGENTS.md` لديك. + +--- + +## الإشارة إلى ملفات خارجية + +على الرغم من أن opencode لا يقوم تلقائيًا بتحليل مراجع الملفات داخل `AGENTS.md`، يمكنك تحقيق وظيفة مشابهة بطريقتين: + +### استخدام opencode.json + +النهج الموصى به هو استخدام الحقل `instructions` في `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### تعليمات يدوية في AGENTS.md + +يمكنك تعليم opencode قراءة ملفات خارجية عبر تقديم تعليمات صريحة داخل `AGENTS.md`. إليك مثالًا عمليًا: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +يتيح لك هذا النهج ما يلي: + +- إنشاء ملفات قواعد معيارية قابلة لإعادة الاستخدام +- مشاركة القواعد عبر المشاريع باستخدام symlinks أو git submodules +- إبقاء AGENTS.md موجزًا مع الإشارة إلى إرشادات تفصيلية +- ضمان أن opencode يحمّل الملفات فقط عند الحاجة للمهمة المحددة + +:::tip +بالنسبة للمستودعات متعددة الحزم (monorepos) أو المشاريع ذات المعايير المشتركة، فإن استخدام `opencode.json` مع أنماط glob (مثل `packages/*/AGENTS.md`) أسهل للصيانة من التعليمات اليدوية. +::: diff --git a/packages/web/src/content/docs/ar/sdk.mdx b/packages/web/src/content/docs/ar/sdk.mdx new file mode 100644 index 00000000000..83cdcad764a --- /dev/null +++ b/packages/web/src/content/docs/ar/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: مجموعة تطوير البرمجيات (SDK) +description: عميل JavaScript آمن الأنواع لخادم opencode. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +توفر SDK الخاصة بـ opencode لـ JS/TS عميلا آمنا للأنواع للتفاعل مع الخادم. +استخدمها لبناء التكاملات والتحكم في opencode برمجيا. + +[اعرف المزيد](/docs/server) حول كيفية عمل الخادم. للاطلاع على أمثلة، تفقد [المشاريع](/docs/ecosystem#projects) التي أنشأها المجتمع. + +--- + +## التثبيت + +ثبّت SDK من npm: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## إنشاء عميل + +أنشئ مثيلا من opencode: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +هذا يشغّل خادما وعميلا معا. + +#### الخيارات + +| الخيار | النوع | الوصف | الافتراضي | +| ---------- | ------------- | ----------------------------- | ----------- | +| `hostname` | `string` | اسم مضيف الخادم | `127.0.0.1` | +| `port` | `number` | منفذ الخادم | `4096` | +| `signal` | `AbortSignal` | إشارة إلغاء للإيقاف | `undefined` | +| `timeout` | `number` | مهلة بدء الخادم بالمللي ثانية | `5000` | +| `config` | `Config` | كائن الإعدادات | `{}` | + +--- + +## الإعدادات + +يمكنك تمرير كائن إعدادات لتخصيص السلوك. سيستمر المثيل في التقاط `opencode.json` لديك، لكن يمكنك تجاوز الإعدادات أو إضافة إعدادات مباشرة: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## العميل فقط + +إذا كان لديك مثيل opencode يعمل بالفعل، يمكنك إنشاء مثيل عميل للاتصال به: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### الخيارات + +| الخيار | النوع | الوصف | الافتراضي | +| --------------- | ---------- | --------------------------------- | ----------------------- | +| `baseUrl` | `string` | عنوان URL للخادم | `http://localhost:4096` | +| `fetch` | `function` | تنفيذ fetch مخصص | `globalThis.fetch` | +| `parseAs` | `string` | طريقة تحليل الاستجابة | `auto` | +| `responseStyle` | `string` | أسلوب الإرجاع: `data` أو `fields` | `fields` | +| `throwOnError` | `boolean` | رمي الأخطاء بدلا من إرجاعها | `false` | + +--- + +## الأنواع + +تتضمن SDK تعريفات TypeScript لجميع أنواع API. استوردها مباشرة: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +جميع الأنواع مولّدة من مواصفات OpenAPI الخاصة بالخادم ومتاحة في ملف الأنواع. + +--- + +## الأخطاء + +يمكن أن ترمي SDK أخطاء يمكنك التقاطها ومعالجتها: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## APIs + +توفر SDK جميع واجهات الخادم عبر عميل آمن للأنواع. + +--- + +### عام (`global`) + +| الطريقة | الوصف | الاستجابة | +| ----------------- | ---------------------------- | ------------------------------------ | +| `global.health()` | التحقق من صحة الخادم وإصداره | `{ healthy: true, version: string }` | + +--- + +#### أمثلة + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### التطبيق (`app`) + +| الطريقة | الوصف | الاستجابة | +| -------------- | ------------------------- | ------------------------------------------- | +| `app.log()` | كتابة إدخال في السجل | `boolean` | +| `app.agents()` | سرد جميع الوكلاء المتاحين | Agent[] | + +--- + +#### أمثلة + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### المشروع (`project`) + +| الطريقة | الوصف | الاستجابة | +| ------------------- | ------------------ | --------------------------------------------- | +| `project.list()` | سرد جميع المشاريع | Project[] | +| `project.current()` | جلب المشروع الحالي | Project | + +--- + +#### أمثلة + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### المسار (`path`) + +| الطريقة | الوصف | الاستجابة | +| ------------ | ----------------- | ---------------------------------------- | +| `path.get()` | جلب المسار الحالي | Path | + +--- + +#### أمثلة + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### الإعدادات (`config`) + +| الطريقة | الوصف | الاستجابة | +| -------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | جلب معلومات الإعدادات | Config | +| `config.providers()` | سرد المزوّدين والنماذج الافتراضية | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### أمثلة + +```javascript +const config = await client.config.get() + +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` | + +--- + +#### أمثلة + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### الملفات + +| الطريقة | الوصف | الاستجابة | +| ------------------------- | ----------------------------------- | -------------------------------------------------------------------------------------------- | +| `find.text({ query })` | البحث عن نص داخل الملفات | مصفوفة من كائنات المطابقة مع `path` و`lines` و`line_number` و`absolute_offset` و`submatches` | +| `find.files({ query })` | العثور على الملفات والمجلدات بالاسم | `string[]` (مسارات) | +| `find.symbols({ query })` | العثور على رموز مساحة العمل | Symbol[] | +| `file.read({ query })` | قراءة ملف | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | جلب حالة الملفات المتتبَّعة | File[] | + +يدعم `find.files` بعض حقول الاستعلام الاختيارية: + +- `type`: `"file"` أو `"directory"` +- `directory`: تجاوز جذر المشروع لعملية البحث +- `limit`: الحد الأقصى للنتائج (1–200) + +--- + +#### أمثلة + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### واجهة TUI (`tui`) + +| الطريقة | الوصف | الاستجابة | +| ------------------------------ | ---------------------- | --------- | +| `tui.appendPrompt({ body })` | إلحاق نص بالمطالبة | `boolean` | +| `tui.openHelp()` | فتح مربع حوار المساعدة | `boolean` | +| `tui.openSessions()` | فتح محدد الجلسات | `boolean` | +| `tui.openThemes()` | فتح محدد السمات | `boolean` | +| `tui.openModels()` | فتح محدد النماذج | `boolean` | +| `tui.submitPrompt()` | إرسال المطالبة الحالية | `boolean` | +| `tui.clearPrompt()` | مسح المطالبة | `boolean` | +| `tui.executeCommand({ body })` | تنفيذ أمر | `boolean` | +| `tui.showToast({ body })` | عرض إشعار toast | `boolean` | + +--- + +#### أمثلة + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### المصادقة (`auth`) + +| الطريقة | الوصف | الاستجابة | +| ------------------- | ---------------------------- | --------- | +| `auth.set({ ... })` | تعيين بيانات اعتماد المصادقة | `boolean` | + +--- + +#### أمثلة + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### الأحداث (`event`) + +| الطريقة | الوصف | الاستجابة | +| ------------------- | -------------------------- | -------------------------- | +| `event.subscribe()` | تدفق أحداث مرسلة من الخادم | تدفق أحداث مرسلة من الخادم | + +--- + +#### أمثلة + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/ar/server.mdx b/packages/web/src/content/docs/ar/server.mdx new file mode 100644 index 00000000000..017a81eafa0 --- /dev/null +++ b/packages/web/src/content/docs/ar/server.mdx @@ -0,0 +1,287 @@ +--- +title: الخادم +description: تفاعل مع خادم opencode عبر HTTP. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +يشغّل الأمر `opencode serve` خادما HTTP دون واجهة ويعرض نقطة نهاية OpenAPI يمكن لعميل opencode استخدامها. + +--- + +### الاستخدام + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### الخيارات + +| الخيار | الوصف | الافتراضي | +| --------------- | ------------------------------------- | ---------------- | +| `--port` | المنفذ الذي يستمع عليه | `4096` | +| `--hostname` | اسم المضيف الذي يستمع عليه | `127.0.0.1` | +| `--mdns` | تفعيل اكتشاف mDNS | `false` | +| `--mdns-domain` | اسم نطاق مخصص لخدمة mDNS | `opencode.local` | +| `--cors` | أصول (Origins) متصفح إضافية مسموح بها | `[]` | + +يمكن تمرير `--cors` عدة مرات: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### المصادقة + +عيّن `OPENCODE_SERVER_PASSWORD` لحماية الخادم باستخدام مصادقة HTTP الأساسية. اسم المستخدم افتراضيا هو `opencode`، أو عيّن `OPENCODE_SERVER_USERNAME` لتغييره. ينطبق ذلك على كل من `opencode serve` و `opencode web`. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### كيف يعمل + +عند تشغيل `opencode` يبدأ تشغيل واجهة terminal تفاعلية (TUI) وخادما. تكون الـ TUI هي +العميل الذي يتحدث إلى الخادم. يوفّر الخادم نقطة نهاية لمواصفة OpenAPI 3.1. +وتُستخدم هذه النقطة أيضا لتوليد [SDK](/docs/sdk). + +:::tip +استخدم خادم opencode للتفاعل مع opencode برمجيا. +::: + +تتيح هذه البنية لـ opencode دعم عدة عملاء وتمكّنك من التفاعل مع opencode برمجيا. + +يمكنك تشغيل `opencode serve` لبدء خادم مستقل. إذا كانت واجهة opencode في terminal (TUI) +قيد التشغيل، فسيبدأ `opencode serve` خادما جديدا. + +--- + +#### الاتصال بخادم موجود + +عند بدء الـ TUI تقوم بتعيين منفذ واسم مضيف عشوائيا. يمكنك بدلا من ذلك تمرير [الخيارات](/docs/cli) `--hostname` و `--port`، ثم استخدامهما للاتصال بخادمها. + +يمكن استخدام نقطة النهاية [`/tui`](#tui) للتحكم في الـ TUI عبر الخادم. على سبيل المثال، يمكنك تعبئة الموجّه مسبقا أو تشغيله. يُستخدم هذا الإعداد بواسطة ملحقات OpenCode لـ [IDE](/docs/ide). + +--- + +## المواصفات + +ينشر الخادم مواصفة OpenAPI 3.1 ويمكن عرضها على: + +``` +http://:/doc +``` + +على سبيل المثال: `http://localhost:4096/doc`. استخدم المواصفة لتوليد عملاء أو لفحص أنواع الطلبات والاستجابات. أو اعرضها في مستكشف Swagger. + +--- + +## واجهات API + +يعرض خادم opencode واجهات API التالية. + +--- + +### عام + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | ---------------- | ------------------------------------ | ------------------------------------ | +| `GET` | `/global/health` | الحصول على صحة الخادم وإصداره | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | الحصول على الأحداث العامة (تدفق SSE) | تدفق أحداث | + +--- + +### المشروع + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | ------------------ | ------------------------- | --------------------------------------------- | +| `GET` | `/project` | سرد جميع المشاريع | Project[] | +| `GET` | `/project/current` | الحصول على المشروع الحالي | Project | + +--- + +### المسار و VCS + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | ------- | ------------------------------------- | ------------------------------------------- | +| `GET` | `/path` | الحصول على المسار الحالي | Path | +| `GET` | `/vcs` | الحصول على معلومات VCS للمشروع الحالي | VcsInfo | + +--- + +### المثيل + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | ------------------- | ----------------------- | --------- | +| `POST` | `/instance/dispose` | التخلص من المثيل الحالي | `boolean` | + +--- + +### الإعدادات + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | ------------------- | --------------------------------- | ---------------------------------------------------------------------------------------- | +| `GET` | `/config` | الحصول على معلومات الإعدادات | Config | +| `PATCH` | `/config` | تحديث الإعدادات | Config | +| `GET` | `/config/providers` | سرد المزوّدين والنماذج الافتراضية | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +### المزوّد + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | -------------------------------- | ----------------------------- | ----------------------------------------------------------------------------------- | +| `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` | معالجة رد نداء OAuth لمزوّد | `boolean` | + +--- + +### الجلسات + +| الطريقة | المسار | الوصف | الملاحظات | +| -------- | ---------------------------------------- | ------------------------------------- | -------------------------------------------------------------------------------- | +| `GET` | `/session` | سرد جميع الجلسات | يعيد Session[] | +| `POST` | `/session` | إنشاء جلسة جديدة | المتن: `{ parentID?, title? }`، يعيد Session | +| `GET` | `/session/status` | الحصول على حالة الجلسات جميعها | يعيد `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | الحصول على تفاصيل الجلسة | يعيد Session | +| `DELETE` | `/session/:id` | حذف جلسة وجميع بياناتها | يعيد `boolean` | +| `PATCH` | `/session/:id` | تحديث خصائص الجلسة | المتن: `{ title? }`، يعيد Session | +| `GET` | `/session/:id/children` | الحصول على الجلسات الفرعية لجلسة | يعيد Session[] | +| `GET` | `/session/:id/todo` | الحصول على قائمة المهام (todo) للجلسة | يعيد Todo[] | +| `POST` | `/session/:id/init` | تحليل التطبيق وإنشاء `AGENTS.md` | المتن: `{ messageID, providerID, modelID }`، يعيد `boolean` | +| `POST` | `/session/:id/fork` | تفريع جلسة موجودة عند رسالة | المتن: `{ messageID? }`، يعيد Session | +| `POST` | `/session/:id/abort` | إلغاء جلسة قيد التشغيل | يعيد `boolean` | +| `POST` | `/session/:id/share` | مشاركة جلسة | يعيد Session | +| `DELETE` | `/session/:id/share` | إلغاء مشاركة جلسة | يعيد Session | +| `GET` | `/session/:id/diff` | الحصول على diff لهذه الجلسة | الاستعلام: `messageID?`، يعيد FileDiff[] | +| `POST` | `/session/:id/summarize` | تلخيص الجلسة | المتن: `{ providerID, modelID }`، يعيد `boolean` | +| `POST` | `/session/:id/revert` | التراجع عن رسالة | المتن: `{ messageID, partID? }`، يعيد `boolean` | +| `POST` | `/session/:id/unrevert` | استعادة جميع الرسائل المتراجع عنها | يعيد `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | الرد على طلب إذن | المتن: `{ response, remember? }`، يعيد `boolean` | + +--- + +### الرسائل + +| الطريقة | المسار | الوصف | الملاحظات | +| ------- | --------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `GET` | `/session/:id/message` | سرد رسائل جلسة | الاستعلام: `limit?`، يعيد `{ info: `Message`, parts: `Part[]`}[]` | +| `POST` | `/session/:id/message` | إرسال رسالة والانتظار للحصول على رد | المتن: `{ 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` | إرسال رسالة بشكل غير متزامن (بدون انتظار) | المتن: مثل `/session/:id/message`، يعيد `204 No Content` | +| `POST` | `/session/:id/command` | تنفيذ أمر شرطة مائلة (slash) | المتن: `{ messageID?, agent?, model?, command, arguments }`، يعيد `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/shell` | تشغيل أمر في shell | المتن: `{ agent, model?, command }`، يعيد `{ info: `Message`, parts: `Part[]`}` | + +--- + +### الأوامر + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | ---------- | ---------------- | --------------------------------------------- | +| `GET` | `/command` | سرد جميع الأوامر | Command[] | + +--- + +### الملفات + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | ------------------------ | ----------------------------------- | --------------------------------------------------------------------------------------------------- | +| `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` + +- `query` (مطلوب) — سلسلة البحث (مطابقة ضبابية) +- `type` (اختياري) — حصر النتائج في `"file"` أو `"directory"` +- `directory` (اختياري) — تجاوز جذر المشروع لأجل البحث +- `limit` (اختياري) — الحد الأقصى للنتائج (1–200) +- `dirs` (اختياري) — خيار قديم (إرجاع `"false"` يعيد الملفات فقط) + +--- + +### الأدوات (تجريبية) + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | ------------------------------------------- | --------------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | سرد جميع معرّفات الأدوات | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | سرد الأدوات مع مخططات JSON لنموذج | ToolList | + +--- + +### LSP والمنسّقات و MCP + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | ------------ | ------------------------- | -------------------------------------------------------- | +| `GET` | `/lsp` | الحصول على حالة خادم LSP | LSPStatus[] | +| `GET` | `/formatter` | الحصول على حالة المنسّقات | FormatterStatus[] | +| `GET` | `/mcp` | الحصول على حالة خادم MCP | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | إضافة خادم MCP ديناميكيا | المتن: `{ name, config }`، يعيد كائن حالة MCP | + +--- + +### الوكلاء + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | -------- | ------------------------- | ------------------------------------------- | +| `GET` | `/agent` | سرد جميع الوكلاء المتاحين | Agent[] | + +--- + +### التسجيل + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | ------ | ------------------------------------------------------------- | --------- | +| `POST` | `/log` | كتابة إدخال سجل. المتن: `{ service, level, message, extra? }` | `boolean` | + +--- + +### TUI + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | ----------------------- | ------------------------------------------ | ------------- | +| `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` | عرض toast (`{ title?, message, variant }`) | `boolean` | +| `GET` | `/tui/control/next` | الانتظار لطلب التحكم التالي | كائن طلب تحكم | +| `POST` | `/tui/control/response` | الاستجابة لطلب تحكم (`{ body }`) | `boolean` | + +--- + +### المصادقة + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | ----------- | ------------------------------------------------------------- | --------- | +| `PUT` | `/auth/:id` | تعيين بيانات اعتماد المصادقة. يجب أن يطابق المتن مخطط المزوّد | `boolean` | + +--- + +### الأحداث + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | -------- | -------------------------------------------------------------------------------- | -------------------------- | +| `GET` | `/event` | تدفق أحداث مرسلة من الخادم (SSE). أول حدث هو `server.connected` ثم أحداث الحافلة | تدفق أحداث مرسلة من الخادم | + +--- + +### التوثيق + +| الطريقة | المسار | الوصف | الاستجابة | +| ------- | ------ | ------------------ | ------------------------------ | +| `GET` | `/doc` | مواصفة OpenAPI 3.1 | صفحة HTML تتضمن مواصفة OpenAPI | diff --git a/packages/web/src/content/docs/ar/share.mdx b/packages/web/src/content/docs/ar/share.mdx new file mode 100644 index 00000000000..535d44dadf8 --- /dev/null +++ b/packages/web/src/content/docs/ar/share.mdx @@ -0,0 +1,127 @@ +--- +title: المشاركة +description: شارك محادثات OpenCode الخاصة بك. +--- + +تتيح لك ميزة المشاركة في OpenCode إنشاء روابط عامة لمحادثات OpenCode الخاصة بك، بحيث يمكنك التعاون مع زملائك أو الحصول على المساعدة من الآخرين. + +:::note +المحادثات المشتركة متاحة للعامة لأي شخص لديه الرابط. +::: + +--- + +## كيف تعمل + +عند مشاركة محادثة، يقوم OpenCode بما يلي: + +1. ينشئ عنوان URL عاما فريدا لجلستك +2. يزامن سجل محادثتك مع خوادمنا +3. يجعل المحادثة متاحة عبر رابط قابل للمشاركة — `opncd.ai/s/` + +--- + +## المشاركة + +يدعم OpenCode ثلاثة أوضاع للمشاركة تتحكم في كيفية مشاركة المحادثات: + +--- + +### يدوي (افتراضي) + +افتراضيا، يستخدم OpenCode وضع المشاركة اليدوي. لا تتم مشاركة الجلسات تلقائيا، لكن يمكنك مشاركتها يدويا باستخدام الأمر `/share`: + +``` +/share +``` + +سيُنشئ هذا عنوان URL فريدا وسيُنسخ إلى الحافظة. + +لضبط الوضع اليدوي صراحة في [ملف الإعدادات](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### المشاركة التلقائية + +يمكنك تفعيل المشاركة التلقائية لجميع المحادثات الجديدة عبر ضبط خيار `share` إلى `"auto"` في [ملف الإعدادات](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +عند تفعيل المشاركة التلقائية، ستتم مشاركة كل محادثة جديدة تلقائيا وسيتم إنشاء رابط لها. + +--- + +### معطلة + +يمكنك تعطيل المشاركة بالكامل عبر ضبط خيار `share` إلى `"disabled"` في [ملف الإعدادات](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +لفرض ذلك على مستوى فريقك لمشروع معين، أضفه إلى ملف `opencode.json` في مشروعك ثم قم بإدراجه في Git. + +--- + +## إلغاء المشاركة + +لإيقاف مشاركة محادثة وإزالتها من الوصول العام: + +``` +/unshare +``` + +سيؤدي ذلك إلى إزالة رابط المشاركة وحذف البيانات المتعلقة بالمحادثة. + +--- + +## الخصوصية + +هناك بعض الأمور التي ينبغي وضعها في الاعتبار عند مشاركة محادثة. + +--- + +### الاحتفاظ بالبيانات + +تظل المحادثات المشتركة متاحة حتى تقوم بإلغاء مشاركتها صراحة. يشمل ذلك: + +- سجل المحادثة كاملا +- جميع الرسائل والردود +- بيانات تعريف الجلسة + +--- + +### توصيات + +- شارك فقط المحادثات التي لا تتضمن معلومات حساسة. +- راجع محتوى المحادثة قبل مشاركتها. +- ألغِ مشاركة المحادثات عند اكتمال التعاون. +- تجنب مشاركة المحادثات التي تتضمن شيفرة مملوكة أو بيانات سرية. +- للمشاريع الحساسة، عطّل المشاركة بالكامل. + +--- + +## للمؤسسات + +في عمليات النشر الخاصة بالمؤسسات، يمكن أن تكون ميزة المشاركة: + +- **معطلة** بالكامل للامتثال الأمني +- **مقيدة** على المستخدمين الموثقين عبر SSO فقط +- **مستضافة ذاتيا** على بنيتك التحتية الخاصة + +[تعرّف على المزيد](/docs/enterprise) حول استخدام OpenCode في مؤسستك. diff --git a/packages/web/src/content/docs/ar/skills.mdx b/packages/web/src/content/docs/ar/skills.mdx new file mode 100644 index 00000000000..b658e7d9428 --- /dev/null +++ b/packages/web/src/content/docs/ar/skills.mdx @@ -0,0 +1,222 @@ +--- +title: "مهارات الوكيل" +description: "عرّف سلوكاً قابلاً لإعادة الاستخدام عبر تعريفات SKILL.md" +--- + +تتيح مهارات الوكيل لـ OpenCode اكتشاف تعليمات قابلة لإعادة الاستخدام من مستودعك أو من دليل المنزل. +تُحمَّل المهارات عند الطلب عبر أداة `skill` المدمجة — يرى الوكلاء المهارات المتاحة ويمكنهم تحميل المحتوى الكامل عند الحاجة. + +--- + +## وضع الملفات + +أنشئ مجلداً واحداً لكل اسم مهارة وضع بداخله ملف `SKILL.md`. +يبحث OpenCode في هذه المواقع: + +- إعدادات المشروع: `.opencode/skills//SKILL.md` +- إعدادات عامة: `~/.config/opencode/skills//SKILL.md` +- مشروع متوافق مع Claude: `.claude/skills//SKILL.md` +- عام متوافق مع Claude: `~/.claude/skills//SKILL.md` +- مشروع متوافق مع الوكلاء: `.agents/skills//SKILL.md` +- عام متوافق مع الوكلاء: `~/.agents/skills//SKILL.md` + +--- + +## فهم الاكتشاف + +بالنسبة لمسارات المشروع المحلية، يتدرج OpenCode صعوداً من دليل العمل الحالي حتى يصل إلى `git worktree`. +ويحمّل أي ملفات مطابقة لـ `skills/*/SKILL.md` داخل `.opencode/` وأي ملفات مطابقة لـ `.claude/skills/*/SKILL.md` أو `.agents/skills/*/SKILL.md` على طول الطريق. + +كما تُحمَّل التعريفات العامة أيضاً من `~/.config/opencode/skills/*/SKILL.md` و `~/.claude/skills/*/SKILL.md` و `~/.agents/skills/*/SKILL.md`. + +--- + +## كتابة بيانات `frontmatter` + +يجب أن يبدأ كل ملف `SKILL.md` بـ `frontmatter` بتنسيق YAML. +لا يتم التعرف إلا على الحقول التالية: + +- `name` (مطلوب) +- `description` (مطلوب) +- `license` (اختياري) +- `compatibility` (اختياري) +- `metadata` (اختياري، خريطة من سلسلة إلى سلسلة) + +يتم تجاهل أي حقول `frontmatter` غير معروفة. + +--- + +## التحقق من الأسماء + +يجب أن يكون `name`: + +- بطول 1–64 حرفاً +- أحرفاً وأرقاماً بحروف صغيرة مع فواصل شرطة مفردة +- لا يبدأ ولا ينتهي بـ `-` +- لا يحتوي على `--` متتالية +- يطابق اسم الدليل الذي يحتوي على `SKILL.md` + +التعبير النمطي المكافئ: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## اتباع قواعد الطول + +يجب أن يكون `description` بطول 1-1024 حرفاً. +اجعله محدداً بما يكفي كي يختار الوكيل بشكل صحيح. + +--- + +## استخدم مثالاً + +أنشئ `.opencode/skills/git-release/SKILL.md` بهذا الشكل: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## التعرّف على وصف الأداة + +يعرض OpenCode المهارات المتاحة في وصف أداة `skill`. +يتضمن كل إدخال اسم المهارة ووصفها: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +يقوم الوكيل بتحميل مهارة عبر استدعاء الأداة: + +``` +skill({ name: "git-release" }) +``` + +--- + +## تهيئة الصلاحيات + +تحكم في المهارات التي يمكن للوكلاء الوصول إليها باستخدام صلاحيات مبنية على أنماط داخل `opencode.json`: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| الصلاحية | السلوك | +| -------- | -------------------------------------- | +| `allow` | تُحمَّل المهارة فوراً | +| `deny` | تُخفى المهارة عن الوكيل ويُرفض الوصول | +| `ask` | يُطلب من المستخدم الموافقة قبل التحميل | + +تدعم الأنماط أحرف البدل: يطابق `internal-*` كلاً من `internal-docs` و `internal-tools` وغير ذلك. + +--- + +## تجاوز الإعدادات لكل وكيل + +امنح وكلاء محددين صلاحيات مختلفة عن الإعدادات الافتراضية العامة. + +**للوكلاء المخصصين** (في `frontmatter` الخاص بالوكيل): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**للوكلاء المدمجين** (في `opencode.json`): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## تعطيل أداة skill + +عطّل المهارات بالكامل للوكلاء الذين لا ينبغي أن يستخدموها: + +**للوكلاء المخصصين**: + +```yaml +--- +tools: + skill: false +--- +``` + +**للوكلاء المدمجين**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +عند تعطيلها، يتم حذف قسم `` بالكامل. + +--- + +## استكشاف أخطاء التحميل + +إذا لم تظهر مهارة: + +1. تحقّق من أن `SKILL.md` مكتوب بأحرف كبيرة بالكامل +2. تحقّق من أن `frontmatter` تتضمن `name` و `description` +3. تأكد من أن أسماء المهارات فريدة عبر جميع المواقع +4. تحقّق من الصلاحيات — المهارات ذات `deny` تكون مخفية عن الوكلاء diff --git a/packages/web/src/content/docs/ar/themes.mdx b/packages/web/src/content/docs/ar/themes.mdx new file mode 100644 index 00000000000..822401cdfbc --- /dev/null +++ b/packages/web/src/content/docs/ar/themes.mdx @@ -0,0 +1,369 @@ +--- +title: السمات +description: اختر سمة مدمجة أو عرّف سمة خاصة بك. +--- + +مع OpenCode يمكنك الاختيار من بين عدة سمات مدمجة، أو استخدام سمة تتكيّف مع سمة terminal لديك، أو تعريف سمة مخصصة خاصة بك. + +افتراضيًا، يستخدم OpenCode سمتنا `opencode`. + +--- + +## متطلبات terminal + +لكي تُعرض السمات بشكل صحيح مع لوحة ألوانها الكاملة، يجب أن يدعم terminal لديك **truecolor** (ألوان 24-بت). تدعم معظم تطبيقات terminal الحديثة ذلك افتراضيًا، لكن قد تحتاج إلى تفعيله: + +- **التحقق من الدعم**: شغّل `echo $COLORTERM` - يجب أن يطبع `truecolor` أو `24bit` +- **تفعيل truecolor**: اضبط متغير البيئة `COLORTERM=truecolor` في ملف إعدادات shell +- **توافق terminal**: تأكد من أن محاكي terminal يدعم ألوان 24-بت (معظم تطبيقات terminal الحديثة مثل iTerm2 وAlacritty وKitty وWindows Terminal والإصدارات الحديثة من GNOME Terminal تدعم ذلك) + +بدون دعم truecolor، قد تظهر السمات بدقة ألوان أقل أو تعود إلى أقرب تقريب ضمن 256 لونًا. + +--- + +## السمات المدمجة + +يأتي OpenCode مع عدة سمات مدمجة. + +| الاسم | الوصف | +| ---------------------- | --------------------------------------------------------------------------- | +| `system` | يتكيّف مع لون خلفية terminal لديك | +| `tokyonight` | مبني على سمة [Tokyonight](https://github.com/folke/tokyonight.nvim) | +| `everforest` | مبني على سمة [Everforest](https://github.com/sainnhe/everforest) | +| `ayu` | مبني على السمة الداكنة [Ayu](https://github.com/ayu-theme) | +| `catppuccin` | مبني على سمة [Catppuccin](https://github.com/catppuccin) | +| `catppuccin-macchiato` | مبني على سمة [Catppuccin](https://github.com/catppuccin) | +| `gruvbox` | مبني على سمة [Gruvbox](https://github.com/morhetz/gruvbox) | +| `kanagawa` | مبني على سمة [Kanagawa](https://github.com/rebelot/kanagawa.nvim) | +| `nord` | مبني على سمة [Nord](https://github.com/nordtheme/nord) | +| `matrix` | سمة خضراء على أسود بأسلوب الهاكر | +| `one-dark` | مبني على السمة الداكنة [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) | + +وغير ذلك؛ نضيف سمات جديدة باستمرار. + +--- + +## سمة النظام + +صُممت سمة `system` لتتكيّف تلقائيًا مع مخطط ألوان terminal لديك. وعلى عكس السمات التقليدية التي تستخدم ألوانًا ثابتة، فإن سمة _system_: + +- **توليد تدرج رمادي**: تنشئ تدرجًا رماديًا مخصصًا اعتمادًا على لون خلفية terminal لديك، بما يضمن أفضل تباين. +- **استخدام ألوان ANSI**: تستفيد من ألوان ANSI القياسية (0-15) لإبراز الصياغة وعناصر الواجهة، والتي تحترم لوحة ألوان terminal لديك. +- **الحفاظ على افتراضيات terminal**: تستخدم `none` لألوان النص والخلفية للحفاظ على مظهر terminal الأصلي. + +سمة النظام مناسبة للمستخدمين الذين: + +- يريدون أن يطابق OpenCode مظهر terminal لديهم +- يستخدمون مخططات ألوان مخصصة لـ terminal +- يفضلون مظهرًا متسقًا عبر جميع تطبيقات terminal + +--- + +## استخدام سمة + +يمكنك اختيار سمة بفتح منتقي السمات باستخدام الأمر `/theme`. أو يمكنك تحديدها في [الضبط](/docs/config). + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## سمات مخصصة + +يدعم OpenCode نظام سمات مرنًا قائمًا على JSON يتيح للمستخدمين إنشاء السمات وتخصيصها بسهولة. + +--- + +### التسلسل الهرمي + +تُحمَّل السمات من عدة مجلدات بالترتيب التالي، حيث تتجاوز المجلدات اللاحقة المجلدات السابقة: + +1. **السمات المدمجة** - تكون مضمنة داخل الملف التنفيذي +2. **مجلد ضبط المستخدم** - معرّف في `~/.config/opencode/themes/*.json` أو `$XDG_CONFIG_HOME/opencode/themes/*.json` +3. **مجلد جذر المشروع** - معرّف في `/.opencode/themes/*.json` +4. **مجلد العمل الحالي** - معرّف في `./.opencode/themes/*.json` + +إذا احتوت عدة مجلدات على سمة بالاسم نفسه، فستُستخدم السمة من المجلد ذي الأولوية الأعلى. + +--- + +### إنشاء سمة + +لإنشاء سمة مخصصة، أنشئ ملف JSON في أحد مجلدات السمات. + +للسمات على مستوى المستخدم: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +وللسمات الخاصة بالمشروع: + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### تنسيق JSON + +تستخدم السمات تنسيق JSON مرنًا مع دعم لـ: + +- **ألوان سداسية عشرية**: `"#ffffff"` +- **ألوان ANSI**: `3` (0-255) +- **مراجع الألوان**: `"primary"` أو تعريفات مخصصة +- **متغيرات داكن/فاتح**: `{"dark": "#000", "light": "#fff"}` +- **بدون لون**: `"none"` - يستخدم اللون الافتراضي لـ terminal أو يكون شفافًا + +--- + +### تعريفات الألوان + +قسم `defs` اختياري، ويتيح لك تعريف ألوان قابلة لإعادة الاستخدام يمكن الإشارة إليها داخل السمة. + +--- + +### افتراضيات terminal + +يمكن استخدام القيمة الخاصة `"none"` لأي لون لوراثة اللون الافتراضي لـ terminal. هذا مفيد خصوصًا لإنشاء سمات تمتزج بسلاسة مع مخطط ألوان terminal لديك: + +- `"text": "none"` - يستخدم لون المقدمة الافتراضي لـ terminal +- `"background": "none"` - يستخدم لون الخلفية الافتراضي لـ terminal + +--- + +### مثال + +إليك مثالًا على سمة مخصصة: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/ar/tools.mdx b/packages/web/src/content/docs/ar/tools.mdx new file mode 100644 index 00000000000..fde4403569a --- /dev/null +++ b/packages/web/src/content/docs/ar/tools.mdx @@ -0,0 +1,379 @@ +--- +title: الأدوات +description: إدارة الأدوات التي يمكن لـ LLM استخدامها. +--- + +تتيح الأدوات لـ LLM تنفيذ إجراءات داخل قاعدة الشفرة الخاصة بك. يأتي OpenCode مع مجموعة من الأدوات المدمجة، لكن يمكنك توسيعه عبر [أدوات مخصصة](/docs/custom-tools) أو [خوادم MCP](/docs/mcp-servers). + +افتراضيا، تكون جميع الأدوات **مفعلة** ولا تحتاج إلى إذن للتشغيل. يمكنك التحكم في سلوك الأدوات عبر [الأذونات](/docs/permissions). + +--- + +## التهيئة + +استخدم الحقل `permission` للتحكم في سلوك الأدوات. يمكنك السماح أو الرفض أو طلب الموافقة لكل أداة. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +يمكنك أيضا استخدام أحرف البدل للتحكم في عدة أدوات دفعة واحدة. على سبيل المثال، لطلب الموافقة على جميع الأدوات القادمة من خادم MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[اعرف المزيد](/docs/permissions) حول تهيئة الأذونات. + +--- + +## المدمجة + +فيما يلي جميع الأدوات المدمجة المتاحة في OpenCode. + +--- + +### bash + +نفذ أوامر shell في بيئة مشروعك. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +تتيح هذه الأداة لـ LLM تشغيل أوامر terminal مثل `npm install` و`git status` أو أي أمر shell آخر. + +--- + +### edit + +عدّل الملفات الموجودة باستخدام استبدال نصي مطابق تماما. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +تجري هذه الأداة تعديلات دقيقة على الملفات عبر استبدال مقاطع نصية متطابقة. وهي الطريقة الأساسية التي يعدّل بها LLM الشفرة. + +--- + +### write + +أنشئ ملفات جديدة أو اكتب فوق الملفات الموجودة. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +استخدم هذا للسماح لـ LLM بإنشاء ملفات جديدة. سيكتب فوق الملفات الموجودة إذا كانت موجودة بالفعل. + +:::note +تُدار أداة `write` عبر إذن `edit`، والذي يشمل جميع تعديلات الملفات (`edit` و`write` و`patch` و`multiedit`). +::: + +--- + +### read + +اقرأ محتويات الملفات من قاعدة الشفرة الخاصة بك. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +تقرأ هذه الأداة الملفات وتعيد محتوياتها. وتدعم قراءة نطاقات محددة من الأسطر للملفات الكبيرة. + +--- + +### grep + +ابحث في محتوى الملفات باستخدام التعابير النمطية (Regex). + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +بحث سريع في المحتوى عبر قاعدة الشفرة الخاصة بك. يدعم صياغة Regex الكاملة وتصفية الملفات عبر أنماط المسارات. + +--- + +### glob + +اعثر على الملفات عبر مطابقة الأنماط. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +ابحث عن الملفات باستخدام أنماط glob مثل `**/*.js` أو `src/**/*.ts`. يعيد مسارات الملفات المطابقة مرتبة حسب وقت التعديل. + +--- + +### list + +اعرض قائمة بالملفات والمجلدات في مسار محدد. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +تعرض هذه الأداة محتويات المجلد. وتقبل أنماط glob لتصفية النتائج. + +--- + +### lsp (experimental) + +تفاعل مع خوادم LSP التي قمت بتهيئتها للحصول على ميزات ذكاء الشفرة مثل التعاريف والمراجع ومعلومات التحويم وتسلسل الاستدعاءات. + +:::note +هذه الأداة متاحة فقط عند ضبط `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (أو `OPENCODE_EXPERIMENTAL=true`). +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +تتضمن العمليات المدعومة: `goToDefinition` و`findReferences` و`hover` و`documentSymbol` و`workspaceSymbol` و`goToImplementation` و`prepareCallHierarchy` و`incomingCalls` و`outgoingCalls`. + +لتهيئة خوادم LSP المتاحة لمشروعك، راجع [خوادم LSP](/docs/lsp). + +--- + +### patch + +طبّق الرقع (Patches) على الملفات. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +تطبق هذه الأداة ملفات الرقع على قاعدة الشفرة الخاصة بك. وهي مفيدة لتطبيق الفروقات (Diffs) والرقع من مصادر متعددة. + +:::note +تُدار أداة `patch` عبر إذن `edit`، والذي يشمل جميع تعديلات الملفات (`edit` و`write` و`patch` و`multiedit`). +::: + +--- + +### skill + +حمّل [مهارة](/docs/skills) (ملف `SKILL.md`) وأعد محتواها ضمن المحادثة. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +أدِر قوائم المهام أثناء جلسات البرمجة. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +تنشئ هذه الأداة قوائم المهام وتحدّثها لتتبع التقدم أثناء العمليات المعقدة. يستخدمها LLM لتنظيم المهام متعددة الخطوات. + +:::note +هذه الأداة معطلة للوكلاء الفرعيين افتراضيا، لكن يمكنك تفعيلها يدويا. [اعرف المزيد](/docs/agents/#permissions) +::: + +--- + +### todoread + +اقرأ قوائم المهام الموجودة. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +تقرأ هذه الأداة الحالة الحالية لقائمة المهام. يستخدمها LLM لتتبع المهام المعلقة أو المكتملة. + +:::note +هذه الأداة معطلة للوكلاء الفرعيين افتراضيا، لكن يمكنك تفعيلها يدويا. [اعرف المزيد](/docs/agents/#permissions) +::: + +--- + +### webfetch + +اجلب محتوى الويب. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +تتيح هذه الأداة لـ LLM جلب صفحات الويب وقراءتها. وهي مفيدة للبحث عن التوثيق أو لاستكشاف موارد عبر الإنترنت. + +--- + +### websearch + +ابحث في الويب عن معلومات. + +:::note +هذه الأداة متاحة فقط عند استخدام مزود OpenCode أو عند ضبط متغير البيئة `OPENCODE_ENABLE_EXA` على أي قيمة منطقية صحيحة (مثل `true` أو `1`). + +للتفعيل عند تشغيل OpenCode: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +تجري عمليات بحث على الويب باستخدام Exa AI للعثور على معلومات ذات صلة عبر الإنترنت. وهي مفيدة للبحث في المواضيع، والعثور على أحداث جارية، أو جمع معلومات تتجاوز حد بيانات التدريب. + +لا يلزم مفتاح API - إذ تتصل الأداة مباشرة بخدمة MCP المستضافة لدى Exa AI دون مصادقة. + +:::tip +استخدم `websearch` عندما تحتاج إلى العثور على معلومات (Discovery)، واستخدم `webfetch` عندما تحتاج إلى جلب محتوى من رابط محدد (Retrieval). +::: + +--- + +### question + +اطرح على المستخدم أسئلة أثناء التنفيذ. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +تتيح هذه الأداة لـ LLM طرح أسئلة على المستخدم أثناء المهمة. وهي مفيدة من أجل: + +- جمع تفضيلات المستخدم أو متطلباته +- توضيح التعليمات غير الواضحة +- الحصول على قرارات حول خيارات التنفيذ +- تقديم خيارات حول الاتجاه الذي يجب اتباعه + +يتضمن كل سؤال عنوانا ونص السؤال وقائمة بالخيارات. يمكن للمستخدمين الاختيار من الخيارات المتاحة أو كتابة إجابة مخصصة. وعند وجود عدة أسئلة، يمكن للمستخدمين التنقل بينها قبل إرسال جميع الإجابات. + +--- + +## أدوات مخصصة + +تتيح لك الأدوات المخصصة تعريف دوالك الخاصة التي يمكن لـ LLM استدعاؤها. تُعرّف هذه الأدوات في ملف التهيئة ويمكنها تنفيذ شفرة عشوائية. + +[اعرف المزيد](/docs/custom-tools) حول إنشاء أدوات مخصصة. + +--- + +## خوادم MCP + +تتيح لك خوادم MCP (Model Context Protocol) دمج أدوات وخدمات خارجية. يشمل ذلك الوصول إلى قواعد البيانات وتكاملات API وخدمات الجهات الخارجية. + +[اعرف المزيد](/docs/mcp-servers) حول تهيئة خوادم MCP. + +--- + +## التفاصيل الداخلية + +داخليا، تستخدم أدوات مثل `grep` و`glob` و`list` أداة [ripgrep](https://github.com/BurntSushi/ripgrep) في الخلفية. افتراضيا، يحترم ripgrep أنماط `.gitignore`، ما يعني أن الملفات والمجلدات المدرجة في `.gitignore` ستُستبعد من عمليات البحث وعرض القوائم. + +--- + +### أنماط التجاهل + +لتضمين ملفات يتم تجاهلها عادة، أنشئ ملف `.ignore` في جذر المشروع. يمكن لهذا الملف السماح صراحة بمسارات محددة. + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +على سبيل المثال، يسمح ملف `.ignore` هذا لـ ripgrep بالبحث داخل مجلدات `node_modules/` و`dist/` و`build/` حتى لو كانت مدرجة في `.gitignore`. diff --git a/packages/web/src/content/docs/ar/troubleshooting.mdx b/packages/web/src/content/docs/ar/troubleshooting.mdx new file mode 100644 index 00000000000..5b3d11e3c41 --- /dev/null +++ b/packages/web/src/content/docs/ar/troubleshooting.mdx @@ -0,0 +1,299 @@ +--- +title: استكشاف الأخطاء وإصلاحها +description: المشكلات الشائعة وكيفية حلها. +--- + +لاستكشاف المشكلات في OpenCode وإصلاحها، ابدأ بالتحقق من السجلات والبيانات المحلية التي يخزنها على القرص. + +--- + +## السجلات + +يتم حفظ ملفات السجل في: + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: اضغط `WIN+R` والصق `%USERPROFILE%\.local\share\opencode\log` + +تتم تسمية ملفات السجل بطوابع زمنية (مثل `2025-01-09T123456.log`) ويتم الاحتفاظ بأحدث 10 ملفات سجل. + +يمكنك ضبط مستوى السجل باستخدام خيار CLI `--log-level` للحصول على معلومات تصحيح أكثر تفصيلا. على سبيل المثال: `opencode --log-level DEBUG`. + +--- + +## التخزين + +يخزن opencode بيانات الجلسات وبيانات التطبيق الأخرى على القرص في: + +- **macOS/Linux**: `~/.local/share/opencode/` +- **Windows**: اضغط `WIN+R` والصق `%USERPROFILE%\.local\share\opencode` + +يحتوي هذا الدليل على: + +- `auth.json` - بيانات المصادقة مثل مفاتيح API ورموز OAuth +- `log/` - سجلات التطبيق +- `project/` - بيانات خاصة بالمشروع مثل بيانات الجلسة والرسائل + - إذا كان المشروع داخل مستودع Git، فسيتم تخزينه في `.//storage/` + - إذا لم يكن داخل مستودع Git، فسيتم تخزينه في `./global/storage/` + +--- + +## تطبيق سطح المكتب + +يشغل OpenCode Desktop خادما محليا لـ OpenCode (العملية الجانبية `opencode-cli`) في الخلفية. معظم المشكلات سببها إضافة لا تعمل بشكل صحيح، أو ذاكرة تخزين مؤقت تالفة، أو إعداد خادم غير صحيح. + +### فحوصات سريعة + +- أغلق التطبيق تماما ثم أعد تشغيله. +- إذا عرض التطبيق شاشة خطأ، انقر **Restart** وانسخ تفاصيل الخطأ. +- على macOS فقط: قائمة `OpenCode` -> **Reload Webview** (يفيد إذا كانت الواجهة فارغة/متجمدة). + +--- + +### تعطيل الإضافات + +إذا كان تطبيق سطح المكتب يتعطل عند التشغيل، أو يتوقف عن الاستجابة، أو يتصرف بشكل غريب، فابدأ بتعطيل الإضافات. + +#### تحقق من الإعدادات العامة + +افتح ملف الإعدادات العام وابحث عن المفتاح `plugin`. + +- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (أو `~/.config/opencode/opencode.json`) +- **macOS/Linux** (عمليات تثبيت أقدم): `~/.local/share/opencode/opencode.jsonc` +- **Windows**: اضغط `WIN+R` والصق `%USERPROFILE%\.config\opencode\opencode.jsonc` + +إذا كانت لديك إضافات مضبوطة، فقم بتعطيلها مؤقتا بإزالة المفتاح أو ضبطه على مصفوفة فارغة: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### تحقق من أدلة الإضافات + +يمكن لـ OpenCode أيضا تحميل إضافات محلية من القرص. انقلها مؤقتا إلى مكان آخر (أو أعد تسمية المجلد) ثم أعد تشغيل تطبيق سطح المكتب: + +- **إضافات عامة** + - **macOS/Linux**: `~/.config/opencode/plugins/` + - **Windows**: اضغط `WIN+R` والصق `%USERPROFILE%\.config\opencode\plugins` +- **إضافات المشروع** (فقط إذا كنت تستخدم إعدادات لكل مشروع) + - `/.opencode/plugins/` + +إذا عاد التطبيق للعمل، فأعد تفعيل الإضافات واحدة تلو الأخرى لمعرفة أيها يسبب المشكلة. + +--- + +### مسح ذاكرة التخزين المؤقت + +إذا لم يساعد تعطيل الإضافات (أو كانت عملية تثبيت إضافة عالقة)، فامسح ذاكرة التخزين المؤقت حتى يتمكن OpenCode من إعادة بنائها. + +1. أغلق OpenCode Desktop تماما. +2. احذف دليل ذاكرة التخزين المؤقت: + +- **macOS**: Finder -> `Cmd+Shift+G` -> الصق `~/.cache/opencode` +- **Linux**: احذف `~/.cache/opencode` (أو شغّل `rm -rf ~/.cache/opencode`) +- **Windows**: اضغط `WIN+R` والصق `%USERPROFILE%\.cache\opencode` + +3. أعد تشغيل OpenCode Desktop. + +--- + +### إصلاح مشكلات اتصال الخادم + +يمكن لـ OpenCode Desktop إما تشغيل خادمه المحلي (افتراضيا) أو الاتصال بعنوان URL لخادم قمت بتهيئته. + +إذا ظهرت نافذة **"Connection Failed"** (أو لم يتجاوز التطبيق شاشة البداية)، فتحقق مما إذا كان هناك عنوان URL مخصص للخادم. + +#### مسح عنوان URL الافتراضي لخادم سطح المكتب + +من شاشة Home، انقر اسم الخادم (مع نقطة الحالة) لفتح محدد الخوادم. في قسم **Default server**، انقر **Clear**. + +#### إزالة `server.port` / `server.hostname` من الإعدادات + +إذا كان `opencode.json(c)` يحتوي على قسم `server`، فأزله مؤقتا ثم أعد تشغيل تطبيق سطح المكتب. + +#### تحقق من متغيرات البيئة + +إذا كان `OPENCODE_PORT` مضبوطا في بيئتك، فسيحاول تطبيق سطح المكتب استخدام ذلك المنفذ للخادم المحلي. + +- أزل ضبط `OPENCODE_PORT` (أو اختر منفذا متاحا) ثم أعد التشغيل. + +--- + +### Linux: مشكلات Wayland / X11 + +على Linux، قد تتسبب بعض إعدادات Wayland في نوافذ فارغة أو أخطاء في مدير التركيب (compositor). + +- إذا كنت تستخدم Wayland وكانت نافذة التطبيق فارغة/يتعطل، فجرّب التشغيل مع `OC_ALLOW_WAYLAND=1`. +- إذا جعل ذلك الأمور أسوأ، فأزل هذا المتغير وجرّب التشغيل ضمن جلسة X11 بدلا من ذلك. + +--- + +### Windows: بيئة تشغيل WebView2 + +على Windows، يتطلب OpenCode Desktop وجود **WebView2 Runtime** الخاصة بـ Microsoft Edge. إذا فتح التطبيق نافذة فارغة أو لم يبدأ، فقم بتثبيت/تحديث WebView2 ثم جرّب مجددا. + +--- + +### Windows: مشكلات الأداء العامة + +إذا كنت تواجه بطءا في الأداء، أو مشكلات في الوصول إلى الملفات، أو مشكلات في terminal على Windows، فجرّب استخدام [WSL (نظام Windows الفرعي لـ Linux)](/docs/windows-wsl). يوفر WSL بيئة Linux تعمل بسلاسة أكبر مع ميزات OpenCode. + +--- + +### الإشعارات لا تظهر + +لا يعرض OpenCode Desktop إشعارات النظام إلا عندما: + +- تكون الإشعارات مفعلة لـ OpenCode في إعدادات نظام التشغيل، و +- تكون نافذة التطبيق غير نشطة. + +--- + +### إعادة تعيين تخزين تطبيق سطح المكتب (كحل أخير) + +إذا لم يبدأ التطبيق ولم تتمكن من مسح الإعدادات من داخل الواجهة، فأعد تعيين الحالة المحفوظة لتطبيق سطح المكتب. + +1. أغلق OpenCode Desktop. +2. اعثر على هذه الملفات واحذفها (توجد في دليل بيانات تطبيق OpenCode Desktop): + +- `opencode.settings.dat` (عنوان URL الافتراضي لخادم سطح المكتب) +- `opencode.global.dat` و `opencode.workspace.*.dat` (حالة الواجهة مثل الخوادم/المشاريع الأخيرة) + +للعثور على الدليل بسرعة: + +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (ثم ابحث عن أسماء الملفات أعلاه) +- **Linux**: ابحث ضمن `~/.local/share` عن أسماء الملفات أعلاه +- **Windows**: اضغط `WIN+R` -> `%APPDATA%` (ثم ابحث عن أسماء الملفات أعلاه) + +--- + +## الحصول على المساعدة + +إذا كنت تواجه مشكلات مع OpenCode: + +1. **الإبلاغ عن المشكلات على GitHub** + + أفضل طريقة للإبلاغ عن الأخطاء أو طلب الميزات هي عبر مستودعنا على GitHub: + + [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + + قبل إنشاء مشكلة جديدة، ابحث في المشكلات الموجودة لمعرفة ما إذا كانت مشكلتك قد تم الإبلاغ عنها بالفعل. + +2. **انضم إلى Discord** + + للحصول على مساعدة فورية ونقاشات المجتمع، انضم إلى خادم Discord الخاص بنا: + + [**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## مشكلات شائعة + +فيما يلي بعض المشكلات الشائعة وكيفية حلها. + +--- + +### OpenCode لا يبدأ + +1. تحقق من السجلات بحثا عن رسائل الخطأ +2. جرّب التشغيل مع `--print-logs` لرؤية المخرجات في terminal +3. تأكد من أنك تستخدم أحدث إصدار عبر `opencode upgrade` + +--- + +### مشكلات المصادقة + +1. جرّب إعادة المصادقة باستخدام الأمر `/connect` في واجهة TUI +2. تحقق من أن مفاتيح API الخاصة بك صالحة +3. تأكد من أن شبكتك تسمح بالاتصال بواجهة API الخاصة بالمزوّد + +--- + +### النموذج غير متاح + +1. تحقق من أنك قمت بالمصادقة مع المزوّد +2. تأكد من أن اسم النموذج في الإعدادات صحيح +3. قد تتطلب بعض النماذج صلاحيات وصول محددة أو اشتراكات + +إذا واجهت `ProviderModelNotFoundError` فمن المرجح أنك تشير إلى نموذج بشكل غير صحيح في مكان ما. +يجب الإشارة إلى النماذج بهذه الصيغة: `/` + +أمثلة: + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +لمعرفة النماذج التي لديك صلاحية الوصول إليها، شغّل `opencode models` + +--- + +### ProviderInitError + +إذا واجهت ProviderInitError، فمن المحتمل أن إعداداتك غير صالحة أو تالفة. + +لحل ذلك: + +1. أولا، تحقق من أن المزوّد مضبوط بشكل صحيح باتباع [دليل المزوّدين](/docs/providers) +2. إذا استمرت المشكلة، فجرّب مسح الإعدادات المخزنة لديك: + + ```bash + rm -rf ~/.local/share/opencode + ``` + + على Windows، اضغط `WIN+R` واحذف: `%USERPROFILE%\.local\share\opencode` + +3. أعد المصادقة مع المزوّد باستخدام الأمر `/connect` في واجهة TUI. + +--- + +### AI_APICallError ومشكلات حزم المزوّد + +إذا واجهت أخطاء في استدعاءات API، فقد يكون السبب حزم مزوّد قديمة. يقوم opencode بتثبيت حزم المزوّد (OpenAI و Anthropic و Google وغير ذلك) ديناميكيا عند الحاجة ويقوم بتخزينها مؤقتا محليا. + +لحل مشكلات حزم المزوّد: + +1. امسح ذاكرة التخزين المؤقت لحزم المزوّد: + + ```bash + rm -rf ~/.cache/opencode + ``` + + على Windows، اضغط `WIN+R` واحذف: `%USERPROFILE%\.cache\opencode` + +2. أعد تشغيل opencode لإعادة تثبيت أحدث حزم المزوّد + +سيجبر ذلك opencode على تنزيل أحدث إصدارات حزم المزوّد، وهو ما يحل غالبا مشكلات التوافق مع معاملات النماذج وتغييرات API. + +--- + +### النسخ/اللصق لا يعمل على Linux + +يحتاج مستخدمو Linux إلى تثبيت إحدى أدوات الحافظة التالية حتى تعمل ميزة النسخ/اللصق: + +**لأنظمة X11:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**لأنظمة Wayland:** + +```bash +apt install -y wl-clipboard +``` + +**للبيئات بدون واجهة رسومية (Headless):** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +سيكتشف opencode ما إذا كنت تستخدم Wayland ويفضل `wl-clipboard`، وإلا فسيحاول العثور على أدوات الحافظة بالترتيب التالي: `xclip` ثم `xsel`. diff --git a/packages/web/src/content/docs/ar/tui.mdx b/packages/web/src/content/docs/ar/tui.mdx new file mode 100644 index 00000000000..149f2909390 --- /dev/null +++ b/packages/web/src/content/docs/ar/tui.mdx @@ -0,0 +1,387 @@ +--- +title: TUI +description: استخدام واجهة المستخدم TUI في OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +يوفّر OpenCode واجهة terminal تفاعلية (TUI) للعمل على مشاريعك باستخدام LLM. + +يؤدي تشغيل OpenCode إلى بدء واجهة TUI للدليل الحالي. + +```bash +opencode +``` + +أو يمكنك تشغيلها لدليل عمل محدد. + +```bash +opencode /path/to/project +``` + +بعد الدخول إلى واجهة TUI، يمكنك إرسال رسالة كطلب. + +```text +Give me a quick summary of the codebase. +``` + +--- + +## مراجع الملفات + +يمكنك الإشارة إلى الملفات في رسائلك باستخدام `@`. يُجري ذلك بحثا ضبابيا عن الملفات ضمن دليل العمل الحالي. + +:::tip +يمكنك أيضا استخدام `@` للإشارة إلى الملفات في رسائلك. +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +تُضاف محتويات الملف إلى المحادثة تلقائيا. + +--- + +## أوامر Bash + +ابدأ الرسالة بـ `!` لتشغيل أمر في shell. + +```bash frame="none" +!ls -la +``` + +يُضاف خرج الأمر إلى المحادثة كنتيجة أداة. + +--- + +## الأوامر + +عند استخدام واجهة OpenCode في terminal، يمكنك كتابة `/` متبوعة باسم أمر لتنفيذ الإجراءات بسرعة. مثلا: + +```bash frame="none" +/help +``` + +تملك معظم الأوامر أيضا اختصارا باستخدام `ctrl+x` كمفتاح قائد، حيث إن `ctrl+x` هو المفتاح القائد الافتراضي. [اعرف المزيد](/docs/keybinds). + +فيما يلي جميع أوامر الشرطة المائلة المتاحة: + +--- + +### connect + +أضف موفّرا إلى OpenCode. يتيح لك اختيار أحد الموفّرين المتاحين وإضافة مفاتيح API الخاصة بهم. + +```bash frame="none" +/connect +``` + +--- + +### compact + +قم بضغط الجلسة الحالية. _الاسم المستعار_: `/summarize` + +```bash frame="none" +/compact +``` + +**اختصار لوحة المفاتيح:** `ctrl+x c` + +--- + +### details + +بدّل عرض تفاصيل تنفيذ الأدوات. + +```bash frame="none" +/details +``` + +**اختصار لوحة المفاتيح:** `ctrl+x d` + +--- + +### editor + +افتح محررا خارجيا لكتابة الرسائل. يستخدم المحرر المحدد في متغير البيئة `EDITOR`. [اعرف المزيد](#editor-setup). + +```bash frame="none" +/editor +``` + +**اختصار لوحة المفاتيح:** `ctrl+x e` + +--- + +### exit + +اخرج من OpenCode. _الأسماء المستعارة_: `/quit`, `/q` + +```bash frame="none" +/exit +``` + +**اختصار لوحة المفاتيح:** `ctrl+x q` + +--- + +### export + +صدّر المحادثة الحالية إلى Markdown وافتحها في المحرر الافتراضي لديك. يستخدم المحرر المحدد في متغير البيئة `EDITOR`. [اعرف المزيد](#editor-setup). + +```bash frame="none" +/export +``` + +**اختصار لوحة المفاتيح:** `ctrl+x x` + +--- + +### help + +اعرض مربع حوار المساعدة. + +```bash frame="none" +/help +``` + +**اختصار لوحة المفاتيح:** `ctrl+x h` + +--- + +### init + +أنشئ ملف `AGENTS.md` أو حدّثه. [اعرف المزيد](/docs/rules). + +```bash frame="none" +/init +``` + +**اختصار لوحة المفاتيح:** `ctrl+x i` + +--- + +### models + +اعرض النماذج المتاحة. + +```bash frame="none" +/models +``` + +**اختصار لوحة المفاتيح:** `ctrl+x m` + +--- + +### new + +ابدأ جلسة جديدة. _الاسم المستعار_: `/clear` + +```bash frame="none" +/new +``` + +**اختصار لوحة المفاتيح:** `ctrl+x n` + +--- + +### redo + +أعِد تنفيذ رسالة تم التراجع عنها سابقا. متاح فقط بعد استخدام `/undo`. + +:::tip +ستتم أيضا استعادة أي تغييرات على الملفات. +::: + +داخليا، يستخدم هذا Git لإدارة تغييرات الملفات. لذلك يجب أن يكون مشروعك **مستودع Git**. + +```bash frame="none" +/redo +``` + +**اختصار لوحة المفاتيح:** `ctrl+x r` + +--- + +### sessions + +اعرض الجلسات وبدّل بينها. _الأسماء المستعارة_: `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +**اختصار لوحة المفاتيح:** `ctrl+x l` + +--- + +### share + +شارك الجلسة الحالية. [اعرف المزيد](/docs/share). + +```bash frame="none" +/share +``` + +**اختصار لوحة المفاتيح:** `ctrl+x s` + +--- + +### themes + +اعرض السمات المتاحة. + +```bash frame="none" +/theme +``` + +**اختصار لوحة المفاتيح:** `ctrl+x t` + +--- + +### thinking + +بدّل إظهار كتل التفكير/الاستدلال في المحادثة. عند تفعيله، يمكنك رؤية عملية استدلال النموذج للنماذج التي تدعم التفكير الموسّع. + +:::note +يتحكم هذا الأمر فقط فيما إذا كانت كتل التفكير **تُعرض**؛ ولا يفعّل أو يعطّل قدرات الاستدلال في النموذج. لتبديل قدرات الاستدلال فعليا، استخدم `ctrl+t` للتنقّل بين إصدارات النموذج. +::: + +```bash frame="none" +/thinking +``` + +--- + +### undo + +تراجع عن آخر رسالة في المحادثة. يزيل أحدث رسالة للمستخدم، وكل الردود اللاحقة، وأي تغييرات على الملفات. + +:::tip +سيتم أيضا التراجع عن أي تغييرات على الملفات. +::: + +داخليا، يستخدم هذا Git لإدارة تغييرات الملفات. لذلك يجب أن يكون مشروعك **مستودع Git**. + +```bash frame="none" +/undo +``` + +**اختصار لوحة المفاتيح:** `ctrl+x u` + +--- + +### unshare + +ألغِ مشاركة الجلسة الحالية. [اعرف المزيد](/docs/share#un-sharing). + +```bash frame="none" +/unshare +``` + +--- + +## إعداد المحرر + +يستخدم الأمران `/editor` و`/export` المحرر المحدد في متغير البيئة `EDITOR`. + + + + ```bash + # مثال لـ nano أو vim + export EDITOR=nano + export EDITOR=vim + + # للمحررات الرسومية، VS Code، Cursor، VSCodium، Windsurf، Zed، إلخ. + # قم بتضمين --wait + export EDITOR="code --wait" + ``` + + لجعل ذلك دائما، أضف هذا إلى ملف تهيئة shell لديك؛ + `~/.bashrc`، `~/.zshrc`، إلخ. + + + + + ```bash + set EDITOR=notepad + + # للمحررات الرسومية، VS Code، Cursor، VSCodium، Windsurf، Zed، إلخ. + # قم بتضمين --wait + set EDITOR=code --wait + ``` + + لجعل ذلك دائما، استخدم **System Properties** > **Environment Variables**. + + + + + ```powershell + $env:EDITOR = "notepad" + + # للمحررات الرسومية، VS Code، Cursor، VSCodium، Windsurf، Zed، إلخ. + # قم بتضمين --wait + $env:EDITOR = "code --wait" + ``` + + لجعل ذلك دائما، أضف هذا إلى ملف تهيئة PowerShell لديك. + + + + +تتضمن خيارات المحررات الشائعة ما يلي: + +- `code` - Visual Studio Code +- `cursor` - Cursor +- `windsurf` - Windsurf +- `nvim` - محرر Neovim +- `vim` - محرر Vim +- `nano` - محرر Nano +- `notepad` - Windows Notepad +- `subl` - Sublime Text + +:::note +تحتاج بعض المحررات مثل VS Code إلى التشغيل مع الخيار `--wait`. +::: + +تحتاج بعض المحررات إلى وسائط CLI لتعمل بوضع الحجب. يجعل الخيار `--wait` عملية المحرر تنتظر حتى يتم إغلاقها. + +--- + +## الإعداد + +يمكنك تخصيص سلوك واجهة TUI عبر ملف إعدادات OpenCode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### الخيارات + +- `scroll_acceleration` - فعّل تسارع التمرير على نمط macOS لتمرير سلس وطبيعي. عند تفعيله، تزداد سرعة التمرير مع إيماءات التمرير السريعة وتبقى دقيقة للحركات الأبطأ. **يتقدّم هذا الإعداد على `scroll_speed` ويستبدله عند تفعيله.** +- `scroll_speed` - يتحكم في سرعة تمرير واجهة TUI عند استخدام أوامر التمرير (الحد الأدنى: `1`). القيمة الافتراضية هي `3`. **ملاحظة: يتم تجاهل هذا إذا تم ضبط `scroll_acceleration.enabled` على `true`.** + +--- + +## التخصيص + +يمكنك تخصيص جوانب مختلفة من عرض واجهة TUI باستخدام لوحة الأوامر (`ctrl+x h` أو `/help`). تبقى هذه الإعدادات محفوظة عبر عمليات إعادة التشغيل. + +--- + +#### عرض اسم المستخدم + +بدّل ما إذا كان اسم المستخدم يظهر في رسائل الدردشة. يمكنك الوصول إلى هذا عبر: + +- لوحة الأوامر: ابحث عن "username" أو "hide username" +- يُحفظ الإعداد تلقائيا وسيتم تذكره عبر جلسات واجهة TUI diff --git a/packages/web/src/content/docs/ar/web.mdx b/packages/web/src/content/docs/ar/web.mdx new file mode 100644 index 00000000000..30df068767d --- /dev/null +++ b/packages/web/src/content/docs/ar/web.mdx @@ -0,0 +1,142 @@ +--- +title: الويب +description: استخدام OpenCode في متصفحك. +--- + +يمكن تشغيل OpenCode كتطبيق ويب داخل متصفحك، ليمنحك تجربة البرمجة القوية بالذكاء الاصطناعي نفسها دون الحاجة إلى terminal. + +![OpenCode Web - جلسة جديدة](../../../assets/web/web-homepage-new-session.png) + +## البدء + +ابدأ تشغيل واجهة الويب عبر تنفيذ: + +```bash +opencode web +``` + +يؤدي ذلك إلى تشغيل خادم محلي على `127.0.0.1` بمنفذ عشوائي متاح، ويفتح OpenCode تلقائيا في المتصفح الافتراضي لديك. + +:::caution +إذا لم يتم تعيين `OPENCODE_SERVER_PASSWORD` فسيكون الخادم دون حماية. هذا مناسب للاستخدام المحلي، لكنه يجب أن يكون مُعينا عند إتاحة الوصول عبر الشبكة. +::: + +:::tip[مستخدمو Windows] +لأفضل تجربة، شغّل `opencode web` من [WSL](/docs/windows-wsl) بدلا من PowerShell. يضمن ذلك وصولا صحيحا إلى نظام الملفات وتكاملا أفضل مع terminal. +::: + +--- + +## الإعدادات + +يمكنك ضبط خادم الويب باستخدام خيارات CLI أو عبر [ملف الإعدادات](/docs/config). + +### المنفذ + +افتراضيا، يختار OpenCode منفذا متاحا. يمكنك تحديد منفذ: + +```bash +opencode web --port 4096 +``` + +### اسم المضيف + +افتراضيا، يرتبط الخادم بـ `127.0.0.1` (للاستخدام المحلي فقط). لجعل OpenCode متاحا على شبكتك: + +```bash +opencode web --hostname 0.0.0.0 +``` + +عند استخدام `0.0.0.0` سيعرض OpenCode كلا من عناوين الوصول المحلي وعناوين الشبكة: + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### اكتشاف mDNS + +فعّل mDNS لجعل خادمك قابلا للاكتشاف على الشبكة المحلية: + +```bash +opencode web --mdns +``` + +يضبط ذلك تلقائيا اسم المضيف إلى `0.0.0.0` ويعلن عن الخادم باسم `opencode.local`. + +يمكنك تخصيص اسم نطاق mDNS لتشغيل عدة نسخ على الشبكة نفسها: + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +للسماح بنطاقات إضافية عبر CORS (مفيد للواجهات الأمامية المخصصة): + +```bash +opencode web --cors https://example.com +``` + +### المصادقة + +لحماية الوصول، عيّن كلمة مرور عبر متغير البيئة `OPENCODE_SERVER_PASSWORD`: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +اسم المستخدم الافتراضي هو `opencode`، ويمكن تغييره عبر `OPENCODE_SERVER_USERNAME`. + +--- + +## استخدام واجهة الويب + +بعد التشغيل، تتيح لك واجهة الويب الوصول إلى جلسات OpenCode الخاصة بك. + +### الجلسات + +اعرض جلساتك وأدرها من الصفحة الرئيسية. يمكنك رؤية الجلسات النشطة وبدء جلسات جديدة. + +![OpenCode Web - جلسة نشطة](../../../assets/web/web-homepage-active-session.png) + +### حالة الخادم + +انقر على "See Servers" لعرض الخوادم المتصلة وحالتها. + +![OpenCode Web - See Servers (عرض الخوادم)](../../../assets/web/web-homepage-see-servers.png) + +--- + +## إرفاق terminal + +يمكنك إرفاق واجهة terminal (TUI) بخادم ويب قيد التشغيل: + +```bash +# ابدأ خادم الويب +opencode web --port 4096 + +# في محطة طرفية أخرى، اربط TUI +opencode attach http://localhost:4096 +``` + +يتيح لك ذلك استخدام واجهة الويب وterminal في الوقت نفسه، مع مشاركة الجلسات والحالة نفسها. + +--- + +## ملف الإعدادات + +يمكنك أيضا ضبط إعدادات الخادم داخل ملف الإعدادات `opencode.json`: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +تكون خيارات CLI ذات أولوية أعلى من إعدادات ملف الإعدادات. diff --git a/packages/web/src/content/docs/ar/windows-wsl.mdx b/packages/web/src/content/docs/ar/windows-wsl.mdx new file mode 100644 index 00000000000..59d96bd236a --- /dev/null +++ b/packages/web/src/content/docs/ar/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: شغّل OpenCode على Windows باستخدام WSL لأفضل تجربة. +--- + +import { Steps } from "@astrojs/starlight/components" + +رغم أن OpenCode يمكن تشغيله مباشرة على Windows، نوصي باستخدام [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) للحصول على أفضل تجربة. يوفر WSL بيئة Linux تعمل بسلاسة مع ميزات OpenCode. + +:::tip[لماذا WSL؟] +يوفر WSL أداء أفضل لنظام الملفات، ودعمًا كاملًا لـ terminal، وتوافقًا مع أدوات التطوير التي يعتمد عليها OpenCode. +::: + +--- + +## الإعداد + + + +1. **ثبّت WSL** + + إذا لم تقم بذلك بعد، [ثبّت WSL](https://learn.microsoft.com/en-us/windows/wsl/install) باستخدام دليل Microsoft الرسمي. + +2. **ثبّت OpenCode داخل WSL** + + بعد إعداد WSL، افتح terminal داخل WSL وثبّت OpenCode باستخدام إحدى [طرق التثبيت](/docs/). + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **استخدم OpenCode من WSL** + + انتقل إلى مجلد مشروعك (يمكنك الوصول لملفات Windows عبر `/mnt/c/` و`/mnt/d/` وغيرها) ثم شغّل OpenCode. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## تطبيق سطح المكتب + خادم WSL + +إذا كنت تفضّل تطبيق OpenCode لسطح المكتب لكن تريد تشغيل الخادم داخل WSL: + +1. **ابدأ الخادم داخل WSL** مع `--hostname 0.0.0.0` للسماح بالاتصالات الخارجية: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **اربط تطبيق سطح المكتب** على `http://localhost:4096` + +:::note +إذا لم يعمل `localhost` في إعدادك، اتصل باستخدام عنوان IP الخاص بـ WSL بدلًا منه (من داخل WSL: `hostname -I`) واستخدم `http://:4096`. +::: + +:::caution +عند استخدام `--hostname 0.0.0.0`، اضبط `OPENCODE_SERVER_PASSWORD` لحماية الخادم. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## عميل الويب + WSL + +لأفضل تجربة ويب على Windows: + +1. **شغّل `opencode web` من terminal داخل WSL** بدلًا من PowerShell: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **افتحه من متصفح Windows** عبر `http://localhost:` (يعرض OpenCode الرابط) + +تشغيل `opencode web` من WSL يضمن وصولًا صحيحًا لنظام الملفات وتكاملًا أفضل مع terminal، مع بقائه متاحًا من متصفح Windows. + +--- + +## الوصول إلى ملفات Windows + +يمكن لـ WSL الوصول إلى جميع ملفات Windows عبر مجلد `/mnt/`: + +- قرص `C:` → `/mnt/c/` +- قرص `D:` → `/mnt/d/` +- وهكذا... + +مثال: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +لأفضل سلاسة، يمكنك استنساخ/نسخ المستودع إلى نظام ملفات WSL (مثل `~/code/`) وتشغيل OpenCode من هناك. +::: + +--- + +## نصائح + +- شغّل OpenCode داخل WSL للمشاريع المخزنة على أقراص Windows حتى يكون الوصول للملفات سلسًا +- استخدم [إضافة WSL في VS Code](https://code.visualstudio.com/docs/remote/wsl) مع OpenCode لسير عمل تطوير متكامل +- إعدادات OpenCode وجلساته تُخزَّن داخل بيئة WSL في `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/ar/zen.mdx b/packages/web/src/content/docs/ar/zen.mdx new file mode 100644 index 00000000000..f25b321a9b2 --- /dev/null +++ b/packages/web/src/content/docs/ar/zen.mdx @@ -0,0 +1,243 @@ +--- +title: Zen +description: قائمة منتقاة من النماذج يوفّرها OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen هي قائمة بالنماذج التي اختبرها فريق OpenCode وتحقّق منها. + +:::note +OpenCode Zen متاح حاليا بنسخة تجريبية. +::: + +يعمل Zen مثل أي مزوّد آخر في OpenCode. تسجّل الدخول إلى OpenCode Zen وتحصل على +مفتاح API. استخدامه **اختياري بالكامل** ولا تحتاج إليه لاستخدام OpenCode. + +--- + +## الخلفية + +توجد نماذج كثيرة جدا، لكن عددا قليلا فقط منها يعمل بشكل جيد كعوامل للبرمجة. +بالإضافة إلى ذلك، فإن معظم المزوّدين يختلفون كثيرا في طريقة الإعداد؛ لذلك قد +تحصل على أداء وجودة مختلفين بشكل كبير. + +:::tip +اختبرنا مجموعة منتقاة من النماذج والمزوّدين الذين يعملون جيدا مع OpenCode. +::: + +لذلك إذا كنت تستخدم نموذجا عبر خدمة مثل OpenRouter، فلن تكون واثقا أبدا من أنك +تحصل على أفضل نسخة من النموذج الذي تريده. + +لمعالجة ذلك، قمنا بعدة أمور: + +1. اختبرنا مجموعة منتقاة من النماذج وتحدثنا مع فرقها حول افضل طريقة لتشغيلها. +2. ثم عملنا مع عدد من المزوّدين للتأكد من تقديمها بشكل صحيح. +3. أخيرا، قمنا بقياس أداء توليفة النموذج/المزوّد وخرجنا بقائمة نوصي بها بثقة. + +OpenCode Zen هو بوابة للذكاء الاصطناعي تتيح لك الوصول إلى هذه النماذج. + +--- + +## كيف يعمل + +يعمل OpenCode Zen مثل أي مزوّد آخر في OpenCode. + +1. تسجّل الدخول إلى **OpenCode Zen**، وتضيف تفاصيل الفوترة، ثم تنسخ مفتاح API. +2. تشغّل الأمر `/connect` في واجهة TUI، وتختار OpenCode Zen، ثم تلصق مفتاح API. +3. شغّل `/models` في واجهة TUI لعرض قائمة النماذج التي نوصي بها. + +يتم احتساب الرسوم لكل طلب، ويمكنك إضافة رصيد إلى حسابك. + +--- + +## نقاط النهاية + +يمكنك أيضا الوصول إلى نماذجنا عبر نقاط نهاية API التالية. + +| النموذج | معرّف النموذج | نقطة النهاية | حزمة AI SDK | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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` | + +يستخدم [معرّف النموذج](/docs/config/#models) في إعدادات OpenCode الصيغة `opencode/`. +على سبيل المثال، بالنسبة إلى GPT 5.2 Codex ستستخدم `opencode/gpt-5.2-codex` في إعداداتك. + +--- + +### النماذج + +يمكنك جلب القائمة الكاملة بالنماذج المتاحة وبياناتها الوصفية من: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## التسعير + +ندعم نموذج الدفع حسب الاستخدام. فيما يلي الأسعار **لكل 1M tokens**. + +| النموذج | الإدخال | الإخراج | قراءة مخزنة | كتابة مخزنة | +| --------------------------------- | ------- | ------- | ----------- | ----------- | +| Big Pickle | Free | Free | Free | - | +| MiniMax M2.1 Free | Free | Free | Free | - | +| MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | +| GLM 4.7 Free | Free | Free | Free | - | +| 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 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 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.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 | Free | Free | Free | - | + +قد تلاحظ _Claude Haiku 3.5_ في سجل الاستخدام. هذا [نموذج منخفض التكلفة](/docs/config/#models) يُستخدم لتوليد عناوين جلساتك. + +:::note +يتم تمرير رسوم بطاقات الائتمان بالتكلفة الفعلية (4.4% + $0.30 لكل معاملة)؛ ولا نفرض أي رسوم إضافية غير ذلك. +::: + +النماذج المجانية: + +- GLM 4.7 Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج. +- Kimi K2.5 Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج. +- MiniMax M2.1 Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج. +- Big Pickle نموذج خفي ومتاح مجانا على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج. + +تواصل معنا إذا كانت لديك أي أسئلة. + +--- + +### إعادة الشحن التلقائي + +إذا انخفض رصيدك عن $5، فسيقوم Zen تلقائيا بإعادة شحن $20. + +يمكنك تغيير مبلغ إعادة الشحن التلقائي. ويمكنك أيضا تعطيل إعادة الشحن التلقائي بالكامل. + +--- + +### الحدود الشهرية + +يمكنك أيضا تعيين حد شهري للاستخدام لمساحة العمل بالكامل ولكل عضو في فريقك. + +على سبيل المثال، لنفترض أنك ضبطت حد الاستخدام الشهري على $20، فلن يتجاوز Zen مبلغ $20 خلال شهر. +لكن إذا كانت إعادة الشحن التلقائي مفعّلة، فقد ينتهي الأمر بخصم أكثر من $20 إذا انخفض رصيدك عن $5. + +--- + +## الخصوصية + +تتم استضافة جميع نماذجنا في الولايات المتحدة. يلتزم مزوّدونا بسياسة عدم الاحتفاظ بالبيانات (zero-retention) ولا يستخدمون بياناتك لتدريب النماذج، مع الاستثناءات التالية: + +- Big Pickle: خلال فترة إتاحته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج. +- GLM 4.7 Free: خلال فترة إتاحته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج. +- Kimi K2.5 Free: خلال فترة إتاحته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج. +- MiniMax M2.1 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). + +--- + +## للفرق + +يعمل Zen بشكل ممتاز للفرق أيضا. يمكنك دعوة زملاء الفريق، وتعيين الأدوار، وتنظيم +النماذج التي يستخدمها فريقك، والمزيد. + +:::note +مساحات العمل مجانية حاليا للفرق كجزء من النسخة التجريبية. +::: + +إدارة مساحة العمل مجانية حاليا للفرق كجزء من النسخة التجريبية. سنشارك المزيد من التفاصيل حول التسعير قريبا. + +--- + +### الأدوار + +يمكنك دعوة زملاء الفريق إلى مساحة عملك وتعيين الأدوار: + +- **Admin**: إدارة النماذج والأعضاء ومفاتيح API والفوترة +- **Member**: إدارة مفاتيح API الخاصة به فقط + +يمكن للمسؤولين أيضا تعيين حدود إنفاق شهرية لكل عضو للسيطرة على التكاليف. + +--- + +### صلاحيات الوصول للنماذج + +يمكن للمسؤولين تفعيل نماذج محددة لمساحة العمل أو تعطيلها. ستعيد الطلبات المرسلة إلى نموذج معطّل خطأ. + +يفيد ذلك في الحالات التي تريد فيها تعطيل استخدام نموذج يقوم بجمع البيانات. + +--- + +### استخدم مفتاحك الخاص + +يمكنك استخدام مفاتيح API الخاصة بك لدى OpenAI أو Anthropic مع الاستمرار في الوصول إلى نماذج أخرى ضمن Zen. + +عند استخدام مفاتيحك الخاصة، تتم فوترة tokens مباشرة من المزوّد وليس من Zen. + +على سبيل المثال، قد تكون لدى مؤسستك بالفعل مفاتيح لـ OpenAI أو Anthropic وتريد استخدامها بدلا من المفتاح الذي يوفّره Zen. + +--- + +## الأهداف + +أنشأنا OpenCode Zen من أجل: + +1. **قياس الأداء** لأفضل النماذج/المزوّدين لعوامل البرمجة. +2. إتاحة خيارات **عالية الجودة** دون خفض الأداء أو توجيه الطلبات إلى مزوّدين أرخص. +3. تمرير أي **انخفاض في الأسعار** عبر البيع بالتكلفة؛ بحيث تكون الزيادة الوحيدة لتغطية رسوم المعالجة. +4. عدم فرض **أي ارتباط حصري (lock-in)** عبر تمكينك من استخدامه مع أي عامل برمجة آخر، مع إتاحة استخدام أي مزوّد آخر مع OpenCode أيضا. diff --git a/packages/web/src/content/docs/bs/acp.mdx b/packages/web/src/content/docs/bs/acp.mdx new file mode 100644 index 00000000000..a2b2707c882 --- /dev/null +++ b/packages/web/src/content/docs/bs/acp.mdx @@ -0,0 +1,156 @@ +--- +title: ACP podrška +description: Koristite OpenCode u bilo kojem uređivaču kompatibilnom sa ACP. +--- + +OpenCode podržava [Agent Client Protocol](https://agentclientprotocol.com) (ACP), što vam omogućava da ga koristite direktno u kompatibilnim uređivačima i IDE-ovima. + +:::tip +Za listu uređivača i alata koji podržavaju ACP, pogledajte [ACP izvještaj o napretku](https://zed.dev/blog/acp-progress-report#available-now). +::: + +ACP je otvoreni protokol koji standardizira komunikaciju između uređivača koda i AI coding agenata. + +--- + +## Konfiguracija + +Da biste koristili OpenCode putem ACP-a, konfigurirajte svoj uređivač da pokrene naredbu `opencode acp`. + +Naredba pokreće OpenCode kao ACP-kompatibilan podproces koji komunicira sa vašim uređivačem preko JSON-RPC-a kroz stdio. + +Ispod su primjeri za popularne uređivače koji podržavaju ACP. + +--- + +### Zed + +Dodajte u svoju [Zed](https://zed.dev) konfiguraciju (`~/.config/zed/settings.json`): + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +Da biste ga otvorili, koristite akciju `agent: new thread` u **Command Palette**. + +Također možete vezati prečicu na tastaturi uređivanjem vašeg `keymap.json`: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### JetBrains IDE-ovi + +Dodajte u svoj [JetBrains IDE](https://www.jetbrains.com/) `acp.json` prema [dokumentaciji](https://www.jetbrains.com/help/ai-assistant/acp.html): + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +Da biste ga otvorili, koristite novog "OpenCode" agenta u AI Chat agent selektoru. + +--- + +### Avante.nvim + +Dodajte u svoju [Avante.nvim](https://github.com/yetone/avante.nvim) konfiguraciju: + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +Ako trebate proslijediti varijable okruženja: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +Da koristite OpenCode kao ACP agenta u [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim), dodajte sljedeće u svoju Neovim konfiguraciju: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +Ova konfiguracija postavlja CodeCompanion da koristi OpenCode kao ACP chat agenta. + +Ako trebate proslijediti varijable okruženja (kao što je `OPENCODE_API_KEY`), pogledajte [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) u dokumentaciji CodeCompanion.nvim. + +## Podržane funkcije + +OpenCode radi isto kroz ACP kao i u terminalu. Podržane su sve funkcije: + +:::note +Neke ugrađene komande kao što su `/undo` i `/redo` trenutno nisu podržane. +::: + +- Ugrađeni alati (operacije sa datotekama, naredbe terminala, itd.) +- Prilagođeni alati i slash komande +- MCP serveri konfigurisani u vašoj OpenCode konfiguraciji +- Pravila specifična za projekat `AGENTS.md` +- Prilagođeni formateri i linteri +- Agenti i sistem dozvola diff --git a/packages/web/src/content/docs/bs/agents.mdx b/packages/web/src/content/docs/bs/agents.mdx new file mode 100644 index 00000000000..8ff674ae67e --- /dev/null +++ b/packages/web/src/content/docs/bs/agents.mdx @@ -0,0 +1,746 @@ +--- +title: Agenti +description: Konfigurirajte i koristite specijalizirane agente. +--- + +Agenti su specijalizirani AI asistenti koji se mogu konfigurirati za specifične zadatke i tokove posla. Oni vam omogućavaju da kreirate fokusirane alate sa prilagođenim upitima, modelima i pristupom alatima. + +:::tip +Koristite agenta plana za analizu koda i pregled prijedloga bez ikakvih promjena koda. +::: + +Možete se prebacivati ​​između agenata tokom sesije ili ih pozvati spominjanjem `@`. + +--- + +## Vrste + +Postoje dvije vrste agenata u OpenCode: primarni agenti i podagenti. + +--- + +### Primarni agenti + +Primarni agenti su glavni pomoćnici s kojima direktno komunicirate. Možete se kretati kroz njih pomoću tipke **Tab** ili vašeg konfigurisanog povezivanja tipki `switch_agent`. Ovi agenti vode vaš glavni razgovor. Pristup alatima se konfiguriše putem dozvola — na primjer, Build ima omogućene sve alate dok je Plan ograničen. + +:::tip +Možete koristiti tipku **Tab** za prebacivanje između primarnih agenata tokom sesije. +::: + +OpenCode dolazi sa dva ugrađena primarna agenta, **Build** i **Plan**. Pogledat ćemo ih u nastavku. + +--- + +### Subagenti + +Subagenti su specijalizovani pomoćnici koje primarni agenti mogu pozvati za određene zadatke. Možete ih i ručno pozvati **@ spominjanjem** u svojim porukama. + +OpenCode dolazi sa dva ugrađena subagenta, **General** i **Explore**. Ovo ćemo pogledati u nastavku. + +--- + +## Ugrađeni + +OpenCode dolazi sa dva ugrađena primarna agenta i dva ugrađena subagenta. + +--- + +### Build agent + +_Režim_: `primary` + +Build je **podrazumevani** primarni agent sa svim omogućenim alatima. Ovo je standardni agent za razvojni rad gdje vam je potreban pun pristup operacijama datoteka i sistemskim komandama. + +--- + +### Plan agent + +_Režim_: `primary` + +Ograničeni agent dizajniran za planiranje i analizu. Koristimo sistem dozvola kako bismo vam pružili veću kontrolu i spriječili neželjene promjene. +Prema zadanim postavkama, sve sljedeće je postavljeno na `ask`: + +- `file edits`: Sva upisivanja, zakrpe i uređivanja +- `bash`: Sve bash komande + +Ovaj agent je koristan kada želite da LLM analizira kod, predloži promjene ili kreira planove bez stvarnih modifikacija vaše baze koda. + +--- + +### General agent + +_Režim_: `subagent` + +Agent opće namjene za istraživanje složenih pitanja i izvršavanje zadataka u više koraka. Ima potpuni pristup alatima (osim todo), tako da može mijenjati fajlove kada je to potrebno. Koristite ovo za paralelno pokretanje više jedinica rada. + +--- + +### Explore agent + +_Režim_: `subagent` + +Brzi agent samo za čitanje za istraživanje kodnih baza. Nije moguće mijenjati fajlove. Koristite ovo kada trebate brzo pronaći datoteke po uzorku, pretražiti kod za ključne riječi ili odgovoriti na pitanja o bazi kodova. + +--- + +### Compaction agent + +_Režim_: `primary` + +Skriveni sistemski agent koji sažima dugi kontekst u manji sažetak. Pokreće se automatski kada je potrebno i ne može se odabrati u korisničkom interfejsu. + +--- + +### Title agent + +_Režim_: `primary` + +Skriveni sistemski agent koji generiše kratke naslove sesija. Pokreće se automatski i ne može se odabrati u korisničkom interfejsu. + +--- + +### Summary agent + +_Režim_: `primary` + +Skriveni sistemski agent koji kreira sažetke sesije. Pokreće se automatski i ne može se odabrati u korisničkom interfejsu. + +--- + +## Korištenje + +1. Za primarne agente, koristite taster **Tab** za kretanje kroz njih tokom sesije. Također možete koristiti svoju konfiguriranu vezu tipke `switch_agent`. + +2. Subagenti se mogu pozvati: + - **Automatski** od strane primarnih agenata za specijalizovane zadatke na osnovu njihovih opisa. + - Ručno **@ spominjanjem** subagenta u vašoj poruci. Na primjer. + + ```txt frame="none" + @general help me search for this function + ``` + +3. **Navigacija između sesija**: Kada subagenti kreiraju vlastite podređene sesije, možete se kretati između roditeljske sesije i svih podređenih sesija koristeći: + - **\+Right** (ili vaša konfigurirana `session_child_cycle` veza) za kretanje naprijed kroz roditelj → dijete1 → dijete2 → ... → roditelj + - **\+Left** (ili vaše konfigurirano povezivanje tipki `session_child_cycle_reverse`) za kretanje unazad kroz roditelj ← dijete1 ← dijete2 ← ... ← roditelj + + Ovo vam omogućava neprimetno prebacivanje između glavnog razgovora i rada specijalizovanog podagenta. + +--- + +## Konfiguracija + +Možete prilagoditi ugrađene agente ili kreirati vlastite kroz konfiguraciju. Agenti se mogu konfigurisati na dva načina: + +--- + +### JSON + +Konfigurirajte agente u svom konfiguracijskom fajlu `opencode.json`: + +```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 + +Također možete definirati agente koristeći markdown datoteke. Stavite ih u: + +- Globalno: `~/.config/opencode/agents/` +- Po projektu: `.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. +``` + +Ime markdown datoteke postaje ime agenta. Na primjer, `review.md` kreira `review` agenta. + +--- + +## Opcije + +Pogledajmo ove opcije konfiguracije detaljno. + +--- + +### Opis + +Koristite opciju `description` da pružite kratak opis onoga što agent radi i kada ga koristiti. + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +Ovo je **obavezna** opcija konfiguracije. + +--- + +### Temperatura + +Kontrolišite slučajnost i kreativnost odgovora LLM-a pomoću `temperature` konfiguracije. + +Niže vrijednosti čine odgovore fokusiranijim i determinističkim, dok više vrijednosti povećavaju kreativnost i varijabilnost. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Vrijednosti temperature se obično kreću od 0.0 do 1.0: + +- **0.0-0.2**: Vrlo fokusirani i deterministički odgovori, idealni za analizu i planiranje koda +- **0.3-0.5**: Uravnoteženi odgovori sa malo kreativnosti, dobro za opšte razvojne zadatke +- **0.6-1.0**: Kreativniji i raznovrsniji odgovori, korisni za razmišljanje i istraživanje + +```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}" + } + } +} +``` + +Ako temperatura nije navedena, OpenCode koristi standardne postavke specifične za model; obično 0 za većinu modela, 0.55 za Qwen modele. + +--- + +### Maksimalan broj koraka + +Kontrolirajte maksimalni broj iteracija agenta koje agent može izvesti prije nego što bude prisiljen da odgovori samo tekstom. Ovo omogućava korisnicima koji žele kontrolirati troškove da postave ograničenje na akcije agenta. + +Ako ovo nije postavljeno, agent će nastaviti iterirati sve dok model ne odluči da se zaustavi ili korisnik ne prekine sesiju. + +```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 + } + } +} +``` + +Kada se dostigne ograničenje, agent prima poseban sistemski prompt koji ga upućuje da odgovori sa rezimeom svog rada i preporučenim preostalim zadacima. + +:::caution +Naslijeđeno polje `maxSteps` je zastarjelo. Umjesto toga koristite `steps`. +::: + +--- + +### Onemogućavanje + +Postavite na `true` da onemogućite agenta. + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### Upit + +Navedite prilagođenu sistemsku prompt datoteku za ovog agenta sa `prompt` konfiguracijom. Datoteka s promptom treba da sadrži upute specifične za svrhu agenta. + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Ova putanja je relativna u odnosu na mjesto gdje se nalazi konfiguracijski fajl. Dakle, ovo radi i za globalnu OpenCode konfiguraciju i za konfiguraciju specifične za projekat. + +--- + +### Model + +Koristite `model` konfiguraciju da nadjačate model za ovog agenta. Korisno za korištenje različitih modela optimiziranih za različite zadatke. Na primjer, brži model za planiranje, sposobniji model za implementaciju. + +:::tip +Ako ne navedete model, primarni agenti koriste [model globalno konfiguriran](/docs/config#models) dok će podagenti koristiti model primarnog agenta koji je pozvao subagenta. +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +ID modela u vašoj OpenCode konfiguraciji koristi format `provider/model-id`. Na primjer, ako koristite [OpenCode Zen](/docs/zen), koristili biste `opencode/gpt-5.1-codex` za GPT 5.1 Codex. + +--- + +### Alati + +Kontrolirajte koji su alati dostupni u ovom agentu koristeći konfiguraciju `tools`. Možete omogućiti ili onemogućiti određene alate tako što ćete ih postaviti na `true` ili `false`. + +```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 +Konfiguracija specifična za agenta poništava globalnu konfiguraciju. +::: + +Također možete koristiti zamjenske znakove za kontrolu više alata odjednom. Na primjer, da onemogućite sve alate sa MCP servera: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[Saznajte više o alatima](/docs/tools). + +--- + +### Dozvole + +Možete konfigurirati dozvole za upravljanje radnjama koje agent može poduzeti. Trenutno se dozvole za alate `edit`, `bash` i `webfetch` mogu konfigurirati na: + +- `"ask"` — Zatražite odobrenje prije pokretanja alata +- `"allow"` — Dozvoli sve operacije bez odobrenja +- `"deny"` — Onemogućite alat + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +Možete nadjačati ove dozvole po agentu. + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +Također možete postaviti dozvole u Markdown agentima. + +```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. +``` + +Možete postaviti dozvole za određene bash komande. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +Ovo može koristiti glob uzorak. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +Također možete koristiti zamjenski znak `*` za kontrolu dozvola za sve komande. +Budući da posljednje podudarno pravilo ima prednost, prvo postavite zamjenski znak `*`, a zatim navedena pravila. + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[Saznajte više o dozvolama](/docs/permissions). + +--- + +### Način rada + +Kontrolirajte način rada agenta koristeći konfiguraciju `mode`. Opcija `mode` se koristi da specificira kako se agent može koristiti. + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +Opcija `mode` se može postaviti na `primary`, `subagent` ili `all`. Ako `mode` nije specificirano, podrazumevano je `all`. + +--- + +### Skriveno + +Sakrij podagenta iz `@` menija za automatsko dovršavanje sa `hidden: true`. Korisno za interne podagente koje bi drugi agenti trebali programski pozvati samo preko Task alata. + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +Ovo utiče samo na vidljivost korisnika u meniju za automatsko dovršavanje. Skriveni agenti se i dalje mogu pozvati od strane modela putem alata Task ako dozvole to dozvoljavaju. + +:::note +Odnosi se samo na `mode: subagent` agente. +::: + +--- + +### Dozvole zadataka + +Kontrolirajte koje podagente agent može pozvati preko Task alata sa `permission.task`. Koristi glob uzorke za fleksibilno uparivanje. + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +Kada se postavi na `deny`, subagent se u potpunosti uklanja iz opisa alata za zadatak, tako da ga model neće pokušati pozvati. + +:::tip +Pravila se procjenjuju po redoslijedu i **posljednje odgovarajuće pravilo pobjeđuje**. U gornjem primjeru, `orchestrator-planner` odgovara i `*` (deny) i `orchestrator-*` (allow), ali pošto `orchestrator-*` dolazi nakon `*`, rezultat je `allow`. +::: + +:::tip +Korisnici uvijek mogu pozvati bilo kojeg subagenta direktno preko `@` menija za autodovršavanje, čak i ako bi dozvole za zadatak agenta to uskratile. +::: + +--- + +### Boja + +Prilagodite vizualni izgled agenta u korisničkom sučelju s opcijom `color`. Ovo utiče na to kako se agent pojavljuje u interfejsu. + +Koristite važeću heksadecimalnu boju (npr. `#FF5733`) ili boju teme: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +Kontrolirajte raznolikost odgovora s opcijom `top_p`. Alternativa temperaturi za kontrolu nasumice. + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +Vrijednosti se kreću od 0.0 do 1.0. Niže vrijednosti su više fokusirane, više vrijednosti raznovrsnije. + +--- + +### Dodatno + +Sve druge opcije koje navedete u konfiguraciji agenta će biti **direktno proslijeđene** dobavljaču kao opcije modela. Ovo vam omogućava da koristite karakteristike i parametre specifične za provajdera. + +Na primjer, sa OpenAI-jevim modelima rezonovanja, možete kontrolisati napor rasuđivanja: + +```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" + } + } +} +``` + +Ove dodatne opcije su specifične za model i dobavljača. U dokumentaciji vašeg provajdera provjerite dostupne parametre. + +:::tip +Pokrenite `opencode models` da vidite listu dostupnih modela. +::: + +--- + +## Kreiranje agenata + +Možete kreirati nove agente koristeći sljedeću naredbu: + +```bash +opencode agent create +``` + +Ova interaktivna komanda će: + +1. Pitajte gdje da sačuvate agenta; globalno ili specifično za projekat. +2. Opis onoga što agent treba da uradi. +3. Generirajte odgovarajući sistemski prompt i identifikator. +4. Omogućite vam da odaberete kojim alatima agent može pristupiti. +5. Konačno, kreirajte markdown datoteku s konfiguracijom agenta. + +--- + +## Primjeri upotrebe + +Evo nekoliko uobičajenih slučajeva upotrebe različitih agenata. + +- **Build agent**: Potpuni razvojni rad sa svim omogućenim alatima +- **Plan agent**: Analiza i planiranje bez unošenja promjena +- **Review agent**: Code review sa pristupom samo za čitanje plus alati za dokumentaciju +- **Debug agent**: Fokusiran na istragu sa omogućenim bash i alatima za čitanje +- **Docs agent**: Pisanje dokumentacije sa operacijama datoteka, ali bez sistemskih naredbi + +--- + +## Primjeri + +Evo nekoliko primjera agenata koji bi vam mogli biti korisni. + +:::tip +Imate li agenta kojeg biste željeli podijeliti? [Pošalji PR](https://github.com/anomalyco/opencode). +::: + +--- + +### Agent za dokumentaciju + +```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 +``` + +--- + +### Sigurnosni revizor + +```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/bs/cli.mdx b/packages/web/src/content/docs/bs/cli.mdx new file mode 100644 index 00000000000..049b43497f7 --- /dev/null +++ b/packages/web/src/content/docs/bs/cli.mdx @@ -0,0 +1,600 @@ +--- +title: CLI +description: OpenCode CLI opcije i naredbe. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode CLI po defaultu pokreće [TUI](/docs/tui) kada se pokrene bez ikakvih argumenata. + +```bash +opencode +``` + +Ali takođe prihvata naredbe kao što je dokumentovano na ovoj stranici. Ovo vam omogućava programsku interakciju sa OpenCode. + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +Pokrenite OpenCode terminalski korisnički interfejs. + +```bash +opencode [project] +``` + +#### Opcije + +| Opcija | Kratko | Opis | +| ------------ | ------ | ------------------------------------------------------------------------ | +| `--continue` | `-c` | Nastavite posljednju sesiju | +| `--session` | `-s` | ID sesije za nastavak | +| `--fork` | | Forkujte sesiju pri nastavku (koristiti sa `--continue` ili `--session`) | +| `--prompt` | | Prompt za upotrebu | +| `--model` | `-m` | Model za korištenje u obliku provider/model | +| `--agent` | | Agent za korištenje | +| `--port` | | Port na kojem treba slušati | +| `--hostname` | | Hostname na kojem treba slušati | + +--- + +## Naredbe + +OpenCode CLI takođe ima sljedeće naredbe. + +--- + +### agent + +Upravljajte OpenCode agentima. + +```bash +opencode agent [command] +``` + +--- + +### attach + +Priključite terminal na već pokrenut OpenCode backend server pokrenut putem `serve` ili `web` naredbi. + +```bash +opencode attach [url] +``` + +Ovo omogućava korištenje TUI-ja sa udaljenim OpenCode backend-om. Na primjer: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### Opcije + +| Opcija | Kratko | Opis | +| ----------- | ------ | ------------------------------------ | +| `--dir` | | Radni direktorij za pokretanje TUI-a | +| `--session` | `-s` | ID sesije za nastavak | + +--- + +#### create + +Kreirajte novog agenta s prilagođenom konfiguracijom. + +```bash +opencode agent create +``` + +Ova naredba će vas voditi kroz kreiranje novog agenta sa prilagođenim sistemskim promptom i konfiguracijom alata. + +--- + +#### list + +Navedite sve dostupne agente. + +```bash +opencode agent list +``` + +--- + +### auth + +Naredba za upravljanje vjerodajnicama i prijavom za provajdere. + +```bash +opencode auth [command] +``` + +--- + +#### login + +OpenCode pokreće lista provajdera na [Models.dev](https://models.dev), tako da možete koristiti `opencode auth login` da konfigurirate API ključeve za bilo kojeg provajdera kojeg želite koristiti. Ovo je pohranjeno u `~/.local/share/opencode/auth.json`. + +```bash +opencode auth login +``` + +Kada se OpenCode pokrene, učitava dobavljače iz datoteke vjerodajnica. I ako postoje neki ključevi definirani u vašim okruženjima ili `.env` fajl u vašem projektu. + +--- + +#### list + +Navodi sve autentifikovane dobavljače pohranjene u datoteci vjerodajnica. + +```bash +opencode auth list +``` + +Ili kratka verzija. + +```bash +opencode auth ls +``` + +--- + +#### logout + +Odjavljuje vas s provajdera tako što ga briše iz datoteke vjerodajnica. + +```bash +opencode auth logout +``` + +--- + +### github + +Upravljajte GitHub agentom za automatizaciju repozitorija. + +```bash +opencode github [command] +``` + +--- + +#### install + +Instalirajte GitHub agenta u svoj repozitorij. + +```bash +opencode github install +``` + +Ovo postavlja neophodni tok rada GitHub Actions i vodi vas kroz proces konfiguracije. [Saznajte više](/docs/github). + +--- + +#### run + +Pokrenite GitHub agent. Ovo se obično koristi u GitHub Actions. + +```bash +opencode github run +``` + +##### Opcije + +| Opcija | Opis | +| --------- | -------------------------------------- | +| `--event` | GitHub mock event za pokretanje agenta | +| `--token` | GitHub Personal Access Token | + +--- + +### mcp + +Upravljajte Model Context Protocol (MCP) serverima. + +```bash +opencode mcp [command] +``` + +--- + +#### add + +Dodajte MCP server svojoj konfiguraciji. + +```bash +opencode mcp add +``` + +Ova naredba će vas voditi kroz dodavanje lokalnog ili udaljenog MCP servera. + +--- + +#### list + +Navedite sve konfigurirane MCP servere i njihov status veze. + +```bash +opencode mcp list +``` + +Ili koristite kratku verziju. + +```bash +opencode mcp ls +``` + +--- + +#### auth + +Autentifikujte se sa MCP serverom koji je omogućen za OAuth. + +```bash +opencode mcp auth [name] +``` + +Ako ne navedete ime servera, od vas će biti zatraženo da izaberete neki od dostupnih servera koji podržavaju OAuth. +Također možete navesti servere koji podržavaju OAuth i njihov status autentifikacije. + +```bash +opencode mcp auth list +``` + +Ili koristite kratku verziju. + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +Uklonite OAuth vjerodajnice za MCP server. + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +Otklanjanje grešaka (debug) OAuth veze sa MCP serverom. + +```bash +opencode mcp debug +``` + +--- + +### models + +Navedite sve dostupne modele konfiguriranih provajdera. + +```bash +opencode models [provider] +``` + +Ova naredba prikazuje sve modele dostupne kod vaših konfiguriranih provajdera u formatu `provider/model`. +Ovo je korisno za pronalaženje tačnog naziva modela za korištenje u [vašoj konfiguraciji](/docs/config/). +Opciono možete proslijediti ID provajdera za filtriranje modela po tom dobavljaču. + +```bash +opencode models anthropic +``` + +#### Opcije + +| Opcija | Opis | +| ----------- | ------------------------------------------------------------------------ | +| `--refresh` | Osvježite keš modela sa models.dev | +| `--verbose` | Koristite detaljniji izlaz modela (uključuje metapodatke poput troškova) | + +Koristite `--refresh` zastavicu da ažurirate keširanu listu modela. Ovo je korisno kada su novi modeli dodani provajderu i želite da ih vidite u OpenCode. + +```bash +opencode models --refresh +``` + +--- + +### run + +Pokrenite OpenCode u neinteraktivnom modu tako što ćete direktno proslijediti prompt. + +```bash +opencode run [message..] +``` + +Ovo je korisno za skriptiranje, automatizaciju ili kada želite brz odgovor bez pokretanja punog TUI-ja. Na primjer: + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +Također možete priključiti pokrenutu `opencode serve` instancu kako biste izbjegli vrijeme hladnog pokretanja MCP servera pri svakom pokretanju: + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### Opcije + +| Opcija | Kratko | Opis | +| ------------ | ------ | ------------------------------------------------------------------------ | +| `--command` | | Naredba za pokretanje, koristite poruku za argumente | +| `--continue` | `-c` | Nastavite posljednju sesiju | +| `--session` | `-s` | ID sesije za nastavak | +| `--fork` | | Forkujte sesiju pri nastavku (koristiti sa `--continue` ili `--session`) | +| `--share` | | Podijelite sesiju | +| `--model` | `-m` | Model za korištenje u obliku provider/model | +| `--agent` | | Agent za korištenje | +| `--file` | `-f` | Fajlovi koje treba priložiti poruci | +| `--format` | | Format: default (formatiran) ili json (sirovi JSON događaji) | +| `--title` | | Naslov sesije (koristi skraćeni prompt ako nije navedena vrijednost) | +| `--attach` | | Priključite na pokrenuti OpenCode server (npr. http://localhost:4096) | +| `--port` | | Port za lokalni server (zadano na nasumični port) | + +--- + +### serve + +Pokrenite OpenCode headless server za API pristup. Pogledajte [server docs](/docs/server) za kompletan HTTP interfejs. + +```bash +opencode serve +``` + +Ovo pokreće HTTP server koji pruža API pristup funkcionalnosti OpenCode-a bez TUI interfejsa. Postavite `OPENCODE_SERVER_PASSWORD` da omogućite HTTP osnovnu auth (korisničko ime je zadano na `opencode`). + +#### Opcije + +| Opcija | Opis | +| ------------ | ----------------------------------------------------- | +| `--port` | Port na kojem treba slušati | +| `--hostname` | Hostname na kojem treba slušati | +| `--mdns` | Omogući mDNS otkrivanje | +| `--cors` | Dodatni origin(i) pretraživača koji dozvoljavaju CORS | + +--- + +### session + +Upravljajte OpenCode sesijama. + +```bash +opencode session [command] +``` + +--- + +#### list + +Navedite sve OpenCode sesije. + +```bash +opencode session list +``` + +##### Opcije + +| Opcija | Kratko | Opis | +| ------------- | ------ | -------------------------------------- | +| `--max-count` | `-n` | Ograničenje na N najnovijih sesija | +| `--format` | | Izlazni format: table ili json (table) | + +--- + +### stats + +Prikaži statistiku upotrebe tokena i troškova za vaše OpenCode sesije. + +```bash +opencode stats +``` + +#### Opcije + +| Opcija | Opis | +| ----------- | ---------------------------------------------------------------------------------------------------------- | +| `--days` | Prikaži statistiku za zadnjih N dana (sva vremena) | +| `--tools` | Broj alata za prikaz (svi) | +| `--models` | Prikaži raščlambu korištenja modela (skriveno prema zadanim postavkama). Proslijedite broj za prikaz top N | +| `--project` | Filtriraj po projektu (svi projekti, prazan niz: trenutni projekt) | + +--- + +### export + +Izvezite podatke sesije kao JSON. + +```bash +opencode export [sessionID] +``` + +Ako ne unesete ID sesije, od vas će biti zatraženo da odaberete neku od dostupnih sesija. + +--- + +### import + +Uvezite podatke sesije iz JSON datoteke ili OpenCode dijeljenog URL-a. + +```bash +opencode import +``` + +Možete uvesti iz lokalne datoteke ili OpenCode dijeljenog URL-a. + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +Pokrenite OpenCode headless server sa web interfejsom. + +```bash +opencode web +``` + +Ovo pokreće HTTP server i otvara web pretraživač za pristup OpenCode-u preko web interfejsa. Postavite `OPENCODE_SERVER_PASSWORD` da omogućite HTTP osnovnu auth (korisničko ime je zadano na `opencode`). + +#### Opcije + +| Opcija | Opis | +| ------------ | ----------------------------------------------------- | +| `--port` | Port na kojem treba slušati | +| `--hostname` | Hostname na kojem treba slušati | +| `--mdns` | Omogući mDNS otkrivanje | +| `--cors` | Dodatni origin(i) pretraživača koji dozvoljavaju CORS | + +--- + +### acp + +Pokrenite ACP (Agent Client Protocol) server. + +```bash +opencode acp +``` + +Ova naredba pokreće ACP server koji komunicira preko stdin/stdout koristeći nd-JSON. + +#### Opcije + +| Opcija | Opis | +| ------------ | --------------------------- | +| `--cwd` | Radni direktorij | +| `--port` | Port na kojem treba slušati | +| `--hostname` | Hostname na kojem slušati | + +--- + +### uninstall + +Deinstalirajte OpenCode i uklonite sve povezane datoteke. + +```bash +opencode uninstall +``` + +#### Opcije + +| Opcija | Kratko | Opis | +| --------------- | ------ | --------------------------------------------- | +| `--keep-config` | `-c` | Sačuvajte konfiguracijske datoteke | +| `--keep-data` | `-d` | Sačuvajte podatke i snimke sesije | +| `--dry-run` | | Pokažite šta bi bilo uklonjeno bez uklanjanja | +| `--force` | `-f` | Preskoči upite za potvrdu | + +--- + +### upgrade + +Ažurira OpenCode na najnoviju verziju ili određenu verziju. + +```bash +opencode upgrade [target] +``` + +Za nadogradnju na najnoviju verziju. + +```bash +opencode upgrade +``` + +Za nadogradnju na određenu verziju. + +```bash +opencode upgrade v0.1.48 +``` + +#### Opcije + +| Opcija | Kratko | Opis | +| ---------- | ------ | ------------------------------------------------------- | +| `--method` | `-m` | Korišteni način instalacije; curl, npm, pnpm, bun, brew | + +--- + +## Globalne opcije + +OpenCode CLI prihvata sljedeće globalne zastavice. + +| Opcija | Kratko | Opis | +| -------------- | ------ | ----------------------------------------- | +| `--help` | `-h` | Prikaži pomoć | +| `--version` | `-v` | Ispiši broj verzije | +| `--print-logs` | | Ispis logova u stderr | +| `--log-level` | | Nivo logovanja (DEBUG, INFO, WARN, ERROR) | + +--- + +## Varijable okruženja + +OpenCode se može konfigurirati pomoću varijabli okruženja. + +| Varijabla | Tip | Opis | +| ------------------------------------- | ------- | ------------------------------------------------------------------ | +| `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_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 | +| `OPENCODE_DISABLE_PRUNE` | boolean | Onemogući brisanje (pruning) starih podataka | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | Onemogući automatsko ažuriranje naslova terminala | +| `OPENCODE_PERMISSION` | string | Inline json konfiguracija dozvola | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | Onemogući podrazumijevane dodatke (plugins) | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | Onemogući automatsko preuzimanje LSP servera | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | Omogući eksperimentalne modele | +| `OPENCODE_DISABLE_AUTOCOMPACT` | boolean | Onemogući automatsko sažimanje konteksta | +| `OPENCODE_DISABLE_CLAUDE_CODE` | boolean | Onemogući čitanje iz `.claude` (prompt + vještine) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | Onemogući čitanje `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | Onemogući učitavanje `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | boolean | Onemogući dohvaćanje modela iz udaljenih izvora | +| `OPENCODE_FAKE_VCS` | string | Lažni VCS provajder za potrebe testiranja | +| `OPENCODE_DISABLE_FILETIME_CHECK` | boolean | Onemogući provjeru vremena datoteke radi optimizacije | +| `OPENCODE_CLIENT` | string | Identifikator klijenta (zadano na `cli`) | +| `OPENCODE_ENABLE_EXA` | boolean | Omogući Exa alate za web pretraživanje | +| `OPENCODE_SERVER_PASSWORD` | string | Omogući osnovnu autentifikaciju za `serve`/`web` | +| `OPENCODE_SERVER_USERNAME` | string | Poništi osnovno korisničko ime autentifikacije (zadano `opencode`) | +| `OPENCODE_MODELS_URL` | string | Prilagođeni URL za dohvaćanje konfiguracije modela | + +--- + +### Eksperimentalno + +Ove varijable okruženja omogućavaju eksperimentalne karakteristike koje se mogu promijeniti ili ukloniti. + +| Varijabla | Tip | Opis | +| ----------------------------------------------- | ------- | ------------------------------------------------- | +| `OPENCODE_EXPERIMENTAL` | boolean | Omogući sve eksperimentalne funkcije | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | Omogući otkrivanje ikona | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | Onemogući kopiranje pri odabiru u TUI | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number | Zadano vremensko ograničenje za bash naredbe u ms | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | number | Maksimalni izlazni tokeni za LLM odgovore | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolean | Omogući praćenje datoteka za cijeli direktorij | +| `OPENCODE_EXPERIMENTAL_OXFMT` | boolean | Omogući oxfmt formatter | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolean | Omogući eksperimentalni LSP alat | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | Onemogući praćenje datoteka | +| `OPENCODE_EXPERIMENTAL_EXA` | boolean | Omogući eksperimentalne Exa funkcije | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolean | Omogući eksperimentalnu provjeru tipa LSP | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolean | Omogući eksperimentalne Markdown funkcije | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolean | Omogući Plan mod | diff --git a/packages/web/src/content/docs/bs/commands.mdx b/packages/web/src/content/docs/bs/commands.mdx new file mode 100644 index 00000000000..388a4504bde --- /dev/null +++ b/packages/web/src/content/docs/bs/commands.mdx @@ -0,0 +1,316 @@ +--- +title: Komande +description: Kreirajte prilagođene komande za zadatke koji se ponavljaju. +--- + +Prilagođene komande vam omogućavaju da odredite prompt koji želite da pokrenete kada se ta naredba izvrši u TUI-ju. + +```bash frame="none" +/my-command +``` + +Prilagođene komande su dodatak ugrađenim komandama kao što su `/init`, `/undo`, `/redo`, `/share`, `/help`. [Saznajte više](/docs/tui#commands). + +--- + +## Kreiranje datoteka naredbi + +Kreirajte markdown fajlove u direktorijumu `commands/` da definišete prilagođene komande. +Kreiraj `.opencode/commands/test.md`: + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Frontmatter definira svojstva komande. Sadržaj postaje predložak. +Koristite komandu tako što ćete upisati `/` nakon čega slijedi naziv komande. + +```bash frame="none" +"/test" +``` + +--- + +## Konfiguracija + +Možete dodati prilagođene komande kroz OpenCode konfiguraciju ili kreiranjem markdown datoteka u direktoriju `commands/`. + +--- + +### JSON + +Koristite opciju `command` u svom OpenCode [config](/docs/config): + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Sada možete pokrenuti ovu naredbu u TUI: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +Također možete definirati komande koristeći markdown datoteke. Stavite ih u: + +- Globalno: `~/.config/opencode/commands/` +- Po projektu: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Ime markdown datoteke postaje ime naredbe. Na primjer, `test.md` vam omogućava da pokrenete: + +```bash frame="none" +/test +``` + +--- + +## Konfiguracija upita + +Promptovi za prilagođene komande podržavaju nekoliko posebnih čuvara mjesta i sintakse. + +--- + +### Argumenti + +Proslijedite argumente naredbama koristeći čuvar mjesta `$ARGUMENTS`. + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +Pokrenite naredbu s argumentima: + +```bash frame="none" +/component Button +``` + +I `$ARGUMENTS` će biti zamijenjen sa `Button`. +Također možete pristupiti pojedinačnim argumentima koristeći pozicione parametre: + +- `$1` - Prvi argument +- `$2` - Drugi argument +- `$3` - Treći argument +- I tako dalje... + +Na primjer: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +Pokrenite naredbu: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +Ovo zamjenjuje: + +- `$1` do `config.json` +- `$2` do `src` +- `$3` do `{ "key": "value" }` + +--- + +### Shell izlaz + +Koristite _!`command`_ da ubacite izlaz [bash command](/docs/tui#bash-commands) u svoj prompt. +Na primjer, da kreirate prilagođenu naredbu koja analizira pokrivenost testom: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +Ili da vidite nedavne promjene: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +Naredbe se pokreću u korijenskom direktoriju vašeg projekta i njihov izlaz postaje dio prompta. + +--- + +### Reference datoteka + +Uključite datoteke u svoju naredbu koristeći `@` nakon čega slijedi naziv datoteke. + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +Sadržaj datoteke se automatski uključuje u prompt. + +--- + +## Opcije + +Pogledajmo detaljno opcije konfiguracije. + +--- + +### Šablon + +Opcija `template` definira prompt koji će biti poslan LLM-u kada se naredba izvrši. + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +Ovo je **obavezna** opcija konfiguracije. + +--- + +### Opis + +Koristite opciju `description` da pružite kratak opis onoga što naredba radi. + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +Ovo se prikazuje kao opis u TUI-u kada unesete naredbu. + +--- + +### Agent + +Koristite `agent` konfiguraciju da opciono odredite koji [agent](/docs/agents) treba da izvrši ovu naredbu. +Ako je ovo [subagent](/docs/agents/#subagents) naredba će po defaultu pokrenuti pozivanje subagenta. +Da onemogućite ovo ponašanje, postavite `subtask` na `false`. + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +Ovo je **opciona** opcija konfiguracije. Ako nije navedeno, podrazumevano je vaš trenutni agent. + +--- + +### Podzadatak + +Koristite `subtask` boolean da prisilite naredbu da pokrene [subagent](/docs/agents/#subagents) pozivanje. +Ovo je korisno ako želite da naredba ne zagađuje vaš primarni kontekst i da će **primorati** agenta da djeluje kao subagent, +čak i ako je `mode` postavljeno na `primary` u konfiguraciji [agent](/docs/agents). + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +Ovo je **opciona** opcija konfiguracije. + +--- + +### Model + +Koristite `model` konfiguraciju da nadjačate zadani model za ovu naredbu. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Ovo je **opciona** opcija konfiguracije. + +--- + +## Ugrađene naredbe + +OpenCode uključuje nekoliko ugrađenih naredbi kao što su `/init`, `/undo`, `/redo`, `/share`, `/help`; [saznaj više](/docs/tui#commands). +:::note +Prilagođene komande mogu nadjačati ugrađene komande. +::: +Ako definirate prilagođenu naredbu s istim imenom, ona će nadjačati ugrađenu naredbu. diff --git a/packages/web/src/content/docs/bs/config.mdx b/packages/web/src/content/docs/bs/config.mdx new file mode 100644 index 00000000000..3e20f1890d4 --- /dev/null +++ b/packages/web/src/content/docs/bs/config.mdx @@ -0,0 +1,655 @@ +--- +title: Konfiguracija +description: Korištenje OpenCode JSON konfiguracije. +--- + +Možete konfigurirati OpenCode koristeći JSON konfiguracijski fajl. + +--- + +## Format + +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, +} +``` + +--- + +## Lokacije + +Možete postaviti svoju konfiguraciju na nekoliko različitih lokacija i one imaju drugačiji redoslijed prioriteta. + +:::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. + +--- + +### Redoslijed prioriteta + +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 +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. + ::: + +--- + +### 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" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +Možete omogućiti određene servere u vašoj lokalnoj konfiguraciji: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### 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. +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. +:::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. + +--- + +### Prilagođena konfiguracija + +Navedite prilagođenu putanju konfiguracijske datoteke koristeći varijablu okruženja `OPENCODE_CONFIG`. + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +Prilagođena konfiguracija se učitava između globalne i projektne konfiguracije po redoslijedu prioriteta. + +--- + +### Prilagođeni direktorij + +Navedite prilagođeni konfiguracijski direktorij koristeći `OPENCODE_CONFIG_DIR` varijablu okruženja. U ovom direktoriju će se tražiti agenti, komande, modovi i dodaci baš kao standardni `.opencode` direktorij, i trebali bi pratiti istu strukturu. + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +Prilagođeni direktorij se učitava nakon direktorija globalne konfiguracije i `.opencode`, tako da **može nadjačati** njihove postavke. + +--- + +## Šema + +Konfiguracijski fajl ima šemu koja je definirana u [**`opencode.ai/config.json`**](https://opencode.ai/config.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`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +Dostupne opcije: + +- `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. + +--- + +### Server + +Možete konfigurirati postavke servera za naredbe `opencode serve` i `opencode web` putem opcije `server`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +Dostupne opcije: + +- `port` - Port za slušanje. +- `hostname` - Hostname za slušanje. Kada je `mdns` omogućen i nije postavljeno ime hosta, podrazumevano je `0.0.0.0`. +- `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. + +--- + +### Alati + +Možete upravljati alatima koje LLM može koristiti putem opcije `tools`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[Saznajte više o alatima](/docs/tools) ovdje. + +--- + +### Model + +Možete konfigurirati dobavljače i modele koje želite koristiti u svojoj OpenCode konfiguraciji kroz opcije `provider`, `model` i `small_model`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +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" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `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). + +--- + +#### Opcije specifične za provajdere + +Neki provajderi podržavaju dodatne opcije konfiguracije osim generičkih postavki `timeout` i `apiKey`. + +##### Amazon Bedrock + +Amazon Bedrock podržava konfiguraciju specifičnu za AWS: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `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). + +--- + +### Tema + +Možete konfigurirati temu koju želite koristiti u svojoj OpenCode konfiguraciji putem opcije `theme`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[Saznajte više ovdje](/docs/themes). + +--- + +### Agenti + +Možete konfigurirati specijalizirane agente za određene zadatke putem opcije `agent`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +Također možete definirati agente koristeći markdown datoteke u `~/.config/opencode/agents/` ili `.opencode/agents/`. [Saznajte više ovdje](/docs/agents). + +--- + +### Zadani agent + +Možete postaviti zadanog agenta koristeći opciju `default_agent`. Ovo određuje koji se agent koristi kada nijedan nije eksplicitno specificiran. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +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. + +--- + +### Dijeljenje + +Možete konfigurirati funkciju [share](/docs/share) putem opcije `share`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +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`. + +--- + +### Naredbe + +Možete konfigurirati prilagođene naredbe za ponavljanje zadataka putem opcije `command`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +Također možete definirati naredbe koristeći markdown fajlove u `~/.config/opencode/commands/` ili `.opencode/commands/`. [Saznajte više ovdje](/docs/commands). + +--- + +### Prečice tipki + +Možete prilagoditi svoje veze tipki putem opcije `keybinds`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[Saznajte više ovdje](/docs/keybinds). + +--- + +### Automatsko ažuriranje + +OpenCode će automatski preuzeti sva nova ažuriranja kada se pokrene. Ovo možete onemogućiti opcijom `autoupdate`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +Ako ne želite ažuriranja, ali želite biti obaviješteni kada nova verzija bude dostupna, postavite `autoupdate` na `"notify"`. +Imajte na umu da ovo funkcionira samo ako nije instalirano pomoću upravitelja paketa kao što je Homebrew. + +--- + +### Formateri + +Možete konfigurirati formatere koda putem opcije `formatter`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[Saznajte više o formaterima](/docs/formatters) ovdje. + +--- + +### 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" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[Saznajte više o dozvolama](/docs/permissions) ovdje. + +--- + +### Sažimanje + +Možete kontrolirati ponašanje sažimanja konteksta putem opcije `compaction`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto` - Automatski sažimanje sesije kada je kontekst pun (podrazumevano: `true`). +- `prune` - Uklonite stare izlaze alata da sačuvate tokene (podrazumevano: `true`). + +--- + +### Promatrač (Watcher) + +Možete konfigurirati obrasce ignoriranja promatrača datoteka putem opcije `watcher`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +Obrasci prate glob sintaksu. Koristite ovo da isključite bučne direktorije iz pregleda datoteka. + +--- + +### MCP serveri + +Možete konfigurirati MCP servere koje želite koristiti putem opcije `mcp`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[Saznajte više ovdje](/docs/mcp-servers). + +--- + +### 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" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[Saznajte više ovdje](/docs/plugins). + +--- + +### Uputstva + +Možete konfigurirati upute za model koji koristite putem opcije `instructions`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Ovo uzima niz putanja i glob uzoraka do datoteka instrukcija. [Saznajte više o pravilima ovdje](/docs/rules). + +--- + +### Onemogućeni provajderi + +Možete onemogućiti dobavljače koji se automatski učitavaju preko opcije `disabled_providers`. Ovo je korisno kada želite spriječiti učitavanje određenih provajdera čak i ako su njihovi vjerodajnici dostupni. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::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. +- Neće se učitati čak i ako su API ključevi konfigurirani putem `/connect` naredbe. +- Modeli dobavljača se neće pojaviti na listi za odabir modela. + +--- + +### Omogućeni provajderi + +Možete odrediti listu dozvoljenih dobavljača putem opcije `enabled_providers`. Kada se podesi, samo navedeni provajderi će biti omogućeni, a svi ostali će biti zanemareni. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +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. + +--- + +### Eksperimentalno + +Ključ `experimental` sadrži opcije koje su u aktivnom razvoju. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +Eksperimentalne opcije nisu stabilne. Mogu se promijeniti ili ukloniti bez prethodne najave. +::: + +--- + +## Varijable + +Možete koristiti zamjenu varijabli u vašim konfiguracijskim datotekama da biste referencirali varijable okruženja i sadržaj datoteke. + +--- + +### Varijable okruženja + +Koristite `{env:VARIABLE_NAME}` za zamjenu varijabli okruženja: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +Ako varijabla okruženja nije postavljena, bit će zamijenjena praznim nizom. + +--- + +### Datoteke + +Koristite `{file:path/to/file}` da zamijenite sadržaj fajla: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +Putanja fajla mogu biti: + +- U odnosu na direktorij konfiguracijskih datoteka +- Ili apsolutne staze koje počinju sa `/` ili `~` + 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 new file mode 100644 index 00000000000..e452ce6a562 --- /dev/null +++ b/packages/web/src/content/docs/bs/custom-tools.mdx @@ -0,0 +1,169 @@ +--- +title: Prilagođeni alati +description: Kreirajte alate koje LLM može pozvati u otvorenom kodu. +--- + +Prilagođeni alati su funkcije koje kreirate i koje LLM može pozvati tokom razgovora. Oni rade zajedno sa [ugrađenim opencode](/docs/tools) alatima kao što su `read`, `write` i `bash`. + +--- + +## Kreiranje alata + +Alati su definisani kao **TypeScript** ili **JavaScript** datoteke. Međutim, definicija alata može pozvati skripte napisane na **bilo kom jeziku** — TypeScript ili JavaScript se koriste samo za samu definiciju alata. + +--- + +### Lokacija + +Mogu se definisati: + +- Lokalno postavljanjem u `.opencode/tools/` direktorij vašeg projekta. +- Ili globalno, postavljanjem u `~/.config/opencode/tools/`. + +--- + +### Struktura + +Najlakši način za kreiranje alata je korištenje pomoćnika `tool()` koji pruža sigurnost tipa i validaciju. + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +**ime datoteke** postaje **naziv alata**. Gore navedeno je kreirano pomoću `database` alata. + +--- + +#### Više alata po datoteci + +Također možete izvesti više alata iz jedne datoteke. Svaki izvoz postaje **poseban alat** pod nazivom **`_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +Ovo stvara dva alata: `math_add` i `math_multiply`. + +--- + +### Argumenti + +Možete koristiti `tool.schema`, što je samo [Zod](https://zod.dev), da definirate tipove argumenata. + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +Također možete direktno uvesti [Zod](https://zod.dev) i vratiti običan objekt: + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### Kontekst + +Alati primaju kontekst o trenutnoj sesiji: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +Koristite `context.directory` za radni direktorij sesije. +Koristite `context.worktree` za korijen git radnog stabla. + +--- + +## Primjeri + +### Pisanje alata u Python-u + +Možete pisati svoje alate na bilo kom jeziku koji želite. Evo primjera koji zbraja dva broja koristeći Python. +Prvo kreirajte alat kao Python skriptu: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +Zatim kreirajte definiciju alata koja ga poziva: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +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/ecosystem.mdx b/packages/web/src/content/docs/bs/ecosystem.mdx new file mode 100644 index 00000000000..c7dea0c6e2d --- /dev/null +++ b/packages/web/src/content/docs/bs/ecosystem.mdx @@ -0,0 +1,72 @@ +--- +title: Ekosistem +description: Projekti i integracije izgrađeni uz OpenCode. +--- + +Kolekcija projekata zajednice izgrađenih na OpenCode. +:::note +Želite li na ovu listu dodati svoj OpenCode projekat? Pošaljite PR. +::: +Također možete pogledati [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) i [opencode.cafe](https://opencode.cafe), zajednicu koja spaja ekosistem i zajednicu. + +--- + +## Dodaci + +| Ime | Opis | +| --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | --- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------- | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | Automatski pokrenite OpenCode sesije u izoliranim Daytona sandboxovima uz git sinhronizaciju i preglede uživo | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | Automatski ubacite Helicone zaglavlja sesije za grupisanje zahtjeva | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | Automatski ubaci TypeScript/Svelte tipove u čitanje datoteka pomoću alata za pretraživanje | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | Koristite svoju ChatGPT Plus/Pro pretplatu umjesto API kredita | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | Koristite svoj postojeći Gemini plan umjesto API naplate | +| [opencodentigravity-auth](https://github.com/NoeFabris/opencodentigravity-auth) | Koristite besplatne modele Antigravity umjesto API naplate | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Izolacija devcontainer-a s više grana s plitkim klonovima i automatski dodijeljenim portovima | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Google Antigravity OAuth dodatak, s podrškom za Google pretraživanje i robusnijim API rukovanjem | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Optimizirajte korištenje tokena smanjenjem izlaza zastarjelih alata | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Dodajte podršku za izvorno web pretraživanje za podržane provajdere sa stilom utemeljenim na Googleu | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Omogućuje AI agentima da pokreću pozadinske procese u PTY-u, šalju im interaktivni ulaz. | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Upute za neinteraktivne naredbe ljuske - sprječava visi od TTY ovisnih operacija | | [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Pratite upotrebu OpenCode sa Wakatime | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Očistite tabele umanjenja vrijednosti koje su izradili LLM | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | 10x brže uređivanje koda s Morph Fast Apply API-jem i markerima za lijeno uređivanje | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Pozadinski agenti, unapred izgrađeni LSP/AST/MCP alati, kurirani agenti, kompatibilni sa Claude Code | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | Obavještenja na radnoj površini i zvučna upozorenja za OpenCode sesije | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Obavještenja na radnoj površini i zvučna upozorenja za dozvole, završetak i događaje greške | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | Automatsko imenovanje Zellij sesije na bazi OpenCode konteksta | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Dozvolite OpenCode agentima da lijeno učitavaju upite na zahtjev uz otkrivanje vještina i ubrizgavanje | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Trajna memorija kroz sesije koristeći Supermemory | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Interaktivni pregled plana s vizualnim napomenama i privatnim/offline dijeljenjem | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Proširite opencode /komande u moćan sistem orkestracije sa granularnom kontrolom toka | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | Planirajte ponavljajuće poslove koristeći launchd (Mac) ili systemd (Linux) sa cron sintaksom | | [micode](https://github.com/vtemian/micode) | Strukturirana Brainstorm → Plan → Implementacija toka rada uz kontinuitet sesije | +| [octto](https://github.com/vtemian/octto) | Interaktivno korisničko sučelje pretraživača za AI brainstorming sa obrascima za više pitanja | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | Pozadinski agenti u stilu Claudea s asinhroniziranim delegiranjem i postojanošću konteksta | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | Notifikacije izvornog OS-a za OpenCode – znajte kada se zadaci dovrše | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | Uvezeni višeagentni orkestracijski pojas – 16 komponenti, jedna instalacija | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | Git radna stabla bez trenja za OpenCode | + +--- + +## Projekti + +| Ime | Opis | +| ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- | +| [kimaki](https://github.com/remorses/kimaki) | Discord bot za kontrolu OpenCode sesija, izgrađen na SDK | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Neovim dodatak za upite svjestan uređivača, izgrađen na API | +| [portal](https://github.com/hosenur/portal) | Mobilni korisnički interfejs za OpenCode preko Tailscale/VPN | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | Predložak za izgradnju OpenCode dodataka | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Neovim frontend za opencode - terminal baziran AI agent za kodiranje | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Vercel AI SDK dobavljač za korištenje OpenCode putem @opencodei/sdk | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | Web / Desktop App i VS Code Extension za OpenCode | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Obsidian dodatak koji ugrađuje OpenCode u Obsidian-ov UI | +| [OpenWork](https://github.com/different-ai/openwork) | Alternativa otvorenog koda Claudeu Coworku, pokretana pomoću OpenCode | +| [ocx](https://github.com/kdcokenny/ocx) | OpenCode menadžer ekstenzija sa prenosivim, izolovanim profilima. | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | Desktop, Web, Mobile i Remote Client aplikacija za OpenCode | + +--- + +## Agenti + +| Ime | Opis | +| ------------------------------------------------------------- | --------------------------------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | Modularni AI agenti i komande za strukturirani razvoj | +| [opencodegents](https://github.com/darrenhinde/opencodegents) | Konfiguracije, upiti, agenti i dodaci za poboljšane tokove rada | diff --git a/packages/web/src/content/docs/bs/enterprise.mdx b/packages/web/src/content/docs/bs/enterprise.mdx new file mode 100644 index 00000000000..5851498aeb5 --- /dev/null +++ b/packages/web/src/content/docs/bs/enterprise.mdx @@ -0,0 +1,165 @@ +--- +title: Za preduzeća +description: Sigurno korištenje OpenCode u vašoj organizaciji. +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +OpenCode Enterprise je za organizacije koje žele osigurati da njihov kod i podaci nikada ne napuštaju njihovu infrastrukturu. To omogućava centralizovana konfiguracija koja se integriše s vašim SSO-om i internim AI gateway-om. + +:::note +OpenCode ne pohranjuje nijedan vaš kod ili kontekstualne podatke. +::: + +Da započnete s OpenCode Enterprise: + +1. Uradite interni probni period sa svojim timom. +2. **Kontaktirajte nas** da razgovaramo o cijenama i opcijama implementacije. + +--- + +## Proba + +OpenCode je otvorenog koda i ne pohranjuje vaš kod niti kontekstualne podatke, tako da vaši developeri mogu jednostavno [započeti](/docs/) i provesti probu. + +--- + +### Rukovanje podacima + +**OpenCode ne pohranjuje vaš kod ni kontekstualne podatke.** Sva obrada se odvija lokalno ili putem direktnih API poziva vašem AI provajderu. + +To znači da, sve dok koristite provajdera kojem vjerujete ili interni AI gateway, OpenCode možete koristiti sigurno. + +Jedina iznimka je opcionalna funkcija `/share`. + +--- + +#### Dijeljenje razgovora + +Ako korisnik uključi funkciju `/share`, razgovor i povezani podaci šalju se servisu koji koristimo za hosting ovih share stranica na opencode.ai. + +Podaci se trenutno serviraju kroz edge mrežu našeg CDN-a i keširaju se blizu korisnika. + +Preporučujemo da ovo onemogućite tokom probe. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[Saznajte više o dijeljenju](/docs/share). + +--- + +### Vlasništvo koda + +**Vi posjedujete sav kod koji OpenCode proizvede.** Nema ograničenja licenciranja niti zahtjeva za vlasništvo. + +--- + +## Cijene + +Koristimo model naplate po sjedištu za OpenCode Enterprise. Ako imate vlastiti LLM gateway, ne naplaćujemo korištene tokene. Za više detalja o cijenama i opcijama implementacije, **kontaktirajte nas**. + +--- + +## Postavljanje + +Nakon što završite probni period i spremni ste koristiti OpenCode u svojoj organizaciji, možete **kontaktirati nas** da razgovaramo o cijenama i opcijama implementacije. + +--- + +### Centralna konfiguracija + +Možemo postaviti OpenCode da koristi jednu centralnu konfiguraciju za cijelu organizaciju. + +Ta centralizovana konfiguracija može se integrisati s vašim SSO provajderom i osigurava da svi korisnici pristupaju samo vašem internom AI gateway-u. + +--- + +### SSO integracija + +Kroz centralnu konfiguraciju, OpenCode se može integrisati sa SSO provajderom vaše organizacije za autentifikaciju. + +To omogućava OpenCode da dobije vjerodajnice za interni AI gateway kroz vaš postojeći sistem upravljanja identitetom. + +--- + +### Interni AI gateway + +Uz centralnu konfiguraciju, OpenCode se može podesiti da koristi samo vaš interni AI gateway. + +Također možete onemogućiti sve druge AI provajdere, čime osiguravate da svi zahtjevi prolaze kroz odobrenu infrastrukturu vaše organizacije. + +--- + +### Samostalno hostovanje + +Iako preporučujemo onemogućavanje share stranica kako biste osigurali da podaci nikada ne napuštaju vašu organizaciju, možemo vam pomoći i da ih samostalno hostujete na vlastitoj infrastrukturi. + +Ovo je trenutno na našoj mapi puta. Ako ste zainteresovani, **javite nam**. + +--- + +## Često postavljana pitanja + +

+Šta je OpenCode Enterprise? + +OpenCode Enterprise je za organizacije koje žele osigurati da njihov kod i podaci nikada ne napuštaju njihovu infrastrukturu. To omogućava centralizovana konfiguracija koja se integriše s vašim SSO-om i internim AI gateway-om. + +
+ +
+Kako započeti s OpenCode Enterprise? + +Jednostavno započnite internu probu sa svojim timom. OpenCode po defaultu ne pohranjuje vaš kod ni kontekstualne podatke, što olakšava početak. + +Zatim **kontaktirajte nas** da razgovaramo o cijenama i opcijama implementacije. + +
+ +
+Kako funkcionišu enterprise cijene? + +Nudimo enterprise cijene po sjedištu. Ako imate vlastiti LLM gateway, ne naplaćujemo korištene tokene. Za više detalja, **kontaktirajte nas** za prilagođenu ponudu prema potrebama vaše organizacije. + +
+ +
+Jesu li moji podaci sigurni uz OpenCode Enterprise? + +Da. OpenCode ne pohranjuje vaš kod niti kontekstualne podatke. Sva obrada se odvija lokalno ili putem direktnih API poziva vašem AI provajderu. Uz centralnu konfiguraciju i SSO integraciju, vaši podaci ostaju sigurni unutar infrastrukture vaše organizacije. + +
+ +
+Možemo li koristiti vlastiti privatni NPM registar? + +OpenCode podržava privatne npm registre kroz Bunovu izvornu podršku za `.npmrc` datoteku. Ako vaša organizacija koristi privatni registar, kao što je JFrog Artifactory, Nexus ili slično, osigurajte da su developeri autentifikovani prije pokretanja OpenCode. + +Da postavite autentifikaciju s privatnim registrom: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +Ovo kreira `~/.npmrc` s detaljima za autentifikaciju. OpenCode će to automatski prepoznati. + +:::caution +Morate biti prijavljeni na privatni registar prije pokretanja OpenCode. +::: + +Alternativno, možete ručno konfigurisati `.npmrc` datoteku: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +Developeri moraju biti prijavljeni na privatni registar prije pokretanja OpenCode kako bi se paketi mogli instalirati iz vašeg enterprise registra. + +
diff --git a/packages/web/src/content/docs/bs/formatters.mdx b/packages/web/src/content/docs/bs/formatters.mdx new file mode 100644 index 00000000000..1b70e0906aa --- /dev/null +++ b/packages/web/src/content/docs/bs/formatters.mdx @@ -0,0 +1,123 @@ +--- +title: Formateri +description: OpenCode koristi formatere specifične za jezik. +--- + +OpenCode automatski formatira datoteke nakon što su napisane ili uređene pomoću formatera specifičnih za jezik. Ovo osigurava da kod koji se generira prati stilove koda vašeg projekta. + +--- + +## Ugrađeni + +OpenCode dolazi sa nekoliko ugrađenih formatera za popularne jezike i okvire. Ispod je lista formatera, podržanih ekstenzija datoteka i naredbi ili opcija konfiguracije koje su mu potrebne. +| Formatter | Ekstenzije | Zahtjevi +|-------------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| gofmt | .go | `gofmt` komanda dostupna | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | `mix` komanda dostupna | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml i [više](https://prettier.io/docs/en/index.html) | `prettier` zavisnost u `package.json` | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml i [više](https://biomejs.dev/) | `biome.json(c)` konfiguracijski fajl | +| zig | .zig, .zon | `zig` komanda dostupna | +| clang-format | .c, .cpp, .h, .hpp, .ino i [više](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` konfiguracijski fajl | +| ktlint | .kt, .kts | `ktlint` komanda dostupna | +| ruff | .py, .pyi | `ruff` komanda dostupna sa konfiguracijom | +| rustfmt | .rs | `rustfmt` komanda dostupna | +| cargofmt | .rs | `cargo fmt` komanda dostupna | +| uv | .py, .pyi | `uv` komanda dostupna || rubocop | .rb, .rake, .gemspec, .ru | `rubocop` komanda dostupna | +| standardrb | .rb, .rake, .gemspec, .ru | `standardrb` komanda dostupna | +| htmlbeautifier | .erb, .html.erb | `htmlbeautifier` komanda dostupna | +| air | .R | `air` komanda dostupna | +| dart | .dart | `dart` komanda dostupna | +| ocamlformat | .ml, .mli | `ocamlformat` komanda dostupna i `.ocamlformat` konfiguracioni fajl | +| terraform | .tf, .tfvars | `terraform` komanda dostupna | +| gleam | .bleam | `gleam` komanda dostupna | +| nixfmt | .nix | `nixfmt` komanda dostupna | +| shfmt | .sh, .bash | `shfmt` komanda dostupna | +| pint | .php | `laravel/pint` zavisnost u `composer.json` || oxfmt (Eksperimentalno) | .js, .jsx, .ts, .tsx | `oxfmt` zavisnost u `package.json` i [eksperimentalna env varijabla flag](/docs/cli/#experimental) | +| ormolu | .hs | `ormolu` komanda dostupna | +Dakle, ako vaš projekat ima `prettier` u vašem `package.json`, OpenCode će ga automatski koristiti. + +--- + +## Kako radi + +Kada OpenCode piše ili uređuje datoteku, on: + +1. Provjerava ekstenziju datoteke prema svim omogućenim formaterima. +2. Pokreće odgovarajuću naredbu za formatiranje na datoteci. +3. Automatski primjenjuje promjene formatiranja. + Ovaj proces se događa u pozadini, osiguravajući da se vaši stilovi koda održavaju bez ikakvih ručnih koraka. + +--- + +## Konfiguracija + +Možete prilagoditi formatere kroz `formatter` odjeljak u vašoj OpenCode konfiguraciji. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +Svaka konfiguracija formatera podržava sljedeće: +| Svojstvo | Vrsta | Opis +|------------- | -------- | ------------------------------------------------------- | +| `disabled` | boolean | Postavite ovo na `true` da onemogućite formater | +| `command` | string[] | Naredba za pokretanje za formatiranje | +| `environment` | objekt | Varijable okruženja koje treba postaviti prilikom pokretanja formatera | +| `extensions` | string[] | Ekstenzije datoteka koje ovaj formater treba da obrađuje | +Pogledajmo neke primjere. + +--- + +### Onemogućavanje formatera + +Da onemogućite **sve** formatere globalno, postavite `formatter` na `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +Da onemogućite **specifični** formater, postavite `disabled` na `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### Prilagođeni formateri + +Možete nadjačati ugrađene formatere ili dodati nove navođenjem naredbe, varijabli okruženja i ekstenzija datoteke: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +**`$FILE` čuvar mjesta** u naredbi će biti zamijenjen putanjom do datoteke koja se formatira. diff --git a/packages/web/src/content/docs/bs/github.mdx b/packages/web/src/content/docs/bs/github.mdx new file mode 100644 index 00000000000..5946b344290 --- /dev/null +++ b/packages/web/src/content/docs/bs/github.mdx @@ -0,0 +1,311 @@ +--- +title: GitHub +description: Koristite OpenCode u GitHub problemima i zahtjevima za povlačenjem. +--- + +OpenCode se integriše sa vašim GitHub tokovom rada. Spomenite `/opencode` ili `/oc` u svom komentaru i OpenCode će izvršiti zadatke unutar vašeg GitHub Actions runnera. + +--- + +## Funkcije + +- **Problemi trijaže**: Zamolite OpenCode da ispita problem i objasni vam ga. +- **Popravi i implementiraj**: Zamolite OpenCode da popravi problem ili implementira funkciju. I radit će u novoj poslovnici i dostavljati PR sa svim promjenama. +- **Secure**: OpenCode se pokreće unutar pokretača vašeg GitHub-a. + +--- + +## Instalacija + +Pokrenite sljedeću naredbu u projektu koji se nalazi u GitHub repo: + +```bash +opencode github install +``` + +Ovo će vas provesti kroz instalaciju GitHub aplikacije, kreiranje toka posla i postavljanje tajni. + +--- + +### Ručno podešavanje + +Ili ga možete postaviti ručno. + +1. **Instalirajte GitHub aplikaciju** + Idite na [**github.com/apps/opencodegent**](https://github.com/apps/opencodegent). Uvjerite se da je instaliran na ciljnom spremištu. +2. **Dodajte radni tok** + Dodajte sljedeći fajl toka posla u `.github/workflows/opencode.yml` u svoj repo. Obavezno postavite odgovarajuće `model` i potrebne API ključeve u `env`. + +```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx +``` + +3. **Sačuvaj API ključeve u tajne** + U **postavkama** organizacije ili projekta proširite **Tajne i varijable** na lijevoj strani i odaberite **Radnje**. I dodajte potrebne API ključeve. + +--- + +## Konfiguracija + +- `model`: Model za korištenje s OpenCode. Uzima format `provider/model`. Ovo je **obavezno**. +- `agent`: Agent za korištenje. Mora biti primarni agent. Vraća se na `default_agent` iz konfiguracije ili `"build"` ako nije pronađen. +- `share`: Da li dijeliti OpenCode sesiju. Podrazumevano je **true** za javna spremišta. +- `prompt`: Opcioni prilagođeni upit za nadjačavanje zadanog ponašanja. Koristite ovo da prilagodite kako OpenCode obrađuje zahtjeve. +- `token`: Opcionalni GitHub pristupni token za izvođenje operacija kao što su kreiranje komentara, upisivanje promjena i otvaranje zahtjeva za povlačenjem. OpenCode prema zadanim postavkama koristi token za pristup instalaciji iz aplikacije OpenCode GitHub, tako da se urezivanje, komentari i zahtjevi za povlačenjem pojavljuju kao da dolaze iz aplikacije. + Alternativno, možete koristiti GitHub Action runner [ugrađeni `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) bez instaliranja OpenCode GitHub aplikacije. Samo se pobrinite da date potrebna odobrenja u svom toku rada: + +```yaml +permissions: + id-token: write + contents: write + pull-requests: write + issues: write +``` + +Također možete koristiti [Personal Access Tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) ako želite. + +--- + +## Podržani događaji + +OpenCode se može pokrenuti sljedećim GitHub događajima: +| Vrsta događaja | Pokrenuo | Detalji +|----------------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| `issue_comment` | Komentirajte problem ili PR | Navedite `/opencode` ili `/oc` u svom komentaru. OpenCode čita kontekst i može kreirati grane, otvarati PR-ove ili odgovarati. | +| `pull_request_review_comment` | Komentirajte određene linije koda u PR-u | Navedite `/opencode` ili `/oc` dok pregledavate kod. OpenCode prima putanju datoteke, brojeve redova i kontekst razlike. | +| `issues` | Broj otvoren ili uređen | Automatski pokrenite OpenCode kada se problemi kreiraju ili modificiraju. Zahtijeva `prompt` unos. | +| `pull_request` | PR otvoren ili ažuriran | Automatski pokrenite OpenCode kada se PR-ovi otvore, sinkroniziraju ili ponovo otvore. Korisno za automatske recenzije. | +| `schedule` | Cron baziran raspored | Pokrenite OpenCode prema rasporedu. Zahtijeva `prompt` unos. Izlaz ide u dnevnike i PR-ove (nema problema za komentarisanje). | +| `workflow_dispatch` | Ručni okidač iz GitHub korisničkog sučelja | Aktivirajte OpenCode na zahtjev preko kartice Akcije. Zahtijeva `prompt` unos. Izlaz ide u dnevnike i PR-ove. | + +### Primjer rasporeda + +Pokrenite OpenCode po rasporedu za obavljanje automatiziranih zadataka: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +Za zakazane događaje, unos `prompt` je **potreban** jer nema komentara za izvlačenje instrukcija. Planirani tokovi posla se pokreću bez korisničkog konteksta za provjeru dozvola, tako da tok posla mora odobriti `contents: write` i `pull-requests: write` ako očekujete da će OpenCode kreirati grane ili PR-ove. + +--- + +### Primjer zahtjeva za povlačenjem + +Automatski pregledajte PR-ove kada se otvore ili ažuriraju: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Za `pull_request` događaje, ako nije naveden `prompt`, OpenCode podrazumevano pregledava zahtjev za povlačenjem. + +--- + +### Primjer trijaže problema + +Automatski triažirajte nove probleme. Ovaj primjer filtrira na račune starije od 30 dana radi smanjenja neželjene pošte: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +Za `issues` događaje, `prompt` unos je **potreban** jer nema komentara za izvlačenje instrukcija. + +--- + +## Prilagođeni upiti + +Zaobiđite zadani prompt da biste prilagodili ponašanje OpenCode za vaš tok posla. + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Ovo je korisno za provođenje specifičnih kriterija pregleda, standarda kodiranja ili fokusnih područja relevantnih za vaš projekt. + +--- + +## Primjeri + +Evo nekoliko primjera kako možete koristiti OpenCode u GitHub. + +- **Objasnite problem** + Dodajte ovaj komentar u GitHub izdanje. + +``` + /opencode explain this issue +``` + +OpenCode će pročitati cijelu temu, uključujući sve komentare, i odgovoriti s jasnim objašnjenjem. + +- **Popravi problem** + U izdanju na GitHub-u recite: + +``` + /opencode fix this +``` + +I OpenCode će kreirati novu granu, implementirati promjene i otvoriti PR sa promjenama. + +- **Pregledajte PR-ove i izvršite izmjene** + Ostavite sljedeći komentar na GitHub PR-u. + +``` + Delete the attachment from S3 when the note is removed /oc +``` + +OpenCode će implementirati traženu promjenu i posvetiti je istom PR-u. + +- **Pregledajte određene linije koda** + Ostavite komentar direktno na linije koda u PR kartici "Files". OpenCode automatski detektuje datoteku, brojeve redova i kontekst razlike kako bi pružio precizne odgovore. + +``` + [Comment on specific lines in Files tab] + /oc add error handling here +``` + +Kada komentarišete određene linije, OpenCode prima: + +- Tačan fajl se pregleda +- Specifične linije koda +- Okolni diff kontekst +- Informacije o broju linije + Ovo omogućava više ciljanih zahtjeva bez potrebe za ručno specificiranjem putanja datoteka ili brojeva linija. diff --git a/packages/web/src/content/docs/bs/gitlab.mdx b/packages/web/src/content/docs/bs/gitlab.mdx new file mode 100644 index 00000000000..a819ef5fd4b --- /dev/null +++ b/packages/web/src/content/docs/bs/gitlab.mdx @@ -0,0 +1,188 @@ +--- +title: GitLab +description: Koristite OpenCode u GitLab problemima i zahtjevima za spajanje. +--- + +OpenCode se integriše sa vašim GitLab radnim tokom kroz vaš GitLab CI/CD cevovod ili sa GitLab Duo. +U oba slučaja, OpenCode će se pokrenuti na vašim GitLab pokretačima. + +--- + +## GitLab CI + +OpenCode radi u redovnom GitLab cevovodu. Možete ga ugraditi u cjevovod kao [CI komponenta](https://docs.gitlab.com/ee/ci/components/) +Ovdje koristimo CI/CD komponentu kreiranu u zajednici za OpenCode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### Funkcije + +- **Koristite prilagođenu konfiguraciju po poslu**: Konfigurirajte OpenCode s prilagođenim konfiguracijskim direktorijem, na primjer `./config/#custom-directory` da omogućite ili onemogućite funkcionalnost po OpenCode pozivanju. +- **Minimalno podešavanje**: CI komponenta postavlja OpenCode u pozadini, samo trebate kreirati OpenCode konfiguraciju i početnu prompt. +- **Fleksibilno**: CI komponenta podržava nekoliko ulaza za prilagođavanje njenog ponašanja + +--- + +### Podešavanje + +1. Sačuvajte JSON za autentifikaciju OpenCode kao CI varijable okruženja tipa datoteke pod **Postavke** > **CI/CD** > **Varijable**. Obavezno ih označite kao "Maskirane i skrivene". +2. Dodajte sljedeće u svoju `.gitlab-ci.yml` datoteku. + +```yaml title=".gitlab-ci.yml" +include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" +``` + +Za više unosa i slučajeva upotrebe [pogledajte dokumente docs](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) za ovu komponentu. + +--- + +## GitLab Duo + +OpenCode se integriše sa vašim GitLab tokovom rada. +Spomenite `@opencode` u komentaru i OpenCode će izvršiti zadatke unutar vašeg GitLab CI cevovoda. + +--- + +### Funkcije + +- **Problemi trijaže**: Zamolite OpenCode da ispita problem i objasni vam ga. +- **Popravi i implementiraj**: Zamolite OpenCode da popravi problem ili implementira funkciju. + To će kreirati novu granu i pokrenuti zahtjev za spajanje s promjenama. +- **Secure**: OpenCode radi na vašim GitLab pokretačima. + +--- + +### Podešavanje + +OpenCode radi u vašem GitLab CI/CD cevovodu, evo šta će vam trebati da ga postavite: +:::tip +Pogledajte [**GitLab dokumente**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) za ažurirane upute. +::: + +1. Konfigurirajte svoje GitLab okruženje +2. Postavite CI/CD +3. Nabavite API ključ dobavljača AI modela +4. Kreirajte nalog usluge +5. Konfigurirajte CI/CD varijable +6. Kreirajte konfiguracijski fajl toka, evo primjera: + +
+ + Konfiguracija toka + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +Možete vidjeti [GitLab CLI agenti docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) za detaljna uputstva. + +--- + +### Primjeri + +Evo nekoliko primjera kako možete koristiti OpenCode u GitLab. +:::tip +Možete konfigurirati da koristite drugu frazu okidača od `@opencode`. +::: + +- **Objasnite problem** + Dodajte ovaj komentar u izdanje GitLaba. + +``` + @opencode explain this issue +``` + +OpenCode će pročitati problem i odgovoriti jasnim objašnjenjem. + +- **Reši problem** + U izdanju GitLaba recite: + +``` + @opencode fix this +``` + +OpenCode će kreirati novu granu, implementirati promjene i otvoriti zahtjev za spajanje s promjenama. + +- **Pregledajte zahtjeve za pridruživanje** + Ostavite sljedeći komentar na zahtjev za spajanje GitLab-a. + +``` + @opencode review this merge request +``` + +OpenCode će pregledati zahtjev za spajanje i dati povratne informacije. diff --git a/packages/web/src/content/docs/bs/ide.mdx b/packages/web/src/content/docs/bs/ide.mdx new file mode 100644 index 00000000000..a455b91ee26 --- /dev/null +++ b/packages/web/src/content/docs/bs/ide.mdx @@ -0,0 +1,47 @@ +--- +title: IDE +description: Ekstenzija OpenCode za VS Code, Cursor i druge IDE +--- + +OpenCode se integriše sa VS kodom, Cursor-om ili bilo kojim IDE-om koji podržava terminal. Samo pokrenite `opencode` u terminalu da započnete. + +--- + +## Korištenje + +- **Brzo pokretanje**: Koristite `Cmd+Esc` (Mac) ili `Ctrl+Esc` (Windows/Linux) da otvorite OpenCode u prikazu podijeljenog terminala ili fokusirajte postojeću terminalsku sesiju ako je već pokrenuta. +- **Nova sesija**: Koristite `Cmd+Shift+Esc` (Mac) ili `Ctrl+Shift+Esc` (Windows/Linux) da započnete novu OpenCode terminalsku sesiju, čak i ako je ona već otvorena. Takođe možete kliknuti na dugme OpenCode u korisničkom sučelju. +- **Svijest o kontekstu**: Automatski dijelite svoj trenutni odabir ili karticu s OpenCode. +- **Prečice za referencu datoteka**: Koristite `Cmd+Option+K` (Mac) ili `Alt+Ctrl+K` (Linux/Windows) za umetanje referenci datoteka. Na primjer, `@File#L37-42`. + +--- + +## Instalacija + +Da biste instalirali OpenCode na VS Code i popularne viljuške kao što su Cursor, Windsurf, VSCodium: + +1. Otvorite VS Code +2. Otvorite integrirani terminal +3. Pokrenite `opencode` - ekstenzija se automatski instalira + Ako s druge strane želite da koristite svoj vlastiti IDE kada pokrenete `/editor` ili `/export` iz TUI-ja, morat ćete postaviti `export EDITOR="code --wait"`. [Saznajte više](/docs/tui/#editor-setup). + +--- + +### Ručna instalacija + +Potražite **OpenCode** na Extension Marketplaceu i kliknite na **Instaliraj**. + +--- + +### Rješavanje problema + +Ako se ekstenzija ne uspije automatski instalirati: + +- Uvjerite se da koristite `opencode` u integriranom terminalu. +- Potvrdite da je CLI za vaš IDE instaliran: + - Za VS kod: `code` naredbu + - Za Cursor: `cursor` naredba + - Za Windsurf: `windsurf` komanda + - Za VSCodium: `codium` komanda + - Ako ne, pokrenite `Cmd+Shift+P` (Mac) ili `Ctrl+Shift+P` (Windows/Linux) i potražite "Shell Command: Install 'code' command in PATH" (ili ekvivalent za vaš IDE) +- Osigurajte da VS Code ima dozvolu za instaliranje ekstenzija diff --git a/packages/web/src/content/docs/bs/index.mdx b/packages/web/src/content/docs/bs/index.mdx new file mode 100644 index 00000000000..5d21e994f9b --- /dev/null +++ b/packages/web/src/content/docs/bs/index.mdx @@ -0,0 +1,322 @@ +--- +title: Uvod +description: Započnite sa OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**OpenCode**](/) je AI agent za kodiranje otvorenog koda. Dostupan je kao interfejs baziran na terminalu, desktop aplikacija ili IDE ekstenzija. +![OpenCode TUI sa opencode temom](../../../assets/lander/screenshot.png) +Hajde da počnemo. + +--- + +#### Preduvjeti + +Da biste koristili OpenCode u svom terminalu, trebat će vam: + +1. Moderan emulator terminala kao što su: + - [WezTerm](https://wezterm.org), više platformi + - [Alacritty](https://alacritty.org), više platformi + - [Ghostty](https://ghostty.org), Linux i macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux i macOS +2. API ključevi za LLM provajdere koje želite koristiti. + +--- + +## Instalacija + +Najlakši način za instaliranje OpenCode je putem instalacijske skripte. + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +Također ga možete instalirati pomoću sljedećih naredbi: + +- **Korištenje Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **Korištenje Homebrew-a na macOS-u i Linux-u** + +```bash + brew install anomalyco/tap/opencode +``` + +> Preporučujemo korištenje OpenCode tap za najnovija izdanja. Službenu formulu `brew install opencode` održava Homebrew tim i ažurira se rjeđe. + +- **Korištenje Parua na Arch Linuxu** + +```bash + paru -S opencode-bin +``` + +#### Windows + +:::tip[Preporučeno: Koristite WSL] +Za najbolje iskustvo na Windows-u preporučujemo korištenje [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Pruža bolje performanse i potpunu kompatibilnost sa OpenCode funkcijama. +::: + +- **Korištenje Chocolatey-a** + +```bash + choco install opencode +``` + +- **Korištenje Scoop-a** + +```bash + scoop install opencode +``` + +- **Korištenje NPM-a** + +```bash + npm install -g opencode-ai +``` + +- **Korištenje Mise** + +```bash + mise use -g github:anomalyco/opencode +``` + +- **Korištenje Dockera** + +```bash + docker run -it --rm ghcr.io/anomalyco/opencode +``` + +Podrška za instaliranje OpenCode na Windows koristeći Bun je trenutno u toku. +Također možete preuzeti binarnu datoteku iz [Releases](https://github.com/anomalyco/opencode/releases). + +--- + +## Konfiguracija + +Uz OpenCode možete koristiti bilo kojeg LLM provajdera tako što ćete konfigurirati njihove API ključeve. +Ako ste tek počeli koristiti LLM provajdere, preporučujemo korištenje [OpenCode Zen](/docs/zen). +To je kurirana lista modela koji su testirani i verifikovani od strane OpenCode tima. + +1. Pokrenite naredbu `/connect` u TUI-u, odaberite opencode i idite na [opencode.ai/auth](https://opencode.ai/auth). + +```txt + /connect +``` + +2. Prijavite se, dodajte svoje detalje naplate i kopirajte svoj API ključ. +3. Zalijepite svoj API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +Alternativno, možete odabrati jednog od drugih provajdera. [Saznajte više](/docs/providers#directory). + +--- + +## Inicijalizacija + +Sada kada ste konfigurisali provajdera, možete se kretati do projekta na kojem želite raditi. + +```bash +cd /path/to/project +``` + +I pokrenite OpenCode. + +```bash +opencode +``` + +Zatim inicijalizirajte OpenCode za projekat pokretanjem sljedeće naredbe. + +```bash frame="none" +/init +``` + +Ovo će omogućiti OpenCode da analizira vaš projekat i kreira `AGENTS.md` fajl u korijenu projekta. +:::tip +Trebali biste komitovati datoteku `AGENTS.md` vašeg projekta u Git. +::: +Ovo pomaže OpenCode da razumije strukturu projekta i obrasce kodiranja koji se koriste. + +--- + +## Korištenje + +Sada ste spremni da koristite OpenCode za rad na svom projektu. Slobodno pitajte bilo šta! +Ako ste novi u korištenju agenta za AI kodiranje, evo nekoliko primjera koji bi mogli pomoći. + +--- + +### Postavljanje pitanja + +Možete zamoliti OpenCode da vam objasni kodnu bazu. +:::tip +Koristite tipku `@` za nejasnu pretragu datoteka u projektu. +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +Ovo je korisno ako postoji dio kodne baze na kojem niste radili. + +--- + +### Dodavanje funkcija + +Možete zamoliti OpenCode da vašem projektu doda nove funkcije. Iako preporučujemo da ga prvo zamolite da napravi plan. + +1. **Kreirajte plan** + OpenCode ima _Plan mod_ koji onemogućuje njegovu sposobnost da pravi promjene i umjesto toga predlaže _kako_ će implementirati ovu funkciju. + Prebacite se na njega pomoću tipke **Tab**. Vidjet ćete indikator za ovo u donjem desnom uglu. + +```bash frame="none" title="Switch to Plan mode" + +``` + +Hajde sada da opišemo šta želimo da uradi. + +```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. +``` + +Želite da date OpenCode dovoljno detalja da razumije šta želite. Pomaže da razgovarate s njim kao da razgovarate sa mlađim programerom u svom timu. +:::tip +Dajte OpenCode dosta konteksta i primjera koji će mu pomoći da razumije šta vi želite. +::: + +2. **Ponovite plan** + Kada vam da plan, možete mu dati povratne informacije ili dodati više detalja. + +```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. +``` + +:::tip +Prevucite i ispustite slike u terminal da biste ih dodali u prompt. +::: +OpenCode može skenirati sve slike koje mu date i dodati ih u prompt. Možete to učiniti povlačenjem i ispuštanjem slike u terminal. + +3. **Izgradite funkciju** + Kada se osjećate ugodno s planom, vratite se na _Build mode_ ponovnim pritiskom na taster **Tab**. + +```bash frame="none" + +``` + +I tražeći od njega da napravi promjene. + +```bash frame="none" + Sounds good! Go ahead and make the changes. +``` + +--- + +### Pravljenje izmjena + +Za jednostavnije promjene, možete zamoliti OpenCode da ga direktno izgradi bez potrebe da prvo pregledate plan. + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +Želite da budete sigurni da ste pružili dobru količinu detalja kako bi OpenCode napravio ispravne promjene. + +--- + +### Poništavanje izmjena + +Recimo da tražite od OpenCode da izvrši neke promjene. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Ali shvatate da to nije ono što ste željeli. Možete **poništiti** promjene koristeći naredbu `/undo`. + +```bash frame="none" +/undo +``` + +OpenCode će sada poništiti promjene koje ste napravili i ponovo prikazati vašu originalnu poruku. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Odavde možete podesiti prompt i zamoliti OpenCode da pokuša ponovo. +:::tip +Možete pokrenuti `/undo` više puta da poništite više promjena. +::: +Ili **možete ponoviti** promjene koristeći naredbu `/redo`. + +```bash frame="none" +/redo +``` + +--- + +## Dijeljenje + +Razgovore koje imate sa OpenCode možete [dijeliti sa vašim timom](/docs/share). + +```bash frame="none" +/share +``` + +Ovo će kreirati vezu do trenutnog razgovora i kopirati je u međuspremnik. +:::note +Razgovori se ne dijele prema zadanim postavkama. +::: +Evo [primjer razgovora](https://opencode.ai/s/4XP1fce5) sa OpenCode. + +--- + +## Prilagođavanje + +I to je to! Sada ste profesionalac u korištenju OpenCode. +Da biste to učinili svojim, preporučujemo [odabir teme](/docs/themes), [prilagođavanje povezivanja tipki](/docs/keybinds), [konfiguriranje formatera koda](/docs/formatters), [kreiranje prilagođenih komandi](/docs/commands), ili igranje sa [OpenCode config](/docs/config). diff --git a/packages/web/src/content/docs/bs/keybinds.mdx b/packages/web/src/content/docs/bs/keybinds.mdx new file mode 100644 index 00000000000..f35dd385257 --- /dev/null +++ b/packages/web/src/content/docs/bs/keybinds.mdx @@ -0,0 +1,190 @@ +--- +title: Prečice tipki +description: Prilagodite svoje veze tipki. +--- + +OpenCode ima listu veza tipki koje možete prilagoditi preko OpenCode konfiguracije. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## 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". + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## Prečice za radnu površinu + +Unos prompta aplikacije OpenCode za desktop podržava uobičajene prečice u stilu Readline/Emacs za uređivanje teksta. One su ugrađene i trenutno se ne mogu konfigurirati putem `opencode.json`. + +| Prečica | Akcija | +| -------- | ------------------------------------------------ | +| `ctrl+a` | Prelazak na početak trenutnog reda | +| `ctrl+e` | Prelazak na kraj trenutnog reda | +| `ctrl+b` | Pomjeri kursor za jedan znak unazad | +| `ctrl+f` | Pomicanje kursora naprijed za jedan znak | +| `alt+b` | Pomjeri kursor za jednu riječ unazad | +| `alt+f` | Pomjeri kursor za jednu riječ unaprijed | +| `ctrl+d` | Izbriši znak ispod kursora | +| `ctrl+k` | Kill do kraja reda | +| `ctrl+u` | Kill do početka reda | +| `ctrl+w` | Kill prethodnu riječ | +| `alt+d` | Kill sljedeću riječ | +| `ctrl+t` | Transponirajte znakove | +| `ctrl+g` | Otkaži iskakanje / poništi odgovor na pokretanje | + +--- + +## Shift+Enter + +Neki terminali ne šalju modifikatorske tipke sa Enter prema zadanim postavkama. Možda ćete trebati konfigurirati svoj terminal da pošalje `Shift+Enter` kao escape sekvencu. + +### Windows Terminal + +Otvorite svoj `settings.json` na: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +Dodajte ovo u niz korijenskog nivoa `actions`: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Dodajte ovo u niz korijenskog nivoa `keybindings`: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Sačuvajte datoteku i ponovo pokrenite Windows Terminal ili otvorite novu karticu. diff --git a/packages/web/src/content/docs/bs/lsp.mdx b/packages/web/src/content/docs/bs/lsp.mdx new file mode 100644 index 00000000000..463d9a0ad99 --- /dev/null +++ b/packages/web/src/content/docs/bs/lsp.mdx @@ -0,0 +1,180 @@ +--- +title: LSP serveri +description: OpenCode se integriše sa vašim LSP serverima. +--- + +OpenCode se integriše sa vašim Language Server Protocol (LSP) serverima kako bi pomogao LLM-u u interakciji s kodnom bazom. Koristi dijagnostiku za slanje povratnih informacija modelu. + +## 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 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`. +::: + +--- + +## Kako radi + +Kada opencode otvori fajl, on: + +1. Provjerava ekstenziju datoteke u odnosu na sve omogućene LSP servere. +2. Pokreće odgovarajući LSP server ako već nije pokrenut. + +--- + +## Konfiguracija + +Možete prilagoditi LSP servere kroz `lsp` odjeljak u vašoj opencode konfiguraciji. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +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 | +Pogledajmo neke primjere. + +--- + +### Varijable okruženja + +Koristite svojstvo `env` za postavljanje varijabli okruženja prilikom pokretanja LSP servera: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### Opcije inicijalizacije + +Koristite svojstvo `initialization` da prosledite opcije inicijalizacije na LSP server. Ovo su postavke specifične za server poslane tokom LSP `initialize` zahtjeva: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +Opcije inicijalizacije razlikuju se od LSP servera. Provjerite dokumentaciju vašeg LSP servera za dostupne opcije. +::: + +--- + +### Onemogućavanje LSP servera + +Da biste onemogućili **sve** LSP servere globalno, postavite `lsp` na `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +Da onemogućite **specifičan** LSP server, postavite `disabled` na `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### Prilagođeni LSP serveri + +Možete dodati prilagođene LSP servere navodeći ekstenzije naredbe i datoteke: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## Dodatne informacije + +### PHP Intelephense + +PHP Intelephense nudi vrhunske funkcije putem licencnog ključa. Možete dati licencni ključ postavljanjem (samo) ključa u tekstualnu datoteku na: + +- Na macOS/Linuxu: `$HOME/intelephense/license.txt` +- Na Windowsima: `%USERPROFILE%/intelephense/license.txt` + Datoteka treba da sadrži samo licencni ključ bez dodatnog sadržaja. diff --git a/packages/web/src/content/docs/bs/mcp-servers.mdx b/packages/web/src/content/docs/bs/mcp-servers.mdx new file mode 100644 index 00000000000..b516bcec08f --- /dev/null +++ b/packages/web/src/content/docs/bs/mcp-servers.mdx @@ -0,0 +1,482 @@ +--- +title: MCP serveri +description: Dodajte lokalne i udaljene MCP alate. +--- + +Možete dodati vanjske alate u OpenCode koristeći _Model Context Protocol_, ili MCP. OpenCode podržava i lokalne i udaljene servere. +Jednom dodani, MCP alati su automatski dostupni LLM-u zajedno sa ugrađenim alatima. + +--- + +#### Upozorenje + +Kada koristite MCP server, on dodaje u kontekst. Ovo se može brzo zbrojiti ako imate puno alata. Stoga preporučujemo da pazite koje MCP servere koristite. +:::tip +MCP serveri dodaju vaš kontekst, tako da želite da budete pažljivi s tim koje ćete omogućiti. +::: + +Određeni MCP serveri, poput GitHub MCP servera, mogu dodati mnogo tokena i lako premašiti limit konteksta. + +## Omogućavanje + +Možete definirati MCP servere u vašoj [OpenCode Config](https://opencode.ai/docs/config/) pod `mcp`. Dodajte svaki MCP sa jedinstvenim imenom. Možete se pozvati na taj MCP po imenu kada tražite LLM. + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +Također možete onemogućiti server postavljanjem `enabled` na `false`. To je korisno kada ga želite privremeno isključiti bez uklanjanja iz konfiguracije. + +### Poništavanje udaljenih zadanih postavki + +Organizacije mogu obezbijediti zadane MCP servere preko svoje krajnje tačke `.well-known/opencode`. Ovi serveri mogu biti onemogućeni prema zadanim postavkama, omogućavajući korisnicima da se odluče za one koji su im potrebni. +Da omogućite određeni server iz udaljene konfiguracije vaše organizacije, dodajte ga u svoju lokalnu konfiguraciju sa `enabled: true`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +Vrijednosti lokalne konfiguracije nadjačavaju udaljene zadane postavke. Pogledajte [config precedence](/docs/config#precedence-order) za više detalja. + +## Lokalno + +Dodajte lokalne MCP servere koristeći `type` u `"local"` unutar MCP objekta. + +```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", + }, + }, + }, +} +``` + +Naredba je način na koji se pokreće lokalni MCP server. Također možete proslijediti listu varijabli okruženja. +Na primjer, evo kako možete dodati testni [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) MCP server. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "mcp_everything": { + "type": "local", + "command": ["npx", "-y", "@modelcontextprotocol/server-everything"], + }, + }, +} +``` + +I da ga koristim mogu dodati `use the mcp_everything tool` u svoje upite. + +```txt "mcp_everything" +use the mcp_everything tool to add the number 3 and 4 +``` + +--- + +#### Opcije + +Ovdje su sve opcije za konfiguriranje lokalnog MCP servera. +| Opcija | Tip | Obavezno | Opis +|------------- | ------- | -------- | ----------------------------------------------------------------------------------- | +| `type` | String | Y | Tip veze sa MCP serverom, mora biti `"local"`. | +| `command` | Niz | Y | Naredba i argumenti za pokretanje MCP servera. | +| `environment` | Objekt | | Varijable okruženja koje treba postaviti prilikom pokretanja servera. | +| `enabled` | Boolean | | Omogućite ili onemogućite MCP server pri pokretanju. | +| `timeout` | Broj | | Vremensko ograničenje u ms za dohvaćanje alata sa MCP servera. Podrazumevano je 5000 (5 sekundi). | + +--- + +## Udaljeno + +Dodajte udaljene MCP servere postavljanjem `type` na `"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" + } + } + } +} +``` + +`url` je URL udaljenog MCP servera, a kroz opciju `headers` možete proslijediti listu zaglavlja. + +#### Opcije + +| Opcija | Tip | Obavezno | Opis | +| --------- | ------- | -------- | -------------------------------------------------------------------------------------------------- | +| `type` | String | Y | Tip veze sa MCP serverom, mora biti `"remote"`. | +| `url` | String | Y | URL udaljenog MCP servera. | +| `enabled` | Boolean | | Omogućite ili onemogućite MCP server pri pokretanju. | +| `headers` | Objekt | | Zaglavlja za slanje uz zahtjev. | +| `oauth` | Objekt | | Konfiguracija OAuth provjere autentičnosti. Pogledajte odjeljak [OAuth](#oauth) ispod. | +| `timeout` | Broj | | Vremensko ograničenje u ms za preuzimanje alata sa MCP servera. Podrazumevano je 5000 (5 sekundi). | + +--- + +## OAuth + +OpenCode automatski rukuje OAuth autentifikacijom za udaljene MCP servere. Kada server zahtijeva autentifikaciju, OpenCode će: + +1. Otkrijte 401 odgovor i pokrenite OAuth tok +2. Koristite **Dynamic Client Registration (RFC 7591)** ako podržava server +3. Sigurno čuvajte tokene za buduće zahtjeve + +--- + +### Automatski + +Za većinu MCP servera sa omogućenim OAuthom nije potrebna posebna konfiguracija. Samo konfigurirajte udaljeni server: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "my-oauth-server": { + "type": "remote", + "url": "https://mcp.example.com/mcp" + } + } +} +``` + +Ako server zahtijeva autentifikaciju, OpenCode će vas tražiti prijavu pri prvom korištenju. Ako se to ne desi, možete [ručno pokrenuti tok](#authenticating) naredbom `opencode mcp auth `. + +### Prethodno registrirano + +Ako imate klijentske vjerodajnice od dobavljača MCP servera, možete ih konfigurirati: + +```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" + } + } + } +} +``` + +--- + +### Autentifikacija + +Možete ručno pokrenuti autentifikaciju ili upravljati vjerodajnicama. +Autentifikacija sa određenim MCP serverom: + +```bash +opencode mcp auth my-oauth-server +``` + +Navedite sve MCP servere i njihov status autentifikacije: + +```bash +opencode mcp list +``` + +Uklonite pohranjene vjerodajnice: + +```bash +opencode mcp logout my-oauth-server +``` + +Komanda `mcp auth` otvara pretraživač za autorizaciju. Nakon odobrenja, OpenCode sigurno čuva tokene u `~/.local/share/opencode/mcp-auth.json`. + +#### Onemogućavanje OAuth-a + +Ako želite onemogućiti automatski OAuth za server (npr. za servere koji umjesto toga koriste API ključeve), postavite `oauth` na `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 opcije + +| Opcija | Tip | Opis | +| -------------- | --------------- | --------------------------------------------------------------------------------------------- | +| `oauth` | Objekt \| false | OAuth konfiguracijski objekt, ili `false` da onemogućite automatsko otkrivanje OAuth. | +| `clientId` | String | ID OAuth klijenta. Ako nije navedeno, pokušat će se izvršiti dinamička registracija klijenta. | +| `clientSecret` | String | Tajna OAuth klijenta, ako to zahtijeva autorizacijski server. | +| `scope` | String | OAuth opseg zahtjeva za vrijeme autorizacije. | + +#### Otklanjanje grešaka + +Ako udaljeni MCP server ne uspije u autentifikaciji, možete dijagnosticirati probleme pomoću: + +```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 +``` + +Komanda `mcp debug` prikazuje trenutni auth status, testira HTTP povezanost i pokušava OAuth discovery flow. + +## Upravljanje + +Vaši MCP serveri su dostupni kao alati u OpenCode, zajedno s ugrađenim alatima. Možete njima upravljati kroz OpenCode konfiguraciju kao i bilo kojim drugim alatom. + +### Globalno + +To znači da ih možete omogućiti ili onemogućiti globalno. + +```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 + } +} +``` + +Također možemo koristiti glob obrazac da onemogućimo sve odgovarajuće MCP-ove. + +```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 + } +} +``` + +Ovdje koristimo glob obrazac `my-mcp*` da onemogućimo sve MCP servere. + +### Po agentu + +Ako imate veliki broj MCP servera, možda ćete želeti da ih omogućite samo po agentu i da ih onemogućite globalno. Da biste to učinili: + +1. Onemogućite ga kao alat globalno. +2. U vašem [agent config](/docs/agents#tools), omogućite MCP server kao alat. + +```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 + } + } + } +} +``` + +--- + +#### Glob uzorci + +Uzorak glob koristi jednostavne šablone globbiranja regularnih izraza: + +- `*` odgovara nuli ili više bilo kojeg znaka (npr. `"my-mcp*"` odgovara `my-mcp_search`, `my-mcp_list`, itd.) +- `?` odgovara tačno jednom znaku +- Svi ostali likovi se bukvalno podudaraju + :::note + MCP serverski alati se registruju sa imenom servera kao prefiksom, tako da onemogućite sve alate za server jednostavno koristite: + +``` +"mymcpservername_*": false +``` + +::: + +--- + +## Primjeri + +Ispod su primjeri uobičajenih MCP servera. Možete poslati PR ako želite dokumentovati druge servere. + +### Sentry + +Dodajte [Sentry MCP server](https://mcp.sentry.dev) za interakciju sa vašim Sentry projektima i problemima. + +```json title="opencode.json" {4-8} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "sentry": { + "type": "remote", + "url": "https://mcp.sentry.dev/mcp", + "oauth": {} + } + } +} +``` + +Nakon dodavanja konfiguracije, autentifikujte se sa Sentry: + +```bash +opencode mcp auth sentry +``` + +Ovo će otvoriti prozor pretraživača da završite OAuth tok i povežete OpenCode sa vašim Sentry nalogom. +Nakon provjere autentičnosti, možete koristiti Sentry alate u svojim upitima za upite o problemima, projektima i podacima o greškama. + +```txt "use sentry" +Show me the latest unresolved issues in my project. use sentry +``` + +--- + +### Context7 + +Dodajte [Context7 MCP server](https://github.com/upstash/context7) za pretraživanje dokumenata. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "context7": { + "type": "remote", + "url": "https://mcp.context7.com/mcp" + } + } +} +``` + +Ako ste se prijavili za besplatni račun, možete koristiti svoj API ključ i dobiti viša ograničenja stope. + +```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}" + } + } + } +} +``` + +Ovdje pretpostavljamo da imate postavljenu varijablu okruženja `CONTEXT7_API_KEY`. +Dodajte `use context7` vašim upitima za korištenje Context7 MCP servera. + +```txt "use context7" +Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 +``` + +Alternativno, možete dodati nešto poput ovoga na svoj [AGENTS.md](/docs/rules/). + +```md title="AGENTS.md" +When you need to search docs, use `context7` tools. +``` + +--- + +### Grep by Vercel + +Dodajte [Grep by Vercel](https://grep.app) MCP server za pretraživanje isječaka koda na GitHub. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "gh_grep": { + "type": "remote", + "url": "https://mcp.grep.app" + } + } +} +``` + +Pošto smo naš MCP server nazvali `gh_grep`, možete dodati `use the gh_grep tool` u svoje upite da natjerate agenta da ga koristi. + +```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 +``` + +Alternativno, možete dodati nešto poput ovoga na svoj [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/bs/models.mdx b/packages/web/src/content/docs/bs/models.mdx new file mode 100644 index 00000000000..b6099740bbc --- /dev/null +++ b/packages/web/src/content/docs/bs/models.mdx @@ -0,0 +1,201 @@ +--- +title: Modeli +description: Konfiguriranje LLM provajdera i modela. +--- + +OpenCode koristi [AI SDK](https://ai-sdk.dev/) i [Models.dev](https://models.dev) za podršku **75+ LLM providera**, uključujući lokalne modele. + +## Provajderi + +Većina popularnih provajdera su unaprijed učitani prema zadanim postavkama. Ako ste dodali vjerodajnice za provajdera putem naredbe `/connect`, oni će biti dostupni kada pokrenete OpenCode. +Saznajte više o [providers](/docs/providers). + +--- + +## Odabir modela + +Nakon što konfigurirate svog provajdera, možete odabrati model koji želite upisivanjem: + +```bash frame="none" +/models +``` + +--- + +## Preporučeni modeli + +Postoji mnogo modela vani, a novi modeli izlaze svake sedmice. +:::tip +Razmislite o korištenju jednog od modela koje preporučujemo. +::: + +Međutim, postoji samo nekoliko njih koji su dobri i u generiranju koda i u pozivanju alata. +Evo nekoliko modela koji dobro rade sa OpenCode, bez posebnog redosleda. (Ovo nije potpuna lista niti je nužno ažurirana): + +- GPT 5.2 +- Codex GPT 5.1 +- Claude Opus 4.5 +- Claude Sonnet 4.5 +- Minimax M2.1 +- Gemini 3 Pro + +--- + +## Postavljanje zadanog + +Da postavite jedan od ovih kao zadani model, možete postaviti ključ `model` u svom +OpenCode config. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +Ovdje je puni ID `provider_id/model_id`. Na primjer, ako koristite [OpenCode Zen](/docs/zen), koristili biste `opencode/gpt-5.1-codex` za GPT 5.1 Codex. +Ako ste konfigurirali [prilagođenog provajdera](/docs/providers#custom), `provider_id` je ključ iz `provider` dijela vaše konfiguracije, a `model_id` je ključ iz `provider.models`. + +--- + +## Konfiguracija modela + +Možete globalno konfigurirati opcije modela kroz config. + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +Ovdje konfiguriramo globalne postavke za dva ugrađena modela: `gpt-5` kada se pristupa preko `openai` provajdera i `claude-sonnet-4-20250514` kada se pristupa preko `anthropic` provajdera. +Ugrađeni dobavljač i nazivi modela mogu se naći na [Models.dev](https://models.dev). +Također možete konfigurirati ove opcije za sve agente koje koristite. Konfiguracija agenta poništava sve globalne opcije ovdje. [Saznajte više](/docs/agents/#additional). +Također možete definirati prilagođene varijante koje proširuju ugrađene. Varijante vam omogućavaju da konfigurirate različite postavke za isti model bez stvaranja duplih unosa: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## Varijante + +Mnogi modeli podržavaju više varijanti sa različitim konfiguracijama. OpenCode se isporučuje sa ugrađenim podrazumevanim varijantama za popularne provajdere. + +### Ugrađene varijante + +OpenCode se isporučuje sa zadanim varijantama za mnoge provajdere: +**Anthropic**: + +- `high` - Visok budžet za razmišljanje (zadano) +- `max` - Maksimalni budžet za razmišljanje + **OpenAI**: + Zavisi od modela, ali otprilike: +- `none` - Bez obrazloženja +- `minimal` - Minimalni napor za rasuđivanje +- `low` - Nizak napor u rasuđivanju +- `medium` - Srednji napor u zaključivanju +- `high` - Veliki napor u rasuđivanju +- `xhigh` - Ekstra visok napor u rasuđivanju + **Google**: +- `low` - Manji trud/budžet tokena +- `high` - Veći budžet za trud/token + :::tip + Ova lista nije sveobuhvatna. Mnogi drugi provajderi također imaju ugrađene zadane postavke. + ::: + +### Prilagođene varijante + +Možete nadjačati postojeće varijante ili dodati svoje: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### Kruženje kroz varijante + +Koristite keybind `variant_cycle` za brzo prebacivanje između varijanti. [Saznajte više](/docs/keybinds). + +## Učitavanje modela + +Kada se OpenCode pokrene, on provjerava modele u sljedećem prioritetnom redoslijedu: + +1. Oznaka komandne linije `--model` ili `-m`. Format je isti kao u konfiguracijskoj datoteci: `provider_id/model_id`. +2. Lista modela u OpenCode konfiguraciji. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" +} +``` + +Format ovdje je `provider/model`. 3. Posljednji korišteni model. 4. Prvi model koji koristi interni prioritet. diff --git a/packages/web/src/content/docs/bs/modes.mdx b/packages/web/src/content/docs/bs/modes.mdx new file mode 100644 index 00000000000..9cff5d58407 --- /dev/null +++ b/packages/web/src/content/docs/bs/modes.mdx @@ -0,0 +1,316 @@ +--- +title: Načini rada +description: Različiti načini za različite slučajeve upotrebe. +--- + +:::caution +Načini se sada konfiguriraju preko opcije `agent` u konfiguraciji otvorenog koda. The +`mode` opcija je sada zastarjela. [Saznajte više](/docs/agents). +::: + +Režimi u otvorenom kodu omogućavaju vam da prilagodite ponašanje, alate i upite za različite slučajeve upotrebe. +Dolazi sa dva ugrađena načina rada: **build** i **plan**. Možete prilagoditi +ove ili konfigurirajte svoje putem opencode config. +Možete se prebacivati ​​između režima tokom sesije ili ih konfigurisati u svom konfiguracionom fajlu. + +--- + +## Ugrađeni + +opencode dolazi sa dva ugrađena načina rada. + +### Build + +Build je **podrazumijevani** režim sa svim omogućenim alatima. Ovo je standardni način rada za razvoj kada vam treba pun pristup fajlovima i sistemskim komandama. + +### Plan + +Ograničeni način rada dizajniran za planiranje i analizu. U načinu plana, sljedeći alati su onemogućeni prema zadanim postavkama: + +- `write` - Ne mogu kreirati nove fajlove +- `edit` - Ne mogu modificirati postojeće fajlove, osim fajlova koji se nalaze na `.opencode/plans/*.md` radi detaljiziranja samog plana +- `patch` - Ne mogu primijeniti zakrpe +- `bash` - Ne mogu izvršiti naredbe ljuske + Ovaj način rada je koristan kada želite da AI analizira kod, predlaže promjene ili kreira planove bez ikakvih stvarnih modifikacija u vašoj bazi kodova. + +--- + +## Prebacivanje + +Možete se prebacivati ​​između načina rada tokom sesije pomoću tipke _Tab_. Ili vaše konfigurirano `switch_mode` spajanje tipki. +Vidi također: [Formatters](/docs/formatters) za informacije o konfiguraciji formatiranja koda. + +--- + +## Konfiguracija + +Možete prilagoditi ugrađene načine rada ili kreirati vlastite kroz konfiguraciju. Modovi se mogu konfigurirati na dva načina: + +### JSON konfiguracija + +Konfigurirajte načine rada u svom `opencode.json` konfiguracijskom fajlu: + +```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 konfiguracija + +Također možete definirati načine rada koristeći markdown datoteke. Postavite ih u: + +- Globalno: `~/.config/opencode/modes/` +- Projekat: `.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. +``` + +Naziv datoteke s uštedom postaje naziv načina (npr. `review.md` kreira `review` način rada). +Pogledajmo ove opcije konfiguracije detaljno. + +--- + +### Model + +Koristite `model` konfiguraciju da nadjačate zadani model za ovaj način rada. Korisno za korištenje različitih modela optimiziranih za različite zadatke. Na primjer, brži model za planiranje, sposobniji model za implementaciju. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### Temperatura + +Kontrolišite slučajnost i kreativnost odgovora AI pomoću `temperature` konfiguracije. Niže vrijednosti čine odgovore fokusiranijim i determinističkim, dok veće vrijednosti povećavaju kreativnost i varijabilnost. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Vrijednosti temperature obično se kreću od 0,0 do 1,0: + +- **0,0-0,2**: Vrlo fokusirani i deterministički odgovori, idealni za analizu i planiranje koda +- **0,3-0,5**: Uravnoteženi odgovori sa malo kreativnosti, dobro za opšte razvojne zadatke +- **0,6-1,0**: kreativniji i raznovrsniji odgovori, korisni za razmišljanje i istraživanje + +```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}" + } + } +} +``` + +Ako temperatura nije navedena, opencode koristi podrazumijevane postavke specifične za model (obično 0 za većinu modela i 0.55 za Qwen modele). + +### Upit + +Navedite prilagođenu sistemsku datoteku prompta za ovaj način rada s konfiguracijom `prompt`. Datoteka s promptom treba da sadrži upute specifične za svrhu načina rada. + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Ova putanja je relativna u odnosu na mjesto gdje se nalazi konfiguracijski fajl. Dakle, ovo radi za +i globalnu konfiguraciju otvorenog koda i konfiguraciju specifične za projekat. + +--- + +### Alati + +Kontrolirajte koji su alati dostupni u ovom načinu rada pomoću `tools` konfiguracije. Možete omogućiti ili onemogućiti određene alate tako što ćete ih postaviti na `true` ili `false`. + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +Ako nijedan alat nije specificiran, svi alati su omogućeni po defaultu. + +#### Dostupni alati + +Ovdje su svi alati koji se mogu kontrolirati kroz konfiguraciju načina rada. +| Alat | Opis +|----------- | ----------------------- | +| `bash` | Izvrši naredbe ljuske | +| `edit` | Izmijenite postojeće datoteke | +| `write` | Kreirajte nove fajlove | +| `read` | Pročitajte sadržaj datoteke | +| `grep` | Pretraži sadržaj datoteke | +| `glob` | Pronađite datoteke po uzorku | +| `list` | Lista sadržaja direktorija | +| `patch` | Primijenite zakrpe na datoteke | +| `todowrite` | Upravljanje listama zadataka | +| `todoread` | Pročitajte liste obaveza | +| `webfetch` | Dohvati web sadržaj | + +--- + +## Prilagođeni načini rada + +Možete kreirati vlastite prilagođene modove tako što ćete ih dodati u konfiguraciju. Evo primjera koji koriste oba pristupa: + +### Korištenje JSON konfiguracije + +```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 + } + } + } +} +``` + +### Korištenje markdown fajlova + +Kreirajte fajlove načina u `.opencode/modes/` za specifične načine rada ili `~/.config/opencode/modes/` za globalne načine: + +```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 +``` + +--- + +### Slučajevi upotrebe + +Evo nekoliko uobičajenih slučajeva upotrebe za različite načine rada. + +- **Build mode**: Potpuni razvojni rad sa svim omogućenim alatima +- **Plan mode**: Analiza i planiranje bez izmjena +- **Review mode**: Pregled koda sa pristupom samo za čitanje plus alati za dokumentaciju +- **Debug mode**: Fokusiran na istragu sa omogućenim bash i alatima za čitanje +- **Docs mode**: Pisanje dokumentacije sa operacijama datoteka, ali bez sistemskih naredbi + Možda ćete također otkriti da su različiti modeli dobri za različite slučajeve upotrebe. diff --git a/packages/web/src/content/docs/bs/network.mdx b/packages/web/src/content/docs/bs/network.mdx new file mode 100644 index 00000000000..aa213328426 --- /dev/null +++ b/packages/web/src/content/docs/bs/network.mdx @@ -0,0 +1,51 @@ +--- +title: Mreža +description: Konfigurirajte proksije i prilagođene certifikate. +--- + +OpenCode podržava standardne proxy varijable okruženja i prilagođene certifikate za enterprise mrežna okruženja. + +## Proksi + +OpenCode poštuje standardne varijable proxy okruženja. + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +TUI komunicira sa lokalnim HTTP serverom. Morate zaobići proxy za ovu vezu kako biste spriječili petlje usmjeravanja. +::: + +Možete konfigurirati port servera i naziv hosta koristeći [CLI flags](/docs/cli#run). + +### Autentikacija + +Ako vaš proxy zahtijeva osnovnu autentifikaciju, uključite vjerodajnice u URL. + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +Izbjegavajte tvrdo kodiranje lozinki. Koristite varijable okruženja ili sigurno skladište vjerodajnica. +::: + +Za proxy servere koji zahtijevaju naprednu autentifikaciju poput NTLM ili Kerberos, razmotrite LLM Gateway koji podržava vašu metodu autentifikacije. + +## Prilagođeni certifikati + +Ako vaše preduzeće koristi prilagođene CA-ove za HTTPS veze, konfigurirajte OpenCode da im vjeruje. + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +Ovo radi i za proxy veze i za direktan pristup API-ju. diff --git a/packages/web/src/content/docs/bs/permissions.mdx b/packages/web/src/content/docs/bs/permissions.mdx new file mode 100644 index 00000000000..8b2061ee0db --- /dev/null +++ b/packages/web/src/content/docs/bs/permissions.mdx @@ -0,0 +1,230 @@ +--- +title: Dozvole +description: Kontrolirajte koje radnje zahtijevaju odobrenje za pokretanje. +--- + +OpenCode koristi `permission` konfiguraciju da odluči da li će se određena radnja pokrenuti automatski, zatražiti od vas ili biti blokirana. +Od `v1.1.1`, naslijeđena `tools` logička konfiguracija je zastarjela i spojena je u `permission`. Stara `tools` konfiguracija je još uvijek podržana za kompatibilnost unatrag. + +--- + +## Akcije + +Svako pravilo dozvole rješava jedno od: + +- `"allow"` — pokrenuti bez odobrenja +- `"ask"` — upit za odobrenje +- `"deny"` — blokiraj akciju + +--- + +## Konfiguracija + +Dozvole možete postaviti globalno (sa `*`) i nadjačati određene alate. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +Također možete postaviti sve dozvole odjednom: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## Granularna pravila (sintaksa objekta) + +Za većinu dozvola, možete koristiti objekt za primjenu različitih radnji na osnovu unosa alata. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +Pravila se procjenjuju na osnovu podudaranja uzorka, pri čemu **pobjeđuje **poslednje odgovarajuće pravilo\*\_. Uobičajeni obrazac je da se prvo pravilo `"*"` stavi sveobuhvatno, a poslije njega konkretnija pravila. + +### Zamjenski znakovi + +Uzorci dozvola koriste jednostavno podudaranje zamjenskih znakova: + +- `*` odgovara nula ili više bilo kojeg znaka +- `?` odgovara tačno jednom znaku +- Svi ostali likovi se bukvalno podudaraju + +### Proširenje kućnog direktorija + +Možete koristiti `~` ili `$HOME` na početku obrasca da referencirate svoj početni direktorij. Ovo je posebno korisno za [`external_directory`](#external-directories) pravila. + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### Vanjski direktoriji + +Koristite `external_directory` da dozvolite pozive alata koji dodiruju putanje izvan radnog direktorija gdje je OpenCode pokrenut. Ovo se odnosi na bilo koji alat koji uzima putanju kao ulaz (na primjer `read`, `edit`, `list`, `glob`, `grep` i mnoge `bash` komande). +Proširenje kuće (poput `~/...`) utiče samo na način na koji je obrazac napisan. Ne čini vanjsku stazu dijelom trenutnog radnog prostora, tako da staze izvan radnog direktorija i dalje moraju biti dozvoljene preko `external_directory`. +Na primjer, ovo omogućava pristup svemu pod `~/projects/personal/`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +Svaki direktorij koji je ovdje dozvoljen nasljeđuje iste zadane postavke kao trenutni radni prostor. Pošto je [`read` zadano na `allow`](#defaults), čitanje je također dozvoljeno za unose pod `external_directory` osim ako se ne poništi. Dodajte eksplicitna pravila kada bi alat trebao biti ograničen na ovim stazama, kao što je blokiranje uređivanja uz zadržavanje čitanja: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +Držite ovu listu fokusiranom na pouzdane putanje, a dodatna allow/deny pravila dodajte po potrebi za druge alate (npr. `bash`). + +## Dostupne dozvole + +Dozvole OpenCode su označene imenom alata, plus nekoliko sigurnosnih mjera: + +- `read` — čitanje datoteke (odgovara putanji datoteke) +- `edit` — sve izmjene fajlova (pokriva `edit`, `write`, `patch`, `multiedit`) +- `glob` — globbiranje fajla (odgovara glob uzorku) +- `grep` — pretraga sadržaja (podudara se sa regularnim izrazom) +- `list` — lista fajlova u direktorijumu (podudara se sa putanjom direktorijuma) +- `bash` — izvođenje komandi ljuske (podudara se s raščlanjenim komandama kao što je `git status --porcelain`) +- `task` — pokretanje subagenta (odgovara tipu podagenta) +- `skill` — učitavanje vještine (odgovara nazivu vještine) +- `lsp` — pokretanje LSP upita (trenutno negranularno) +- `todoread`, `todowrite` — čitanje/ažuriranje liste obaveza +- `webfetch` — dohvaćanje URL-a (odgovara URL-u) +- `websearch`, `codesearch` — pretraživanje weba/koda (odgovara upitu) +- `external_directory` — pokreće se kada alat dodirne staze izvan radnog direktorija projekta +- `doom_loop` — aktivira se kada se isti poziv alata ponovi 3 puta sa identičnim unosom + +--- + +## Zadane postavke + +Ako ništa ne navedete, OpenCode počinje od dozvoljenih zadanih vrijednosti: + +- Većina dozvola je zadana na `"allow"`. +- `doom_loop` i `external_directory` zadano na `"ask"`. +- `read` je `"allow"`, ali `.env` fajlovi su po defaultu odbijeni: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## Šta radi “Ask” + +Kada OpenCode zatraži odobrenje, korisničko sučelje nudi tri ishoda: + +- `once` — odobri samo ovaj zahtjev +- `always` — odobri buduće zahtjeve koji odgovaraju predloženim obrascima (za ostatak trenutne OpenCode sesije) +- `reject` — odbiti zahtjev + Skup obrazaca koje bi `always` odobrio pruža alat (na primjer, bash odobrenja obično stavljaju na bijelu listu sigurni prefiks komande kao što je `git status*`). + +--- + +## Agenti + +Možete nadjačati dozvole po agentu. Dozvole agenta su spojene sa globalnom konfiguracijom, a pravila agenta imaju prednost. [Saznajte više](/docs/agents#permissions) o dozvolama agenta. +:::note +Pogledajte gornji odjeljak [Granularna pravila (sintaksa objekata)](#granular-rules-object-syntax) za detaljnije primjere podudaranja uzoraka. +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +Također možete konfigurirati dozvole agenta u Markdownu: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +Koristite podudaranje uzoraka za naredbe s argumentima. `"grep *"` dozvoljava `grep pattern file.txt`, dok bi ga samo `"grep"` blokirao. Naredbe poput `git status` rade za zadano ponašanje, ali zahtijevaju eksplicitnu dozvolu (kao `"git status *"`) kada se prosljeđuju argumenti. +::: diff --git a/packages/web/src/content/docs/bs/plugins.mdx b/packages/web/src/content/docs/bs/plugins.mdx new file mode 100644 index 00000000000..9b7e9f12b74 --- /dev/null +++ b/packages/web/src/content/docs/bs/plugins.mdx @@ -0,0 +1,371 @@ +--- +title: Dodaci +description: Napišite vlastite dodatke za proširenje OpenCode. +--- + +Dodaci vam omogućavaju da proširite OpenCode spajanjem na različite događaje i prilagođavanjem ponašanja. Možete kreirati dodatke za dodavanje novih funkcija, integraciju sa eksternim uslugama ili izmenu zadanog ponašanja OpenCode. +Za primjere, pogledajte [plugins](/docs/ecosystem#plugins) kreirane od strane zajednice. + +--- + +## Korištenje dodatka + +Postoje dva načina za učitavanje dodataka. + +### Iz lokalnih datoteka + +Postavite JavaScript ili TypeScript datoteke u direktorij dodataka. + +- `.opencode/plugins/` - Dodaci na nivou projekta +- `~/.config/opencode/plugins/` - Globalni dodaci + Datoteke u ovim direktorijumima se automatski učitavaju pri pokretanju. + +--- + +### Iz npm-a + +Navedite npm pakete u vašoj konfiguracijskoj datoteci. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +Podržani su i regularni i npm paketi sa opsegom. +Pregledajte dostupne dodatke u [ecosystem](/docs/ecosystem#plugins). + +--- + +### Kako se instaliraju dodaci + +**npm dodaci** se instaliraju automatski pomoću Bun pri pokretanju. Paketi i njihove zavisnosti su keširani u `~/.cache/opencode/node_modules/`. +**Lokalni dodaci** se učitavaju direktno iz direktorija dodataka. Da biste koristili vanjske pakete, morate kreirati `package.json` unutar svog konfiguracijskog direktorija (pogledajte [Zavisnosti](#dependencies)) ili objaviti dodatak na npm i [dodati ga u svoju konfiguraciju](/docs/config#plugins). + +--- + +### Redoslijed učitavanja + +Dodaci se učitavaju iz svih izvora i svi zakačnjaci rade u nizu. Redoslijed učitavanja je: + +1. Globalna konfiguracija (`~/.config/opencode/opencode.json`) +2. Konfiguracija projekta (`opencode.json`) +3. Globalni direktorij dodataka (`~/.config/opencode/plugins/`) +4. Direktorij dodataka projekta (`.opencode/plugins/`) + Duplicirani npm paketi sa istim imenom i verzijom se učitavaju jednom. Međutim, lokalni dodatak i npm dodatak sa sličnim nazivima se učitavaju odvojeno. + +--- + +## Kreiranje dodatka + +Dodatak je **JavaScript/TypeScript modul** koji izvozi jedan ili više dodataka +funkcije. Svaka funkcija prima objekt konteksta i vraća hooks objekt. + +--- + +### Zavisnosti + +Lokalni dodaci i prilagođeni alati mogu koristiti vanjske npm pakete. Dodajte `package.json` u svoj konfiguracijski direktorij sa zavisnostima koje su vam potrebne. + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +OpenCode pokreće `bun install` pri pokretanju da ih instalira. Vaši dodaci i alati ih zatim mogu uvesti. + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### Osnovna struktura + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +Funkcija dodatka prima: + +- `project`: Trenutne informacije o projektu. +- `directory`: Trenutni radni direktorij. +- `worktree`: Putanja git radnog stabla. +- `client`: Opencode SDK klijent za interakciju sa AI. +- `$`: Bun's [shell API](https://bun.com/docs/runtime/shell) za izvršavanje naredbi. + +--- + +### Podrška za TypeScript + +Za TypeScript dodatke, možete uvesti tipove iz paketa dodataka: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### Događaji + +Dodaci se mogu pretplatiti na događaje kao što je prikazano ispod u odjeljku Primjeri. Evo liste različitih dostupnih događaja. + +#### Komandni događaji + +- `command.executed` + +#### Događaji datoteka + +- `file.edited` +- `file.watcher.updated` + +#### Instalacijski događaji + +- `installation.updated` + +#### LSP događaji + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### Događaji poruka + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### Događaji dozvola + +- `permission.asked` +- `permission.replied` + +#### Serverski događaji + +- `server.connected` + +#### Događaji sesije + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### Todo događaji + +- `todo.updated` + +#### Shell događaji + +- `shell.env` + +#### Događaji alata + +- `tool.execute.after` +- `tool.execute.before` + +#### TUI događaji + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## Primjeri + +Evo nekoliko primjera dodataka koje možete koristiti za proširenje OpenCode. + +### Slanje obavještenja + +Pošaljite obavještenja kada se dogode određeni događaji: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +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. +::: + +--- + +### .env zaštita + +Spriječite opencode da čita `.env` fajlove: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### Ubacivanje varijabli okruženja + +Ubacite varijable okruženja u sva izvršavanja ljuske (AI alati i korisnički terminali): + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### Prilagođeni alati + +Dodaci također mogu dodati prilagođene alate u opencode: + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +Pomoćnik `tool` kreira prilagođeni alat koji opencode može pozvati. Uzima funkciju Zod sheme i vraća definiciju alata sa: + +- `description`: Šta alat radi +- `args`: Zod šema za argumente alata +- `execute`: Funkcija koja se pokreće kada se pozove alat + Vaši prilagođeni alati će biti dostupni za opencode zajedno sa ugrađenim alatima. + +--- + +### Bilježenje + +Koristite `client.app.log()` umjesto `console.log` za strukturirano bilježenje: + +```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" }, + }, + }) +} +``` + +Nivoi su: `debug`, `info`, `warn`, `error`. Pogledajte [SDK dokumentaciju](https://opencode.ai/docs/sdk) za detalje. + +### Kuke za sažimanje + +Prilagodite kontekst uključen kada se sesija zbije: + +```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` kuka se aktivira prije nego što LLM generira sažetak nastavka. Koristite ga za ubacivanje konteksta specifičnog za domenu koji bi zadani prompt za sažimanje propustio. +Također možete u potpunosti zamijeniti prompt za sabijanje postavljanjem `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. +` + }, + } +} +``` + +Kada je `output.prompt` postavljen, on u potpunosti zamjenjuje zadani prompt za sažimanje. Niz `output.context` se zanemaruje u ovom slučaju. diff --git a/packages/web/src/content/docs/bs/providers.mdx b/packages/web/src/content/docs/bs/providers.mdx new file mode 100644 index 00000000000..2415cda2778 --- /dev/null +++ b/packages/web/src/content/docs/bs/providers.mdx @@ -0,0 +1,1895 @@ +--- +title: Provajderi +description: Korištenje bilo kojeg LLM provajdera u OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console + +OpenCode koristi [AI SDK](https://ai-sdk.dev/) i [Models.dev](https://models.dev) za podršku **75+ LLM provajdera** i podržava pokretanje lokalnih modela. + +Za dodavanje provajdera potrebno je: + +1. Dodajte API ključeve za provajdera koristeći naredbu `/connect`. +2. Konfigurirajte dobavljača u vašoj OpenCode konfiguraciji. + +--- + +### Vjerodajnice + +Kada dodate API ključeve dobavljača sa naredbom `/connect`, oni se pohranjuju +u `~/.local/share/opencode/auth.json`. + +--- + +### Konfiguracija + +Možete prilagoditi dobavljače putem odjeljka `provider` u vašem OpenCode +config. + +--- + +#### Osnovni URL + +Možete prilagoditi osnovni URL za bilo kojeg provajdera postavljanjem opcije `baseURL`. Ovo je korisno kada koristite proxy usluge ili prilagođene krajnje tačke. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen je lista modela koje je obezbedio OpenCode tim koji su bili +testirano i potvrđeno da dobro radi sa OpenCode. [Saznajte više](/docs/zen). + +:::tip +Ako ste novi, preporučujemo da počnete sa OpenCode Zen. +::: + +1. Pokrenite naredbu `/connect` u TUI-u, odaberite opencode i idite na [opencode.ai/auth](https://opencode.ai/auth). + +```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 `/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 +listu, slobodno otvori PR. + +:::note +Ne vidite provajdera ovdje? Pošaljite PR. +::: + +--- + +### 302.AI + +1. Idite na [302.AI konzolu](https://302.ai/), kreirajte račun i generirajte API ključ. + +2. Pokrenite naredbu `/connect` i potražite **302.AI**. + +```txt + /connect +``` + +3. Unesite svoj 302.AI API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model. + +```txt + /models +``` + +--- + +### Amazon Bedrock + +Da biste koristili Amazon Bedrock s OpenCode: + +1. Idite na **Katalog modela** na Amazon Bedrock konzoli i zatražite + pristup modelima koje želite. + + :::tip + Morate imati pristup modelu koji želite u Amazon Bedrock. + ::: + +2. **Konfigurirajte autentifikaciju** koristeći jedan od sljedećih metoda: + + #### Varijable okruženja (Brzi početak) + + Postavite jednu od ovih varijabli okruženja dok pokrećete opencode: + +```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode +``` + +Ili ih dodajte na svoj bash profil: + +```bash title="~/.bash_profile" + export AWS_PROFILE=my-dev-profile + export AWS_REGION=us-east-1 +``` + +#### Konfiguracijski fajl (Preporučeno) + +Za konfiguraciju specifičnu za projekat ili trajnu konfiguraciju, koristite `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile" + } + } + } +} +``` + +**Dostupne opcije:** + +- `region` - ​​AWS regija (npr. `us-east-1`, `eu-west-1`) +- `profile` - ​​AWS je imenovao profil od `~/.aws/credentials` +- `endpoint` - ​​URL prilagođene krajnje tačke za VPC krajnje tačke (pseudonim za generičku opciju `baseURL`) + +:::tip +Opcije konfiguracijske datoteke imaju prednost nad varijablama okruženja. +::: + +#### Napredno: VPC krajnje tačke + +Ako koristite VPC krajnje tačke za Bedrock: + +```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 +Opcija `endpoint` je pseudonim za generičku opciju `baseURL`, koristeći terminologiju specifičnu za AWS. Ako su specificirani i `endpoint` i `baseURL`, `endpoint` ima prednost. +::: + +#### Metode provjere autentičnosti + +- **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: Kreirajte IAM korisnika i generirajte pristupne ključeve u AWS konzoli +- **`AWS_PROFILE`**: Koristite imenovane profile od `~/.aws/credentials`. Prvo konfigurirajte sa `aws configure --profile my-profile` ili `aws sso login` +- **`AWS_BEARER_TOKEN_BEDROCK`**: Generirajte dugoročne API ključeve sa Amazon Bedrock konzole +- **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: Za EKS IRSA (IAM uloge za servisne naloge) ili druga Kubernetes okruženja sa OIDC federacijom. Kubernetes automatski ubacuje ove varijable okruženja kada se koriste napomene naloga usluge. + +#### Prioritet autentifikacije + +Amazon Bedrock koristi sljedeći prioritet autentifikacije: + +1. **Token nosioca** - `AWS_BEARER_TOKEN_BEDROCK` varijabla okruženja ili token iz naredbe `/connect` +2. **AWS lanac vjerodajnica** - profil, pristupni ključevi, dijeljeni vjerodajnici, IAM uloge, tokeni web identiteta (EKS IRSA), metapodaci instance + +:::note +Kada se postavi token nosioca (putem `/connect` ili `AWS_BEARER_TOKEN_BEDROCK`), on ima prednost nad svim AWS metodama akreditiva uključujući konfigurirane profile. +::: + +3. Pokrenite naredbu `/models` da odaberete model koji želite. + +```txt + /models +``` + +:::note +Za prilagođene profile zaključivanja, koristite ime modela i dobavljača u ključu i postavite svojstvo `id` na arn. Ovo osigurava ispravno keširanje: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. Nakon što ste se prijavili, pokrenite naredbu `/connect` i odaberite Anthropic. + +```txt + /connect +``` + +2. Ovdje možete odabrati opciju **Claude Pro/Max** i ona će otvoriti vaš pretraživač + i traži od vas da se autentifikujete. + +```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ +``` + +3. Sada bi svi Anthropic modeli trebali biti dostupni kada koristite naredbu `/models`. + +```txt + /models +``` + +:::info +[Anthropic] (https://anthropic.com) službeno ne podržava korištenje vaše Claude Pro/Max pretplate u OpenCode. +::: + +##### Korištenje API ključeva + +Također možete odabrati **Kreiraj API ključ** ako nemate Pro/Max pretplatu. Također će otvoriti vaš pretraživač i zatražiti od vas da se prijavite na Anthropic i dati vam kod koji možete zalijepiti u svoj terminal. + +Ili ako već imate API ključ, možete odabrati **Ručno unesite API ključ** i zalijepite ga u svoj terminal. + +--- + +### Azure OpenAI + +:::note +Ako naiđete na greške "Žao mi je, ali ne mogu pomoći s tim zahtjevom", pokušajte promijeniti filter sadržaja iz **DefaultV2** u **Default** u vašem Azure resursu. +::: + +1. Idite na [Azure portal](https://portal.azure.com/) i kreirajte **Azure OpenAI** resurs. trebat će vam: + - **Naziv resursa**: Ovo postaje dio vaše krajnje tačke API-ja (`https://RESOURCE_NAME.openai.azure.com/`) + - **API ključ**: Ili `KEY 1` ili `KEY 2` sa vašeg izvora + +2. Idite na [Azure AI Foundry](https://ai.azure.com/) i implementirajte model. + + :::note + Ime implementacije mora odgovarati imenu modela da bi opencode ispravno radio. + ::: + +3. Pokrenite naredbu `/connect` i potražite **Azure**. + +```txt + /connect +``` + +4. Unesite svoj API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +5. Postavite ime vašeg resursa kao varijablu okruženja: + +```bash + AZURE_RESOURCE_NAME=XXX opencode +``` + +Ili ga dodajte na svoj bash profil: + +```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX +``` + +6. Pokrenite naredbu `/models` da odaberete svoj raspoređeni model. + +```txt + /models +``` + +--- + +### Azure Cognitive Services + +1. Idite na [Azure portal](https://portal.azure.com/) i kreirajte **Azure OpenAI** resurs. trebat će vam: + - **Naziv resursa**: Ovo postaje dio vaše krajnje tačke API-ja (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) + - **API ključ**: Ili `KEY 1` ili `KEY 2` sa vašeg izvora + +2. Idite na [Azure AI Foundry](https://ai.azure.com/) i implementirajte model. + + :::note + Ime implementacije mora odgovarati imenu modela da bi opencode ispravno radio. + ::: + +3. Pokrenite naredbu `/connect` i potražite **Azure kognitivne usluge**. + +```txt + /connect +``` + +4. Unesite svoj API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +5. Postavite ime vašeg resursa kao varijablu okruženja: + +```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode +``` + +Ili ga dodajte na svoj bash profil: + +```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX +``` + +6. Pokrenite naredbu `/models` da odaberete svoj raspoređeni model. + +```txt + /models +``` + +--- + +### Baseten + +1. Idite na [Baseten](https://app.baseten.co/), kreirajte račun i generirajte API ključ. + +2. Pokrenite naredbu `/connect` i potražite **Baseten**. + +```txt + /connect +``` + +3. Unesite svoj Baseten API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model. + +```txt + /models +``` + +--- + +### Cerebras + +1. Idite na [Cerebras konzolu](https://inference.cerebras.ai/), kreirajte račun i generirajte API ključ. + +2. Pokrenite naredbu `/connect` i potražite **Cerebras**. + +```txt + /connect +``` + +3. Unesite svoj Cerebras API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model kao što je _Qwen 3 Coder 480B_. + +```txt + /models +``` + +--- + +### Cloudflare AI Gateway + +Cloudflare AI Gateway vam omogućava da pristupite modelima iz OpenAI, Anthropic, Workers AI i više preko objedinjene krajnje tačke. Sa [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) nisu vam potrebni posebni API ključevi za svakog provajdera. + +1. Idite na [Cloudflare kontrolnu tablu](https://dash.cloudflare.com/), idite na **AI** > **AI Gateway** i kreirajte novi pristupnik. + +2. Postavite svoj ID naloga i ID pristupnika kao varijable okruženja. + +```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id +``` + +3. Pokrenite naredbu `/connect` i potražite **Cloudflare AI Gateway**. + +```txt + /connect +``` + +4. Unesite svoj Cloudflare API token. + +```txt + ┌ API key + │ + │ + └ enter +``` + +Ili ga postavite kao varijablu okruženja. + +```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token +``` + +5. Pokrenite naredbu `/models` da odaberete model. + +```txt + /models +``` + +Također možete dodati modele kroz svoju opencode konfiguraciju. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } +} +``` + +--- + +### Cortecs + +1. Idite na [Cortecs konzolu](https://cortecs.ai/), kreirajte račun i generirajte API ključ. + +2. Pokrenite naredbu `/connect` i potražite **Cortecs**. + +```txt + /connect +``` + +3. Unesite svoj Cortecs API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model kao što je _Kimi K2 Instruct_. + +```txt + /models +``` + +--- + +### DeepSeek + +1. Idite na [DeepSeek konzolu](https://platform.deepseek.com/), kreirajte nalog i kliknite na **Kreiraj novi API ključ**. + +2. Pokrenite naredbu `/connect` i potražite **DeepSeek**. + +```txt + /connect +``` + +3. Unesite svoj DeepSeek API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete DeepSeek model kao što je _DeepSeek Reasoner_. + +```txt + /models +``` + +--- + +### Deep Infra + +1. Idite na [Deep Infra kontrolnu tablu](https://deepinfra.com/dash), kreirajte nalog i generišite API ključ. + +2. Pokrenite naredbu `/connect` i potražite **Deep Infra**. + +```txt + /connect +``` + +3. Unesite svoj Deep Infra API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model. + +```txt + /models +``` + +--- + +### Firmware + +1. Idite na [kontrolnu tablu firmvera](https://app.firmware.ai/signup), kreirajte nalog i generišite API ključ. + +2. Pokrenite naredbu `/connect` i potražite **Firmware**. + +```txt + /connect +``` + +3. Unesite svoj Firmware API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model. + +```txt + /models +``` + +--- + +### Fireworks AI + +1. Idite na [Fireworks AI konzolu](https://app.fireworks.ai/), kreirajte račun i kliknite na **Kreiraj API ključ**. + +2. Pokrenite naredbu `/connect` i potražite **Fireworks AI**. + +```txt + /connect +``` + +3. Unesite svoj Fireworks AI API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model kao što je _Kimi K2 Instruct_. + +```txt + /models +``` + +--- + +### GitLab Duo + +GitLab Duo pruža agentsko ćaskanje sa AI-om sa izvornim mogućnostima pozivanja alata preko GitLab-ovog Anthropic proxyja. + +1. Pokrenite naredbu `/connect` i odaberite GitLab. + +```txt + /connect +``` + +2. Odaberite svoj način autentifikacije: + +```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ +``` + +#### Korištenje OAuth-a (preporučeno) + +Odaberite **OAuth** i vaš pretraživač će se otvoriti za autorizaciju. + +#### Korištenje tokena ličnog pristupa + +1. Idite na [GitLab korisničke postavke > Pristupni tokeni](https://gitlab.com/-/user_settings/personal_access_tokens) +2. Kliknite **Dodaj novi token** +3. Naziv: `OpenCode`, opseg: `api` +4. Kopirajte token (počinje sa `glpat-`) +5. Unesite ga u terminal + +6. Pokrenite naredbu `/models` da vidite dostupne modele. + +```txt + /models +``` + +Dostupna su tri modela bazirana na Claudeu: + +- **duo-chat-haiku-4-5** (zadano) - Brzi odgovori za brze zadatke +- **duo-chat-sonnet-4-5** - Uravnotežene performanse za većinu tokova posla +- **duo-chat-opus-4-5** - Najsposobniji za kompleksnu analizu + +:::note +Također možete odrediti 'GITLAB_TOKEN' varijablu okruženja ako ne želite +da pohrani token u opencode auth memoriju. +::: + +##### Samostalni GitLab + +:::note[Napomena o usklađenosti] +OpenCode koristi mali model za neke AI zadatke kao što je generiranje naslova sesije. +Podrazumevano je konfigurisan da koristi gpt-5-nano, a hostuje ga Zen. Da zaključate OpenCode +da biste koristili samo svoju vlastitu instancu koju hostuje GitLab, dodajte sljedeće u svoju +`opencode.json` fajl. Također se preporučuje da onemogućite dijeljenje sesije. + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +Za GitLab instance koje hostuju sami: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +Ako vaša instanca pokreće prilagođeni AI Gateway: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +Ili dodajte na svoj bash profil: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +Vaš GitLab administrator mora omogućiti sljedeće: + +1. [Duo Agent Platforma](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) za korisnika, grupu ili instancu +2. Zastavice funkcija (preko Rails konzole): + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: + +##### OAuth za self-hosted instance + +Da bi Oauth radio za vašu instancu koju sami hostujete, morate kreirati +novu aplikaciju (Podešavanja → Aplikacije) sa +URL povratnog poziva `http://127.0.0.1:8080/callback` i sljedeći opseg: + +- api (pristupite API-ju u svoje ime) +- read_user (Pročitajte svoje lične podatke) +- read_repository (omogućava pristup spremištu samo za čitanje) + +Zatim izložite ID aplikacije kao varijablu okruženja: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +Više dokumentacije na početnoj stranici [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth). + +##### Konfiguracija + +Prilagodite putem `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### GitLab API alati (opciono, ali se preporučuje) + +Za pristup GitLab alatima (zahtjevi za spajanje, problemi, cjevovodi, CI/CD, itd.): + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +Ovaj dodatak pruža sveobuhvatne mogućnosti upravljanja GitLab repozitorijumom, uključujući MR preglede, praćenje problema, praćenje procesa i još mnogo toga. + +--- + +### GitHub Copilot + +Da biste koristili svoju GitHub Copilot pretplatu s opencode: + +:::note +Neki modeli će možda trebati [Pro+ +pretplata](https://github.com/features/copilot/plans) za korištenje. + +Neki modeli moraju biti ručno omogućeni u vašim [postavkama GitHub Copilot](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use). +::: + +1. Pokrenite naredbu `/connect` i potražite GitHub Copilot. + +```txt + /connect +``` + +2. Idite na [github.com/login/device](https://github.com/login/device) i unesite kod. + +```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + └ Waiting for authorization... +``` + +3. Sada pokrenite naredbu `/models` da odaberete model koji želite. + +```txt + /models +``` + +--- + +### Google Vertex AI + +Za korištenje Google Vertex AI s OpenCode: + +1. Idite do **Model Garden** u Google Cloud Console i provjerite + modeli dostupni u vašoj regiji. + + :::note + Morate imati Google Cloud projekat sa omogućenim Vertex AI API. + ::: + +2. Postavite potrebne varijable okruženja: + - `GOOGLE_CLOUD_PROJECT`: ID vašeg Google Cloud projekta + - `VERTEX_LOCATION` (opciono): Region za Vertex AI (podrazumevano na `global`) + - Autentifikacija (odaberite jednu): + - `GOOGLE_APPLICATION_CREDENTIALS`: Put do JSON ključnog fajla vašeg naloga usluge + - Autentifikacija koristeći gcloud CLI: `gcloud auth application-default login` + + Postavite ih dok se pokreće opencode. + +```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode +``` + +Ili ih dodajte svom bash profilu. + +```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 +Regija `global` poboljšava dostupnost i smanjuje greške bez dodatnih troškova. Koristite regionalne krajnje tačke (npr. `us-central1`) za zahtjeve rezidentnosti podataka. [Saznajte više](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. Pokrenite naredbu `/models` da odaberete model koji želite. + +```txt + /models +``` + +--- + +### Groq + +1. Idite na [Groq konzolu](https://console.groq.com/), kliknite **Kreiraj API ključ** i kopirajte ključ. + +2. Pokrenite naredbu `/connect` i potražite Groq. + +```txt + /connect +``` + +3. Unesite API ključ za provajdera. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete onu koju želite. + +```txt + /models +``` + +--- + +### Hugging Face + +[Hugging Face Inference Providers](https://huggingface.co/docs/inference-providers) omogućava pristup otvorenim modelima koje podržava 17+ provajdera. + +1. Idite na [Postavke zagrljaja](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained) da kreirate token s dozvolom za upućivanje poziva dobavljačima inference. + +2. Pokrenite naredbu `/connect` i potražite **Hugging Face**. + +```txt + /connect +``` + +3. Unesite svoj token Hugging Face. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model kao što je _Kimi-K2-Instruct_ ili _GLM-4.6_. + +```txt + /models +``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) je platforma za praćenje LLM koja pruža evidenciju, praćenje i analitiku za vaše AI aplikacije. Helicone AI Gateway automatski usmjerava vaše zahtjeve do odgovarajućeg provajdera na osnovu modela. + +1. Idite na [Helicone](https://helicone.ai), kreirajte račun i generirajte API ključ sa svoje kontrolne table. + +2. Pokrenite naredbu `/connect` i potražite **Helicone**. + +```txt + /connect +``` + +3. Unesite svoj Helicone API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model. + +```txt + /models +``` + +Za više provajdera i napredne funkcije kao što su keširanje i ograničavanje brzine, provjerite [Helicone dokumentaciju](https://docs.helicone.ai). + +#### Opcione konfiguracije + +U slučaju da vidite funkciju ili model iz Helicone-a koji nije automatski konfiguriran putem opencodea, uvijek ga možete sami konfigurirati. + +Evo [Heliconeov katalog modela](https://helicone.ai/models), ovo će vam trebati da preuzmete ID-ove modela koje želite dodati. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### Prilagođena zaglavlja + +Helicone podržava prilagođena zaglavlja za funkcije kao što su keširanje, praćenje korisnika i upravljanje sesijom. Dodajte ih u konfiguraciju svog provajdera koristeći `options.headers`: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### Praćenje sesije + +Heliconeova funkcija [Sessions](https://docs.helicone.ai/features/sessions) vam omogućava da grupišete povezane LLM zahtjeve zajedno. Koristite dodatak [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) da automatski prijavite svaki OpenCode razgovor kao sesiju u Helicone-u. + +```bash +npm install -g opencode-helicone-session +``` + +Dodajte ga u svoju konfiguraciju. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +Dodatak ubacuje zaglavlja `Helicone-Session-Id` i `Helicone-Session-Name` u vaše zahtjeve. Na stranici Helicone Sessions, vidjet ćete svaki OpenCode razgovor naveden kao zasebna sesija. + +##### Uobičajena Helicone zaglavlja + +| Header | Opis | +| -------------------------- | ------------------------------------------------------------------- | +| `Helicone-Cache-Enabled` | Omogući keširanje odgovora (`true`/`false`) | +| `Helicone-User-Id` | Pratite metriku po korisniku | +| `Helicone-Property-[Name]` | Dodajte prilagođena svojstva (npr. `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | Povezivanje zahtjeva sa brzim verzijama | + +Pogledajte [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory) za sva dostupna zaglavlja. + +--- + +### llama.cpp + +Možete konfigurirati opencode za korištenje lokalnih modela putem [llama.cpp's](https://github.com/ggml-org/llama.cpp) uslužnog programa llama-server + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +U ovom primjeru: + +- `llama.cpp` je ID prilagođenog provajdera. Ovo može biti bilo koji niz koji želite. +- `npm` specificira paket koji će se koristiti za ovog provajdera. Ovdje se `@ai-sdk/openai-compatible` koristi za bilo koji OpenAI kompatibilan API. +- `name` je ime za prikaz za provajdera u korisničkom sučelju. +- `options.baseURL` je krajnja tačka za lokalni server. +- `models` je mapa ID-ova modela prema njihovim konfiguracijama. Naziv modela će biti prikazan na listi za odabir modela. + +--- + +### IO.NET + +IO.NET nudi 17 modela optimiziranih za različite slučajeve upotrebe: + +1. Idite na [IO.NET konzolu](https://ai.io.net/), kreirajte račun i generirajte API ključ. + +2. Pokrenite naredbu `/connect` i potražite **IO.NET**. + +```txt + /connect +``` + +3. Unesite svoj IO.NET API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model. + +```txt + /models +``` + +--- + +### LM Studio + +Možete konfigurirati opencode za korištenje lokalnih modela preko LM Studio. + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +U ovom primjeru: + +- `lmstudio` je ID prilagođenog provajdera. Ovo može biti bilo koji niz koji želite. +- `npm` specificira paket koji će se koristiti za ovog provajdera. Ovdje se `@ai-sdk/openai-compatible` koristi za bilo koji OpenAI kompatibilan API. +- `name` je ime za prikaz za provajdera u korisničkom sučelju. +- `options.baseURL` je krajnja tačka za lokalni server. +- `models` je mapa ID-ova modela prema njihovim konfiguracijama. Naziv modela će biti prikazan na listi za odabir modela. + +--- + +### Moonshot AI + +Da biste koristili Kimi K2 iz Moonshot AI: + +1. Idite na [Moonshot AI konzolu](https://platform.moonshot.ai/console), kreirajte nalog i kliknite na **Kreiraj API ključ**. + +2. Pokrenite naredbu `/connect` i potražite **Moonshot AI**. + +```txt + /connect +``` + +3. Unesite svoj Moonshot API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete _Kimi K2_. + +```txt + /models +``` + +--- + +### MiniMax + +1. Prijeđite na [MiniMax API konzolu](https://platform.minimax.io/login), kreirajte račun i generirajte API ključ. + +2. Pokrenite naredbu `/connect` i potražite **MiniMax**. + +```txt + /connect +``` + +3. Unesite svoj MiniMax API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model kao što je _M2.1_. + +```txt + /models +``` + +--- + +### Nebius Token Factory + +1. Idite na [Nebius Token Factory konzolu](https://tokenfactory.nebius.com/), kreirajte nalog i kliknite na **Dodaj ključ**. + +2. Pokrenite naredbu `/connect` i potražite **Nebius Token Factory**. + +```txt + /connect +``` + +3. Unesite svoj Nebius Token Factory API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model kao što je _Kimi K2 Instruct_. + +```txt + /models +``` + +--- + +### Ollama + +Možete konfigurirati opencode za korištenje lokalnih modela putem Ollame. + +:::tip +Ollama se može automatski konfigurirati za OpenCode. Pogledajte [Ollama integracijske dokumente](https://docs.ollama.com/integrations/opencode) za detalje. +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +U ovom primjeru: + +- `ollama` je ID prilagođenog provajdera. Ovo može biti bilo koji niz koji želite. +- `npm` specificira paket koji će se koristiti za ovog provajdera. Ovdje se `@ai-sdk/openai-compatible` koristi za bilo koji OpenAI kompatibilan API. +- `name` je ime za prikaz za provajdera u korisničkom sučelju. +- `options.baseURL` je krajnja tačka za lokalni server. +- `models` je mapa ID-ova modela prema njihovim konfiguracijama. Naziv modela će biti prikazan na listi za odabir modela. + +:::tip +Ako pozivi alata ne rade, pokušajte povećati `num_ctx` u Ollama. Počnite oko 16k - 32k. +::: + +--- + +### Ollama Cloud + +Da biste koristili Ollama Cloud s OpenCode: + +1. Idite na [https://ollama.com/](https://ollama.com/) i prijavite se ili kreirajte račun. + +2. Idite na **Postavke** > **Ključevi** i kliknite na **Dodaj API ključ** da generišete novi API ključ. + +3. Kopirajte API ključ za korištenje u OpenCode. + +4. Pokrenite naredbu `/connect` i potražite **Ollama Cloud**. + +```txt + /connect +``` + +5. Unesite svoj Ollama Cloud API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +6. **Važno**: Prije upotrebe modela oblaka u OpenCode, morate lokalno povući informacije o modelu: + +```bash + ollama pull gpt-oss:20b-cloud +``` + +7. Pokrenite naredbu `/models` da odaberete svoj model Ollama Cloud. + +```txt + /models +``` + +--- + +### OpenAI + +Preporučujemo da se prijavite za [ChatGPT Plus ili Pro](https://chatgpt.com/pricing). + +1. Nakon što ste se prijavili, pokrenite naredbu `/connect` i odaberite OpenAI. + +```txt + /connect +``` + +2. Ovdje možete odabrati opciju **ChatGPT Plus/Pro** i ona će otvoriti vaš pretraživač + i traži od vas da se autentifikujete. + +```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ +``` + +3. Sada bi svi OpenAI modeli trebali biti dostupni kada koristite naredbu `/models`. + +```txt + /models +``` + +##### Korištenje API ključeva + +Ako već imate API ključ, možete odabrati **Ručno unesite API ključ** i zalijepite ga u svoj terminal. + +--- + +### OpenCode Zen + +OpenCode Zen je lista testiranih i verifikovanih modela koju je obezbedio OpenCode tim. [Saznajte više](/docs/zen). + +1. Prijavite se na **OpenCode Zen** i kliknite na **Kreiraj API ključ**. + +2. Pokrenite naredbu `/connect` i potražite **OpenCode Zen**. + +```txt + /connect +``` + +3. Unesite svoj OpenCode API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model kao što je _Qwen 3 Coder 480B_. + +```txt + /models +``` + +--- + +### OpenRouter + +1. Idite na [OpenRouter nadzornu ploču](https://openrouter.ai/settings/keys), kliknite na **Kreiraj API ključ** i kopirajte ključ. + +2. Pokrenite naredbu `/connect` i potražite OpenRouter. + +```txt + /connect +``` + +3. Unesite API ključ za provajdera. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Mnogi OpenRouter modeli su unapred učitani po defaultu, pokrenite naredbu `/models` da odaberete onaj koji želite. + +```txt + /models +``` + +Također možete dodati dodatne modele putem vaše opencode konfiguracije. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "somecoolnewmodel": {} + } + } + } +} +``` + +5. Također ih možete prilagoditi putem vaše opencode konfiguracije. Evo primjera navođenja provajdera + +```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 omogućava pristup preko 40+ modela iz OpenAI, Anthropic, Google, Amazon, Meta, Mistral i AI21 putem objedinjene platforme. + +1. Idite na vaš [SAP BTP Cockpit](https://account.hana.ondemand.com/), idite na instancu usluge SAP AI Core i kreirajte servisni ključ. + + :::tip + Servisni ključ je JSON objekat koji sadrži `clientid`, `clientsecret`, `url` i `serviceurls.AI_API_URL`. Svoju AI Core instancu možete pronaći pod **Usluge** > **Instance i pretplate** u BTP kokpitu. + ::: + +2. Pokrenite naredbu `/connect` i potražite **SAP AI Core**. + +```txt + /connect +``` + +3. Unesite JSON svoj servisni ključ. + +```txt + ┌ Service key + │ + │ + └ enter +``` + +Ili postavite varijablu okruženja `AICORE_SERVICE_KEY`: + +```bash + AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode +``` + +Ili ga dodajte na svoj bash profil: + +```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' +``` + +4. Opciono postavite ID implementacije i grupu resursa: + +```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode +``` + +:::note +Ove postavke su opcione i treba ih konfigurirati u skladu s vašim SAP AI Core postavkama. +::: + +5. Pokrenite naredbu `/models` da odaberete između 40+ dostupnih modela. + +```txt + /models +``` + +--- + +### OVHcloud AI krajnje tačke + +1. Idite na [OVHcloud panel](https://ovh.com/manager). Idite do odjeljka `Public Cloud`, `AI & Machine Learning` > `AI Endpoints` i na kartici `API Keys` kliknite na **Kreiraj novi API ključ**. + +2. Pokrenite naredbu `/connect` i potražite **OVHcloud AI krajnje točke**. + +```txt + /connect +``` + +3. Unesite svoj OVHcloud AI Endpoints API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model kao što je _gpt-oss-120b_. + +```txt + /models +``` + +--- + +### Scaleway + +Da biste koristili [Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/) sa Opencodeom: + +1. Prijeđite na [Scaleway Console IAM postavke](https://console.scaleway.com/iam/api-keys) da generišete novi API ključ. + +2. Pokrenite naredbu `/connect` i potražite **Scaleway**. + +```txt + /connect +``` + +3. Unesite svoj Scaleway API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model kao što je _devstral-2-123b-instruct-2512_ ili _gpt-oss-120b_. + +```txt + /models +``` + +--- + +### Together AI + +1. Idite na [Together AI console](https://api.together.ai), kreirajte nalog i kliknite na **Dodaj ključ**. + +2. Pokrenite naredbu `/connect` i potražite **Together AI**. + +```txt + /connect +``` + +3. Unesite svoj Together AI API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model kao što je _Kimi K2 Instruct_. + +```txt + /models +``` + +--- + +### Venice AI + +1. Idite na [Venice AI konzolu](https://venice.ai), kreirajte račun i generirajte API ključ. + +2. Pokrenite naredbu `/connect` i potražite **Venice AI**. + +```txt + /connect +``` + +3. Unesite svoj Venice AI API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model kao što je _Llama 3.3 70B_. + +```txt + /models +``` + +--- + +### Vercel AI Gateway + +Vercel AI Gateway vam omogućava da pristupite modelima iz OpenAI, Anthropic, Google, xAI i drugih putem objedinjene krajnje tačke. Modeli se nude po kataloškim cijenama bez maraka. + +1. Idite na [Vercel kontrolnu tablu](https://vercel.com/), idite na karticu **AI Gateway** i kliknite na **API ključevi** da kreirate novi API ključ. + +2. Pokrenite naredbu `/connect` i potražite **Vercel AI Gateway**. + +```txt + /connect +``` + +3. Unesite svoj Vercel AI Gateway API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model. + +```txt + /models +``` + +Također možete prilagoditi modele kroz svoju opencode konfiguraciju. Evo primjera specificiranja redoslijeda usmjeravanja dobavljača. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "vercel": { + "models": { + "anthropic/claude-sonnet-4": { + "options": { + "order": ["anthropic", "vertex"] + } + } + } + } + } +} +``` + +Neke korisne opcije rutiranja: + +| Opcija | Opis | +| ------------------- | ------------------------------------------------------------------ | +| `order` | Redoslijed dobavljača za pokušaj | +| `only` | Ograničiti na određene provajdere | +| `zeroDataRetention` | Koristite samo provajdere sa nultom politikom zadržavanja podataka | + +--- + +### xAI + +1. Prijeđite na [xAI konzolu](https://console.x.ai/), kreirajte račun i generirajte API ključ. + +2. Pokrenite naredbu `/connect` i potražite **xAI**. + +```txt + /connect +``` + +3. Unesite svoj xAI API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model kao što je _Grok Beta_. + +```txt + /models +``` + +--- + +### Z.AI + +1. Idite na [Z.AI API konzolu](https://z.ai/manage-apikey/apikey-list), kreirajte nalog i kliknite na **Kreiraj novi API ključ**. + +2. Pokrenite naredbu `/connect` i potražite **Z.AI**. + +```txt + /connect +``` + +Ako ste pretplaćeni na **GLM plan kodiranja**, odaberite **Z.AI plan kodiranja**. + +3. Unesite svoj Z.AI API ključ. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Pokrenite naredbu `/models` da odaberete model kao što je _GLM-4.7_. + +```txt + /models +``` + +--- + +### ZenMux + +1. Idite na [ZenMux kontrolnu tablu](https://zenmux.ai/settings/keys), kliknite na **Kreiraj API ključ** i kopirajte ključ. + +2. Pokrenite naredbu `/connect` i potražite ZenMux. + +```txt + /connect +``` + +3. Unesite API ključ za provajdera. + +```txt + ┌ API key + │ + │ + └ enter +``` + +4. Mnogi ZenMux modeli su unaprijed učitani po defaultu, pokrenite naredbu `/models` da odaberete onaj koji želite. + +```txt + /models +``` + +Također možete dodati dodatne modele putem vaše opencode konfiguracije. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "zenmux": { + "models": { + "somecoolnewmodel": {} + } + } + } +} +``` + +--- + +## Prilagođeni provajder + +Da biste dodali bilo kojeg **OpenAI-kompatibilnog** provajdera koji nije naveden u naredbi `/connect`: + +:::tip +Možete koristiti bilo kojeg OpenAI kompatibilnog provajdera s opencode-om. Većina modernih AI provajdera nudi API-je kompatibilne sa OpenAI. +::: + +1. Pokrenite naredbu `/connect` i pomaknite se prema dolje do **Ostalo**. + +```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ +``` + +2. Unesite jedinstveni ID za provajdera. + +```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ +``` + +:::note +Odaberite ID koji se pamti, to ćete koristiti u svom konfiguracijskom fajlu. +::: + +3. Unesite svoj API ključ za provajdera. + +```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. Kreirajte ili ažurirajte svoju `opencode.json` datoteku u direktoriju projekta: + +```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" + } + } + } + } +} +``` + +Evo opcija konfiguracije: + +- **npm**: AI SDK paket za korištenje, `@ai-sdk/openai-compatible` za OpenAI-kompatibilne provajdere +- **name**: Ime za prikaz u korisničkom sučelju. +- **modeli**: Dostupni modeli. +- **options.baseURL**: URL krajnje tačke API-ja. +- **options.apiKey**: Opciono postavite API ključ, ako ne koristite auth. +- **options.headers**: Opciono postavite prilagođena zaglavlja. + +Više o naprednim opcijama u primjeru ispod. + +5. Pokrenite naredbu `/models` i vaš prilagođeni provajder i modeli će se pojaviti na listi izbora. + +--- + +##### Primjer + +Evo primjera postavljanja opcija `apiKey`, `headers` i modela `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 + } + } + } + } + } +} +``` + +Detalji konfiguracije: + +- **apiKey**: Postavite pomoću sintakse varijable `env`, [saznajte više](/docs/config#env-vars). +- **zaglavlja**: Prilagođena zaglavlja se šalju sa svakim zahtjevom. +- **limit.context**: Maksimalni ulazni tokeni koje model prihvata. +- **limit.output**: Maksimalni tokeni koje model može generirati. + +Polja `limit` omogućavaju OpenCode da shvati koliko vam je konteksta ostalo. Standardni dobavljači ih automatski preuzimaju sa models.dev. + +--- + +## Rješavanje problema + +Ako imate problema s konfiguracijom provajdera, provjerite sljedeće: + +1. **Provjerite postavke autentifikacije**: Pokrenite `opencode auth list` da vidite da li su vjerodajnice + za provajdera se dodaju u vašu konfiguraciju. + + Ovo se ne odnosi na dobavljače kao što je Amazon Bedrock, koji se oslanjaju na varijable okruženja za svoju autentifikaciju. + +2. Za prilagođene provajdere, provjerite OpenCode konfiguraciju i: + - Uvjerite se da ID provajdera korišten u naredbi `/connect` odgovara ID-u u vašoj opencode konfiguraciji. + - Za provajdera se koristi pravi npm paket. Na primjer, koristite `@ai-sdk/cerebras` za Cerebras. A za sve ostale OpenAI kompatibilne provajdere, koristite `@ai-sdk/openai-compatible`. + - Provjerite da li se ispravna krajnja tačka API-ja koristi u polju `options.baseURL`. diff --git a/packages/web/src/content/docs/bs/rules.mdx b/packages/web/src/content/docs/bs/rules.mdx new file mode 100644 index 00000000000..3d186a045dd --- /dev/null +++ b/packages/web/src/content/docs/bs/rules.mdx @@ -0,0 +1,180 @@ +--- +title: Pravila +description: Postavite prilagodena uputstva za opencode. +--- + +Mozete dodati prilagodena uputstva za opencode tako sto kreirate `AGENTS.md` datoteku. Ovo je slicno pravilima u Cursor-u. Sadrzi uputstva koja se ubacuju u LLM kontekst da prilagode ponasanje za vas projekat. + +--- + +## Inicijalizacija + +Da kreirate novu `AGENTS.md` datoteku, pokrenite `/init` komandu u opencode. + +:::tip +Preporuceno je da `AGENTS.md` iz projekta commitujete u Git. +::: + +Ovo skenira projekat i njegov sadrzaj, razumije cemu projekat sluzi i generise `AGENTS.md`. Tako opencode bolje navigira kroz kod. + +Ako vec imate `AGENTS.md`, komanda ce pokusati da ga dopuni. + +--- + +## Primjer + +Datoteku mozete napraviti i rucno. Evo primjera sta mozete staviti u `AGENTS.md`. + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +Ovdje dodajete uputstva specificna za projekat koja se dijele sa timom. + +--- + +## Tipovi + +opencode podrzava citanje `AGENTS.md` datoteke sa vise lokacija. Svaka lokacija ima drugu svrhu. + +### Projekat + +Stavite `AGENTS.md` u korijen projekta za pravila specificna za taj projekat. Primjenjuju se samo kada radite u tom direktoriju ili poddirektorijima. + +### Globalno + +Mozete imati i globalna pravila u `~/.config/opencode/AGENTS.md`. Ona se primjenjuju u svim opencode sesijama. + +Posto se ovo ne commituje u Git niti dijeli s timom, najbolje je da ovdje cuvate licna pravila koja LLM treba pratiti. + +### Kompatibilnost s Claude Code + +Za korisnike koji prelaze sa Claude Code, OpenCode podrzava i Claude konvencije datoteka kao rezervu: + +- **Pravila projekta**: `CLAUDE.md` u direktoriju projekta (koristi se ako ne postoji `AGENTS.md`) +- **Globalna pravila**: `~/.claude/CLAUDE.md` (koristi se ako ne postoji `~/.config/opencode/AGENTS.md`) +- **Skills**: `~/.claude/skills/` — pogledajte [Agent Skills](/docs/skills/) za detalje + +Da iskljucite kompatibilnost sa Claude Code, postavite jednu od ovih varijabli okruzenja: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## Prioritet + +Kada se opencode pokrene, trazi datoteke pravila ovim redoslijedom: + +1. **Lokalne datoteke** pretrazivanjem prema gore od trenutnog direktorija (`AGENTS.md`, `CLAUDE.md`) +2. **Globalna datoteka** na `~/.config/opencode/AGENTS.md` +3. **Claude Code datoteka** na `~/.claude/CLAUDE.md` (osim ako je iskljucena) + +Prva pronadena datoteka pobjeduje u svakoj kategoriji. Na primjer, ako imate i `AGENTS.md` i `CLAUDE.md`, koristi se samo `AGENTS.md`. Isto tako, `~/.config/opencode/AGENTS.md` ima prednost nad `~/.claude/CLAUDE.md`. + +--- + +## Prilagođena uputstva + +Mozete navesti prilagodene datoteke uputstava u `opencode.json` ili globalnom `~/.config/opencode/opencode.json`. Tako vi i tim ponovo koristite postojeca pravila bez dupliranja u AGENTS.md. + +Primjer: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Mozete koristiti i udaljene URL-ove za ucitavanje uputstava sa weba. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +Udaljena uputstva se preuzimaju uz timeout od 5 sekundi. + +Sve datoteke uputstava se kombinuju sa vasim `AGENTS.md` datotekama. + +--- + +## Referenciranje eksternih datoteka + +Iako opencode ne parsira automatski reference datoteka u `AGENTS.md`, slicno ponasanje mozete dobiti na dva nacina: + +### Korištenje opencode.json + +Preporuceni pristup je da koristite `instructions` polje u `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### Ručna uputstva u AGENTS.md + +Mozete nauciti opencode da cita eksterne datoteke tako sto cete dati eksplicitna uputstva u `AGENTS.md`. Evo prakticnog primjera: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +Ovaj pristup vam omogucava da: + +- Kreirate modularne datoteke pravila koje se mogu ponovo koristiti +- Dijelite pravila izmedu projekata kroz symlinkove ili git submodule +- Drzite AGENTS.md kratkim dok upucujete na detaljne smjernice +- Osigurate da opencode ucitava datoteke samo kad su potrebne za konkretan zadatak + +:::tip +Za monorepo projekte ili projekte sa zajednickim standardima, odrzivije je koristiti `opencode.json` sa glob obrascima (npr. `packages/*/AGENTS.md`) nego rucna uputstva. +::: diff --git a/packages/web/src/content/docs/bs/sdk.mdx b/packages/web/src/content/docs/bs/sdk.mdx new file mode 100644 index 00000000000..fe6ab4ef141 --- /dev/null +++ b/packages/web/src/content/docs/bs/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: Type-safe JS klijent za opencode server. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +opencode JS/TS SDK pruza type-safe klijent za interakciju sa serverom. +Koristite ga za izradu integracija i programsko upravljanje opencode-om. + +[Saznajte vise](/docs/server) kako server radi. Za primjere pogledajte [projects](/docs/ecosystem#projects) koje je napravila zajednica. + +--- + +## Instalacija + +Instalirajte SDK sa npm-a: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## Kreiranje klijenta + +Kreirajte instancu opencode: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +Ovo pokrece i server i klijent + +#### Opcije + +| Opcija | Tip | Opis | Default | +| ---------- | ------------- | ----------------------------- | ----------- | +| `hostname` | `string` | Hostname servera | `127.0.0.1` | +| `port` | `number` | Port servera | `4096` | +| `signal` | `AbortSignal` | Abort signal za otkazivanje | `undefined` | +| `timeout` | `number` | Timeout u ms za start servera | `5000` | +| `config` | `Config` | Konfiguracijski objekat | `{}` | + +--- + +## Konfiguracija + +Mozete proslijediti konfiguracijski objekat za prilagodavanje ponasanja. Instanca i dalje ucitava `opencode.json`, ali konfiguraciju mozete nadjacati ili dodati inline: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## Samo klijent + +Ako vec imate pokrenutu opencode instancu, mozete napraviti klijentsku instancu i povezati se na nju: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### Opcije + +| Opcija | Tip | Opis | Default | +| --------------- | ---------- | --------------------------------- | ----------------------- | +| `baseUrl` | `string` | URL servera | `http://localhost:4096` | +| `fetch` | `function` | Prilagodena fetch implementacija | `globalThis.fetch` | +| `parseAs` | `string` | Metoda parsiranja odgovora | `auto` | +| `responseStyle` | `string` | Stil povrata: `data` ili `fields` | `fields` | +| `throwOnError` | `boolean` | Baci greske umjesto povrata | `false` | + +--- + +## Tipovi + +SDK ukljucuje TypeScript definicije za sve API tipove. Uvezite ih direktno: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +Svi tipovi su generisani iz OpenAPI specifikacije servera i dostupni u types datoteci. + +--- + +## Greške + +SDK moze baciti greske koje mozete uhvatiti i obraditi: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## API-ji + +SDK izlaže sve server API-je kroz type-safe klijent. + +--- + +### Global + +| Metoda | Opis | Odgovor | +| ----------------- | --------------------------- | ------------------------------------ | +| `global.health()` | Provjera zdravlja i verzije | `{ healthy: true, version: string }` | + +--- + +#### Primjeri + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### App + +| Metoda | Opis | Odgovor | +| -------------- | ----------------------- | ------------------------------------------- | +| `app.log()` | Upis log zapisa | `boolean` | +| `app.agents()` | Lista dostupnih agenata | Agent[] | + +--- + +#### Primjeri + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### Project + +| Metoda | Opis | Odgovor | +| ------------------- | -------------------- | --------------------------------------------- | +| `project.list()` | Lista svih projekata | Project[] | +| `project.current()` | Trenutni projekat | Project | + +--- + +#### Primjeri + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### Path + +| Metoda | Opis | Odgovor | +| ------------ | ---------------- | ---------------------------------------- | +| `path.get()` | Trenutna putanja | Path | + +--- + +#### Primjeri + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### Konfiguracija + +| Metoda | Opis | Odgovor | +| -------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | Info o konfiguraciji | Config | +| `config.providers()` | Lista provajdera i default modela | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### Primjeri + +```javascript +const config = await client.config.get() + +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` | + +--- + +#### Primjeri + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### Datoteke + +| Metoda | Opis | Odgovor | +| ------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------- | +| `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[] | + +`find.files` supports a few optional query fields: + +- `type`: `"file"` or `"directory"` +- `directory`: override the project root for the search +- `limit`: max results (1–200) + +--- + +#### Primjeri + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| Metoda | Opis | Odgovor | +| ------------------------------ | ------------------------- | --------- | +| `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` | + +--- + +#### Primjeri + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### Auth + +| Metoda | Opis | Odgovor | +| ------------------- | ------------------------------ | --------- | +| `auth.set({ ... })` | Set authentication credentials | `boolean` | + +--- + +#### Primjeri + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### Događaji + +| Metoda | Opis | Odgovor | +| ------------------- | ------------------------- | ------------------------- | +| `event.subscribe()` | Server-sent events stream | Server-sent events stream | + +--- + +#### Primjeri + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/bs/server.mdx b/packages/web/src/content/docs/bs/server.mdx new file mode 100644 index 00000000000..7d270fb4aae --- /dev/null +++ b/packages/web/src/content/docs/bs/server.mdx @@ -0,0 +1,284 @@ +--- +title: Server +description: Komunicirajte s opencode serverom preko HTTP-a. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +Komanda `opencode serve` pokrece headless HTTP server koji izlaže OpenAPI endpoint koji opencode klijent moze koristiti. + +--- + +### Korištenje + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### Opcije + +| Zastava | Opis | Default | +| --------------- | ----------------------------------- | ---------------- | +| `--port` | Port na kojem slusa | `4096` | +| `--hostname` | Hostname na kojem slusa | `127.0.0.1` | +| `--mdns` | Ukljuci mDNS otkrivanje | `false` | +| `--mdns-domain` | Prilagodeni domen za mDNS servis | `opencode.local` | +| `--cors` | Dodatni browser origin-i koje dozv. | `[]` | + +`--cors` mozete navesti vise puta: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### Autentifikacija + +Postavite `OPENCODE_SERVER_PASSWORD` da zastitite server HTTP basic auth mehanizmom. Korisnicko ime je po defaultu `opencode`, ili postavite `OPENCODE_SERVER_USERNAME` za nadjacavanje. Ovo vazi i za `opencode serve` i za `opencode web`. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### Kako radi + +Kada pokrenete `opencode`, pokrecu se TUI i server. TUI je klijent koji komunicira sa serverom. Server izlaže OpenAPI 3.1 spec endpoint koji se koristi i za generisanje [SDK-a](/docs/sdk). + +:::tip +Koristite opencode server za programsku interakciju sa opencode-om. +::: + +Ova arhitektura omogucava opencode podrsku za vise klijenata i programsku interakciju. + +Mozete pokrenuti `opencode serve` da startate standalone server. Ako je opencode TUI vec pokrenut, `opencode serve` ce pokrenuti novi server. + +--- + +#### Povezivanje na postojeći server + +Kada pokrenete TUI, port i hostname se nasumicno dodijele. Umjesto toga, mozete zadati `--hostname` i `--port` [zastave](/docs/cli), pa se povezati na taj server. + +Endpoint [`/tui`](#tui) mozete koristiti za upravljanje TUI-jem kroz server. Na primjer, mozete unaprijed popuniti ili pokrenuti prompt. Ovaj setup koriste OpenCode [IDE](/docs/ide) pluginovi. + +--- + +## Specifikacija + +Server objavljuje OpenAPI 3.1 specifikaciju koju mozete vidjeti na: + +``` +http://:/doc +``` + +Na primjer, `http://localhost:4096/doc`. Koristite specifikaciju da generisete klijente ili pregledate tipove zahtjeva i odgovora. Mozete je otvoriti i u Swagger exploreru. + +--- + +## API-ji + +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 | + +--- + +### Projekt + +| Metoda | Putanja | Opis | Odgovor | +| ------ | ------------------ | ----------------------- | --------------------------------------------- | +| `GET` | `/project` | List all projects | Project[] | +| `GET` | `/project/current` | Get the current project | 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 | + +--- + +### Instanca + +| Metoda | Putanja | Opis | Odgovor | +| ------ | ------------------- | ---------------------------- | --------- | +| `POST` | `/instance/dispose` | Dispose the current instance | `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 } }` | + +--- + +### 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` | + +--- + +### 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` | + +--- + +### 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[]`}` | + +--- + +### Naredbe + +| Metoda | Putanja | Opis | Odgovor | +| ------ | ---------- | ----------------- | --------------------------------------------- | +| `GET` | `/command` | List all commands | 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[] | + +#### `/find/file` parametri upita + +- `query` (obavezno) — niz za pretragu (fuzzy podudaranje) +- `type` (opcionalno) — ograniči rezultate na `"file"` ili `"directory"` +- `directory` (opcionalno) — nadjačaj korijen projekta za pretragu +- `limit` (opcionalno) — maksimalni rezultati (1–200) +- `dirs` (opcionalno) — zastarjela zastavica (`"false"` vraća samo datoteke) + +--- + +### 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 | + +--- + +### LSP, Formateri & MCP + +| 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 | + +--- + +### Agenti + +| Metoda | Putanja | Opis | Odgovor | +| ------ | -------- | ------------------------- | ------------------------------------------- | +| `GET` | `/agent` | List all available agents | Agent[] | + +--- + +### Bilježenje + +| Metoda | Putanja | Opis | Odgovor | +| ------ | ------- | ------------------------------------------------------------ | --------- | +| `POST` | `/log` | Write log entry. Body: `{ 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` | + +--- + +### Autentifikacija + +| Metoda | Putanja | Opis | Odgovor | +| ------ | ----------- | --------------------------------------------------------------- | --------- | +| `PUT` | `/auth/:id` | Set authentication credentials. Body must match provider schema | `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 | + +--- + +### Dokumentacija + +| Metoda | Putanja | Opis | Odgovor | +| ------ | ------- | ------------------------- | --------------------------- | +| `GET` | `/doc` | OpenAPI 3.1 specification | HTML page with OpenAPI spec | diff --git a/packages/web/src/content/docs/bs/share.mdx b/packages/web/src/content/docs/bs/share.mdx new file mode 100644 index 00000000000..a15e1507434 --- /dev/null +++ b/packages/web/src/content/docs/bs/share.mdx @@ -0,0 +1,127 @@ +--- +title: Dijeljenje +description: Dijelite OpenCode razgovore javnim linkovima. +--- + +OpenCode opcija dijeljenja vam omogucava da kreirate javne linkove za razgovore. Tako lakse saradujete s timom ili trazite pomoc od drugih. + +:::note +Dijeljeni razgovori su javno dostupni svakome ko ima link. +::: + +--- + +## Kako radi + +Kada podijelite razgovor, OpenCode: + +1. Kreira jedinstveni javni URL za vasu sesiju +2. Sinhronizuje historiju razgovora na nase servere +3. Cini razgovor dostupnim preko linka za dijeljenje — `opncd.ai/s/` + +--- + +## Dijeljenje + +OpenCode podrzava tri nacina dijeljenja koji odreduju kako se razgovori dijele: + +--- + +### Ručno (zadano) + +Po defaultu, OpenCode koristi rucni nacin dijeljenja. Sesije se ne dijele automatski, ali ih mozete rucno podijeliti komandom `/share`: + +``` +/share +``` + +Ovo ce generisati jedinstveni URL i kopirati ga u clipboard. + +Da eksplicitno postavite rucni nacin u [config datoteci](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### Automatsko dijeljenje + +Mozete ukljuciti automatsko dijeljenje za sve nove razgovore tako sto `share` postavite na `"auto"` u [config datoteci](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +Kada je auto-share ukljucen, svaki novi razgovor se automatski dijeli i kreira se link. + +--- + +### Onemogućeno + +Dijeljenje mozete potpuno iskljuciti tako sto `share` postavite na `"disabled"` u [config datoteci](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +Da ovo vazi za cijeli tim u odredenom projektu, dodajte postavku u projektni `opencode.json` i commitujte u Git. + +--- + +## Uklanjanje dijeljenja + +Da prestanete dijeliti razgovor i uklonite javni pristup: + +``` +/unshare +``` + +Ovo uklanja link za dijeljenje i brise podatke povezane s razgovorom. + +--- + +## Privatnost + +Imajte na umu nekoliko stvari prije dijeljenja razgovora. + +--- + +### Čuvanje podataka + +Dijeljeni razgovori ostaju dostupni dok ih eksplicitno ne uklonite iz dijeljenja. Ovo ukljucuje: + +- Kompletnu historiju razgovora +- Sve poruke i odgovore +- Metapodatke sesije + +--- + +### Preporuke + +- Dijelite samo razgovore koji ne sadrze osjetljive informacije. +- Pregledajte sadrzaj razgovora prije dijeljenja. +- Uklonite dijeljenje kad saradnja zavrsi. +- Izbjegavajte dijeljenje razgovora s vlasnickim kodom ili povjerljivim podacima. +- Za osjetljive projekte potpuno iskljucite dijeljenje. + +--- + +## Za enterprise + +Za enterprise okruzenja, opcija dijeljenja moze biti: + +- **Iskljucena** u potpunosti radi sigurnosne uskladenosti +- **Ogranicena** samo na korisnike autentifikovane kroz SSO +- **Self-hosted** na vasoj infrastrukturi + +[Saznajte vise](/docs/enterprise) o koristenju opencode u organizaciji. diff --git a/packages/web/src/content/docs/bs/skills.mdx b/packages/web/src/content/docs/bs/skills.mdx new file mode 100644 index 00000000000..655dc9d107b --- /dev/null +++ b/packages/web/src/content/docs/bs/skills.mdx @@ -0,0 +1,222 @@ +--- +title: Vještine agenata +description: "Definisite ponasanje koje se moze ponovo koristiti" +--- + +Agent skills omogucavaju OpenCode da pronade uputstva koja se mogu ponovo koristiti iz repozitorija ili home direktorija. +Skills se ucitavaju po potrebi kroz ugradeni `skill` alat - agenti vide dostupne skills i ucitavaju puni sadrzaj kad zatreba. + +--- + +## Postavite datoteke + +Kreirajte jedan folder po nazivu skill-a i stavite `SKILL.md` unutar njega. +OpenCode pretrazuje ove lokacije: + +- Konfiguracija projekta: `.opencode/skills//SKILL.md` +- Globalna konfiguracija: `~/.config/opencode/skills//SKILL.md` +- Claude kompatibilno u projektu: `.claude/skills//SKILL.md` +- Globalno Claude kompatibilno: `~/.claude/skills//SKILL.md` +- Agent kompatibilno u projektu: `.agents/skills//SKILL.md` +- Globalno agent kompatibilno: `~/.agents/skills//SKILL.md` + +--- + +## Razumijte otkrivanje + +Za projektne lokalne putanje, OpenCode ide prema gore od trenutnog radnog direktorija dok ne dode do git worktree-ja. +Usput ucitava sve odgovarajuce `skills/*/SKILL.md` u `.opencode/` i odgovarajuce `.claude/skills/*/SKILL.md` ili `.agents/skills/*/SKILL.md`. + +Globalne definicije se takoder ucitavaju iz `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md` i `~/.agents/skills/*/SKILL.md`. + +--- + +## Pisanje frontmatter-a + +Svaki `SKILL.md` mora poceti YAML frontmatter-om. +Prepoznaju se samo ova polja: + +- `name` (obavezno) +- `description` (obavezno) +- `license` (opcionalno) +- `compatibility` (opcionalno) +- `metadata` (opcionalno, mapa string->string) + +Nepoznata frontmatter polja se ignorisu. + +--- + +## Validirajte nazive + +`name` mora: + +- Imati 1-64 karaktera +- Biti malim slovima i brojevima sa jednim crticama kao razdvajacima +- Ne pocinjati ni zavrsavati sa `-` +- Ne sadrzavati uzastopno `--` +- Odgovarati nazivu direktorija koji sadrzi `SKILL.md` + +Ekvivalentni regex: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## Pravila dužine + +`description` mora imati 1-1024 karaktera. +Neka bude dovoljno precizan da agent moze pravilno odabrati. + +--- + +## Primjer + +Kreirajte `.opencode/skills/git-release/SKILL.md` ovako: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## Opis alata + +OpenCode navodi dostupne skills u opisu `skill` alata. +Svaki unos sadrzi naziv i opis skill-a: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +Agent ucitava skill pozivom alata: + +``` +skill({ name: "git-release" }) +``` + +--- + +## Konfiguracija dozvola + +Kontrolisite kojim skills agenti mogu pristupiti pomocu dozvola baziranih na obrascima u `opencode.json`: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| Dozvola | Ponasanje | +| ------- | ------------------------------------------- | +| `allow` | Skill se ucitava odmah | +| `deny` | Skill je skriven od agenta, pristup odbijen | +| `ask` | Korisnik mora odobriti prije ucitavanja | + +Obrasci podrzavaju wildcard znakove: `internal-*` poklapa `internal-docs`, `internal-tools` itd. + +--- + +## Nadjačavanje po agentu + +Dajte odredenim agentima drugacije dozvole od globalnih defaulta. + +**Za prilagodene agente** (u frontmatter-u agenta): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**Za ugradene agente** (u `opencode.json`): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## Isključivanje skill alata + +Potpuno iskljucite skills za agente koji ih ne bi trebali koristiti: + +**Za prilagodene agente**: + +```yaml +--- +tools: + skill: false +--- +``` + +**Za ugradene agente**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +Kada je iskljuceno, sekcija `` se potpuno izostavlja. + +--- + +## Rješavanje problema s učitavanjem + +Ako se skill ne pojavi: + +1. Provjerite da je naziv `SKILL.md` napisan velikim slovima +2. Provjerite da frontmatter sadrzi `name` i `description` +3. Potvrdite da su nazivi skill-ova jedinstveni na svim lokacijama +4. Provjerite dozvole - skills sa `deny` su skriveni od agenata diff --git a/packages/web/src/content/docs/bs/themes.mdx b/packages/web/src/content/docs/bs/themes.mdx new file mode 100644 index 00000000000..a513e5a2092 --- /dev/null +++ b/packages/web/src/content/docs/bs/themes.mdx @@ -0,0 +1,369 @@ +--- +title: Teme +description: Izaberite ugradenu temu ili napravite svoju. +--- + +U OpenCode mozete birati izmedu vise ugradenih tema, koristiti temu koja se prilagodava terminalu ili definisati vlastitu temu. + +Po defaultu, OpenCode koristi nasu `opencode` temu. + +--- + +## Zahtjevi terminala + +Da bi teme bile prikazane ispravno sa punom paletom boja, terminal mora podrzavati **truecolor** (24-bitne boje). Vecina modernih terminala to podrzava, ali nekad ga treba ukljuciti: + +- **Provjerite podrsku**: Pokrenite `echo $COLORTERM` - trebalo bi vratiti `truecolor` ili `24bit` +- **Ukljucite truecolor**: Postavite varijablu okruzenja `COLORTERM=truecolor` u shell profilu +- **Kompatibilnost terminala**: Potvrdite da emulator terminala podrzava 24-bitne boje (vecina modernih terminala kao iTerm2, Alacritty, Kitty, Windows Terminal i novije verzije GNOME Terminala) + +Bez truecolor podrske, teme mogu imati slabiju preciznost boja ili pasti na najblizu 256-color aproksimaciju. + +--- + +## Ugrađene teme + +OpenCode dolazi sa vise ugradenih tema. + +| Naziv | Opis | +| ---------------------- | -------------------------------------------------------------------------- | +| `system` | Prilagodava se boji pozadine vaseg terminala | +| `tokyonight` | Bazirana na [Tokyonight](https://github.com/folke/tokyonight.nvim) temi | +| `everforest` | Bazirana na [Everforest](https://github.com/sainnhe/everforest) temi | +| `ayu` | Bazirana na [Ayu](https://github.com/ayu-theme) dark temi | +| `catppuccin` | Bazirana na [Catppuccin](https://github.com/catppuccin) temi | +| `catppuccin-macchiato` | Bazirana na [Catppuccin](https://github.com/catppuccin) temi | +| `gruvbox` | Bazirana na [Gruvbox](https://github.com/morhetz/gruvbox) temi | +| `kanagawa` | Bazirana na [Kanagawa](https://github.com/rebelot/kanagawa.nvim) temi | +| `nord` | Bazirana na [Nord](https://github.com/nordtheme/nord) temi | +| `matrix` | Hacker stil zelena-na-crnom tema | +| `one-dark` | Bazirana na [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark temi | + +I jos mnogo njih, stalno dodajemo nove teme. + +--- + +## System tema + +`system` tema je napravljena da se automatski prilagodi sem i boja vaseg terminala. Za razliku od tradicionalnih tema sa fiksnim bojama, _system_ tema: + +- **Generise sivu skalu**: Pravi prilagodenu sivu skalu na osnovu boje pozadine terminala za optimalan kontrast. +- **Koristi ANSI boje**: Koristi standardne ANSI boje (0-15) za sintaksno isticanje i UI elemente, uz postovanje palete terminala. +- **Cuva terminalske defaulte**: Koristi `none` za boju teksta i pozadine da zadrzi izvorni izgled terminala. + +System tema je za korisnike koji: + +- Zele da OpenCode odgovara izgledu njihovog terminala +- Koriste prilagodene seme boja terminala +- Preferiraju konzistentan izgled kroz sve terminalske aplikacije + +--- + +## Korištenje teme + +Temu mozete izabrati preko selektora tema komandom `/theme`. Mozete je navesti i u [configu](/docs/config). + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## Prilagođene teme + +OpenCode podrzava fleksibilan sistem tema baziran na JSON-u koji olaksava kreiranje i prilagodavanje tema. + +--- + +### Hijerarhija + +Teme se ucitavaju iz vise direktorija ovim redoslijedom, gdje kasniji direktoriji prepisuju ranije: + +1. **Ugradene teme** - Ugradene su u binarni fajl +2. **Korisnicki config direktorij** - `~/.config/opencode/themes/*.json` ili `$XDG_CONFIG_HOME/opencode/themes/*.json` +3. **Korijenski direktorij projekta** - `/.opencode/themes/*.json` +4. **Trenutni radni direktorij** - `./.opencode/themes/*.json` + +Ako vise direktorija sadrzi temu istog naziva, koristit ce se tema iz direktorija s vecim prioritetom. + +--- + +### Kreiranje teme + +Da kreirate prilagodenu temu, napravite JSON datoteku u jednom od direktorija za teme. + +Za korisnicke teme na nivou sistema: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +I za teme specificne za projekat. + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### JSON struktura + +Teme koriste fleksibilan JSON format koji podrzava: + +- **Hex boje**: `"#ffffff"` +- **ANSI boje**: `3` (0-255) +- **Reference boja**: `"primary"` ili prilagodene definicije +- **Dark/light varijante**: `{"dark": "#000", "light": "#fff"}` +- **Bez boje**: `"none"` - koristi defaultnu boju terminala ili transparentno + +--- + +### Definicije boja + +Sekcija `defs` je opcionalna i omogucava da definisete boje koje se mogu ponovo koristiti kroz temu. + +--- + +### Terminalske zadane vrijednosti + +Specijalna vrijednost `"none"` moze se koristiti za bilo koju boju da naslijedi defaultnu boju terminala. Ovo je korisno za teme koje se prirodno uklapaju u semu boja terminala: + +- `"text": "none"` - koristi defaultnu boju teksta terminala +- `"background": "none"` - koristi defaultnu boju pozadine terminala + +--- + +### Primjer + +Evo primjera prilagodene teme: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/bs/tools.mdx b/packages/web/src/content/docs/bs/tools.mdx new file mode 100644 index 00000000000..cef02ddda16 --- /dev/null +++ b/packages/web/src/content/docs/bs/tools.mdx @@ -0,0 +1,379 @@ +--- +title: Alati +description: Upravljajte alatima koje LLM moze koristiti. +--- + +Alati omogucavaju LLM-u da izvrsava akcije u vasem kodu. OpenCode dolazi sa skupom ugradenih alata, a mozete ga prosiriti kroz [custom tools](/docs/custom-tools) ili [MCP servers](/docs/mcp-servers). + +Po defaultu su svi alati **ukljuceni** i ne traze dozvolu za pokretanje. Ponasanje alata kontrolisete kroz [permissions](/docs/permissions). + +--- + +## Konfiguracija + +Koristite polje `permission` za kontrolu ponasanja alata. Za svaki alat mozete postaviti allow, deny ili ask. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +Mozete koristiti i wildcard obrasce da kontrolisete vise alata odjednom. Na primjer, da trazite odobrenje za sve alate jednog MCP servera: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[Saznajte vise](/docs/permissions) o konfigurisanju dozvola. + +--- + +## Ugrađeni + +Ovo su svi ugradeni alati dostupni u OpenCode. + +--- + +### bash + +Izvrsava shell komande u okruzenju projekta. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +Ovaj alat omogucava LLM-u da pokrece terminalske komande kao `npm install`, `git status` i druge shell komande. + +--- + +### edit + +Mijenja postojece datoteke tacnim zamjenama stringova. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Ovaj alat radi precizne izmjene datoteka zamjenom tacnih poklapanja teksta. To je glavni nacin na koji LLM mijenja kod. + +--- + +### write + +Kreira nove datoteke ili prepisuje postojece. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Koristite ovo da dozvolite LLM-u kreiranje novih datoteka. Ako datoteka vec postoji, bit ce prepisana. + +:::note +`write` alat kontrolise `edit` dozvola, koja pokriva sve izmjene datoteka (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### read + +Cita sadrzaj datoteka iz vaseg koda. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +Ovaj alat cita datoteke i vraca njihov sadrzaj. Podrzava citanje odredenih raspona linija kod velikih fajlova. + +--- + +### grep + +Pretrazuje sadrzaj datoteka pomocu regularnih izraza. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +Brza pretraga sadrzaja kroz cijeli kod. Podrzava puni regex i filtriranje po obrascima datoteka. + +--- + +### glob + +Pronalazi datoteke po obrascima. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +Trazi datoteke koristeci glob obrasce kao `**/*.js` ili `src/**/*.ts`. Vraca putanje sortirane po vremenu izmjene. + +--- + +### list + +Ispisuje datoteke i direktorije na zadanoj putanji. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +Ovaj alat ispisuje sadrzaj direktorija. Prihvata glob obrasce za filtriranje rezultata. + +--- + +### lsp (eksperimentalno) + +Komunicira sa konfigurisanim LSP serverima za funkcije inteligencije koda kao definicije, reference, hover info i hijerarhija poziva. + +:::note +Ovaj alat je dostupan samo kada je `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (ili `OPENCODE_EXPERIMENTAL=true`). +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +Podrzane operacije ukljucuju `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls` i `outgoingCalls`. + +Za konfiguraciju dostupnih LSP servera u projektu, pogledajte [LSP Servers](/docs/lsp). + +--- + +### patch + +Primjenjuje zakrpe na datoteke. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Ovaj alat primjenjuje patch datoteke na kod. Koristan je za diffs i patch-eve iz razlicitih izvora. + +:::note +`patch` alat kontrolise `edit` dozvola, koja pokriva sve izmjene datoteka (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### skill + +Ucitajte [skill](/docs/skills) (`SKILL.md` datoteku) i vratite njegov sadrzaj u razgovor. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +Upravlja todo listama tokom coding sesija. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +Kreira i azurira liste zadataka za pracenje napretka tokom slozenih operacija. LLM ovo koristi za organizaciju zadataka u vise koraka. + +:::note +Ovaj alat je po defaultu iskljucen za subagente, ali ga mozete rucno ukljuciti. [Saznajte vise](/docs/agents/#permissions) +::: + +--- + +### todoread + +Cita postojece todo liste. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +Cita trenutno stanje todo liste. LLM ga koristi da prati sta je na cekanju i sta je zavrseno. + +:::note +Ovaj alat je po defaultu iskljucen za subagente, ali ga mozete rucno ukljuciti. [Saznajte vise](/docs/agents/#permissions) +::: + +--- + +### webfetch + +Preuzima web sadrzaj. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +Omogucava LLM-u da preuzima i cita web stranice. Korisno za dokumentaciju i online istrazivanje. + +--- + +### websearch + +Pretrazuje web za informacije. + +:::note +Ovaj alat je dostupan samo uz OpenCode provajdera ili kada je varijabla `OPENCODE_ENABLE_EXA` postavljena na truthy vrijednost (npr. `true` ili `1`). + +Da ukljucite pri pokretanju OpenCode: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +Vrsi web pretrage preko Exa AI da pronade relevantne informacije online. Korisno za istrazivanje tema, aktuelnosti i podataka van granice trening skupa. + +API kljuc nije potreban - alat se direktno povezuje na Exa AI hosted MCP servis bez autentifikacije. + +:::tip +Koristite `websearch` kada trebate pronaci informacije (discovery), a `webfetch` kada trebate preuzeti sadrzaj sa konkretnog URL-a (retrieval). +::: + +--- + +### question + +Postavlja korisniku pitanja tokom izvrsavanja. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +Ovaj alat omogucava LLM-u da postavlja pitanja korisniku tokom zadatka. Koristan je za: + +- Prikupljanje korisnickih preferencija i zahtjeva +- Razjasnjavanje nejasnih uputstava +- Donosenje odluka oko implementacije +- Nudjenje izbora o smjeru rada + +Svako pitanje ukljucuje naslov, tekst pitanja i listu opcija. Korisnici mogu izabrati ponudenu opciju ili upisati vlastiti odgovor. Kada ima vise pitanja, mogu se kretati izmedu njih prije slanja svih odgovora. + +--- + +## Prilagođeni alati + +Custom tools vam omogucavaju da definisete vlastite funkcije koje LLM moze pozivati. Definisu se u config datoteci i mogu izvrsavati proizvoljan kod. + +[Saznajte vise](/docs/custom-tools) o kreiranju custom tools. + +--- + +## MCP serveri + +MCP (Model Context Protocol) serveri omogucavaju integraciju eksternih alata i servisa. Ovo ukljucuje pristup bazama, API integracije i third-party servise. + +[Saznajte vise](/docs/mcp-servers) o konfigurisanju MCP servera. + +--- + +## Interno + +Interno, alati kao `grep`, `glob` i `list` koriste [ripgrep](https://github.com/BurntSushi/ripgrep). Po defaultu, ripgrep postuje `.gitignore` obrasce, pa se fajlovi i direktoriji iz `.gitignore` izostavljaju iz pretraga i listinga. + +--- + +### Obrasci ignorisanja + +Da ukljucite fajlove koji bi inace bili ignorisani, kreirajte `.ignore` datoteku u korijenu projekta. Ova datoteka moze eksplicitno dozvoliti odredene putanje. + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +Na primjer, ova `.ignore` datoteka dozvoljava ripgrep-u da pretrazuje `node_modules/`, `dist/` i `build/` direktorije i kada su navedeni u `.gitignore`. diff --git a/packages/web/src/content/docs/bs/troubleshooting.mdx b/packages/web/src/content/docs/bs/troubleshooting.mdx new file mode 100644 index 00000000000..7dff4b24c08 --- /dev/null +++ b/packages/web/src/content/docs/bs/troubleshooting.mdx @@ -0,0 +1,300 @@ +--- +title: Rješavanje problema +description: Uobičajeni problemi i kako ih riješiti. +--- + +Da biste otklonili probleme s OpenCode, počnite provjeravanjem dnevnika i lokalnih podataka koje pohranjuje na disku. + +--- + +## Dnevnici + +Log fajlovi se pišu na: + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: Pritisnite `WIN+R` i zalijepite `%USERPROFILE%\.local\share\opencode\log` + +Datoteke evidencije se imenuju vremenskim oznakama (npr. `2025-01-09T123456.log`) i čuvaju se najnovijih 10 datoteka dnevnika. + +Možete postaviti nivo dnevnika pomoću opcije komandne linije `--log-level` da biste dobili detaljnije informacije o otklanjanju grešaka. Na primjer, `opencode --log-level DEBUG`. + +--- + +## Pohrana + +OpenCode pohranjuje podatke o sesiji i druge podatke aplikacije na disku na: + +- **macOS/Linux**: `~/.local/share/opencode/` +- **Windows**: Pritisnite `WIN+R` i zalijepite `%USERPROFILE%\.local\share\opencode` + +Ovaj direktorij sadrži: + +- `auth.json` - ​​Podaci o autentifikaciji kao što su API ključevi, OAuth tokeni +- `log/` - ​​Dnevnici aplikacije +- `project/` - ​​Podaci specifični za projekat kao što su podaci o sesiji i poruci + - Ako je projekat unutar Git repo-a, on je pohranjen u `.//storage/` + - Ako nije Git repo, pohranjuje se u `./global/storage/` + +--- + +## Desktop aplikacija + +OpenCode Desktop pokreće lokalni OpenCode server (`opencode-cli` sidecar) u pozadini. Većina problema je uzrokovana nedostatkom dodatka, oštećenom keš memorijom ili lošim postavkama servera. + +### Brze provjere + +- Potpuno zatvorite i ponovo pokrenite aplikaciju. +- Ako aplikacija prikaže ekran s greškom, kliknite na **Restart** i kopirajte detalje o grešci. +- samo za macOS: `OpenCode` meni -> **Ponovo učitaj Webview** (pomaže ako je korisnički interfejs prazan/zamrznut). + +--- + +### Onemogućavanje dodataka + +Ako se desktop aplikacija ruši pri pokretanju, visi ili se čudno ponaša, počnite s onemogućavanjem dodataka. + +#### Provjerite globalnu konfiguraciju + +Otvorite svoju globalnu konfiguracijsku datoteku i potražite ključ `plugin`. + +- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (ili `~/.config/opencode/opencode.json`) +- **macOS/Linux** (starije instalacije): `~/.local/share/opencode/opencode.jsonc` +- **Windows**: Pritisnite `WIN+R` i zalijepite `%USERPROFILE%\.config\opencode\opencode.jsonc` + +Ako imate konfigurirane dodatke, privremeno ih onemogućite uklanjanjem ključa ili postavljanjem na prazan niz: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### Provjera direktorija dodataka + +OpenCode također može učitati lokalne dodatke s diska. Privremeno ih maknite s puta (ili preimenujte folder) i ponovo pokrenite desktop aplikaciju: + +- **Globalni dodaci** + - **macOS/Linux**: `~/.config/opencode/plugins/` + - **Windows**: Pritisnite `WIN+R` i zalijepite `%USERPROFILE%\.config\opencode\plugins` +- **Projektni dodaci** (samo ako koristite konfiguraciju po projektu) + - `/.opencode/plugins/` + +Ako aplikacija ponovo počne raditi, ponovo omogućite dodatke jedan po jedan kako biste otkrili koji od njih uzrokuje problem. + +--- + +### Brisanje keš memorije + +Ako onemogućavanje dodataka ne pomogne (ili se instalacija dodatka zaglavila), obrišite keš memoriju kako bi ga OpenCode mogao ponovo izgraditi. + +1. Potpuno zatvorite OpenCode Desktop. +2. Izbrišite keš direktorij: + +- **macOS**: Finder -> `Cmd+Shift+G` -> zalijepi `~/.cache/opencode` +- **Linux**: obrišite `~/.cache/opencode` (ili pokrenite `rm -rf ~/.cache/opencode`) +- **Windows**: Pritisnite `WIN+R` i zalijepite `%USERPROFILE%\.cache\opencode` + +3. Ponovo pokrenite OpenCode Desktop. + +--- + +### Rješavanje problema sa vezom na serveru + +OpenCode Desktop može ili pokrenuti svoj lokalni server (podrazumevano) ili se povezati na URL servera koji ste konfigurisali. + +Ako vidite dijaloški okvir **"Povezivanje nije uspjelo"** (ili aplikacija nikada ne prođe kroz početni ekran), provjerite da li postoji prilagođeni URL servera. + +#### Obrišite zadani URL servera radne površine + +Na početnom ekranu kliknite na ime servera (sa tačkom statusa) da otvorite birač servera. U odjeljku **Podrazumevani server** kliknite na **Obriši**. + +#### Uklonite `server.port` / `server.hostname` iz vaše konfiguracije + +Ako vaš `opencode.json(c)` sadrži odjeljak `server`, privremeno ga uklonite i ponovo pokrenite desktop aplikaciju. + +#### Provjerite varijable okruženja + +Ako ste postavili `OPENCODE_PORT` u svom okruženju, desktop aplikacija će pokušati da koristi taj port za lokalni server. + +- Poništite `OPENCODE_PORT` (ili odaberite slobodan port) i ponovo pokrenite. + +--- + +### Linux: Wayland / X11 problemi + +Na Linuxu, neka podešavanja Waylanda mogu uzrokovati prazne prozore ili greške sastavljača. + +- Ako ste na Waylandu, a aplikacija je prazna/ispada, pokušajte pokrenuti sa `OC_ALLOW_WAYLAND=1`. +- Ako to pogorša stvari, uklonite ga i pokušajte pokrenuti pod X11 sesijom umjesto toga. + +--- + +### Windows: WebView2 izvršno okruženje + +Na Windows-u, OpenCode Desktop zahtijeva Microsoft Edge **WebView2 Runtime**. Ako se aplikacija otvori u praznom prozoru ili se ne pokrene, instalirajte/ažurirajte WebView2 i pokušajte ponovo. + +--- + +### Windows: Opšti problemi sa performansama + +Ako imate spore performanse, probleme s pristupom datotekama ili probleme s terminalom na Windows-u, pokušajte koristiti [WSL (Windows podsistem za Linux)](/docs/windows-wsl). WSL pruža Linux okruženje koje radi neprimetnije sa OpenCode karakteristikama. + +--- + +### Obavještenja se ne prikazuju + +OpenCode Desktop prikazuje sistemska obavještenja samo kada: + +- obavještenja su omogućena za OpenCode u postavkama vašeg OS-a, i +- prozor aplikacije nije fokusiran. + +--- + +### Resetovanje pohrane desktop aplikacije + +Ako se aplikacija ne pokrene i ne možete izbrisati postavke unutar korisničkog sučelja, resetirajte spremljeno stanje desktop aplikacije. + +1. Zatvorite OpenCode Desktop. +2. Pronađite i izbrišite ove datoteke (oni žive u direktoriju podataka OpenCode Desktop aplikacije): + +- `opencode.settings.dat` (URL zadanog servera za desktop) +- `opencode.global.dat` i `opencode.workspace.*.dat` (stanje korisničkog interfejsa poput nedavnih servera/projekata) + +Da brzo pronađete direktorij: + +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (onda potražite nazive fajlova iznad) +- **Linux**: potražite nazive fajlova iznad pod `~/.local/share` +- **Windows**: Pritisnite `WIN+R` -> `%APPDATA%` (zatim potražite nazive fajlova iznad) + +--- + +## Traženje pomoći + +Ako imate problema s OpenCode: + +1. **Prijavite probleme na GitHub** + + Najbolji način da prijavite greške ili zatražite funkcije je putem našeg GitHub spremišta: + + [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + + Prije kreiranja novog problema, pretražite postojeće probleme da vidite je li vaš problem već prijavljen. + +2. **Pridružite se našem Discordu** + + Za pomoć u stvarnom vremenu i diskusiju u zajednici, pridružite se našem Discord serveru: + + [**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## Uobičajeni problemi + +Evo nekih uobičajenih problema i kako ih riješiti. + +--- + +### OpenCode se ne pokreće + +1. Provjerite dnevnike za poruke o greškama +2. Pokušajte pokrenuti sa `--print-logs` da vidite izlaz u terminalu +3. Uvjerite se da imate najnoviju verziju sa `opencode upgrade` + +--- + +### Problemi s autentifikacijom + +1. Pokušajte ponovo autentifikovati sa naredbom `/connect` u TUI +2. Provjerite da li su vaši API ključevi važeći +3. Uvjerite se da vaša mreža dozvoljava veze s API-jem provajdera + +--- + +### Model nije dostupan + +1. Provjerite jeste li se autentifikovali kod provajdera +2. Provjerite je li naziv modela u vašoj konfiguraciji tačan +3. Neki modeli mogu zahtijevati poseban pristup ili pretplate + +Ako naiđete na `ProviderModelNotFoundError` najvjerovatnije niste u pravu +referenciranje modela negdje. +Modele treba referencirati ovako: `/` + +primjeri: + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +Da saznate kojim modelima imate pristup, pokrenite `opencode models` + +--- + +### ProviderInitError + +Ako naiđete na grešku ProviderInitError, vjerovatno imate nevažeću ili oštećenu konfiguraciju. + +Da biste ovo riješili: + +1. Prvo provjerite da li je vaš provajder ispravno postavljen slijedeći [vodič za pružatelje](/docs/providers) +2. Ako se problem nastavi, pokušajte obrisati pohranjenu konfiguraciju: + +```bash + rm -rf ~/.local/share/opencode +``` + +Na Windows-u pritisnite `WIN+R` i izbrišite: `%USERPROFILE%\.local\share\opencode` + +3. Ponovo izvršite autentifikaciju kod svog provajdera koristeći naredbu `/connect` u TUI. + +--- + +### AI_APICallError i problemi sa paketom dobavljača + +Ako naiđete na greške API poziva, to može biti zbog zastarjelih paketa dobavljača. OpenCode dinamički instalira pakete dobavljača (OpenAI, Anthropic, Google, itd.) po potrebi i kešira ih lokalno. + +Da biste riješili probleme s paketom dobavljača: + +1. Obrišite keš paketa provajdera: + +```bash + rm -rf ~/.cache/opencode +``` + +Na Windows-u pritisnite `WIN+R` i izbrišite: `%USERPROFILE%\.cache\opencode` + +2. Ponovo pokrenite OpenCode da ponovo instalirate najnovije pakete dobavljača + +Ovo će prisiliti OpenCode da preuzme najnovije verzije paketa dobavljača, što često rješava probleme kompatibilnosti s parametrima modela i promjenama API-ja. + +--- + +### Copy/paste ne radi na Linuxu + +Korisnici Linuxa moraju imati instaliran jedan od sljedećih uslužnih programa međuspremnika da bi funkcionirala funkcionalnost kopiranja/lijepljenja: + +**Za X11 sisteme:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**Za Wayland sisteme:** + +```bash +apt install -y wl-clipboard +``` + +**Za okruženja bez glave:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +OpenCode će otkriti da li koristite Wayland i preferirate `wl-clipboard`, u suprotnom će pokušati pronaći alate međuspremnika po redoslijedu: `xclip` i `xsel`. diff --git a/packages/web/src/content/docs/bs/tui.mdx b/packages/web/src/content/docs/bs/tui.mdx new file mode 100644 index 00000000000..96b075aa130 --- /dev/null +++ b/packages/web/src/content/docs/bs/tui.mdx @@ -0,0 +1,393 @@ +--- +title: TUI +description: Korištenje korisničkog interfejsa OpenCode terminala. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode pruža interaktivni terminalski interfejs ili TUI za rad na vašim projektima sa LLM. + +Pokretanje OpenCode pokreće TUI za trenutni direktorij. + +```bash +opencode +``` + +Ili ga možete pokrenuti za određeni radni direktorij. + +```bash +opencode /path/to/project +``` + +Kada uđete u TUI, možete to zatražiti porukom. + +```text +Give me a quick summary of the codebase. +``` + +--- + +## Reference datoteka + +Možete referencirati datoteke u svojim porukama koristeći `@`. Ovo vrši nejasnu pretragu datoteka u trenutnom radnom direktoriju. + +:::tip +Također možete koristiti `@` da referencirate datoteke u svojim porukama. +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +Sadržaj datoteke se automatski dodaje u razgovor. + +--- + +## Bash naredbe + +Započnite poruku sa `!` da pokrenete komandu ljuske. + +```bash frame="none" +!ls -la +``` + +Izlaz naredbe se dodaje u razgovor kao rezultat alata. + +--- + +## Naredbe + +Kada koristite OpenCode TUI, možete upisati `/` nakon čega slijedi ime komande da biste brzo izvršili radnje. na primjer: + +```bash frame="none" +/help +``` + +Većina naredbi također ima vezu pomoću `ctrl+x` kao vodeće tipke, gdje je `ctrl+x` zadani vodeći ključ. [Saznajte više](/docs/keybinds). + +Ovdje su sve dostupne komande kose crte: + +--- + +### connect + +Dodajte provajdera u OpenCode. Omogućava vam da odaberete između dostupnih provajdera i dodate njihove API ključeve. + +```bash frame="none" +/connect +``` + +--- + +### compact + +Sažimanje trenutne sesije. _Alias_: `/summarize` + +```bash frame="none" +/compact +``` + +**Tastatura:** `ctrl+x c` + +--- + +### details + +Prebacite detalje o izvršavanju alata. + +```bash frame="none" +/details +``` + +**Tastatura:** `ctrl+x d` + +--- + +### editor + +Otvorite vanjski uređivač za sastavljanje poruka. Koristi editor postavljen u vašoj varijabli okruženja `EDITOR`. [Saznajte više](#editor-setup). + +```bash frame="none" +/editor +``` + +**Tastatura:** `ctrl+x e` + +--- + +### exit + +Izađite iz OpenCode. _Aliases_: `/quit`, `/q` + +```bash frame="none" +/exit +``` + +**Tastatura:** `ctrl+x q` + +--- + +### export + +Izvezite trenutni razgovor u Markdown i otvorite ga u zadanom uređivaču. Koristi editor postavljen u vašoj varijabli okruženja `EDITOR`. [Saznajte više](#editor-setup). + +```bash frame="none" +/export +``` + +**Tastatura:** `ctrl+x x` + +--- + +### help + +Prikaži dijalog pomoći. + +```bash frame="none" +/help +``` + +**Tastatura:** `ctrl+x h` + +--- + +### init + +Kreirajte ili ažurirajte datoteku `AGENTS.md`. [Saznajte više](/docs/rules). + +```bash frame="none" +/init +``` + +**Tastatura:** `ctrl+x i` + +--- + +### models + +Navedite dostupne modele. + +```bash frame="none" +/models +``` + +**Tastatura:** `ctrl+x m` + +--- + +### new + +Započnite novu sesiju. _Alias_: `/clear` + +```bash frame="none" +/new +``` + +**Tastatura:** `ctrl+x n` + +--- + +### redo + +Ponovite prethodno poništenu poruku. Dostupno samo nakon korištenja `/undo`. + +:::tip +Sve promjene fajla će također biti vraćene. +::: + +Interno, ovo koristi Git za upravljanje promjenama datoteke. Dakle, vaš projekat **treba +biti Git spremište**. + +```bash frame="none" +/redo +``` + +**Tastatura:** `ctrl+x r` + +--- + +### sessions + +Listanje i prebacivanje između sesija. _Aliases_: `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +**Tastatura:** `ctrl+x l` + +--- + +### share + +Podijelite trenutnu sesiju. [Saznajte više](/docs/share). + +```bash frame="none" +/share +``` + +**Tastatura:** `ctrl+x s` + +--- + +### themes + +Navedite dostupne teme. + +```bash frame="none" +/theme +``` + +**Tastatura:** `ctrl+x t` + +--- + +### thinking + +Uključite/isključite vidljivost blokova razmišljanja/rezoniranja u razgovoru. Kada je omogućeno, možete vidjeti proces rezonovanja modela za modele koji podržavaju prošireno razmišljanje. + +:::note +Ova naredba samo kontrolira da li se blokovi razmišljanja **prikažu** - ne omogućava niti onemogućuje mogućnosti razmišljanja modela. Da biste uključili stvarne mogućnosti zaključivanja, koristite `ctrl+t` za kretanje kroz varijante modela. +::: + +```bash frame="none" +/thinking +``` + +--- + +### undo + +Poništi posljednju poruku u razgovoru. Uklanja najnoviju korisničku poruku, sve naknadne odgovore i sve promjene datoteke. + +:::tip +Sve promjene u fajlu će također biti poništene. +::: + +Interno, ovo koristi Git za upravljanje promjenama datoteke. Dakle, vaš projekat **treba +biti Git spremište**. + +```bash frame="none" +/undo +``` + +**Tastatura:** `ctrl+x u` + +--- + +### unshare + +Poništi dijeljenje trenutne sesije. [Saznajte više](/docs/share#un-sharing). + +```bash frame="none" +/unshare +``` + +--- + +## Podešavanje uređivača + +Obje naredbe `/editor` i `/export` koriste editor specificiran u vašoj varijabli okruženja `EDITOR`. + + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + + Da biste ga učinili trajnim, dodajte ovo u svoj shell profil; + `~/.bashrc`, `~/.zshrc`, itd. + + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + + Da biste ga učinili trajnim, koristite **Svojstva sistema** > **Okruženje + Varijable**. + + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + + Da biste ga učinili trajnim, dodajte ovo u svoj PowerShell profil. + + + + +Popularne opcije uređivača uključuju: + +- `code` - ​​Visual Studio Code +- `cursor` - ​​Cursor +- `windsurf` - ​​Windsurf +- `nvim` - ​​Neovim editorom +- `vim` - ​​Vim editor +- `nano` - ​​Nano editor +- `notepad` - ​​Windows Notepad +- `subl` - ​​Sublime Text + +:::note +Neki uređivači kao što je VS Code moraju biti pokrenuti sa `--wait` zastavicom. +::: + +Nekim uređivačima su potrebni argumenti komandne linije da bi se pokrenuli u načinu blokiranja. Oznaka `--wait` blokira proces uređivača dok se ne zatvori. + +--- + +## Konfiguracija + +Možete prilagoditi TUI ponašanje putem vašeg OpenCode konfiguracionog fajla. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### 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`.** + +--- + +## Prilagođavanje + +Možete prilagoditi različite aspekte TUI prikaza koristeći paletu komandi (`ctrl+x h` ili `/help`). Ove postavke traju i nakon ponovnog pokretanja. + +--- + +#### Prikaz korisničkog imena + +Uključite da li se vaše korisničko ime pojavljuje u porukama za ćaskanje. Pristupite ovome putem: + +- Paleta naredbi: Potražite "korisničko ime" ili "sakrij korisničko ime" +- Postavka se automatski nastavlja i pamtit će se tijekom TUI sesija diff --git a/packages/web/src/content/docs/bs/web.mdx b/packages/web/src/content/docs/bs/web.mdx new file mode 100644 index 00000000000..6110162a974 --- /dev/null +++ b/packages/web/src/content/docs/bs/web.mdx @@ -0,0 +1,142 @@ +--- +title: Web +description: Korišćenje OpenCode u vašem pretraživaču. +--- + +OpenCode može raditi kao web aplikacija u vašem pretraživaču, pružajući isto moćno iskustvo AI kodiranja bez potrebe za terminalom. + +![OpenCode Web - Nova sesija](../../../assets/web/web-homepage-new-session.png) + +## Početak rada + +Pokrenite web interfejs tako što ćete pokrenuti: + +```bash +opencode web +``` + +Ovo pokreće lokalni server na `127.0.0.1` sa nasumičnim dostupnim portom i automatski otvara OpenCode u vašem podrazumevanom pretraživaču. + +:::caution +Ako `OPENCODE_SERVER_PASSWORD` nije postavljen, server će biti nezaštićen. Ovo je u redu za lokalnu upotrebu, ali bi trebalo biti postavljeno za pristup mreži. +::: + +:::tip[Windows korisnici] +Za najbolje iskustvo, pokrenite `opencode web` iz [WSL](/docs/windows-wsl) umjesto PowerShell-a. Ovo osigurava pravilan pristup sistemu datoteka i integraciju terminala. +::: + +--- + +## Konfiguracija + +Možete konfigurirati web server koristeći oznake komandne linije ili u vašoj [config file](/docs/config). + +### Port + +OpenCode podrazumevano bira dostupni port. Možete odrediti port: + +```bash +opencode web --port 4096 +``` + +### Ime hosta + +Podrazumevano, server se vezuje za `127.0.0.1` (samo lokalni host). Da biste OpenCode učinili dostupnim na vašoj mreži: + +```bash +opencode web --hostname 0.0.0.0 +``` + +Kada koristite `0.0.0.0`, OpenCode će prikazati i lokalne i mrežne adrese: + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### mDNS Otkrivanje + +Omogućite mDNS kako bi vaš server bio vidljiv na lokalnoj mreži: + +```bash +opencode web --mdns +``` + +Ovo automatski postavlja ime hosta na `0.0.0.0` i oglašava server kao `opencode.local`. + +Možete prilagoditi ime mDNS domene za pokretanje više instanci na istoj mreži: + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +Da biste omogućili dodatne domene za CORS (korisno za prilagođene frontendove): + +```bash +opencode web --cors https://example.com +``` + +### Autentifikacija + +Da biste zaštitili pristup, postavite lozinku koristeći varijablu okruženja `OPENCODE_SERVER_PASSWORD`: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +Korisničko ime podrazumevano je `opencode`, ali se može promeniti sa `OPENCODE_SERVER_USERNAME`. + +--- + +## Korištenje web sučelja + +Jednom pokrenut, web sučelje pruža pristup vašim OpenCode sesijama. + +### Sesije + +Pregledajte i upravljajte svojim sesijama sa početne stranice. Možete vidjeti aktivne sesije i započeti nove. + +![OpenCode Web - aktivna sesija](../../../assets/web/web-homepage-active-session.png) + +### Status servera + +Kliknite "Pogledajte servere" da vidite povezane servere i njihov status. + +![OpenCode Web - Vidi servere](../../../assets/web/web-homepage-see-servers.png) + +--- + +## Povezivanje terminala + +Možete priključiti TUI terminala na aktivni web server: + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +Ovo vam omogućava da istovremeno koristite i web sučelje i terminal, dijeleći iste sesije i stanje. + +--- + +## Konfiguracioni fajl + +Također možete konfigurirati postavke servera u svom `opencode.json` konfiguracijskom fajlu: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +Oznake komandne linije imaju prednost nad postavkama konfiguracione datoteke. diff --git a/packages/web/src/content/docs/bs/windows-wsl.mdx b/packages/web/src/content/docs/bs/windows-wsl.mdx new file mode 100644 index 00000000000..04d62a53145 --- /dev/null +++ b/packages/web/src/content/docs/bs/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: Pokrenite OpenCode na Windowsu preko WSL-a. +--- + +import { Steps } from "@astrojs/starlight/components" + +Iako OpenCode moze raditi direktno na Windowsu, preporucujemo [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) za najbolje iskustvo. WSL daje Linux okruzenje koje glatko radi sa OpenCode funkcijama. + +:::tip[Zašto WSL?] +WSL nudi bolje performanse fajl sistema, punu terminalsku podrsku i kompatibilnost s razvojnim alatima na koje se OpenCode oslanja. +::: + +--- + +## Postavljanje + + + +1. **Instalirajte WSL** + + Ako vec niste, [instalirajte WSL](https://learn.microsoft.com/en-us/windows/wsl/install) prema zvanicnom Microsoft vodicu. + +2. **Instalirajte OpenCode u WSL-u** + + Kad je WSL spreman, otvorite WSL terminal i instalirajte OpenCode jednom od [metoda instalacije](/docs/). + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **Koristite OpenCode iz WSL-a** + + Idite u direktorij projekta (Windows fajlovima pristupate preko `/mnt/c/`, `/mnt/d/` itd.) i pokrenite OpenCode. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## Desktop aplikacija + WSL Server + +Ako preferirate OpenCode Desktop aplikaciju, ali zelite da server radi u WSL-u: + +1. **Pokrenite server u WSL-u** sa `--hostname 0.0.0.0` da dozvolite vanjske konekcije: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **Povezite Desktop aplikaciju** na `http://localhost:4096` + +:::note +Ako `localhost` ne radi u vasem setupu, povezte se preko WSL IP adrese (u WSL-u: `hostname -I`) i koristite `http://:4096`. +::: + +:::caution +Kada koristite `--hostname 0.0.0.0`, postavite `OPENCODE_SERVER_PASSWORD` da zastitite server. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## Web klijent + WSL + +Za najbolje web iskustvo na Windowsu: + +1. **Pokrenite `opencode web` u WSL terminalu** umjesto u PowerShell-u: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Otvorite iz Windows browsera** na `http://localhost:` (OpenCode ispisuje URL) + +Pokretanje `opencode web` iz WSL-a osigurava ispravan pristup fajl sistemu i terminalsku integraciju, a i dalje je dostupno iz Windows browsera. + +--- + +## Pristup Windows fajlovima + +WSL moze pristupiti svim Windows fajlovima kroz `/mnt/` direktorij: + +- Disk `C:` → `/mnt/c/` +- Disk `D:` → `/mnt/d/` +- I tako dalje... + +Primjer: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +Za najgladje iskustvo, razmislite da klonirate/kopirate repo u WSL fajl sistem (npr. pod `~/code/`) i tu pokrenete OpenCode. +::: + +--- + +## Savjeti + +- Drzite OpenCode u WSL-u za projekte na Windows diskovima - pristup fajlovima je jednostavan +- Koristite VS Code [WSL ekstenziju](https://code.visualstudio.com/docs/remote/wsl) uz OpenCode za integrisan tok rada +- Vase OpenCode konfiguracije i sesije cuvaju se u WSL okruzenju na `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/bs/zen.mdx b/packages/web/src/content/docs/bs/zen.mdx new file mode 100644 index 00000000000..f9733370861 --- /dev/null +++ b/packages/web/src/content/docs/bs/zen.mdx @@ -0,0 +1,236 @@ +--- +title: Zen +description: Kurirana lista modela koje nudi OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen je lista testiranih i provjerenih modela koje obezbjeduje OpenCode tim. + +:::note +OpenCode Zen je trenutno u beta fazi. +::: + +Zen radi kao i svaki drugi provajder u OpenCode. Prijavite se u OpenCode Zen i uzmete API kljuc. Ovo je **potpuno opcionalno** i ne morate ga koristiti da biste koristili OpenCode. + +--- + +## Pozadina + +Postoji veliki broj modela, ali samo mali dio radi dobro kao coding agent. Dodatno, vecina provajdera je drugacije konfigurisana, pa su performanse i kvalitet cesto neujednaceni. + +:::tip +Testirali smo odabranu grupu modela i provajdera koji dobro rade s OpenCode. +::: + +Ako model koristite preko servisa poput OpenRouter-a, cesto ne mozete biti sigurni da dobijate najbolju verziju zeljenog modela. + +Da to rijesimo, uradili smo nekoliko stvari: + +1. Testirali smo odabrane modele i razgovarali sa njihovim timovima kako ih najbolje pokretati. +2. Zatim smo saradjivali s nekoliko provajdera da potvrdimo da se modeli isporucuju ispravno. +3. Na kraju smo benchmarkirali kombinacije model/provajder i sastavili listu koju preporucujemo. + +OpenCode Zen je AI gateway koji vam daje pristup tim modelima. + +--- + +## Kako radi + +OpenCode Zen radi kao i svaki drugi provajder u OpenCode. + +1. Prijavite se na **OpenCode Zen**, dodajte billing podatke i kopirajte API kljuc. +2. U TUI-ju pokrenite `/connect`, izaberite OpenCode Zen i zalijepite API kljuc. +3. Pokrenite `/models` u TUI-ju da vidite listu preporucenih modela. + +Naplata je po zahtjevu i mozete dodavati kredit na racun. + +--- + +## Endpoints + +Nasim modelima mozete pristupiti i preko sljedecih API endpointa. + +| Model | Model ID | Endpoint | AI SDK Package | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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` | + +[model id](/docs/config/#models) u OpenCode konfiguraciji koristi format `opencode/`. Na primjer, za GPT 5.2 Codex u konfiguraciji koristite `opencode/gpt-5.2-codex`. + +--- + +### Modeli + +Pun spisak dostupnih modela i metapodataka mozete preuzeti na: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## Cijene + +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.1 | $0.30 | $1.20 | $0.10 | - | +| GLM 4.7 Free | Free | Free | Free | - | +| 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 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 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.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 | Free | Free | Free | - | + +U historiji koristenja mozete primijetiti _Claude Haiku 3.5_. To je [low cost model](/docs/config/#models) koji se koristi za generisanje naslova sesija. + +:::note +Naknade kartica se prenose po stvarnom trosku (4.4% + $0.30 po transakciji) i ne naplacujemo nista preko toga. +::: + +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. + +Ako imate pitanja, kontaktirajte nas. + +--- + +### Automatska dopuna + +Ako vam stanje padne ispod $5, Zen ce automatski dopuniti $20. + +Iznos auto-reloada mozete promijeniti. Auto-reload mozete i potpuno iskljuciti. + +--- + +### Mjesečni limiti + +Mozete postaviti mjesecni limit potrosnje za cijeli workspace i za svakog clana tima. + +Na primjer, ako postavite mjesecni limit na $20, Zen nece potrositi vise od $20 u mjesecu. Ali ako je auto-reload ukljucen, ukupna naplata moze preci $20 ako stanje padne ispod $5. + +--- + +## Privatnost + +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). + +--- + +## Za timove + +Zen odlicno radi i za timove. Mozete pozvati clanove tima, dodijeliti uloge, birati modele koje tim koristi i jos mnogo toga. + +:::note +Workspaces su trenutno besplatni za timove kao dio beta faze. +::: + +Upravljanje workspace-om je trenutno besplatno za timove tokom beta faze. Vise detalja o cijenama podijelit cemo uskoro. + +--- + +### Uloge + +Mozete pozvati clanove tima u workspace i dodijeliti uloge: + +- **Admin**: upravlja modelima, clanovima, API kljucevima i billingom +- **Member**: upravlja samo svojim API kljucevima + +Admini mogu postaviti i mjesecne limite potrosnje po clanu da drze troskove pod kontrolom. + +--- + +### Pristup modelima + +Admini mogu ukljuciti ili iskljuciti odredene modele za workspace. Zahtjevi prema iskljucenom modelu vracaju gresku. + +Ovo je korisno kada zelite zabraniti model koji prikuplja podatke. + +--- + +### Donesite vlastiti ključ + +Mozete koristiti vlastite OpenAI ili Anthropic API kljuceve i dalje koristiti ostale modele u Zen-u. + +Kada koristite vlastite kljuceve, tokene direktno naplacuje provajder, ne Zen. + +Na primjer, vasa organizacija mozda vec ima OpenAI ili Anthropic kljuc i zelite koristiti njega umjesto onog koji daje Zen. + +--- + +## Ciljevi + +OpenCode Zen smo napravili da: + +1. **Benchmarkiramo** najbolje kombinacije model/provajder za coding agente. +2. Omogucimo pristup opcijama **najviseg kvaliteta** bez degradacije performansi i preusmjeravanja na jeftinije provajdere. +3. Prenesemo svaka **snizenja cijena** prodajom po trosku, tako da je jedini markup pokrice processing naknada. +4. Obezbijedimo **bez lock-ina** tako da Zen mozete koristiti sa bilo kojim coding agentom, uz slobodu koristenja drugih provajdera u OpenCode. diff --git a/packages/web/src/content/docs/da/acp.mdx b/packages/web/src/content/docs/da/acp.mdx new file mode 100644 index 00000000000..06cdc89c40c --- /dev/null +++ b/packages/web/src/content/docs/da/acp.mdx @@ -0,0 +1,156 @@ +--- +title: ACP-understøttelse +description: Brug OpenCode i enhver ACP-kompatibel editor. +--- + +OpenCode understøtter [Agent Client Protocol](https://agentclientprotocol.com) eller (ACP), så du kan bruge det direkte i kompatible editorer og IDE'er. + +:::tip +For en liste over editorer og værktøjer, der understøtter ACP, tjek [ACP fremskridtsrapport](https://zed.dev/blog/acp-progress-report#available-now). +::: + +ACP er en åben protokol, der standardiserer kommunikation mellem kodeeditorer og AI-kodningsagenter. + +--- + +## Konfiguration + +For at bruge OpenCode via ACP, konfigurer din editor til at køre kommandoen `opencode acp`. + +Kommandoen starter OpenCode som en ACP-kompatibel underproces, der kommunikerer med din editor over JSON-RPC via stdio. + +Nedenfor er eksempler på populære editorer, der understøtter ACP. + +--- + +### Zed + +Føj til din [Zed](https://zed.dev)-konfiguration (`~/.config/zed/settings.json`): + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +For at åbne den skal du bruge handlingen `agent: new thread` i **Kommandopaletten**. + +Du kan også binde en tastaturgenvej ved at redigere din `keymap.json`: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### JetBrains IDE'er + +Tilføj til din [JetBrains IDE](https://www.jetbrains.com/) acp.json i henhold til [dokumentationen](https://www.jetbrains.com/help/ai-assistant/acp.html): + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +For at åbne den skal du bruge den nye 'OpenCode'-agent i AI Chat-agentvælgeren. + +--- + +### Avante.nvim + +Føj til din [Avante.nvim](https://github.com/yetone/avante.nvim)-konfiguration: + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +Hvis du har brug for at videregive miljøvariabler: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +For at bruge OpenCode som en ACP-agent i [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim), skal du tilføje følgende til din Neovim-konfiguration: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +Denne konfiguration sætter CodeCompanion til at bruge OpenCode som ACP-agent til chat. + +Hvis du har brug for at sende miljøvariabler (som `OPENCODE_API_KEY`), henvises til [Konfiguration af adaptere: Miljøvariabler](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) i CodeCompanion.nvim-dokumentationen for alle detaljer. + +## Understøttelse + +OpenCode fungerer på samme måde via ACP som i terminalen. Alle funktioner understøtter: + +:::note +Nogle indbyggede slash-kommandoer som `/undo` og `/redo` er i øjeblikket ikke understøttet. +::: + +- Indbyggede værktøjer (filoperationer, terminalkommandoer osv.) +- Brugerdefinerede værktøjer og slash-kommandoer +- MCP-servere konfigureret i din OpenCode-konfiguration +- Projektspecifikke regler fra `AGENTS.md` +- Brugerdefinerede formatere og linters +- Agenter og tilladelsessystem diff --git a/packages/web/src/content/docs/da/agents.mdx b/packages/web/src/content/docs/da/agents.mdx new file mode 100644 index 00000000000..6ab2e7c39d6 --- /dev/null +++ b/packages/web/src/content/docs/da/agents.mdx @@ -0,0 +1,747 @@ +--- +title: Agenter +description: Konfigurer og brug specialiserede agenter. +--- + +Agenter er specialiserede AI-assistenter, der kan konfigureres til specifikke opgaver og arbejdsgange. De giver dig mulighed for at oprette en central værktøj med brugerdefinerede prompter, modeller og værktøjsadgang. + +:::tip +Brug planagenten til at analysere kode og gennemgå forslag uden at foretage nogen kodeændringer. +::: + +Du kan skifte mellem agenter under en session eller kalde dem med `@`-omtalen. + +--- + +## Typer + +Der er to typer agenter i OpenCode; primære agenter og subagenter. + +--- + +### Primær agent + +Primære agenter er de vigtigste assistenter, du interagerer direkte med. Du kan bladre gennem dem ved at bruge **Tab**-tasten eller din konfigurerede `switch_agent`-tastebinding. Disse agenter håndterer din hovedsamtale. Værktøjsadgang konfigureres via tilladelser - for eksempel har Build alle aktiveret, mens Plan er begrænset. + +:::tip +Du kan bruge **Tab**-tasten til at skifte mellem primære agenter under en session. +::: + +OpenCode leveres med indbyggede primære agenter, **Build** og **Plan**. Vi vil +se på disse nedenfor. + +--- + +### Subagent + +Subagenter er specialiserede assistenter, som primære agenter kan påbegynde sig til specifikke opgaver. Du kan også kalde dem manuelt ved at **@ nævne** dem i dine beskeder. + +OpenCode leveres med to indbyggede underagenter, **Generelt** og **Udforsk**. Vi vil se på dette nedenfor. + +--- + +## Indbyggede + +OpenCode leveres med to indbyggede primære agenter og to indbyggede subagenter. + +--- + +### Build-agenten + +_Tilstand_: `primary` + +Byg er den **standard** primære agent med alle aktiveret. Dette er standardagenten til udviklingsarbejde, hvor du har brug for fuld adgang til filhandlinger og systemkommandoer. + +--- + +### Plan-agenten + +_Tilstand_: `primary` + +En begrænset agent designet til planlægning og analyse. Vi bruger et tilladelsessystem til at give dig mere kontrol og forhindre utilsigtede ændringer. +Som standard er alle følgende indstillet til `ask`: + +- `file edits`: Alle skrivninger, patches og redigeringer +- `bash`: Alle bash-kommandoer + +Denne agent er nyttig, når du vil have LLM til at analysere kode, foreslå ændringer eller oprette planer uden at foretage egentlige ændringer af din kodebase. + +--- + +### General-agenten + +_Tilstand_: `subagent` + +En agent til generelt formål at undersøge komplekse spørgsmål og udføre opgaver i flere trin. Har fuld værktøjsadgang (undtagen todo), så den kan foretage filændringer, når det er nødvendigt. Brug dette til at køre flere arbejdsenheder parallelt. + +--- + +### Explore-agenten + +_Tilstand_: `subagent` + +En hurtig, skrivebeskyttet agent til at udforske kodebaser. Kan ikke ændre filer. Brug dette, når du hurtigt skal finde filer efter mønstre, søge kode efter nøgleord eller besvare spørgsmål om kodebasen. + +--- + +### Compact-agenten + +_Tilstand_: `primary` + +Skjult systemagent, der komprimerer lang kontekst til et mindre resumé. Det kører automatisk, når det er nødvendigt og ikke kan vælges i brugergrænsefladen. + +--- + +### Title-agenten + +_Tilstand_: `primary` + +Skjult systemagent, der genererer korte sessionstitler. Den kører automatisk og kan ikke vælges i brugergrænsefladen. + +--- + +### Resume-agenten + +_Tilstand_: `primary` + +Skjult systemagent, der opretter sessionsoversigter. Den kører automatisk og kan ikke vælges i brugergrænsefladen. + +--- + +## Anvendelse + +1. For primære agenter skal du bruge tasten **Tab** til at bladre gennem dem under en session. Du kan også bruge din konfigurerede `switch_agent` nøglebinding. + +2. Subagenter kan påberåbes: + - **Automatisk** af primære agenter til specialiserede opgaver baseret på deres beskrivelser. + - Manuelt ved at **@ nævne** en underagent i din besked. F.eks. + + ```txt frame="none" + @general help me search for this function + ``` + +3. **Navigation mellem sessioner**: Når underagenter opretter deres egne underordnede sessioner, kan du navigere mellem den overordnede session og alle underordnede sessioner ved hjælp af: + - **\+Højre** (eller din konfigurerede `session_child_cycle`-tastebinding) for at cykle fremad gennem forælder → barn1 → barn2 →... → forælder + - **\+Venstre** (eller din konfigurerede `session_child_cycle_reverse`-tastebinding) for at cykle baglæns gennem forælder ← barn1 ← barn2 ←... ← forælder + + Dette giver dig mulighed for problemfrit at skifte mellem hovedsamtalen og specialiseret subagent arbejde. + +--- + +## Konfiguration + +Du kan tilpasse de indbyggede agenter eller oprette dine egne gennem konfiguration. Agenter kan konfigureres på følgende måder: + +--- + +### JSON + +Konfigurer agent i din `opencode.json`-konfigurationsfil: + +```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 + +Du kan også definere agenter ved hjælp af markdown-filer. Placer dem i: + +- Globalt: `~/.config/opencode/agents/` +- Pr. projekt: `.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-filnavnet bliver agentnavnet. For eksempel opretter `review.md` og `review`-agent. + +--- + +## Indstillinger + +Lad os se nærmere på disse konfigurationsmuligheder. + +--- + +### Beskrivelse (`description`) + +Brug indstillingen `description` til at give en kort beskrivelse af, hvad agenten gør, og hvornår den skal bruges. + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +Dette er en **påkrævet** konfigurationsindstilling. + +--- + +### Temperatur (`temperature`) + +Styr tilfældigheden og kreativiteten af ​​​​LLMs svar med `temperature`-konfigurationen. + +Lavere værdier gør svar mere fokuserede og deterministiske, mens højere værdier øger kreativitet og variabilitet. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Temperaturværdier typisk fra 0,0 til 1,0: + +- **0.0-0.2**: Meget fokuseret og deterministisk svar, ideel til kodeanalyse og planlægning +- **0,3-0,5**: Afbalancerede svar med en vis kreativitet, god til generelle udviklingsopgaver +- **0.6-1.0**: Mere kreative og varierede svar, nyttige til brainstorming og udforskning + +```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}" + } + } +} +``` + +Hvis ingen temperatur er angivet, bruger OpenCode modelspecifikke standardindstillinger; typisk 0 for de fleste modeller, 0,55 for Qwen-modeller. + +--- + +### Trin (`steps`) + +Kontrollerer det maksimale antal agent-gentagelser, som en agent kan udføre, før han bliver tvunget til kun at svare med tekst. Dette giver brugere, der ønsker at kontrollere, mulighed for at sætte en grænse for agenthandlinger. + +Hvis dette ikke er indstillet, vil agenten fortsætte med at iterere, indtil modellen vælger at stoppe, eller brugeren afbryder sessionen. + +```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 + } + } +} +``` + +Når grænsen er nået, modtager agenten en speciel systemprompt, der instruerer den om at svare med en opsummering af sit arbejde og anbefalede resterende opgaver. + +:::caution +Det gamle `maxSteps`-felt er forældet. Brug `steps` i stedet. +::: + +--- + +### Deaktivering (`disable`) + +Indstil til `true` for at deaktivere agenten. + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### Prompt (`prompt`) + +Angiv en brugerdefineret systempromptfil for denne agent med `prompt`-konfigurationen. Promptfilen skal indeholde instruktioner, der er specifikke for agentens formål. + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Denne sti er i forhold til, hvor konfigurationsfilen er placeret. Så dette virker både for den globale OpenCode-konfiguration og den projektspecifikke konfiguration. + +--- + +### Model (`model`) + +Brug `model`-konfigurationen til at tilsidesætte modeller for denne agent. Nyttigt til brug af forskellige modeller optimeret til forskellige opgaver. For eksempel en hurtigere model til planlægning, en dygtig model til implementering. + +:::tip +Hvis du ikke angiver en model, bruger primære agenter [model konfigureret globalt](/docs/config#models), mens subagenter vil bruge modeller for den primære agent, der påkaldte subagenten. +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +Model-id'et i din OpenCode-konfiguration brugerformatet `provider/model-id`. For eksempel, hvis du bruger [OpenCode Zen](/docs/zen), vil du bruge `opencode/gpt-5.1-codex` til GPT 5.1 Codex. + +--- + +### Værktøjer (`tools`) + +Kontroller, hvilke værktøjer der er tilgængelige i denne agent med `tools`-konfigurationen. Du kan aktivere eller deaktivere specifikke redskaber ved at indstille dem til `true` eller `false`. + +```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 +Den agentspecifikke konfiguration tilsidesætter den globale konfiguration. +::: + +Du kan også bruge jokertegn til at styre flere værktøjer på én gang. For eksempel, for at deaktivere alle værktøjer fra en MCP-server: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[Læs mere om værktøjer](/docs/tools). + +--- + +### Tilladelser (`permission`) + +Du kan konfigurere tilladelser til at administrere, hvilke handlinger og agenter kan udføre. I øjeblikket kan tilladelserne til værktøjerne `edit`, `bash` og `webfetch` konfigureres til: + +- `"ask"` — Bed om godkendelse, før du kører værktøjet +- `"allow"` — Tillad alle operationer uden godkendelse +- `"deny"` — Deaktiver værktøjet + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +Du kan tilsidesætte disse tilladelser pr. agent. + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +Du kan også angive tilladelser i Markdown-agenter. + +```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. +``` + +Du kan indstille tilladelser til specifikke bash-kommandoer. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +Dette kan tage et globmønster. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +Og du kan også bruge jokertegnet `*` til at administrere tilladelser for alle kommandoer. +Da den sidste matchningsregel har forrang, skal du sætte jokertegnet `*` først og specifikke regler efter. + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[Læs mere om tilladelser](/docs/permissions). + +--- + +### Tilstand (`mode`) + +Styr agentens tilstand med `mode`-konfigurationen. Indstillingen `mode` bruges til at bestemme, hvordan agenten kan bruges. + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +Indstillingen `mode` kan indstilles til `primary`, `subagent` eller `all`. Hvis der ikke er angivet nogen `mode`, er den som standard `all`. + +--- + +### Skjult (`hidden`) + +Skjul en underagent fra `@` autofuldførelsesmenuen med `hidden: true`. Nyttigt for interne underagenter, der kun bør startes programmatisk af andre agenter via opgaveværktøjet. + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +Dette påvirker kun brugerens synlighed i autofuldførelsesmenuen. Skjulte agenter kan stadig påkaldes af modellen via opgaveværktøjet, hvis tilladelser tillader det. + +:::note +Gælder kun for `mode: subagent`-agent. +::: + +--- + +### Opgavetilladelser (`permission.task`) + +Kontroller, hvilke subagenter en agent kan påkalde via opgaveværktøjet med `permission.task`. Bruger glob-mønstre til fleksibel matchning. + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +Når den er indstillet til `deny`, fjernes subagenten helt fra opgaveværktøjsbeskrivelsen, så modeller vil ikke forsøge at starte den. + +:::tip +Reglerne vurderer i rækkefølge, og den **sidste matchende regel vinder**. I eksemplet ovenfor matcher `orchestrator-planner` både `*` (afvis) og `orchestrator-*` (tillad), men da `orchestrator-*` kommer efter `*`, er resultatet `allow`. +::: + +:::tip +Brugere kan altid påkalde enhver underagent direkte via `@` autofuldførelsesmenuen, nægt agentens opgavetilladelser ville det. +::: + +--- + +### Farve (`color`) + +Tilpas agentens visuelle udseende i brugergrænsefladen med muligheden `color`. Dette påvirker, hvordan agenter vises i grænsefladen. + +Brug en gyldig hex-farve (f.eks. `#FF5733`) eller temafarve: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +Styr responsdiversiteten med `top_p`-muligheden. Alternativ til temperatur for at kontrollere tilfældighed. + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +Værdier spænder fra 0,0 til 1,0. Lavere værdier er mere fokuserede, højere værdier mere forskelligartede. + +--- + +### Yderligere + +Alle andre muligheder, du angiver i din agentkonfiguration, vil blive **overført direkte** til udbyderen som modelvalg. Dette giver dig mulighed for at bruge udbyderspecifikke funktioner og parametre. + +For eksempel, med OpenAIs ræsoneringsmodeller kan du styre ræsonnementindsatsen: + +```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" + } + } +} +``` + +Disse yderligere muligheder er model- og udbyderspecifikke. Tjek din udbyders dokumentation for tilgængelige parametre. + +:::tip +Kør `opencode models` for at se en liste over de tilgængelige modeller. +::: + +--- + +## Oprettelse af agent + +Du kan oprette nye agenter ved hjælp af følgende kommando: + +```bash +opencode agent create +``` + +Denne interaktive kommando vil: + +1. Spørg, hvor agenten skal gemmes; globalt eller projektspecifikt. +2. Beskrivelse af, hvad agenten skal gøre. +3. Generer en passende systemprompt og identifikator. +4. Lad dig vælge, hvilke værktøjer agenter har adgang til. +5. Til sidst skal du oprette en markdown-fil med agentkonfigurationen. + +--- + +## Anvendelsesmuligheder + +Her er nogle almindelige use cases for forskellige agenter. + +- **Byggeagent**: Fuldt udviklingsarbejde med alle aktiveret +- **Planagent**: Analyse og planlægning uden ændringer +- **Anmeldelsesagent**: Kodegennemgang med skrivebeskyttet adgang plus dokumentationsværktøjer +- **Debug agent**: Fokuseret på undersøgelse med bash og læseværktøjer aktiveret +- **Docs-agent**: Dokumentationsskrivning med filhandlinger, men ingen systemkommandoer + +--- + +## Eksempler + +Her er nogle eksempler på agenter, du kan finde nyttige. + +:::tip +Har du en agent, du gerne vil dele? [Send en PR](https://github.com/anomalyco/opencode). +::: + +--- + +### Dokumentations-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 +``` + +--- + +### Sikkerheds-agent + +```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/da/cli.mdx b/packages/web/src/content/docs/da/cli.mdx new file mode 100644 index 00000000000..c29559df261 --- /dev/null +++ b/packages/web/src/content/docs/da/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: OpenCode CLI muligheder og kommandoer. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode CLI starter som standard [TUI](/docs/tui), når den kører uden nogen argumenter. + +```bash +opencode +``` + +Men den accepterer også kommandoer som dokumenteret på denne side. Dette giver dig mulighed for at interagere med OpenCode programmatisk. + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +Start OpenCode terminalbrugergrænsefladen. + +```bash +opencode [project] +``` + +#### Flag + +| Flag | Kort | Beskrivelse | +| ------------ | ---- | ---------------------------------------------------------------------------- | +| `--continue` | `-c` | Fortsæt sidste session | +| `--session` | `-s` | Sessions-id for at fortsætte | +| `--fork` | | Forgren sessionen ved fortsættelse (brug med `--continue` eller `--session`) | +| `--prompt` | | Spørg om at bruge | +| `--model` | `-m` | Model til brug i form af provider/model | +| `--agent` | | Agent hos bruge | +| `--port` | | Port at lytte på | +| `--hostname` | | Værtsnavn at lytte på | + +--- + +## Kommandoer + +OpenCode CLI har også følgende kommandoer. + +--- + +### agent + +Administrer agenter i OpenCode. + +```bash +opencode agent [command] +``` + +--- + +### attach + +Tilslut en terminal til en allerede kørende OpenCode backend-server startet via `serve` eller `web` kommandoer. + +```bash +opencode attach [url] +``` + +Dette gør det muligt at bruge TUI med en ekstern OpenCode backend. For eksempel: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### Flag + +| Flag | Kort | Beskrivelse | +| ----------- | ---- | -------------------------------- | +| `--dir` | | Arbejdsmappe til at starte TUI i | +| `--session` | `-s` | Sessions-id for at fortsætte | + +--- + +#### create + +Opret en ny agent med brugerdefineret konfiguration. + +```bash +opencode agent create +``` + +Denne kommando vil guide dig gennem oprettelse af en ny agent med en brugerdefineret systemprompt og værktøjskonfiguration. + +--- + +#### list + +Liste over alle tilgængelige agenter. + +```bash +opencode agent list +``` + +--- + +### auth + +Kommando til at administrere legitimationsoplysninger og login for udbydere. + +```bash +opencode auth [command] +``` + +--- + +#### login + +OpenCode drives af udbyderlisten på [Models.dev](https://models.dev), så du kan bruge `opencode auth login` til at konfigurere API-nøgler for enhver udbyder, du vil bruge. Dette er gemt i `~/.local/share/opencode/auth.json`. + +```bash +opencode auth login +``` + +Når OpenCode starter op, indlæser den udbyderne fra legitimationsfilen. Og hvis der er nogen nøgler defineret i dine miljøer eller en `.env` fil i dit projekt. + +--- + +#### list + +Viser alle de godkendte udbydere som gemt i legitimationsfilen. + +```bash +opencode auth list +``` + +Eller den korte version. + +```bash +opencode auth ls +``` + +--- + +#### logout + +Logger dig ud af en udbyder ved at rydde den fra legitimationsfilen. + +```bash +opencode auth logout +``` + +--- + +### github + +Administrator GitHub-agenten til lagerautomatisering. + +```bash +opencode github [command] +``` + +--- + +#### install + +Installatør GitHub-agenten i dit lager. + +```bash +opencode github install +``` + +Dette opsætter det nødvendige GitHub Actions workflow og guider dig gennem konfigurationsprocessen. [Learn more](/docs/github). + +--- + +#### run + +Kør GitHub-agenten. Dette bruges typisk i GitHub Actions. + +```bash +opencode github run +``` + +##### Flag + +| Flag | Beskrivelse | +| --------- | ---------------------------------------------- | +| `--event` | GitHub mock begivenhed for at køre agenten for | +| `--token` | GitHub personlig adgangstoken | + +--- + +### mcp + +Administrator Model Context Protocol-servere. + +```bash +opencode mcp [command] +``` + +--- + +#### add + +Tilføj en MCP-server til din konfiguration. + +```bash +opencode mcp add +``` + +Denne kommando vil guide dig gennem tilføjelse af enten en lokal eller ekstern MCP-server. + +--- + +#### list + +Liste over alle konfigurerede MCP-servere og deres forbindelsesstatus. + +```bash +opencode mcp list +``` + +Eller brug den korte version. + +```bash +opencode mcp ls +``` + +--- + +#### auth + +Godkendt med en OAuth-aktiveret MCP-server. + +```bash +opencode mcp auth [name] +``` + +Hvis du ikke angiver et servernavn, bliver du bedt om at vælge blandt tilgængelige OAuth-kompatible servere. + +Du kan også angive OAuth-kompatible servere og deres godkendelsesstatus. + +```bash +opencode mcp auth list +``` + +Eller brug den korte version. + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +Fjern OAuth-legitimationsoplysninger for en MCP-server. + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +Fejlfinding af OAuth-forbindelsesproblemer for en MCP-server. + +```bash +opencode mcp debug +``` + +--- + +### models + +Liste over alle tilgængelige modeller fra konfigurerede udbydere. + +```bash +opencode models [provider] +``` + +Denne kommando viser alle tilgængelige modeller på tværs af dine konfigurerede udbydere i formatet `provider/model`. + +Dette er nyttigt til at finde ud af det nøjagtige modelnavn, der skal bruges i [your config](/docs/config/). + +Du kan eventuelt videregive et udbyder-id for at filtrere modeller efter den udbyder. + +```bash +opencode models anthropic +``` + +#### Flag + +| Flag | Beskrivelse | +| ----------- | ----------------------------------------------------------------------- | +| `--refresh` | Opdater modelcachen fra models.dev | +| `--verbose` | Brug mere detaljeret modeloutput (inkluderer metadata som omkostninger) | + +Brug flaget `--refresh` til at opdatere den cachelagrede modelliste. Dette er nyttigt, når nye modeller er blevet tilføjet til en udbyder, og du vil se dem i OpenCode. + +```bash +opencode models --refresh +``` + +--- + +### run + +Kør opencode i ikke-interaktiv tilstand ved at sende en prompt direkte. + +```bash +opencode run [message..] +``` + +Dette er nyttigt til scripting, automatisering, eller når du vil have et hurtigt svar uden at starte hele TUI. F.eks. + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +Du kan også vedhæfte til en kørende `opencode serve`-instans for at undgå MCP serverens kolde opstartstider ved hver kørsel: + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### Flag + +| Flag | Kort | Beskrivelse | +| ------------ | ---- | ----------------------------------------------------------------------------------- | +| `--command` | | Kommandoen til at køre, brug besked til args | +| `--continue` | `-c` | Fortsæt sidste session | +| `--session` | `-s` | Sessions-id for at fortsætte | +| `--fork` | | Forgren sessionen ved fortsættelse (brug med `--continue` eller `--session`) | +| `--share` | | Del sessionen | +| `--model` | `-m` | Model til brug i form af provider/model | +| `--agent` | | Agent til brug | +| `--file` | `-f` | Fil(er), der skal vedhæftes til meddelelsen | +| `--format` | | Format: standard (formateret) eller json (rå JSON hændelser) | +| `--title` | | Titel for sessionen (bruger trunkeret prompt, hvis der ikke er angivet nogen værdi) | +| `--attach` | | Tilslut til en kørende opencode-server (f.eks. http://localhost:4096) | +| `--port` | | Port til den lokale server (standard til vilkårlig port) | + +--- + +### serve + +Start en hovedløs OpenCode-server til API-adgang. Tjek [server docs](/docs/server) for den fulde HTTP-grænseflade. + +```bash +opencode serve +``` + +Dette starter en HTTP-server, der giver API-adgang til opencode-funktionalitet uden TUI-grænsefladen. Indstil `OPENCODE_SERVER_PASSWORD` for at aktivere HTTP grundlæggende godkendelse (brugernavn er standard til `opencode`). + +#### Flag + +| Flag | Beskrivelse | +| ------------ | ------------------------------------------------ | +| `--port` | Port at lytte på | +| `--hostname` | Værtsnavn at lytte på | +| `--mdns` | Aktiver mDNS-opdagelse | +| `--cors` | Yderligere browseroprindelse til at tillade CORS | + +--- + +### session + +Administrator OpenCode sessionsholder. + +```bash +opencode session [command] +``` + +--- + +#### list + +Liste over alle OpenCode sessioner. + +```bash +opencode session list +``` + +##### Flag + +| Flag | Kort | Beskrivelse | +| ------------- | ---- | -------------------------------------- | +| `--max-count` | `-n` | Begræns til N seneste sessioner | +| `--format` | | Outputformat: tabel eller json (tabel) | + +--- + +### stats + +Vis tokenbrug og omkostningsstatistikker for dine OpenCode-sessioner. + +```bash +opencode stats +``` + +#### Flag + +| Flag | Beskrivelse | +| ----------- | --------------------------------------------------------------------------- | +| `--days` | Vis statistik for de sidste N dage (hele tiden) | +| `--tools` | Antal værktøjer, der skal vises (alle) | +| `--models` | Vis modelbrugsopdeling (skjult som standard). Send et tal for at vise top N | +| `--project` | Filtre efter projekt (alle projekter, tom streng: nuværende projekt) | + +--- + +### export + +Eksporter sessionsdata som JSON. + +```bash +opencode export [sessionID] +``` + +Hvis du ikke angiver et sessions-id, bliver du bedt om at vælge mellem tilgængelige sessioner. + +--- + +### import + +Importer sessionsdata fra en JSON fil eller OpenCode del URL. + +```bash +opencode import +``` + +Du kan importere fra en lokal fil eller en OpenCode share URL. + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +Start en hovedløs OpenCode-server med en webgrænseflade. + +```bash +opencode web +``` + +Dette starter en HTTP-server og åbner en webbrowser for at få adgang til OpenCode via en webgrænseflade. Indstil `OPENCODE_SERVER_PASSWORD` for at aktivere HTTP grundlæggende godkendelse (brugernavn er standard til `opencode`). + +#### Flag + +| Flag | Beskrivelse | +| ------------ | ------------------------------------------------ | +| `--port` | Port at lytte på | +| `--hostname` | Værtsnavn at lytte på | +| `--mdns` | Aktiver mDNS-opdagelse | +| `--cors` | Yderligere browseroprindelse til at tillade CORS | + +--- + +### acp + +Start en ACP-server (Agent Client Protocol). + +```bash +opencode acp +``` + +Denne kommando starter en ACP-server, der kommunikerer via stdin/stdout ved hjælp af nd-JSON. + +#### Flag + +| Flag | Beskrivelse | +| ------------ | --------------------- | +| `--cwd` | Arbejdsmappe | +| `--port` | Port at lytte på | +| `--hostname` | Værtsnavn at lytte på | + +--- + +### uninstall + +Afinstaller OpenCode og fjern alle relaterede filer. + +```bash +opencode uninstall +``` + +#### Flag + +| Flag | Kort | Beskrivelse | +| --------------- | ---- | ------------------------------------------------ | +| `--keep-config` | `-c` | Se konfigurationsfiler | +| `--keep-data` | `-d` | Gem sessionsdata og snapshots | +| `--dry-run` | | Vis, hvad der ville blive fjernet uden at fjerne | +| `--force` | `-f` | Spring bekræftelsesspørgsmål over | + +--- + +### upgrade + +Opdaterer OpenCode til den nyeste version eller en specifik version. + +```bash +opencode upgrade [target] +``` + +For at opgradere til den nyeste version. + +```bash +opencode upgrade +``` + +For at opgradere til en bestemt version. + +```bash +opencode upgrade v0.1.48 +``` + +#### upgrade + +| Flag | Kort | Beskrivelse | +| ---------- | ---- | ---------------------------------------------------------------- | +| `--method` | `-m` | Installationsmetoden, der blev brugt; curl, npm, pnpm, bun, brew | + +--- + +## Globale flag + +opencode CLI tager følgende globale flag. + +| Flag | Kort | Beskrivelse | +| -------------- | ---- | ------------------------------------ | +| `--help` | `-h` | Vis hjælp | +| `--version` | `-v` | Udskriftsversionsnummer | +| `--print-logs` | | Udskriv logfiler til stderr | +| `--log-level` | | Logniveau (DEBUG, INFO, WARN, ERROR) | + +--- + +## Miljøvariabler + +OpenCode kan konfigureres ved hjælp af miljøvariabler. + +| Variabel | Skriv | Beskrivelse | +| ------------------------------------- | ------- | --------------------------------------------------------------------- | +| `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_CONFIG_DIR` | string | Sti til konfigurationsmappe | +| `OPENCODE_CONFIG_CONTENT` | string | Indbygget json-konfigurationsindhold | +| `OPENCODE_DISABLE_AUTOUPDATE` | boolean | Deaktiver automatisk opdateringskontrol | +| `OPENCODE_DISABLE_PRUNE` | boolean | Deaktiver beskæring af gamle data | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | Deaktiver automatisk opdatering af terminaltitel | +| `OPENCODE_PERMISSION` | string | Indbygget json-tilladelseskonfiguration | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | Deaktiver standard plugins | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | Deaktiver automatisk LSP-serverdownloads | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | Aktive eksperimentelle modeller | +| `OPENCODE_DISABLE_AUTOCOMPACT` | boolean | Deaktiver automatisk kontekstkomprimering | +| `OPENCODE_DISABLE_CLAUDE_CODE` | boolean | Deaktiver læsning fra `.claude` (prompt + færdigheder) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | Deaktiver læsning `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | Deaktiver indlæsning af `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | boolean | Deaktivering af modeller fra eksterne kilder | +| `OPENCODE_FAKE_VCS` | string | Falsk VCS-udbyder til testformål | +| `OPENCODE_DISABLE_FILETIME_CHECK` | boolean | Deaktiver filtidskontrol for optimering | +| `OPENCODE_CLIENT` | string | Klient-id (standard til `cli`) | +| `OPENCODE_ENABLE_EXA` | boolean | Aktiver Exa-websøgeværktøjer | +| `OPENCODE_SERVER_PASSWORD` | string | Aktiver grundlæggende godkendelse for `serve`/`web` | +| `OPENCODE_SERVER_USERNAME` | string | Tilsidesæt grundlæggende godkendelsesbrugernavn (standard `opencode`) | +| `OPENCODE_MODELS_URL` | string | Brugerdefineret URL til hentning af modelkonfiguration | + +--- + +### Flag + +Disse miljøvariabler muliggør eksperimentelle funktioner, der kan ændres eller fjernes. + +| Variabel | Skriv | Beskrivelse | +| ----------------------------------------------- | ------- | ------------------------------------------ | +| `OPENCODE_EXPERIMENTAL` | boolean | Aktiver alle eksperimentelle funktioner | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | Aktiver ikonopdagelse | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | Deaktiver kopi ved valg i TUI | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | nummer | Standard timeout for bash-kommandoer i ms | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | nummer | Maks. output-tokens for LLM-svar | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolean | Aktiver filovervågning for hele dir | +| `OPENCODE_EXPERIMENTAL_OXFMT` | boolean | Aktiver oxfmt formatter | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolean | Aktive eksperimenter LSP værktøj | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | Deaktiver filovervågning | +| `OPENCODE_EXPERIMENTAL_EXA` | boolean | Aktive eksperimenter Exa-funktioner | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolean | Aktive forsøg LSP typekontrol | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolean | Aktive eksperimentelle markdown-funktioner | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolean | Aktiver plantilstand | diff --git a/packages/web/src/content/docs/da/commands.mdx b/packages/web/src/content/docs/da/commands.mdx new file mode 100644 index 00000000000..1b624b57a39 --- /dev/null +++ b/packages/web/src/content/docs/da/commands.mdx @@ -0,0 +1,323 @@ +--- +title: Kommandoer +description: Opret brugerdefinerede kommandoer til gentagne opgaver. +--- + +Brugerdefinerede kommandoer giver mulighed for at angive en prompt, du vil køre, når denne kommando udføres i TUI. + +```bash frame="none" +/my-command +``` + +Brugerdefinerede kommandoer er ud over de indbyggede kommandoer som `/init`, `/undo`, `/redo`, `/share`, `/help`. [Learn more](/docs/tui#commands). + +--- + +## Oprettelse af kommandofiler + +Opret markdown-filer i mappen `commands/` for at definere brugerdefinerede kommandoer. + +Opret `.opencode/commands/test.md`: + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Frontmatter definerer kommandoegenskaber. Indholdet bliver skabelonen. + +Brug kommandoen ved at skrive `/` efterfulgt af kommandonavnet. + +```bash frame="none" +"/test" +``` + +--- + +## Konfiguration + +Du kan tilføje brugerdefinerede kommandoer gennem OpenCode-konfigurationen eller ved at oprette markdown-filer i `commands/`-mappen. + +--- + +### JSON + +Brug indstillingerne `command` i din OpenCode [config](/docs/config): + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Nu kan du køre denne kommando i TUI: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +Du kan også definere kommandoer ved hjælp af markdown-filer. Placer dem i: + +- Globalt: `~/.config/opencode/commands/` +- Pr. projekt: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Markdown-filnavnet bliver kommandonavnet. For eksempel lader `test.md` +du løber: + +```bash frame="none" +/test +``` + +--- + +## Prompt-konfiguration + +Spørgsmålene til de brugerdefinerede kommandoer understøtter flere specielle pladsholdere og syntaks. + +--- + +### Argumenter + +Send argumenter til kommandoer ved hjælp af pladsholderen `$ARGUMENTS`. + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +Kør kommandoen med argumenter: + +```bash frame="none" +/component Button +``` + +Og `$ARGUMENTS` vil blive erstattet med `Button`. + +Du kan også få adgang til individuelle argumenter ved hjælp af positionelle parametre: + +- `$1` - Første argument +- `$2` - Andet argument +- `$3` - Tredje argument +- Og så videre... + +For eksempel: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +Kør kommandoen: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +Dette erstatter: + +- `$1` med `config.json` +- `$2` med `src` +- `$3` med `{ "key": "value" }` + +--- + +### Shell-output + +Brug _!`command`_ til at injicere [bash command](/docs/tui#bash-commands) output i din prompt. + +For eksempel, for at oprette en brugerdefineret kommando, der analyserer testdækning: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +Eller for at gennemgå de seneste ændringer: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +Kommandoer kører i dit projekts rodmappe, og deres output bliver en del af prompten. + +--- + +### Fil-referencer + +Inkluder filer i din kommando ved hjælp af `@` efterfulgt af filnavnet. + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +Filindholdet bliver automatisk integreret i prompten. + +--- + +## Indstillinger + +Lad os se nærmere på konfigurationsmulighederne. + +--- + +### Skabelon (`template`) + +Indstillingen `template` definerer den prompt, der sendes til LLM, når kommandoen udføres. + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +Dette er en **påkrævet** konfigurationsindstilling. + +--- + +### Beskrivelse (`description`) + +Brug indstillingen `description` til at give en kort beskrivelse af, hvad kommandoen gør. + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +Dette vises som beskrivelsen i TUI, når du indtaster kommandoen. + +--- + +### Agent + +Brug `agent`-konfigurationen til valgfrit at angive, hvilken [agent](/docs/agents) der skal udføre denne kommando. +Hvis dette er en [subagent](/docs/agents/#subagents), vil kommandoen som standard udløse en subagent påkaldelse. +For at deaktivere denne adfærd skal du indstille `subtask` til `false`. + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +Dette er en **valgfri** konfigurationsindstilling. Hvis det ikke er angivet, er standarden din nuværende agent. + +--- + +### Underopgave (`subtask`) + +Brug `subtask` boolean til at tvinge kommandoen til at udløse en [subagent](/docs/agents/#subagents) påkaldelse. +Dette er nyttigt, hvis du ønsker, at kommandoen ikke skal forurene din primære kontekst og vil **tvinge** agenten til at fungere som en underagent, +øjeblikkelig `mode` er sat til `primary` på [agent](/docs/agents) konfigurationen. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +Dette er en **valgfri** konfigurationsindstilling. + +--- + +### Model + +Brug `model`-konfigurationen til at tilsidesætte standardmodellen for denne kommando. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Dette er en **valgfri** konfigurationsindstilling. + +--- + +## Indbyggede kommandoer + +opencode indeholder flere indbyggede kommandoer som `/init`, `/undo`, `/redo`, `/share`, `/help`; [learn more](/docs/tui#commands). + +:::note +Brugerdefinerede kommandoer kan tilsidesætte indbyggede kommandoer. +::: + +Hvis du definerer en brugerdefineret kommando med samme navn, vil den tilsidesætte den indbyggede kommando. diff --git a/packages/web/src/content/docs/da/config.mdx b/packages/web/src/content/docs/da/config.mdx new file mode 100644 index 00000000000..5b45f8b0486 --- /dev/null +++ b/packages/web/src/content/docs/da/config.mdx @@ -0,0 +1,685 @@ +--- +title: Konfiguration +description: Ved at bruge OpenCode JSON konfig. +--- + +Du kan konfigurere OpenCode ved hjælp af en JSON-konfigurationsfil. + +--- + +## Format + +OpenCode understø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, +} +``` + +--- + +## Placeringer + +Du kan placere din konfiguration et par forskellige steder, og de har en +forskellig rækkefølge. + +:::note +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. + +--- + +### Prioritetsrækkefølge + +Konfigurationskilder indlæses i denne rækkefølge (senere kilder tilsidesætter tidligere): + +1. **Fjernkonfiguration** (fra `.well-known/opencode`) - organisatoriske standardindstillinger +2. **Global config** (`~/.config/opencode/opencode.json`) - brugerpræferencer +3. **Tilpasset konfiguration** (`OPENCODE_CONFIG` env var) - tilpassede tilsidesættelser +4. **Project config** (`opencode.json` i projekt) - projektspecifikke indstillinger +5. **`.opencode` mapper** - agent, kommandoer, plugins +6. **Inline config** (`OPENCODE_CONFIG_CONTENT` env var) - runtime tilsidesættelser + +Dette betyder, at projektkonfigurationer kan tilsidesætte globale standardindstillinger, og globale konfigurationer kan tilsidesætte eksterne organisatoriske standarder. + +:::note +`.opencode` og `~/.config/opencode` mapperne bruger **flertalsnavne** for undermapper: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/` og `themes/`. Enkelte navne (f.eks. `agent/`) understøtter også bagudkompatibilitet. +::: + +--- + +### Ekstern konfiguration + +Organisationer kan levere standardkonfiguration via `.well-known/opencode`-slutpunktet. Dette hentes automatisk, når du godkender med en udbyder, der understøtter det. + +Remote config indlæses først og fungerer som basislaget. Alle andre konfigurationskilder (global, projekt) kan tilsidesætte disse standardindstillinger. + +Hvis din organisation f.eks. leverer MCP-servere, der er deaktiveret som standard: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +Du kan aktivere specifikke servere i din lokale konfiguration: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### Global + +Placer din globale OpenCode-konfiguration i `~/.config/opencode/opencode.json`. Brug global konfiguration til brugerdækkende præferencer som temaer, udbydere eller nøglebindinger. + +Global config tilsidesætter eksterne organisatoriske standarder. + +--- + +### Projekt-niveau + +Tilføj `opencode.json` i dit projektrod. Project config har den højeste forrang blandt standard config-filer - den tilsidesætter både globale og eksterne config. + +:::tip +Placer projektspecifik konfiguration i roden af ​​dit projekt. +::: + +Når OpenCode starter op, søger den efter en konfigurationsfil i den aktuelle mappe eller går op til den nærmeste Git-mappe. + +Dette er også sikkert at blive tjekket ind i Git og bruger det samme skema som det globale. + +--- + +### Brugerdefineret sti + +Angiv en brugerdefineret konfigurationsfilsti ved hjælp af miljøvariablen `OPENCODE_CONFIG`. + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +Brugerdefineret konfigurationsindlæses mellem globale konfigurationer og projektkonfigurationer i prioriteret rækkefølge. + +--- + +### Brugerdefineret mappe + +Angiv en brugerdefineret konfigurationsmappe ved hjælp af `OPENCODE_CONFIG_DIR` +miljøvariabel. Dette kort vil blive søgt efter agenter, kommandoer, +modes og plugins ligesom standard `.opencode` mappen, og bør +følge samme struktur. + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +Den brugerdefinerede mappe indlæses efter den globale konfig og `.opencode` mapper, så den **kan tilsidesætte** deres indstillinger. + +--- + +## Skema + +Konfigurationsfilen har et skema, der defineres i [**`opencode.ai/config.json`**](https://opencode.ai/config.json). + +Din editor skal være i stand til at validere og autofuldføre baseret på skemaet. + +--- + +### TUI + +Du kan konfigurere TUI-specifikke indstillinger gennem indstillingen `tui`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +Tilgængelige muligheder: + +- `scroll_acceleration.enabled` - Aktiver macOS-stil rulleacceleration. **Har forrang frem for `scroll_speed`.** +- `scroll_speed` - Brugerdefineret rullehastighedsmultiplikator (standard: `3`, minimum: `1`). Ignoreres, hvis `scroll_acceleration.enabled` er `true`. +- `diff_style` - Kontroller diff-gengivelse. `"auto"` tilpasser sig terminalbredden, `"stacked"` viser altid en enkelt kolonne. + +[Learn more about using the TUI here](/docs/tui). + +--- + +### Server + +Du kan konfigurere serverindstillinger for kommandoerne `opencode serve` og `opencode web` gennem indstillingen `server`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +Tilgængelige muligheder: + +- `port` - Port til at lytte på. +- `hostname` - Værtsnavn at lytte på. Når `mdns` er aktiveret, og der ikke er angivet noget værtsnavn, er standarden `0.0.0.0`. +- `mdns` - Aktiver mDNS-tjenesteopdagelse. Dette gør det muligt for andre enheder på netværket at opdage din OpenCode-server. +- `mdnsDomain` - Brugerdefineret domænenavn til mDNS-tjeneste. Som standard er `opencode.local`. Nyttigt til at køre flere forekomster på det samme netværk. +- `cors` - Yderligere oprindelser for at tillade CORS ved brug af HTTP-serveren fra en browserbaseret klient. Værdier skal være fulde oprindelser (skema + vært + valgfri port), f.eks. `https://app.example.com`. + +[Learn more about the server here](/docs/server). + +--- + +### Værktøjer (`tools`) + +Du kan administrere de værktøjer, en LLM kan bruge, gennem indstillingen `tools`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[Learn more about tools here](/docs/tools). + +--- + +### Modeller (`models`) + +Du kan konfigurere de udbydere og modeller, du vil bruge i din OpenCode-konfiguration, gennem mulighederne `provider`, `model` og `small_model`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +Indstillingen `small_model` konfigurerer en separat model til lette opgaver som titelgenerering. Som standard forsøger OpenCode at bruge en billigere model, hvis en er tilgængelig fra din udbyder, ellers falder den tilbage til din hovedmodel. + +Udbydermuligheder kan omfatte `timeout` og `setCacheKey`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` - Anmodningstimeout i millisekunder (standard: 300000). Indstil til `false` for at deaktivere. +- `setCacheKey` - Sørg for, at en cache-nøgle altid er indstillet til den udpegede udbyder. + +Du kan også konfigurere [local models](/docs/models#local). [Learn more](/docs/models). + +--- + +#### Udbyder-specifikke muligheder + +Nogle udbydere understøtter yderligere konfigurationsmuligheder ud over de generiske `timeout` og `apiKey` indstillinger. + +##### Amazon Bedrock + +Amazon Bedrock understøtter AWS-specifik konfiguration: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` - AWS region for Bedrock (standard til `AWS_REGION` env var eller `us-east-1`) +- `profile` - AWS navngivet profil fra `~/.aws/credentials` (standard til `AWS_PROFILE` env var) +- `endpoint` - Brugerdefineret slutpunkt URL for VPC-endepunkter. Dette er et alias for den generiske `baseURL`-indstilling, der bruger AWS-specifik terminologi. Hvis begge er angivet, har `endpoint` forrang. + +:::note +Bearer tokens (`AWS_BEARER_TOKEN_BEDROCK` eller `/connect`) har forrang over profilbaseret godkendelse. Se [authentication precedence](/docs/providers#authentication-precedence) for detaljer. +::: + +[Learn more about Amazon Bedrock configuration](/docs/providers#amazon-bedrock). + +--- + +### Temaer (`themes`) + +Du kan konfigurere det tema, du vil bruge i din OpenCode-konfiguration, gennem indstillingen `theme`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[Learn more here](/docs/themes). + +--- + +### Agent + +Du kan konfigurere opgaver specialiserede agenter til specifikke indstillinger gennem indstillingen `agent`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +Du kan også definere agenter ved at bruge markdown-filer i `~/.config/opencode/agents/` eller `.opencode/agents/`. [Learn more here](/docs/agents). + +--- + +### Standardagent (`default_agent`) + +Du kan indstille standardagenten ved at bruge indstillingen `default_agent`. Dette bestemmer, hvilken agent der bruges, når ingen er eksplicit angivet. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +Standardagenten skal være en primær agent (ikke en subagent). Dette kan være en indbygget agent som `"build"` eller `"plan"`, eller en [custom agent](/docs/agents), du har defineret. Hvis den angivne agent ikke eksisterer eller er en underagent, vil OpenCode falde tilbage til `"build"` med en advarsel. + +Denne indstilling gælder på tværs af alle grænseflader: TUI, CLI (`opencode run`), desktop-app og GitHub Action. + +--- + +### Deling (`share`) + +Du kan konfigurere funktionen [share](/docs/share) gennem indstillingen `share`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +Dette kræver: + +- `"manual"` - Tillad manuel deling via kommandoer (standard) +- `"auto"` - Del automatisk nye samtaler +- `"disabled"` - Deaktiver deling helt + +Som standard er deling indstillet til manuel tilstand, hvor du eksplicit skal dele samtaler ved hjælp af kommandoen `/share`. + +--- + +### Kommandoer (`command`) + +Du kan konfigurere brugerdefinerede kommandoer til gentagne opgaver gennem indstillingen `command`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +Du kan også definere kommandoer ved hjælp af markdown-filer i `~/.config/opencode/commands/` eller `.opencode/commands/`. [Learn more here](/docs/commands). + +--- + +### Tastebindinger (`keybinds`) + +Du kan tilpasse dine nøglebindinger gennem indstillingen `keybinds`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[Learn more here](/docs/keybinds). + +--- + +### Auto-opdatering (`autoupdate`) + +OpenCode vil automatisk downloade alle nye opdateringer, når den starter op. Du kan deaktivere dette med indstillingen `autoupdate`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +Hvis du ikke ønsker opdatering, men ønsker at blive underrettet, når en ny version er tilgængelig, skal du indstille `autoupdate` til `"notify"`. +Bemærk, at dette kun virker, hvis det ikke blev installeret ved hjælp af en pakkehåndtering såsom Homebrew. + +--- + +### Formater (`formatter`) + +Du kan konfigurere kodeformatere gennem indstillingen `formatter`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[Learn more about formatters here](/docs/formatters). + +--- + +### Tilladelse (`permission`) + +Som standard opencode **tillader alle operationer** uden at kræve eksplicit godkendelse. Du kan ændre dette ved at bruge indstillingen `permission`. + +For at sikre, at værktøjerne `edit` og `bash` for eksempel kræver brugergodkendelse: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[Learn more about permissions here](/docs/permissions). + +--- + +### Komprimering (`compaction`) + +Du kan styre kontekstkomprimeringsadfærd gennem indstillingen `compaction`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto` - Komprimer automatisk sessionen, når konteksten er fuld (standard: `true`). +- `prune` - Fjern gamle værktøjsudgange for at gemme tokens (standard: `true`). + +--- + +### Overvågning (`watcher`) + +Du kan konfigurere ignoreringsmønstre for filovervåger gennem indstillingen `watcher`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +Mønstre følger glob-syntaks. Brug dette til at udelukke støjende mapper fra filvisning. + +--- + +### MCP + +Du kan konfigurere MCP-servere, som du vil bruge, gennem indstillingen `mcp`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[Learn more here](/docs/mcp-servers). + +--- + +### Plugin + +[Plugins](/docs/plugins) udvide OpenCode med brugerdefinerede værktøjer, kroge og integrationer. + +Placer plugin-filer i `.opencode/plugins/` eller `~/.config/opencode/plugins/`. Du kan også indlæse plugins fra npm gennem indstillingen `plugin`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[Learn more here](/docs/plugins). + +--- + +### Instruktioner (`instructions`) + +Du kan konfigurere brugervejledningen til den model, du kan gennem indstillingen `instructions`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Dette kræver en række stier og globmønstre til instruktionsfiler. [Læs mere +om regler her](/docs/rules). + +--- + +### Deaktiverede udbydere (`disabled_providers`) + +Du kan deaktivere udbydere, der indlæses automatisk gennem `disabled_providers`-indstillingen. Dette er nyttigt, når du vil forhindre visse udbydere i at blive indlæst, deres legitimationsoplysninger er tilgængelige. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +`disabled_providers` har prioritet over `enabled_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`. +- Udbyderens modeller vises ikke på modelvalgslisten. + +--- + +### Aktiverede udbydere (`enabled_providers`) + +Du kan angive en tilladelsesliste over udbydere gennem muligheden `enabled_providers`. Når den er indstillet, vil kun de angivne udbydere blive aktiveret, og alle andre vil blive ignoreret. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +Dette er nyttigt, når du vil begrænse OpenCode til kun at bruge specifikke udbydere i stedet for at deaktivere dem én efter én. + +:::note +`disabled_providers` har prioritet over `enabled_providers`. +::: + +Hvis en udbyder optræder i både `enabled_providers` og `disabled_providers`, har `disabled_providers` prioritet for bagudkompatibilitet. + +--- + +### Eksperimentel (`experimental`) + +Nøglen `experimental` indeholder muligheder, der er under aktiv udvikling. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +Eksperimentelle muligheder er ikke stabile. De kan ændres eller fjernes uden varsel. +::: + +--- + +## Variabler + +Du kan bruge variabelsubstitution i dine konfigurationsfiler til at referere til miljøvariabler og filindhold. + +--- + +### Miljøvariabler + +Brug `{env:VARIABLE_NAME}` til at erstatte miljøvariabler: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +Hvis miljøvariablen ikke er indstillet, vil den blive erstattet med en tom streng. + +--- + +### Filer + +Brug `{file:path/to/file}` til at erstatte indholdet af en fil: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +Filstier kan være: + +- I forhold til konfigurationsfilbiblioteket +- Eller absolutte stier, der starter med `/` eller `~` + +Disse er nyttige til: + +- Opbevaring af følsomme data som API-nøgler i separate filer. +- Inklusiv store instruktionsfiler uden at rode i din konfiguration. +- Deling af fælles konfigurationsuddrag på tværs af flere konfigurationsfiler. diff --git a/packages/web/src/content/docs/da/custom-tools.mdx b/packages/web/src/content/docs/da/custom-tools.mdx new file mode 100644 index 00000000000..b0839b649c7 --- /dev/null +++ b/packages/web/src/content/docs/da/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: Brugerdefinerede værktøjer +description: Opret værktøjer, som LLM kan kalde opencode ind. +--- + +Brugerdefinerede værktøjer er funktioner, du opretter, som LLM kan kalde under samtaler. De arbejder sammen med opencodes [built-in tools](/docs/tools) som `read`, `write` og `bash`. + +--- + +## Oprettelse af et værktøj + +Værktøjer er defineret som **TypeScript**- eller **JavaScript**-filer. Værktøjsdefinitionen kan dog kalde scripts skrevet på **alle sprog** - TypeScript eller JavaScript bruges kun til selve værktøjsdefinitionen. + +--- + +### Placering + +De kan definere: + +- Lokalt ved at placere dem i biblioteket `.opencode/tools/` i dit projekt. +- Eller globalt ved at placere dem i `~/.config/opencode/tools/`. + +--- + +### Struktur + +Den nemmeste måde at oprette værktøjer på er at bruge `tool()`-hjælperen, som giver typesikkerhed og validering. + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +**filnavnet** bliver **værktøjsnavnet**. Ovenstående opretter et `database` værktøj. + +--- + +#### Flere værktøjer pr. fil + +Du kan også eksportere flere værktøjer fra en enkelt fil. Hver eksport bliver **et separat værktøj** med navnet **`_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +Dette skaber værktøjer: `math_add` og `math_multiply`. + +--- + +### Argumenter + +Du kan bruge `tool.schema`, som kun er [Zod](https://zod.dev), til at definere argumenttyper. + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +Du kan også importere [Zod](https://zod.dev) direkte og returnere et almindeligt objekt: + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### Kontekst + +Værktøjer modtager kontekst om den aktuelle session: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +Brug `context.directory` til sessionens arbejdsmappe. +Brug `context.worktree` til git-arbejdstræets rod. + +--- + +## Eksempler + +### Skriv et værktøj i Python + +Du kan skrive dine værktøjer på et hvilket som helst sprog, du ønsker. Her er et eksempel, der tilføjer til tal ved hjælp af Python. + +Først skal du oprette værktøjet som et Python-script: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +Opret derefter værktøjsdefinitionen, der kalder den: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +Her bruger vi [`Bun.$`](https://bun.com/docs/runtime/shell)-værktøjet til at køre Python-scriptet. diff --git a/packages/web/src/content/docs/da/ecosystem.mdx b/packages/web/src/content/docs/da/ecosystem.mdx new file mode 100644 index 00000000000..8da7e42d10a --- /dev/null +++ b/packages/web/src/content/docs/da/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: Økosystem +description: Projekter og integrationer bygget med OpenCode. +--- + +En samling af samfundsprojekter bygget på OpenCode. + +:::note +Vil du tilføje dit OpenCode-relaterede projekt til denne liste? Send en PR. +::: + +Du kan også tjekke [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) og [opencode.cafe](https://opencode.cafe), et fællesskab, der samler økosystemet og fællesskabet. + +--- + +## Plugins + +| Navn | Beskrivelse | +| --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | Kør automatisk OpenCode-sessioner i isolerede Daytona-sandkasser med git-synkronisering og live forhåndsvisninger | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | Injicer automatisk Helicone-sessionsoverskrifter til anmodningsgruppering | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | Autoinjicer TypeScript/Svelte-typer i fillæsninger med opslagsværktøjer | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | Brug dit ChatGPT Plus/Pro abonnement i stedet for API kreditter | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | Brug din eksisterende Gemini-plan i stedet for API fakturering | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | Brug Antigravitys gratis modeller i stedet for API fakturering | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Multi-branch devcontainer isolation med lavvandede kloner og automatisk tildelte porte | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Google Antigravity OAuth Plugin, med understøttelse af Google søgning og mere robust API håndtering | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Optimer tokenbrug ved at beskære forældede værktøjsoutput | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Tilføj native websearch-understøttelse for understøttede udbydere med Google jordet stil | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Gør det muligt for AI-agenter at køre baggrundsprocesser i en PTY, send interaktive input til dem. | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Instruktioner til ikke-interaktive shell-kommandoer - forhindrer hænger fra TTY-afhængige operationer | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Spor OpenCode brug med Wakatime | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Ryd op afmærkningstabeller produceret af LLMs | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | 10x hurtigere koderedigering med Morph Fast Apply API og dovne redigeringsmarkører | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Baggrundsagenter, præbyggede LSP/AST/MCP værktøjer, kuraterede agenter, Claude Kodekompatibel | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | Skrivebordsmeddelelser og lydadvarsler for OpenCode-sessioner | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Skrivebordsmeddelelser og lydadvarsler for tilladelser, fuldførelse og fejlhændelser | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | AI-drevet automatisk Zellij-sessionsnavngivning baseret på OpenCode-kontekst | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Tillad OpenCode-agenter til dovne load-prompter på efterspørgsel med færdighedsopdagelse og -injektion | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Vedvarende hukommelse på tværs af sessioner ved hjælp af Supermemory | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Interaktiv plangennemgang med visuel annotering og private/offline deling | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Udvid opencode /commands til et kraftfuldt orkestreringssystem med granulær flowkontrol | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | Planlæg tilbagevendende job ved hjælp af launchd (Mac) eller systemd (Linux) med cron-syntaks | +| [micode](https://github.com/vtemian/micode) | Struktureret brainstorm → Plan → Implementer workflow med session kontinuitet | +| [octto](https://github.com/vtemian/octto) | Interaktiv browser-UI til AI-brainstorming med formularer med flere spørgsmål | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | Claude Baggrundsagenter i kodestil med asynkron-delegering og kontekstvedholdenhed | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | Native OS-meddelelser for OpenCode – ved, hvornår opgaver er fuldført | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | Bundled multi-agent orkestreringssele – 16 komponenter, én installation | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | Nulfriktions git-arbejdstræer for OpenCode | + +--- + +## Projekter + +| Navn | Beskrivelse | +| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- | +| [kimaki](https://github.com/remorses/kimaki) | Discord-bot til at styre OpenCode-sessioner, bygget på SDK | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Neovim-plugin til redaktør-bevidste prompter, bygget på API | +| [portal](https://github.com/hosenur/portal) | Mobile-first web UI til OpenCode over Tailscale/VPN | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | Skabelon til at bygge OpenCode plugins | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Neovim-frontend til opencode - en terminalbaseret AI-kodningsagent | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Vercel AI SDK udbyder til brug af OpenCode via @opencode-ai/sdk | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | Web / Desktop App og VS Code udvidelse til OpenCode | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Obsidian plugin, der integrerer OpenCode i Obsidians brugergrænseflade | +| [OpenWork](https://github.com/different-ai/openwork) | Et open source-alternativ til Claude Cowork, drevet af OpenCode | +| [ocx](https://github.com/kdcokenny/ocx) | OpenCode udvidelsesmanager med bærbare, isolerede profiler. | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | Desktop-, web-, mobil- og fjernklientapp til OpenCode | + +--- + +## Agenter + +| Navn | Beskrivelse | +| ----------------------------------------------------------------- | ------------------------------------------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | Modulære AI-agenter og -kommandoer til struktureret udvikling | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | Konfigurationer, prompter, agenter og plugins til forbedrede arbejdsgange | diff --git a/packages/web/src/content/docs/da/enterprise.mdx b/packages/web/src/content/docs/da/enterprise.mdx new file mode 100644 index 00000000000..6228c5c9107 --- /dev/null +++ b/packages/web/src/content/docs/da/enterprise.mdx @@ -0,0 +1,170 @@ +--- +title: Enterprise +description: Brug af OpenCode sikkert i din organisation. +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +OpenCode Enterprise er for organisationer, der ønsker at sikre, at deres kode og data aldrig forlader deres infrastruktur. Det kan gøre dette ved at bruge en centraliseret konfiguration, der integreres med din SSO og interne AI-gateway. + +:::note +OpenCode gemmer ingen af ​​din kode eller kontekstdata. +::: + +Sådan kommer du i gang med OpenCode Enterprise: + +1. Lav en prøvetur internt med dit team. +2. **Kontakt os** for at diskutere priser og implementeringsmuligheder. + +--- + +## Prøveperiode + +OpenCode er open source og gemmer ingen af ​​din kode eller kontekstdata, så dine udviklere kan simpelthen [get started](/docs/) og udføre en prøveversion. + +--- + +### Datahåndtering + +**OpenCode gemmer ikke din kode eller kontekstdata.** Al behandling sker lokalt eller gennem direkte API-opkald til din AI-udbyder. + +Det betyder, at så længe du bruger en udbyder, du stoler på, eller en intern +AI-gateway, du kan bruge OpenCode sikkert. + +Den eneste advarsel her er den valgfrie `/share`-funktion. + +--- + +#### Deling af samtaler + +Hvis en bruger aktiverer funktionen `/share`, sender samtalen og de data, der er knyttet til den, til den tjeneste, vi bruger til at hoste disse delesider på opencode.ai. + +Dataene serveres i øjeblikket gennem vores CDN's edge-netværk og cachelagres på kanten nær dine brugere. + +Vi anbefaler, at du deaktiverer dette for din prøveperiode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[Learn more about sharing](/docs/share). + +--- + +### Kodeejerskab + +**Du ejer al kode produceret af OpenCode.** Der er ingen licensbegrænsninger eller ejerskabskrav. + +--- + +## Priser + +Vi bruger en per-sæde-model til OpenCode Enterprise. Hvis du har din egen LLM-gateway, kræver vi ikke betaling for brugte tokens. For yderligere oplysninger om priser og implementeringsmuligheder, **kontakt os**. + +--- + +## Implementering + +Når du har afsluttet din prøveperiode, og du er klar til at bruge OpenCode kl +din organisation, kan du **kontakte os** for at diskutere +prissætning og implementeringsmuligheder. + +--- + +### Central konfiguration + +Vi kan konfigurere OpenCode til at bruge en enkelt central konfiguration for hele din organisation. + +Denne centraliserede konfiguration kan integreres med din SSO-udbyder og sikrer, at alle brugere kan få adgang til din interne AI-gateway. + +--- + +### SSO-integration + +Gennem den centrale konfiguration kan OpenCode integreres med din organisationer SSO-udbyder til godkendelse. + +Denne giver OpenCode mulighed for at få legitimationsoplysninger til din interne AI-gateway gennem dette eksisterende identitetsadministrationssystem. + +--- + +### Intern AI-gateway + +Med den centrale konfiguration kan OpenCode også konfigureres til kun at bruge din interne AI-gateway. + +Du kan også deaktivere alle andre AI-udbydere og sikre, at alle anmodninger går gennem din organisations godkendte infrastruktur. + +--- + +### Selv-hosting + +Selvom vi anbefaler at deaktivere delesiderne for at sikre, at dine data aldrig forsvinder +din organisation, kan vi også hjælpe dig med at selv hoste dem på din infrastruktur. + +Dette er i øjeblikket på vores køreplan. Hvis du er interesseret, **giv os besked**. + +--- + +## FAQ + +

+Hvad er OpenCode Enterprise? + +OpenCode Enterprise er for organisationer, der ønsker at sikre, at deres kode og data aldrig forlader deres infrastruktur. Det kan gøre dette ved at bruge en centraliseret konfiguration, der integreres med din SSO og interne AI-gateway. + +
+ +
+Hvordan kommer jeg i gang med OpenCode Enterprise? + +Du skal blot starte med en intern prøveperiode med dit team. OpenCode gemmer som standard ikke din kode eller kontekstdata, hvilket gør det nemt at komme i gang. + +Så **kontakt os** for at diskutere priser og implementeringsmuligheder. + +
+ +
+Hvordan fungerer virksomhedspriser? + +Vi tilbyder virksomhedspriser pr. sæde. Hvis du har din egen LLM-gateway, kræver vi ikke betaling for brugte tokens. For yderligere detaljer, **kontakt os** for et brugerdefineret tilbud baseret på din organisations behov. + +
+ +
+Er mine data sikret med OpenCode Enterprise? + +Ja. OpenCode gemmer ikke din kode eller kontekstdata. Al behandling sker lokalt eller gennem direkte API-opkald til din AI-udbyder. Med central konfiguration og SSO-integration forbliver dine data sikre i din organisationers infrastruktur. + +
+ +
+Kan vi bruge vores eget private NPM-register? + +OpenCode understøtter private npm registre gennem Buns oprindelige `.npmrc` filunderstøttelse. Hvis din organisation bruger et privat register, såsom JFrog Artifactory, Nexus eller lignende, skal du sikre dig, at udviklerne er godkendt, før de kører OpenCode. + +Sådan konfigurerer du godkendelse med dit private register: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +Dette opretter `~/.npmrc` med godkendelsesdetaljer. OpenCode vil automatisk +samle dette op. + +:::caution +Du skal være logget ind i det private register, før du kører OpenCode. +::: + +Alternativt kan du manuelt konfigurere en `.npmrc` fil: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +Udviklere skal være logget ind på det private register, før de kører OpenCode for at sikre, at pakker kan installeres fra din virksomhedsregistrering. + +
diff --git a/packages/web/src/content/docs/da/formatters.mdx b/packages/web/src/content/docs/da/formatters.mdx new file mode 100644 index 00000000000..09ff611a66e --- /dev/null +++ b/packages/web/src/content/docs/da/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: Formatere +description: OpenCode bruger sprogspecifikke formatere. +--- + +OpenCode formaterer automatisk filer, efter de er skrevet eller redigeret ved hjælp af sprogspecifikke formatere. Dette sikrer, at den kode, der genereres, følger kodestilene for dit projekt. + +--- + +## Indbyggede + +OpenCode leveres med flere indbyggede formatere til populære sprog og rammer. Nedenfor er en liste over de formatere, understøttede filtypenavne og kommandoer eller konfigurationsmuligheder, der har brug for. + +| Formater | Udvidelser | Krav | +| --------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | +| gofmt | .go | `gofmt` kommando tilgængelig | +| blande | .ex,.exs,.eex,.heex,.leex,.neex,.sface | `mix` kommando tilgængelig | +| smukkere | .js,.jsx,.ts,.tsx,.html,.css,.md,.json,.yaml og [more](https://prettier.io/docs/en/index.html) | `prettier` afhængighed i `package.json` | +| biome | .js,.jsx,.ts,.tsx,.html,.css,.md,.json,.yaml og [more](https://biomejs.dev/) | `biome.json(c)` konfigurationsfil | +| zig | .zig,.zon | `zig` kommando tilgængelig | +| klang-format | .c,.cpp,.h,.hpp,.ino og [more](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` konfigurationsfil | +| ktlint | .kt,.kts | `ktlint` kommando tilgængelig | +| ruff | .py,.pyi | `ruff` kommando tilgængelig med konfiguration | +| rustfmt | .rs | `rustfmt` kommando tilgængelig | +| cargofmt | .rs | `cargo fmt` kommando tilgængelig | +| uv | .py,.pyi | `uv` kommando tilgængelig | +| rubocop | .rb,.rake,.gemspec,.ru | `rubocop` kommando tilgængelig | +| standardrb | .rb,.rake,.gemspec,.ru | `standardrb` kommando tilgængelig | +| htmlbeautifier | .erb,.html.erb | `htmlbeautifier` kommando tilgængelig | +| luft | .R | `air` kommando tilgængelig | +| dart | .dart | `dart` kommando tilgængelig | +| ocamlformat | .ml,.mli | `ocamlformat` kommando tilgængelig og `.ocamlformat` config fil | +| terraform | .tf,.tfvars | `terraform` kommando tilgængelig | +| glimt | .glimt | `gleam` kommando tilgængelig | +| nixfmt | .nix | `nixfmt` kommando tilgængelig | +| shfmt | .sh,.bash | `shfmt` kommando tilgængelig | +| pint | .php | `laravel/pint` afhængighed i `composer.json` | +| oxfmt (Eksperimentel) | .js,.jsx,.ts,.tsx | `oxfmt` afhængighed i `package.json` og en [experimental env variable flag](/docs/cli/#experimental) | +| ormolu | .hs | `ormolu` kommando tilgængelig | + +Så hvis dit projekt har `prettier` i din `package.json`, vil OpenCode automatisk bruge det. + +--- + +## Sådan fungerer det + +Når OpenCode skriver eller redigerer en fil, vil det: + +1. Kontrollerer filtypenavnet mod alle aktiverede formatere. +2. Kører den relevante formateringskommando på filen. +3. Anvender formateringsændringerne automatisk. + +Denne proces sker i baggrunden, hvilket sikrer, at dine kodestile vedligeholdes uden nogen manuelle trin. + +--- + +## Konfiguration + +Du kan tilpasse formatere gennem afsnittet `formatter` i din OpenCode-konfiguration. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +Hver formateringskonfiguration understøtter følgende: + +| Ejendom | Skriv | Beskrivelse | +| ------------- | -------- | -------------------------------------------------------------------- | +| `disabled` | boolean | Indstil dette til `true` for at deaktivere formateringsværktøjet | +| `command` | string[] | Kommandoen til at køre for formatering | +| `environment` | object | Miljøvariabler, der skal indstilles, når formateringsværktøjet køres | +| `extensions` | string[] | Filtypenavne, som denne formaterer skal håndtere | + +Lad os se på nogle eksempler. + +--- + +### Deaktivering af formatere + +For at deaktivere **alle** formatere globalt, skal du indstille `formatter` til `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +For at deaktivere en **specifik** formatter, skal du indstille `disabled` til `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### Brugerdefinerede formatere + +Du kan tilsidesætte de indbyggede formattere eller tilføje nye ved at angive kommandoen, miljøvariabler og filtypenavne: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +**`$FILE` pladsholderen** i kommandoen vil blive erstattet med stien til filen, der formateres. diff --git a/packages/web/src/content/docs/da/github.mdx b/packages/web/src/content/docs/da/github.mdx new file mode 100644 index 00000000000..cffe85f13fc --- /dev/null +++ b/packages/web/src/content/docs/da/github.mdx @@ -0,0 +1,321 @@ +--- +title: GitHub +description: Brug OpenCode i GitHub-problemer og Pull Requests. +--- + +OpenCode integreres med din GitHub arbejdsgang. Nævn `/opencode` eller `/oc` i din kommentar, og OpenCode vil udføre opgaver i din GitHub Actions-løber. + +--- + +## Funktioner + +- **Triageproblemer**: Bed OpenCode om at undersøge et problem og forklare dig det. +- **Ret og implementer**: Bed OpenCode om at løse et problem eller implementere en funktion. Og det vil fungere i en ny branch og indsende en PR med alle ændringerne. +- **Sikker**: OpenCode løber inde i din GitHubs løbere. + +--- + +## Installation + +Kør følgende kommando i et projekt, der er i en GitHub repo: + +```bash +opencode github install +``` + +Dette vil lede dig gennem installation af GitHub-appen, oprettelse af arbejdsgangen og opsætning af hemmeligheder. + +--- + +### Manuel opsætning + +Eller du kan indstille det manuelt. + +1. **Installationsprogrammet GitHub-appen** + + Gå over til [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). Sørg for, at det er installeret på mållageret. + +2. **Tilføj arbejdsgangen** + + Tilføj følgende workflow-fil til `.github/workflows/opencode.yml` i din repo. Sørg for at indstille de relevante `model` og nødvendige API-nøgler i `env`. + + ```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx + ``` + +3. **Opbevar API-nøglerne i hemmeligheder** + + I din organisation eller dit projekt **indstillinger** skal du udvide **Hemmeligheder og variabler** til venstre og vælge **Handlinger**. Og tilføj de nødvendige API-nøgler. + +--- + +## Konfiguration + +- `model`: Den model, der skal bruges med OpenCode. Antager formatet `provider/model`. Dette er **påkrævet**. +- `agent`: Agenten, der skal bruges. Skal være en primær agent. Falder tilbage til `default_agent` fra config eller `"build"`, hvis den ikke findes. +- `share`: Om OpenCode-sessionen skal dele. Standard er **true** for offentlige arkiver. +- `prompt`: Valgfri brugerdefineret prompt for at tilsidesætte standardadfærden. Brug dette til at tilpasse, hvordan OpenCode behandler anmodninger. +- `token`: Valgfrit GitHub adgangstoken til at udføre operationer såsom oprettelse af kommentarer, begå ændringer og åbning af Pull Requests. Som standard bruger OpenCode installationsadgangstokenet fra OpenCode GitHub-appen, så commits, kommentarer og Pull Requests ser ud til at komme fra appen. + + Alternativt kan du bruge GitHub Action runners [built-in `GITHUB_TOKEN`](OpenCode) uden at installere OpenCode GitHub appen. Bare sørg for at give de nødvendige tilladelser i dit workflow: + + ```yaml + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + ``` + + Du kan også bruge en [personal access tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT), hvis det foretrækkes. + +--- + +## Understøttede begivenheder + +OpenCode kan udløses af følgende GitHub hændelser: + +| Begivenhedstype | Udløst af | Detaljer | +| ----------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `issue_comment` | Kommentarer og problemer eller PR | Nævn `/opencode` eller `/oc` i din kommentar. OpenCode læser kontekst og kan oprette brancher, åbne PR'er eller svare. | +| `pull_request_review_comment` | Kommenter specifikke kodelinjer i en PR | Nævn `/opencode` eller `/oc`, mens du gennemgår koden. OpenCode modtager filsti, linjenumre og diff-kontekst. | +| `issues` | Udgave åbnet eller redigeret | Udløs automatisk OpenCode, når problemer oprettes eller ændres. Kræver `prompt` input. | +| `pull_request` | PR åbnet eller opdateret | Udløs automatisk OpenCode, når PR'er åbnes, synkroniseres eller genåbnes. Nyttigt til automatiserede kodegennemgange. | +| `schedule` | Cron-baseret tidsplan | Kør OpenCode efter en tidsplan. Kræver `prompt` input. Output går til logfiler og PR'er (intet problem ved kommentere). | +| `workflow_dispatch` | Manuel trigger fra GitHub UI | Udløs OpenCode efter behov via fanen Handlinger. Kræver `prompt` input. Output går til logfiler og PR'er. | + +### Tidsplan eksempel + +Kør OpenCode efter en tidsplan for at udføre automatiske opgaver: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +For planlagte begivenheder er `prompt` input **påkrævet**, da der ikke er nogen kommentarer at udtrække instruktioner fra. Planlagte arbejdsgange kører uden en brugerkontekst til kontrol af tilladelser, så arbejdsgangen skal give `contents: write` og `pull-requests: write`, hvis du forventer, at OpenCode skal oprette brancher eller PR'er. + +--- + +### Pull Request eksempel + +Gennemgå automatisk PR'er, når de åbnes eller opdateres: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +For `pull_request` hændelser, hvis der ikke er angivet nogen `prompt`, vil OpenCode som standard gennemgå Pull Requesten. + +--- + +### Issues Triage eksempel + +Triage automatisk nye problemer. Dette eksempel filtrerer til konti ældre end 30 dage for at reducere spam: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +For `issues` begivenheder er `prompt` input **påkrævet**, da der ikke er nogen kommentarer at udtrække instruktioner fra. + +--- + +## Brugerdefinerede prompter + +Tilsidesæt standardprompten for at tilpasse OpenCodes adfærd til din arbejdsgang. + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Dette er nyttigt til at håndhæve specifikke gennemgangskriterier, kodningsstandarder eller fokusområder, der er relevante for dit projekt. + +--- + +## Eksempler + +Her er nogle eksempler på, hvordan du kan bruge OpenCode i GitHub. + +- **Forklar et problem** + + Tilføj denne kommentar i et GitHub-nummer. + + ``` + /opencode explain this issue + ``` + + OpenCode vil læse hele tråden, inklusive alle kommentarer, og svare med en klar forklaring. + +- **Løs et problem** + + I et GitHub-problem skal du sige: + + ``` + /opencode fix this + ``` + + Og OpenCode vil oprette en ny branch, implementere ændringer og åbne en PR med ændringer. + +- **Gennemgå PR'er og foretag ændringer** + + Efterlad følgende kommentar på en GitHub PR. + + ``` + Delete the attachment from S3 when the note is removed /oc + ``` + + OpenCode vil implementere den ønskede ændring og forpligtelse til den samme PR. + +- **Gennemgå specifikke kodelinjer** + + Efterlad en kommentar direkte på kodelinjer i PR's faneblad "Filer". OpenCode detekterer automatisk filer, linjenumrene og diff-konteksten for at give præcise svar. + + ``` + [Comment on specific lines in Files tab] + /oc add error handling here + ``` + + Når du kommenterer på specifikke linjer, modtager OpenCode: + - Den nøjagtige fil bliver gennemgået + - De specifikke kodelinjer + - Den omgivende forskellig kontekst + - Linjenummeroplysninger + + Dette giver mulighed for mere målrettede anmodninger uden at skulle angive filstier eller linjenumre manuelt. diff --git a/packages/web/src/content/docs/da/gitlab.mdx b/packages/web/src/content/docs/da/gitlab.mdx new file mode 100644 index 00000000000..8c83daaefb5 --- /dev/null +++ b/packages/web/src/content/docs/da/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: Brug OpenCode i GitLab-problemer og Merge Requests. +--- + +OpenCode integreres med din GitLab-arbejdsgang gennem din GitLab CI/CD-pipeline eller med GitLab Duo. + +I begge tilfælde vil OpenCode køre på dine GitLab-løbere. + +--- + +## GitLab CI + +OpenCode fungerer i en almindelig GitLab-pipeline. Du kan bygge det ind i en pipeline som en [CI component](https://docs.gitlab.com/ee/ci/components/) + +Her bruger vi en community-skabt CI/CD-komponent til OpenCode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### Funktioner + +- **Brug brugerdefineret konfiguration pr. job**: Konfigurer OpenCode med en brugerdefineret konfigurationsmappe, for eksempel `./config/#custom-directory` for at aktivere eller deaktivere funktionalitet pr. OpenCode påkald. +- **Minimal opsætning**: CI-komponenten sætter OpenCode op i baggrunden, du behøver kun at oprette OpenCode-konfigurationen og den indledende prompt. +- **Fleksibel**: CI-komponenten understøtter flere input til at tilpasse dens adfærd + +--- + +### Opsætning + +1. Gem din OpenCode-autentificering JSON som en filtype CI-miljøvariabel under **Indstillinger** > **CI/CD** > **Variabler**. Sørg for at markere dem som "Maskede og skjulte". +2. Tilføj følgende til din `.gitlab-ci.yml` fil. + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +For flere input og use cases [check out the docs](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) for denne komponent. + +--- + +## GitLab Duo + +OpenCode integreres med din GitLab-arbejdsgang. +Nævn `@opencode` i en kommentar, og OpenCode vil udføre opgaver i din GitLab CI-pipeline. + +--- + +### Funktioner + +- **Triageproblemer**: Bed OpenCode om at undersøge et problem og forklare dig det. +- **Ret og implementer**: Bed OpenCode om at løse et problem eller implementere en funktion. + Det vil oprette en ny branch og rejse en Merge Request med ændringer. +- **Sikker**: OpenCode kører på dine GitLab-løbere. + +--- + +### Opsætning + +OpenCode kører i din GitLab CI/CD pipeline, her er hvad du skal bruge for at konfigurere det: + +:::tip +Tjek [**GitLab docs**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) for opdaterede instruktioner. +::: + +1. Konfigurer dit GitLab-miljø +2. Konfigurer CI/CD +3. Få en API-nøgle til en AI-modeludbyder +4. Opret en servicekonto +5. Konfigurer CI/CD variabler +6. Opret en flow-konfigurationsfil, her er et eksempel: + +
+ + Flowkonfiguration + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +Du kan henvise til [GitLab CLI agents docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) for detaljerede instruktioner. + +--- + +### Eksempler + +Her er nogle eksempler på, hvordan du kan bruge OpenCode i GitLab. + +:::tip +Du kan konfigurere til at bruge en anden udløsersætning end `@opencode`. +::: + +- **Forklar et problem** + + Tilføj denne kommentar i et GitLab-problem. + + ``` + @opencode explain this issue + ``` + + OpenCode vil læse spørgsmålet og svare med en klar forklaring. + +- **Løs et problem** + + I et GitLab-nummer skal du sige: + + ``` + @opencode fix this + ``` + + OpenCode vil oprette en ny branch, implementere ændringer og åbne en Merge Request med ændringer. + +- **Gennemgå Merge Requests** + + Efterlad følgende kommentar til en GitLab-Merge Request. + + ``` + @opencode review this merge request + ``` + + OpenCode vil gennemgå din Merge Request og give feedback. diff --git a/packages/web/src/content/docs/da/ide.mdx b/packages/web/src/content/docs/da/ide.mdx new file mode 100644 index 00000000000..17f9cec1e74 --- /dev/null +++ b/packages/web/src/content/docs/da/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: OpenCode-udvidelsen til VS Code, Cursor og andre IDE'er +--- + +OpenCode integreres med VS Code, Cursor eller enhver IDE, der understøtter en terminal. Bare kør `opencode` i terminalen for at komme i gang. + +--- + +## Brug + +- **Hurtig start**: Brug `Cmd+Esc` (Mac) eller `Ctrl+Esc` (Windows/Linux) til at åbne OpenCode i en delt terminalvisning, eller fokuser en eksisterende terminalsession, hvis en allerede kører. +- **Ny session**: Brug `Cmd+Shift+Esc` (Mac) eller `Ctrl+Shift+Esc` (Windows/Linux) til at starte en ny OpenCode terminalsession, mulighed en allerede er åben. Du kan også klikke på knappen OpenCode i brugergrænsefladen. +- **Kontekstbevidsthed**: Del automatisk dit nuværende valg eller din fane med OpenCode. +- **Filreferencegenveje**: Brug `Cmd+Option+K` (Mac) eller `Alt+Ctrl+K` (Linux/Windows) til at indsætte filreferencer. For eksempel `@File#L37-42`. + +--- + +## Installation + +Sådan installeres OpenCode på VS Code og populære gafler som Cursor, Windsurf, VSCodium: + +1. Åbn VS Code +2. Åbn den integrerede terminal +3. Kør `opencode` - udvidelsen installeres automatisk + +Hvis du på den anden side vil bruge din egen IDE, når du kører `/editor` eller `/export` fra TUI, skal du indstille `export EDITOR="code --wait"`. [Learn more](/docs/tui/#editor-setup). + +--- + +### Manuel installation + +Søg efter **OpenCode** i Extension Marketplace, og klik på **Installer**. + +--- + +### Fejlfinding + +Hvis udvidelsen ikke kan installeres automatisk: + +- Sørg for, at du kører `opencode` i den integrerede terminal. +- Bekræft, at CLI for din IDE er installeret: + - For VS Code: `code` kommando + - For Cursor: `cursor` kommando + - For Windsurf: `windsurf` kommando + - For VSCodium: `codium` kommando + - Hvis ikke, så kør `Cmd+Shift+P` (Mac) eller `Ctrl+Shift+P` (Windows/Linux) og søg efter "Shell Command: Install 'code' command in PATH" (eller tilsvarende for din IDE) +- Sørg for, at VS Code har tilladelse til at installere udvidelser diff --git a/packages/web/src/content/docs/da/index.mdx b/packages/web/src/content/docs/da/index.mdx new file mode 100644 index 00000000000..b2623b93d54 --- /dev/null +++ b/packages/web/src/content/docs/da/index.mdx @@ -0,0 +1,359 @@ +--- +title: Introduktion +description: Kom godt i gang med OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**OpenCode**](/) er en open source AI-kodningsagent. Den er tilgængelig som en terminalbaseret grænseflade, desktop-app eller IDE-udvidelse. + +![OpenCode TUI med opencode-temaet](../../../assets/lander/screenshot.png) + +Lad os komme i gang. + +--- + +#### Forudsætninger + +For at bruge OpenCode i din terminal skal du bruge: + +1. En moderne terminalemulator som: + - [WezTerm](https://wezterm.org), på tværs af platforme + - [Alacritty](https://alacritty.org), på tværs af platforme + - [Ghostty](https://ghostty.org), Linux og macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux og macOS + +2. API-nøgler til de LLM udbydere, du vil bruge. + +--- + +## Installation + +Den nemmeste måde at installere OpenCode på er gennem installationsscriptet. + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +Du kan også installere det med følgende kommandoer: + +- **Bruger Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **Brug af Homebrew på macOS og Linux** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > Vi anbefaler at bruge OpenCode-tap for at få de mest opdaterede udgivelser. Den officielle `brew install opencode`-formel vedligeholdes af Homebrew-teamet og opdateret sjældnere. + +- **Brug af Paru på Arch Linux** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[Anbefalet: Brug WSL] +For at få den bedste oplevelse på Windows anbefaler vi at bruge [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Det giver bedre ydeevne og fuld kompatibilitet med OpenCodes funktioner. +::: + +- **Brug af Chocolatey** + + ```bash + choco install opencode + ``` + +- **Brug af Scoop** + + ```bash + scoop install opencode + ``` + +- **Bruger NPM** + + ```bash + npm install -g opencode-ai + ``` + +- **Brug af Mise** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **Brug af Docker** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +Support til installation af OpenCode på Windows ved hjælp af Bun er i gang. + +Du kan også få fat i binæren fra [Releases](https://github.com/anomalyco/opencode/releases). + +--- + +## Konfiguration + +Med OpenCode kan du bruge enhver LLM udbyder ved at konfigurere deres API-nøgler. + +Hvis du er ny til at bruge LLM-udbydere, anbefaler vi at bruge [OpenCode Zen](/docs/zen). +Det er en udvalgt liste over modeller, der er blevet testet og verificeret af OpenCode +holde. + +1. Kør kommandoen `/connect` i TUI, vælg opencode, og gå til [opencode.ai/auth](https://opencode.ai/auth). + + ```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 + ``` + +Alternativt kan du vælge en af ​​de andre udbydere. [Læs mere](/docs/providers#directory). + +--- + +## Initialisering + +Nu hvor du har konfigureret en udbyder, kan du navigere til et projekt, der +du vil arbejde på. + +```bash +cd /path/to/project +``` + +Og kør OpenCode. + +```bash +opencode +``` + +Derefter initialiseres OpenCode for projektet ved at køre følgende kommando. + +```bash frame="none" +/init +``` + +Dette får OpenCode til at analysere dit projekt og oprette en `AGENTS.md` fil i +projektets rod. + +:::tip +Du bør overgive dit projekter `AGENTS.md` fil til Git. +::: + +Dette hjælper OpenCode med at forstå projektstrukturen og kodningsmønstrene +brugt. + +--- + +## Brug + +Du er nu klar til at bruge OpenCode til at arbejde på dit projekt. Spørg det gerne +noget! + +Hvis du er ny til at bruge en AI-kodningsagent, er her nogle eksempler, der evt +hjælp. + +--- + +### Stil spørgsmål + +Du kan bede OpenCode om at forklare kodebasen for dig. + +:::tip +Brug `@`-tasten til at søge efter filer i projektet. +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +Dette er nyttigt, hvis der er en del af kodebasen, som du ikke har arbejdet på. + +--- + +### Tilføj funktioner + +Du kan bede OpenCode om at tilføje nye funktioner til dit projekt. Selvom vi først anbefaler, at du beder den om at lave en plan. + +1. **Opret en plan** + + OpenCode har en _Plan mode_, der deaktiverer dens evne til at foretage ændringer og + foreslå i stedet _hvordan_ det vil implementere funktionen. + + Skift til det ved hjælp af **Tab**-tasten. Du vil se en indikator for dette i nederste højre hjørne. + + ```bash frame="none" title="Skift til Plan-tilstand" + + ``` + + Lad os nu beskrive, hvad vi vil have den til at gøre. + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + Du vil give OpenCode nok detaljer til at forstå, hvad du ønsker. Det hjælper + at tale med det, som om du taler med en juniorudvikler på dit team. + +:::tip +Giv OpenCode masser af kontekst og eksempler for at hjælpe den med at forstå, hvad du +ønsker. +::: + +2. **Gentag om planen** + + Når det giver dig en plan, kan du give den feedback eller tilføje flere detaljer. + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + +:::tip +Træk og slip billeder i terminalen for at tilføje dem til prompten. +::: + +OpenCode kan scanne alle billeder, du giver dem og tilføje dem til prompten. Det kan du +gør dette ved at trække og slippe et billede ind i terminalen. + +3. **Byg funktionen** + + Når du føler dig godt tilpas med planen, skal du skifte tilbage til _Byggetilstand_ ved + trykke på **Tab**-tasten igen. + + ```bash frame="none" + + ``` + + Og beder den om at foretage ændringerne. + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### Foretag ændringer + +For mere ligetil ændringer kan du bede OpenCode om at bygge den direkte +uden at skulle gennemgå planen først. + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +Du vil sikre dig, at du giver en god mængde detaljer, så OpenCode gør det rigtige +ændringer. + +--- + +### Fortryd ændringer + +Lad os sige, at du beder OpenCode om at foretage nogle ændringer. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Men du indser, at det ikke er, hvad du ønskede. Du **kan fortryde** ændringerne +ved hjælp af kommandoen `/undo`. + +```bash frame="none" +/undo +``` + +OpenCode vil nu vende tilbage til ændringerne, du har foretaget, og vise din oprindelige besked +igen. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Herfra kan du justere prompten og bede OpenCode om at prøve igen. + +:::tip +Du kan køre `/undo` flere gange for at fortryde flere ændringer. +::: + +Eller du **kan gentage** ændringerne ved hjælp af kommandoen `/redo`. + +```bash frame="none" +/redo +``` + +--- + +## Deling + +De samtaler, du har med OpenCode, kan [deles med din +team](/docs/share). + +```bash frame="none" +/share +``` + +Dette vil oprette et link til den aktuelle samtale og kopiere det til denne udklipsholder. + +:::note +Samtaler dele ikke som standard. +::: + +Her er en [eksempelsamtale](https://opencode.ai/s/4XP1fce5) med OpenCode. + +--- + +## Tilpasning + +Og det er det! Du er nu en professionel i at bruge OpenCode. + +For at gøre det til dit eget, anbefaler vi [at vælge et tema](/docs/themes), [tilpasse genvejstaster](/docs/keybinds), [konfigurere kodeformater](/docs/formatters), [oprette brugerdefinerede kommandoer](/docs/commands) eller at lege med [OpenCode-konfiguration](/docs/config). diff --git a/packages/web/src/content/docs/da/keybinds.mdx b/packages/web/src/content/docs/da/keybinds.mdx new file mode 100644 index 00000000000..2da3ff9426c --- /dev/null +++ b/packages/web/src/content/docs/da/keybinds.mdx @@ -0,0 +1,192 @@ +--- +title: Tastebindinger +description: Tilpas dine nøglebindinger. +--- + +OpenCode har en liste over nøglebindinger, som du kan tilpasse gennem OpenCode-konfigurationen. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## Ledertast + +OpenCode bruger en `leader` nøgle til de fleste smagsbindinger. Dette undgår konflikter i din terminal. + +Som standard er `ctrl+x` ledertasten, og de fleste handlinger kræver, at du først trykker på ledertasten og derefter genvejen. For eksempel, for at starte en ny session, skal du først trykke på `ctrl+x` og derefter trykke på `n`. + +Du behøver ikke bruge en ledernøgle til dine nøglebindinger, men vi anbefaler at du gør det. + +--- + +## Deaktiver tastebinding + +Du kan deaktivere en nøglebinding ved at tilføje nøglen til din konfiguration med værdien "ingen". + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## Genveje til skrivebordsprompt + +OpenCode desktop app prompt input understøtter almindelige Readline/Emacs-style genveje til redigering af tekst. Disse er indbyggede og i øjeblikket ikke konfigurerede via `opencode.json`. + +| Genvej | Håndtering | +| -------- | ------------------------------------------- | +| `ctrl+a` | Flyt til starten af ​​den aktuelle linje | +| `ctrl+e` | Flyt til slutningen af ​​den aktuelle linje | +| `ctrl+b` | Flyt markøren et tegn tilbage | +| `ctrl+f` | Flyt markøren et tegn frem | +| `alt+b` | Flyt markøren et ord tilbage | +| `alt+f` | Flyt markøren et ord frem | +| `ctrl+d` | Slet tegn under markøren | +| `ctrl+k` | Dræb til slutningen af ​​linjen | +| `ctrl+u` | Dræb til starten af ​​linjen | +| `ctrl+w` | Dræb forrige ord | +| `alt+d` | Dræb næste ord | +| `ctrl+t` | Transponer tegn | +| `ctrl+g` | Annuller popovers / afbryd kørsel af svar | + +--- + +## Shift+Enter + +Nogle terminaler sender ikke modifikationsnøgler med Enter som standard. Du skal muligvis konfigurere din terminal til at sende `Shift+Enter` som en escape-sekvens. + +### Windows Terminal + +Åbn din `settings.json` på: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +Føj dette til `actions`-arrayet på rodniveau: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Føj dette til `keybindings`-arrayet på rodniveau: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Gem fil og genstart Windows Terminal eller åbn en ny fane. diff --git a/packages/web/src/content/docs/da/lsp.mdx b/packages/web/src/content/docs/da/lsp.mdx new file mode 100644 index 00000000000..b0e0d353723 --- /dev/null +++ b/packages/web/src/content/docs/da/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: LSP-servere +description: OpenCode integreres med dine LSP-servere. +--- + +OpenCode integreres med Language Server Protocol (LSP) for at hjælpe LLM med at interagere med din kodebase. Den bruger diagnostik til at give feedback til LLM. + +--- + +## Indbyggede + +OpenCode leveres med flere indbyggede LSP-servere til populære sprog: + +| LSP Server | Udvidelser | Krav | +| ------------------ | --------------------------------------------------------- | --------------------------------------------------------------- | +| astro | .astro | Autoinstallationer til Astro-projekter | +| bash | .sh,.bash,.zsh,.ksh | Autoinstallerer bash-language-server | +| clangd | .c,.cpp,.cc,.cxx,.c++,.h,.hpp,.hh,.hxx,.h++ | Autoinstallationer for C/C++ projekter | +| csharp | .cs | `.NET SDK` installere | +| 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 | +| 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 | +| kotlin-ls | .kt,.kts | Autoinstallationer til Kotlin-projekter | +| lua-ls | .lua | Autoinstallationer til Lua-projekter | +| nixd | .nix | `nixd` kommando tilgængelig | +| ocaml-lsp | .ml,.mli | `ocamllsp` kommando tilgængelig | +| oxlint | .ts,.tsx,.js,.jsx,.mjs,.cjs,.mts,.cts,.vue,.astro,.svelte | `oxlint` afhængighed i projekt | +| php intelephense | .php | Automatiske installationer til PHP-projekter | +| prisma | .prisma | `prisma` kommando tilgængelig | +| pyright | .py,.pyi | `pyright` afhængig installeret | +| ruby-lsp (rubocop) | .rb,.rake,.gemspec,.ru | `ruby` og `gem` kommandoer tilgængelige | +| rust | .rs | `rust-analyzer` kommando tilgængelig | +| sourcekit-lsp | .swift,.objc,.objcpp | `swift` installere (`xcode` på macOS) | +| svelte | .svelte | Autoinstallationer til Svelte-projekter | +| terraform | .tf,.tfvars | Automatiske installationer fra GitHub-udgivelser | +| tinymist | .typ,.typc | Automatiske installationer fra GitHub-udgivelser | +| typescript | .ts,.tsx,.js,.jsx,.mjs,.cjs,.mts,.cts | `typescript` afhængighed i projekt | +| vue | .vue | Autoinstallationer til Vue-projekter | +| 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. + +:::note +Du kan deaktivere automatisk LSP-serverdownloads ved at indstille miljøvariablen `OPENCODE_DISABLE_LSP_DOWNLOAD` til `true`. +::: + +--- + +## Sådan fungerer det + +Når opencode åbner en fil, vil den: + +1. Kontrollerer filtypenavnet mod alle aktiverede LSP-servere. +2. Starter den relevante LSP-server, hvis den ikke allerede kører. + +--- + +## Konfiguration + +Du kan tilpasse LSP-servere gennem sektionen `lsp` i din opencode-konfiguration. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +Hver LSP- server understøtter følgende: + +| Egenskab | Type | Beskrivelse | +| ---------------- | -------- | --------------------------------------------------------- | +| `disabled` | boolean | Indstil dette til `true` for at deaktivere LSP-serveren | +| `command` | string[] | Kommandoen til at starte LSP-serveren | +| `extensions` | string[] | Filtypenavne, som denne LSP-server skal håndtere | +| `env` | object | Miljøvariabler, der skal indstilles, når serveren starter | +| `initialization` | object | Initialiseringsmuligheder for at sende til LSP-serveren | + +Lad os se på nogle eksempler. + +--- + +### Miljøvariabler + +Brug egenskaben `env` til at indstille miljøvariabler, når du starter LSP-serveren: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### Initialiseringsmuligheder + +Brug egenskaben `initialization` til at videregive initialiseringsindstillinger til LSP-serveren. Disse er serverspecifikke indstillinger sendt under LSP `initialize` anmodningen: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +Initialiseringsmuligheder forskellige afhængige af LSP-serveren. Se din LSP-servers dokumentation for tilgængelige muligheder. +::: + +--- + +### Deaktivering af LSP-servere + +For at deaktivere **alle** LSP-servere globalt, skal du indstille `lsp` til `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +For at deaktivere en **specifik** LSP-server skal du indstille `disabled` til `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### Brugerdefinerede LSP-servere + +Du kan tilføje brugerdefinerede LSP-servere ved at angive kommandoen og filtypenavne: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## Yderligere oplysninger + +### PHP Intelephense + +PHP Intelephense tilbyder premium funktioner gennem en licensnøgle. Du kan angive en licensnøgle ved at placere (kun) nøglen i en tekstfil på: + +- På macOS/Linux: `$HOME/intelephense/license.txt` +- På Windows: `%USERPROFILE%/intelephense/license.txt` + +Filen bør kun indeholde licensnøglen uden yderligere indhold. diff --git a/packages/web/src/content/docs/da/mcp-servers.mdx b/packages/web/src/content/docs/da/mcp-servers.mdx new file mode 100644 index 00000000000..fa356131ba3 --- /dev/null +++ b/packages/web/src/content/docs/da/mcp-servers.mdx @@ -0,0 +1,511 @@ +--- +title: MCP-servere +description: Tilføj lokale og eksterne MCP værktøjer. +--- + +Du kan tilføje eksterne værktøjer til OpenCode ved hjælp af _Model Context Protocol_ eller MCP. OpenCode understøtter både lokale og eksterne servere. + +Når de er tilføjet, er MCP automatisk tilgængelig for LLM sammen med indbyggede værktøjer. + +--- + +#### Forbehold + +Når du bruger en MCP-server, føjes den til konteksten. Dette kan hurtigt stige, hvis du har mange værktøjer. Så vi anbefaler at være forsigtig med hvilke MCP-servere du bruger. + +:::tip +MCP-servere tilføjer til din kontekst, så du vil være forsigtig med, hvilke du aktiverer. +::: + +Visse MCP-servere, som GitHub MCP-servere, har en tendens til at tilføje mange tokens og kan nemt overskride kontekstgrænsen. + +--- + +## Aktivering + +Du kan definere MCP-servere i din [OpenCode Config](https://opencode.ai/docs/config/) under `mcp`. Tilføj hver MCP med et unikt navn. Du kan henvise til denne MCP ved navn, når du spørger LLM. + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +Du kan også deaktivere en server ved at indstille `enabled` til `false`. Dette er nyttigt, hvis du midlertidigt vil deaktivere en server uden at fjerne den fra din konfiguration. + +--- + +### Tilsidesættelse af eksterne standarder + +Organisationer kan levere standard MCP-servere via deres `.well-known/opencode`-slutpunkt. Disse servere kan være deaktiveret som standard, hvilket giver brugerne mulighed for at tilmelde sig dem, de har brug for. + +For at aktivere en specifik server fra din organisationers fjernkonfiguration skal du tilføje den til din lokale konfiguration med `enabled: true`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +Dine lokale konfigurationsværdier tilsidesætter fjernstandarderne. Se [config precedence](/docs/config#precedence-order) for flere detaljer. + +--- + +## Lokal + +Tilføj lokale MCP-servere ved hjælp af `type` til `"local"` i MCP-objektet. + +```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", + }, + }, + }, +} +``` + +Kommandoen er, hvordan den lokale MCP-server starter. Du kan også sende en liste over miljøvariabler ind. + +For eksempel kan du tilføje test-MCP-serveren [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything). + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "mcp_everything": { + "type": "local", + "command": ["npx", "-y", "@modelcontextprotocol/server-everything"], + }, + }, +} +``` + +Og for at bruge det kan jeg tilføje `use the mcp_everything tool` til mine prompter. + +```txt "mcp_everything" +use the mcp_everything tool to add the number 3 and 4 +``` + +--- + +#### Indstillinger + +Her er alle muligheder for at konfigurere en lokal MCP-server. + +| Mulighed | Skriv | Påkrævet | Beskrivelse | +| ------------- | ------- | -------- | ------------------------------------------------------------------------------------ | +| `type` | String | Y | Type MCP serverforbindelse, skal være `"local"`. | +| `command` | Array | Y | Kommando og argumenter til at køre MCP-serveren. | +| `environment` | Object | | Miljøvariabler, der skal indstilles, når serveren kører. | +| `enabled` | Boolean | | Aktiver eller deaktiver MCP-serveren ved opstart. | +| `timeout` | Nummer | | Timeout i ms for at hente værktøjer fra MCP-serveren. Standard er 5000 (5 sekunder). | + +--- + +## Ekstern + +Tilføj ekstern MCP-server ved at indstille `type` til `"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" + } + } + } +} +``` + +`url` er URL for den eksterne MCP server, og med indstillingen `headers` kan du sende en liste over overskrifter ind. + +--- + +#### Indstillinger + +| Mulighed | Skriv | Påkrævet | Beskrivelse | +| --------- | ------- | -------- | ------------------------------------------------------------------------------------ | +| `type` | String | Y | Type MCP serverforbindelse, skal være `"remote"`. | +| `url` | String | Y | URL af den eksterne MCP-server. | +| `enabled` | Boolean | | Aktiver eller deaktiver MCP-serveren ved opstart. | +| `headers` | Object | | Overskrifter til at sende med anmodningen. | +| `oauth` | Object | | OAuth-godkendelseskonfiguration. Se afsnittet [OAuth](#oauth) nedenfor. | +| `timeout` | Nummer | | Timeout i ms for at hente værktøjer fra MCP-serveren. Standard er 5000 (5 sekunder). | + +--- + +## OAuth + +OpenCode håndterer automatisk OAuth-godkendelse for eksterne MCP-servere. Når en server kræver godkendelse, vil OpenCode: + +1. Registrer 401-svaret, og start OAuth-flowet +2. Brug **Dynamic Client Registration (RFC 7591)**, hvis det understøtter af serveren +3. Opbevar tokens sikkert til fremtidige anmodninger + +--- + +### Automatisk + +For de fleste OAuth-aktiverede MCP-servere kræver ingen speciel konfiguration. Bare konfigureret fjernserver: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "my-oauth-server": { + "type": "remote", + "url": "https://mcp.example.com/mcp" + } + } +} +``` + +Hvis serveren kræver godkendelse, vil OpenCode bede dig om at godkende, når du prøver at bruge den første gang. Hvis ikke, kan du [manually trigger the flow](#authenticating) med `opencode mcp auth `. + +--- + +### Forhåndsregistreret + +Hvis du har klientlegitimationsoplysninger fra MCP-serverudbyderen, kan du konfigurere dem: + +```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" + } + } + } +} +``` + +--- + +### Godkendelse + +Du kan manuelt udløse godkendelse eller administrere legitimationsoplysninger. + +Godkendt med en specifik MCP-server: + +```bash +opencode mcp auth my-oauth-server +``` + +Liste over alle MCP-servere og deres godkendelsesstatus: + +```bash +opencode mcp list +``` + +Fjern gemte legitimationsoplysninger: + +```bash +opencode mcp logout my-oauth-server +``` + +Kommandoen `mcp auth` åbner din browser for godkendelse. Når du har godkendt, vil OpenCode opbevare tokens sikkert i `~/.local/share/opencode/mcp-auth.json`. + +--- + +#### Deaktivering af OAuth + +Hvis du vil deaktivere automatisk OAuth for en server (f.eks. for servere, der bruger API-nøgler i stedet), skal du indstille `oauth` til `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-indstillinger + +| Mulighed | Skriv | Beskrivelse | +| -------------- | --------------- | ----------------------------------------------------------------------------------------- | +| `oauth` | Object \| false | OAuth-konfigurationsobjekt eller `false` for at deaktivere OAuth-auto-detektion. | +| `clientId` | String | OAuth-klient-id. Hvis det ikke er angivet, vil dynamisk klientregistrering blive forsøgt. | +| `clientSecret` | String | OAuth-klienthemmelighed, hvis det kræves af autorisationsserveren. | +| `scope` | String | OAuth-omfang at anmode om under godkendelse. | + +#### Fejlfinding + +Hvis en ekstern MCP-server ikke kan godkendes, kan du diagnosticere problemer med: + +```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 +``` + +Kommandoen `mcp debug` viser den aktuelle godkendelsesstatus, tester HTTP-forbindelse og forsøger OAuth-opdagelsesflowet. + +--- + +## Administration + +Dine MCPs er tilgængelige som værktøjer i **TK\_** sammen med indbyggede værktøjer. Så du kan administrere dem gennem OpenCode-konfigurationen som ethvert andet værktøj. + +--- + +### Global + +Det betyder, at du kan aktivere eller deaktivere dem globalt. + +```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 + } +} +``` + +Vi kan også bruge et globmønster til at deaktivere alle matchende MCPs. + +```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 + } +} +``` + +Her bruger vi globmønsteret `my-mcp*` til at deaktivere alle MCPs. + +--- + +### Per agent + +Hvis du har et stort antal MCP-servere, vil du måske kun aktivere dem pr. agent og deaktivere dem globalt. Sådan gør du: + +1. Deaktiver det som et værktøj globalt. +2. Aktiver MCP-serveren som et værktøj i din [agent config](/docs/agents#tools). + +```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 + } + } + } +} +``` + +--- + +#### Glob-mønstre + +Glob-mønsteret bruger simple regex-globing-mønstre: + +- `*` matcher nul eller flere af ethvert tegn (f.eks. `"my-mcp*"` matcher `my-mcp_search`, `my-mcp_list` osv.) +- `?` matcher nøjagtigt ét tegn +- Alle andre karakterer matcher bogstaveligt talt + +:::note +MCP serverværktøjer er registreret med servernavn som præfiks, så for at deaktivere alle værktøjer til en server skal du blot bruge: + +``` +"mymcpservername_*": false +``` + +::: + +--- + +## Eksempler + +Nedenfor er eksempler på nogle almindelige MCP-servere. Du kan indsende en PR, hvis du vil dokumentere andre servere. + +--- + +### Sentry + +Tilføj [Sentry MCP server](https://mcp.sentry.dev) for at interagere med dine Sentry-projekter og -problemer. + +```json title="opencode.json" {4-8} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "sentry": { + "type": "remote", + "url": "https://mcp.sentry.dev/mcp", + "oauth": {} + } + } +} +``` + +Efter tilføjelse af konfigurationen skal du godkende med Sentry: + +```bash +opencode mcp auth sentry +``` + +Dette åbner et browservindue for at fuldføre OAuth-flowet og forbinde OpenCode til din Sentry-konto. + +Når du er godkendt, kan du bruge Sentry-værktøjer i dine prompter til at forespørge om problemer, projekter og fejldata. + +```txt "use sentry" +Show me the latest unresolved issues in my project. use sentry +``` + +--- + +### Context7 + +Tilføj [Context7 MCP server](https://github.com/upstash/context7) for at søge i dokumenter. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "context7": { + "type": "remote", + "url": "https://mcp.context7.com/mcp" + } + } +} +``` + +Hvis du har tilmeldt dig en gratis konto, kan du bruge din API-nøgle og få højere satsgrænser. + +```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}" + } + } + } +} +``` + +Her antager vi, at du har sat miljøvariablen `CONTEXT7_API_KEY`. + +Føj `use context7` til dine prompter for at bruge Context7 MCP server. + +```txt "use context7" +Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 +``` + +Alternativt kan du tilføje noget som dette til din [AGENTS.md](/docs/rules/). + +```md title="AGENTS.md" +When you need to search docs, use `context7` tools. +``` + +--- + +### Grep by Vercel + +Tilføj serveren [Grep by Vercel](https://grep.app) MCP for at søge gennem kodestykker på GitHub. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "gh_grep": { + "type": "remote", + "url": "https://mcp.grep.app" + } + } +} +``` + +Da vi navngav vores MCP-server `gh_grep`, kan du tilføje `use the gh_grep tool` til dine prompter for at få agenten til at bruge den. + +```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 +``` + +Alternativt kan du tilføje noget som dette til din [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/da/models.mdx b/packages/web/src/content/docs/da/models.mdx new file mode 100644 index 00000000000..7bacdd9f269 --- /dev/null +++ b/packages/web/src/content/docs/da/models.mdx @@ -0,0 +1,223 @@ +--- +title: Modeller +description: Konfiguration af en LLM udbyder og model. +--- + +OpenCode bruger [AI SDK](https://ai-sdk.dev/) og [Models.dev](https://models.dev) til at understøtte **75+ LLM udbydere** og det understøtter at køre lokale modeller. + +--- + +## Udbydere + +De fleste populære udbydere er forudindlæst som standard. Hvis du har tilføjet legitimationsoplysningerne for en udbyder gennem kommandoen `/connect`, vil de være tilgængelige, når du starter OpenCode. + +Få mere at vide om [providers](/docs/providers). + +--- + +## Vælg en model + +Når du har konfigureret din udbyder, kan du vælge den ønskede model ved at indtaste: + +```bash frame="none" +/models +``` + +--- + +## Anbefalede modeller + +Der er mange modeller derude, og der kommer nye modeller hver uge. + +:::tip +Overvej at bruge en af ​​de modeller, vi anbefaler. +::: + +Der er dog kun få af dem, der er gode til både at generere kode og værktøjsopkald. + +Her er flere modeller, der fungerer godt med OpenCode, uden bestemt rækkefølge. (Dette er ikke en udtømmende liste og er heller ikke nødvendigvis opdateret): + +- GPT 5.2 +- GPT 5.1 Codex +- Claude Opus 4,5 +- Claude Sonnet 4,5 +- Minimax M2.1 +- Gemini 3 Pro + +--- + +## Indstil en standard + +For at indstille en af ​​disse som standardmodellen kan du indstille `model`-nøglen i din +OpenCode konfig. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +Her er det fulde ID `provider_id/model_id`. For eksempel, hvis du bruger [OpenCode Zen](/docs/zen), vil du bruge `opencode/gpt-5.1-codex` til GPT 5.1 Codex. + +Hvis du har konfigureret en [custom provider](/docs/providers#custom), er `provider_id` nøglen fra `provider` delen af ​​din konfiguration, og `model_id` er nøglen fra `provider.models`. + +--- + +## Konfiguration af modeller + +Du kan konfigurere en models muligheder globalt gennem konfigurationen. + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +Her konfigurerer vi globale indstillinger for to indbyggede modeller: `gpt-5` når de tilgås via `openai` udbyderen og `claude-sonnet-4-20250514` når de tilgås via `anthropic` udbyderen. +Den indbyggede udbyder og modelnavne kan findes på [Models.dev](https://models.dev). + +Du kan også konfigurere disse indstillinger for alle agenter, du bruger. Agentkonfigurationen tilsidesætter alle globale muligheder her. [Learn more](/docs/agents/#additional). + +Du kan også definere brugerdefinerede varianter, der udvider de indbyggede. Varianter giver dig mulighed for at konfigurere forskellige indstillinger for den samme model uden at oprette duplikerede poster: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## Varianter + +Mange modeller understøtter flere varianter med forskellige konfigurationer. OpenCode leveres med indbyggede standardvarianter til populære udbydere. + +### Indbyggede varianter + +OpenCode leveres med standardvarianter for mange udbydere: + +**Anthropic**: + +- `high` - Højt tænkende budget (standard) +- `max` - Maksimalt tænkebudget + +**OpenAI**: + +Varierer efter model, men nogenlunde: + +- `none` - Ingen begrundelse +- `minimal` - Minimal ræsonnement indsats +- `low` - Lav ræsonnement indsats +- `medium` - Middel ræsonnement indsats +- `high` - Høj ræsonnement indsats +- `xhigh` - Ekstra høj ræsonnement indsats + +**Google**: + +- `low` - Lavere effort/token budget +- `high` - Højere effort/token budget + +:::tip +Denne liste er ikke udtømmende. Mange andre udbydere har også indbyggede standardindstillinger. +::: + +### Brugerdefinerede varianter + +Du kan tilsidesætte eksisterende varianter eller tilføje dine egne: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### Skift varianter + +Brug tastebindingen `variant_cycle` til hurtigt at skifte mellem varianter. [Learn more](/docs/keybinds). + +--- + +## Indlæsning af modeller + +Når OpenCode starter op, søger den efter modeller i følgende prioriterede rækkefølge: + +1. Kommandolinjeflaget `--model` eller `-m`. Formatet er det samme som i konfigurationsfilen: `provider_id/model_id`. + +2. Modellisten i OpenCode-konfigurationen. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + + Formatet her er `provider/model`. + +3. Den sidst brugte model. + +4. Den første model med en intern prioritet. diff --git a/packages/web/src/content/docs/da/modes.mdx b/packages/web/src/content/docs/da/modes.mdx new file mode 100644 index 00000000000..40a5303f202 --- /dev/null +++ b/packages/web/src/content/docs/da/modes.mdx @@ -0,0 +1,331 @@ +--- +title: Tilstande +description: Forskellige tilstande til forskellige anvendelsestilfælde. +--- + +:::caution +Tilstande er nu konfigureret gennem indstillingen `agent` i opencode-konfigurationen. De +`mode` mulighed er nu forældet. [Learn more](/docs/agents). +::: + +Tilstande i opencode giver dig mulighed for at tilpasse adfærd, værktøjer og prompter til forskellige brugstilfælde. + +Den kommer med to indbyggede tilstande: **build** og **plan**. Du kan tilpasse +disse eller konfigurer dine egne gennem opencode-konfigurationen. + +Du kan skifte mellem tilstande under en session eller konfigurere dem i din konfigurationsfil. + +--- + +## Indbyggede + +opencode leveres med to indbyggede tilstande. + +--- + +### Byg + +Byg er **standard**-tilstanden med alle værktøjer aktiveret. Dette er standardtilstanden for udviklingsarbejde, hvor du har brug for fuld adgang til filhandlinger og systemkommandoer. + +--- + +### Plan + +En begrænset tilstand designet til planlægning og analyse. I plantilstand er følgende værktøjer deaktiveret som standard: + +- `write` - Kan ikke oprette nye filer +- `edit` - Kan ikke ændre eksisterende filer, undtagen filer placeret på `.opencode/plans/*.md` for at detaljere selve planen +- `patch` - Kan ikke anvende patches +- `bash` - Kan ikke udføre shell-kommandoer + +Denne tilstand er nyttig, når du vil have AI til at analysere kode, foreslå ændringer eller oprette planer uden at foretage egentlige ændringer af din kodebase. + +--- + +## Skift + +Du kan skifte mellem tilstande under en session ved at bruge _Tab_-tasten. Eller din konfigurerede `switch_mode` nøglebinding. + +Se også: [Formatters](/docs/formatters) for information om konfiguration af kodeformatering. + +--- + +## Konfiguration + +Du kan tilpasse de indbyggede tilstande eller oprette dine egne gennem konfiguration. Tilstande kan konfigureres på to måder: + +### JSON-konfiguration + +Konfigurer tilstande i din `opencode.json`-konfigurationsfil: + +```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-konfiguration + +Du kan også definere tilstande ved hjælp af markdown-filer. Placer dem i: + +- Globalt: `~/.config/opencode/modes/` +- Projekt: `.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. +``` + +Markdown-filnavnet bliver tilstandsnavnet (f.eks. opretter `review.md` en `review`-tilstand). + +Lad os se nærmere på disse konfigurationsmuligheder. + +--- + +### Model + +Brug `model`-konfigurationen til at tilsidesætte standardmodellen for denne tilstand. Nyttigt til brug af forskellige modeller optimeret til forskellige opgaver. For eksempel en hurtigere model til planlægning, en mere dygtig model til implementering. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### Temperatur + +Styr tilfældigheden og kreativiteten af ​​AI's svar med `temperature`-konfigurationen. Lavere værdier gør svar mere fokuserede og deterministiske, mens højere værdier øger kreativitet og variabilitet. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Temperaturværdier varierer typisk fra 0,0 til 1,0: + +- **0.0-0.2**: Meget fokuserede og deterministiske svar, ideel til kodeanalyse og planlægning +- **0,3-0,5**: Afbalancerede svar med en vis kreativitet, god til generelle udviklingsopgaver +- **0.6-1.0**: Mere kreative og varierede svar, nyttige til brainstorming og udforskning + +```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 der ikke er angivet nogen temperatur, bruger opencode modelspecifikke standarder (typisk 0 for de fleste modeller, 0,55 for Qwen-modeller). + +--- + +### Prompt + +Angiv en brugerdefineret systempromptfil for denne tilstand med `prompt`-konfigurationen. Promptfilen skal indeholde instruktioner, der er specifikke for tilstandens formål. + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Denne sti er i forhold til, hvor konfigurationsfilen er placeret. Så dette virker for +både den globale opencode-konfiguration og den projektspecifikke konfiguration. + +--- + +### Værktøjer + +Kontroller, hvilke værktøjer der er tilgængelige i denne tilstand med `tools`-konfigurationen. Du kan aktivere eller deaktivere specifikke værktøjer ved at indstille dem til `true` eller `false`. + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +Hvis der ikke er angivet nogen værktøjer, er alle værktøjer aktiveret som standard. + +--- + +#### Tilgængelige værktøjer + +Her er alle de værktøjer, der kan styres gennem tilstandskonfigurationen. + +| Værktøj | Beskrivelse | +| ----------- | -------------------------- | +| `bash` | Udfør shell-kommandoer | +| `edit` | Rediger eksisterende filer | +| `write` | Opret nye filer | +| `read` | Læs filindhold | +| `grep` | Søg filindhold | +| `glob` | Find filer efter mønster | +| `list` | Liste biblioteksindhold | +| `patch` | Anvend patches til filer | +| `todowrite` | Administrer todo-lister | +| `todoread` | Læs todo-lister | +| `webfetch` | Hent webindhold | + +--- + +## Brugerdefinerede tilstande + +Du kan oprette dine egne brugerdefinerede tilstande ved at tilføje dem til konfigurationen. Her er eksempler, der bruger begge tilgange: + +### Brug af JSON-konfiguration + +```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 + } + } + } +} +``` + +### Brug af markdown-filer + +Opret tilstandsfiler i `.opencode/modes/` for projektspecifikke tilstande eller `~/.config/opencode/modes/` for globale tilstande: + +```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 +``` + +--- + +### Brugsscenarier + +Her er nogle almindelige brugstilfælde for forskellige tilstande. + +- **Build mode**: Fuldt udviklingsarbejde med alle værktøjer aktiveret +- **Plantilstand**: Analyse og planlægning uden at foretage ændringer +- **Anmeldelsestilstand**: Kodegennemgang med skrivebeskyttet adgang plus dokumentationsværktøjer +- **Fejlretningstilstand**: Fokuseret på undersøgelse med bash og læseværktøjer aktiveret +- **Docs-tilstand**: Dokumentationsskrivning med filhandlinger, men ingen systemkommandoer + +Du kan også finde ud af, at forskellige modeller er gode til forskellige brugssituationer. diff --git a/packages/web/src/content/docs/da/network.mdx b/packages/web/src/content/docs/da/network.mdx new file mode 100644 index 00000000000..a9486890837 --- /dev/null +++ b/packages/web/src/content/docs/da/network.mdx @@ -0,0 +1,57 @@ +--- +title: Netværk +description: Konfigurer proxyer og brugerdefinerede certifikater. +--- + +OpenCode understøtter standard proxymiljøvariabler og brugerdefinerede certifikater til virksomhedsnetværksmiljøer. + +--- + +## Proxy + +OpenCode respekterer standard proxy-miljøvariabler. + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +TUI kommunikerer med en lokal HTTP-server. Du skal omgå proxyen for denne forbindelse for at forhindre routingsløjfer. +::: + +Du kan konfigurere serverens port og værtsnavn ved hjælp af [CLI flags](/docs/cli#run). + +--- + +### Godkendelse + +Hvis din proxy kræver grundlæggende godkendelse, skal du inkludere legitimationsoplysninger i URL. + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +Undgå hardkodning af adgangskoder. Brug miljøvariabler eller sikker lagring af legitimationsoplysninger. +::: + +For proxyer, der kræver avanceret godkendelse som NTLM eller Kerberos, kan du overveje at bruge en LLM Gateway, der understøtter din godkendelsesmetode. + +--- + +## Brugerdefinerede certifikater + +Hvis din virksomhed bruger tilpassede CA'er til HTTPS-forbindelser, skal du konfigurere OpenCode til at stole på dem. + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +Dette virker for både proxy-forbindelser og direkte API-adgang. diff --git a/packages/web/src/content/docs/da/permissions.mdx b/packages/web/src/content/docs/da/permissions.mdx new file mode 100644 index 00000000000..72c839833fd --- /dev/null +++ b/packages/web/src/content/docs/da/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: Tilladelser +description: Kontroller, hvilke handlinger der kræver godkendelse for at køre. +--- + +OpenCode bruger `permission`-konfigurationen til at bestemme, om en given handling skal køre automatisk, bede dig om eller blokeres. + +Fra `v1.1.1` er den ældre `tools` booleske konfiguration forældet og er blevet flettet ind i `permission`. Den gamle `tools`-konfiguration er stadig understøttet for bagudkompatibilitet. + +--- + +## Handlinger + +Hver tilladelsesregel løses til en af: + +- `"allow"` — køre uden godkendelse +- `"ask"` — prompt om godkendelse +- `"deny"` — bloker handlingen + +--- + +## Konfiguration + +Du kan indstille tilladelser globalt (med `*`) og tilsidesætte specifikke værktøjer. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +Du kan også indstille alle tilladelser på én gang: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## Granulære regler (objektsyntaks) + +For de fleste tilladelser kan du bruge et objekt til at anvende forskellige handlinger baseret på værktøjsinputtet. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +Regler evalueres efter mønstermatch, hvor den **sidste matchende regel vinder**. Et almindeligt mønster er at sætte catch-all `"*"` reglen først og mere specifikke regler efter den. + +### Jokertegn + +Tilladelsesmønstre bruger simpel jokertegn-matchning: + +- `*` matcher nul eller flere af et hvilket som helst tegn +- `?` matcher nøjagtigt ét tegn +- Alle andre karakterer matcher bogstaveligt talt + +### Udvidelse af hjemmemappe + +Du kan bruge `~` eller `$HOME` i starten af ​​et mønster til at referere til din hjemmemappe. Dette er især nyttigt for [`external_directory`](#external-directories) regler. + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### Eksterne mapper + +Brug `external_directory` til at tillade værktøjsopkald, der berører stier uden for den arbejdsmappe, hvor OpenCode blev startet. Dette gælder for ethvert værktøj, der tager en sti som input (for eksempel `read`, `edit`, `list`, `glob`, `grep` og mange `bash` kommandoer). + +Hjemmeudvidelse (som `~/...`) påvirker kun, hvordan et mønster skrives. Det gør ikke en ekstern sti til en del af det aktuelle arbejdsområde, så stier uden for arbejdsbiblioteket skal stadig være tilladt via `external_directory`. + +For eksempel giver dette adgang til alt under `~/projects/personal/`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +Enhver mappe, der er tilladt her, arver de samme standarder som det aktuelle arbejdsområde. Siden [`read` defaults to `allow`](#defaults), er læsninger også tilladt for poster under `external_directory`, medmindre de tilsidesættes. Tilføj eksplicitte regler, når et værktøj skal begrænses i disse stier, såsom blokering af redigeringer, mens læsninger bevares: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +Hold listen fokuseret på betroede stier, og lag ekstra tillad eller afvis regler efter behov for andre værktøjer (for eksempel `bash`). + +--- + +## Tilgængelige tilladelser + +OpenCode tilladelser indtastes efter værktøjsnavn plus et par sikkerhedsafskærmninger: + +- `read` — læser en fil (matcher filstien) +- `edit` — alle filændringer (dækker `edit`, `write`, `patch`, `multiedit`) +- `glob` — fil-globing (matcher glob-mønsteret) +- `grep` — indholdssøgning (matcher regex-mønsteret) +- `list` — viser filer i en mappe (matcher mappestien) +- `bash` — kører shell-kommandoer (matcher parsede kommandoer som `git status --porcelain`) +- `task` — lancering af underagenter (matcher underagenttypen) +- `skill` — indlæsning af en færdighed (matcher færdighedsnavnet) +- `lsp` — kører LSP forespørgsler (i øjeblikket ikke-granulære) +- `todoread`, `todowrite` — reading/updating todo-listen +- `webfetch` — henter en URL (matcher URL) +- `websearch`, `codesearch` — web/code søgning (matcher forespørgslen) +- `external_directory` — udløses, når et værktøj berører stier uden for projektets arbejdsmappe +- `doom_loop` — udløses, når det samme værktøjskald gentages 3 gange med identisk input + +--- + +## Standarder + +Hvis du ikke angiver noget, starter OpenCode fra tilladelige standardindstillinger: + +- De fleste tilladelser er som standard `"allow"`. +- `doom_loop` og `external_directory` er som standard `"ask"`. +- `read` er `"allow"`, men `.env` filer nægtes som standard: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## Hvad "Spørg" gør + +Når OpenCode beder om godkendelse, tilbyder brugergrænsefladen tre resultater: + +- `once` — godkend netop denne anmodning +- `always` — godkend fremtidige anmodninger, der matcher de foreslåede mønstre (for resten af ​​den nuværende OpenCode session) +- `reject` — afvis anmodningen + +Sættet af mønstre, som `always` ville godkende, leveres af værktøjet (f.eks. hvidlister bash-godkendelser typisk et sikkert kommandopræfiks som `git status*`). + +--- + +## Agenter + +Du kan tilsidesætte tilladelser pr. agent. Agenttilladelser flettes med den globale konfiguration, og agentregler har forrang. [Learn more](/docs/agents#permissions) om agenttilladelser. + +:::note +Se afsnittet [Granular Rules (Object Syntax)](#granular-rules-object-syntax) ovenfor for mere detaljerede mønstermatchningseksempler. +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +Du kan også konfigurere agenttilladelser i Markdown: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +Brug mønstermatchning til kommandoer med argumenter. `"grep *"` tillader `grep pattern file.txt`, mens `"grep"` alene ville blokere det. Kommandoer som `git status` fungerer for standardadfærd, men kræver eksplicit tilladelse (som `"git status *"`), når argumenter sendes. +::: diff --git a/packages/web/src/content/docs/da/plugins.mdx b/packages/web/src/content/docs/da/plugins.mdx new file mode 100644 index 00000000000..a8532d599ce --- /dev/null +++ b/packages/web/src/content/docs/da/plugins.mdx @@ -0,0 +1,385 @@ +--- +title: Plugins +description: Skriv dine egne plugins for at udvide OpenCode. +--- + +Plugins giver dig mulighed for at udvide OpenCode ved at tilslutte sig forskellige begivenheder og tilpasse adfærd. Du kan oprette plugins for at tilføje nye funktioner, integrere med eksterne tjenester eller ændre OpenCodes standardadfærd. + +For eksempler, tjek [plugins](/docs/ecosystem#plugins) oprettet af fællesskabet. + +--- + +## Brug af plugin + +Der er to måder at indlæse plugins på. + +--- + +### Fra lokale filer + +Placer JavaScript- eller TypeScript-filer i plugin-mappen. + +- `.opencode/plugins/` - Plugins på projektniveau +- `~/.config/opencode/plugins/` - Globale plugins + +Filer i disse mapper indlæses automatisk ved opstart. + +--- + +### Fra npm + +Angiv npm-pakker i din konfigurationsfil. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +Både almindelige og omfangsrige npm-pakker understøttes. + +Gennemse tilgængelige plugins i [ecosystem](/docs/ecosystem#plugins). + +--- + +### Installation af plugins + +**npm plugins** installeres automatisk ved hjælp af Bun ved opstart. Pakker og deres afhængigheder cachelagres i `~/.cache/opencode/node_modules/`. + +**Lokale plugins** indlæses direkte fra plugin-biblioteket. For at bruge eksterne pakker skal du oprette en `package.json` i din konfigurationsmappe (se [Dependencies](#dependencies)), eller udgive pluginnet til npm og [add it to your config](/docs/config#plugins). + +--- + +### Indlæsningsrækkefølge + +Plugins indlæses fra alle kilder, og alle hooks kører i rækkefølge. Indlæsningsrækkefølgen er: + +1. Global konfiguration (`~/.config/opencode/opencode.json`) +2. Projektkonfiguration (`opencode.json`) +3. Global plugin-mappe (`~/.config/opencode/plugins/`) +4. Projekt plugin bibliotek (`.opencode/plugins/`) + +Dublerede npm-pakker med samme navn og version indlæses én gang. Et lokalt plugin og et npm plugin med lignende navne indlæses dog hver for sig. + +--- + +## Oprettelse af plugin + +Et plugin er et **JavaScript/TypeScript modul**, der eksporterer et eller flere plugin +funktioner. Hver funktion modtager et kontekstobjekt og returnerer et hooks-objekt. + +--- + +### Afhængigheder + +Lokale plugins og brugerdefinerede værktøjer kan bruge eksterne npm-pakker. Tilføj en `package.json` til din konfigurationsmappe med de afhængigheder, du har brug for. + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +OpenCode kører `bun install` ved opstart for at installere disse. Dine plugins og værktøjer kan derefter importere dem. + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### Grundlæggende struktur + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +Plugin-funktionen modtager: + +- `project`: Den aktuelle projektinformation. +- `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. + +--- + +### TypeScript-understøttelse + +For TypeScript-plugins kan du importere typer fra plugin-pakken: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### Begivenheder + +Plugins kan abonnere på begivenheder som vist nedenfor i afsnittet Eksempler. Her er en liste over de forskellige arrangementer. + +#### Kommandohændelser + +- `command.executed` + +#### Filhændelser + +- `file.edited` +- `file.watcher.updated` + +#### Installationshændelser + +- `installation.updated` + +#### LSP-hændelser + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### Beskedhændelser + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### Tilladelseshændelser + +- `permission.asked` +- `permission.replied` + +#### Serverhændelser + +- `server.connected` + +#### Sessionshændelser + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### Todo-hændelser + +- `todo.updated` + +#### Shell-hændelser + +- `shell.env` + +#### Værktøjshændelser + +- `tool.execute.after` +- `tool.execute.before` + +#### TUI-hændelser + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## Eksempler + +Her er nogle eksempler på plugins, du kan bruge til at udvide opencode. + +--- + +### Send meddelelser + +Send meddelelser, når visse hændelser indtræffer: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +Vi bruger `osascript` til at køre AppleScript på macOS. Her bruger vi det til at sende notifikationer. + +:::note +Hvis du bruger OpenCode desktop-appen, kan den sende systemmeddelelser automatisk, når et svar er klar, eller når en session fejler. +::: + +--- + +### .env-beskyttelse + +Undgå opencode i at læse `.env` filer: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### Injicer miljøvariabler + +Injicer miljøvariabler i al shell-udførelse (AI-værktøjer og brugerterminaler): + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### Brugerdefinerede værktøjer + +Plugins kan også tilføje brugerdefinerede værktøjer til opencode: + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +`tool`-hjælperen opretter et brugerdefineret værktøj, som opencode kan kalde. Det tager en Zod-skemafunktion og returnerer en værktøjsdefinition med: + +- `description`: Hvad værktøjet gør +- `args`: Zod-skema for værktøjets argumenter +- `execute`: Funktion, der kører, når værktøjet kaldes + +Dine tilpassede værktøjer vil være tilgængelige for opencode sammen med indbyggede værktøjer. + +--- + +### Logning + +Brug `client.app.log()` i stedet for `console.log` til struktureret logning: + +```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" }, + }, + }) +} +``` + +Niveauer: `debug`, `info`, `warn`, `error`. Se [SDK documentation](https://opencode.ai/docs/sdk) for detaljer. + +--- + +### Komprimerings-hooks + +Tilpas konteksten inkluderet, når en session komprimeres: + +```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` krogen affyres, før LLM genererer en fortsættelsesoversigt. Brug den til at injicere domænespecifik kontekst, som standardkomprimeringsprompten ville gå glip af. + +Du kan også erstatte komprimeringsprompten helt ved at indstille `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. +` + }, + } +} +``` + +Når `output.prompt` er indstillet, erstatter den standardkompressionsprompten fuldstændigt. `output.context`-arrayet ignoreres i dette tilfælde. diff --git a/packages/web/src/content/docs/da/providers.mdx b/packages/web/src/content/docs/da/providers.mdx new file mode 100644 index 00000000000..829ae46134b --- /dev/null +++ b/packages/web/src/content/docs/da/providers.mdx @@ -0,0 +1,1883 @@ +--- +title: Udbydere +description: Brug en hvilken som helst LLM-udbyder i OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console + +OpenCode bruger [AI SDK](https://ai-sdk.dev/) og [Models.dev](https://models.dev) til at understøtte **75+ LLM-udbydere** og understøtter kørsel af lokale modeller. + +For at tilføje en udbyder skal du: + +1. Tilføje API-nøglerne for udbyderen ved at bruge kommandoen `/connect`. +2. Konfigurere udbyderen i OpenCode-konfigurationen. + +--- + +### Legitimationsoplysninger + +Når du tilføjer en udbyders API-nøgler med `/connect`-kommandoen, gemmes de i `~/.local/share/opencode/auth.json`. + +--- + +### Konfiguration + +Du kan tilpasse udbyderne gennem `provider`-delen i OpenCode-konfigurationen. + +--- + +#### Base URL + +Du kan tilpasse base URL for enhver udbyder ved at angive muligheden `baseURL`. Dette er nyttigt, når du bruger proxy-tjenester eller tilpassede endpoints. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen er en liste over modeller leveret af OpenCode-teamet, som er blevet testet og verificeret til at fungere godt med OpenCode. [Læs mere](/docs/zen). + +:::tip +Hvis du er ny, anbefaler vi at starte med OpenCode Zen. +::: + +1. Kør kommandoen `/connect` i TUI, vælg opencode og gå til [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. Log ind, tilføj dine faktureringsoplysninger og kopier API-nøglen. + +3. Indsæt API-nøglen. + + ```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. + +:::note +Ser du ikke en udbyder her? Indsend en PR. +::: + +--- + +### 302.AI + +1. Gå til [302.AI-konsollen](https://302.ai/), opret en konto og generer en API-nøgle. + +2. Kør kommandoen `/connect` og søg efter **302.AI**. + + ```txt + /connect + ``` + +3. Indtast 302.AI API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model. + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +Sådan bruger du Amazon Bedrock med OpenCode: + +1. Gå til **modelkataloget** i Amazon Bedrock-konsollen og anmod om adgang til de modeller, du ønsker. + + :::tip + Du skal have adgang til modellen du ønsker i Amazon Bedrock. + ::: + +2. **Konfigurer godkendelse** ved at bruge en af følgende metoder: + + #### Miljøvariabler (hurtigstart) + + Angiv en af disse miljøvariabler, mens du kører opencode: + + ```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode + ``` + + Eller tilføj dem til din bash-profil: + + ```bash title="~/.bash_profile" + export AWS_PROFILE=my-dev-profile + export AWS_REGION=us-east-1 + ``` + + #### Konfigurationsfil (anbefalet) + + For projektspecifik eller vedvarende konfiguration, brug `opencode.json`: + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile" + } + } + } + } + ``` + + **Tilgængelige muligheder:** + - `region` - AWS region (f.eks. `us-east-1`, `eu-west-1`) + - `profile` - AWS navngivet profil fra `~/.aws/credentials` + - `endpoint` - Brugerdefineret endpoint URL for VPC endpoints (alias for generisk `baseURL`-mulighed) + + :::tip + Konfigurationsfil-muligheder har forrang over miljøvariabler. + ::: + + #### Avanceret: VPC Endpoints + + Hvis du bruger VPC endpoints for Bedrock: + + ```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 + Muligheden `endpoint` er et alias for den generiske mulighed `baseURL`, der bruger AWS-specifik terminologi. Hvis både `endpoint` og `baseURL` er specificeret, har `endpoint` forrang. + ::: + + #### Godkendelsesmetoder + - **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: Opret en IAM-bruger og generer adgangsnøgler i AWS-konsollen + - **`AWS_PROFILE`**: Brug navngivne profiler fra `~/.aws/credentials`. Konfigurer først med `aws configure --profile my-profile` eller `aws sso login` + - **`AWS_BEARER_TOKEN_BEDROCK`**: Generer langsigtede API-nøgler fra Amazon Bedrock-konsollen + - **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: For EKS IRSA (IAM roller for tjenestekonti) eller andre Kubernetes-miljøer med OIDC føderation. Disse miljøvariabler injiceres automatisk af Kubernetes, når du bruger tjenestekontokommentarer. + + #### Godkendelsesprioritet + + Amazon Bedrock bruger følgende godkendelsesprioritet: + 1. **Bearer Token** - `AWS_BEARER_TOKEN_BEDROCK` miljøvariabel eller token fra kommandoen `/connect` + 2. **AWS legitimationskæde** - profil, adgangsnøgler, delte legitimationsoplysninger, IAM roller, webidentitetstokens (EKS IRSA), instansmetadata + + :::note + Når et bearer token er angivet (via `/connect` eller `AWS_BEARER_TOKEN_BEDROCK`), har det forrang over alle AWS godkendelsesmetoder inklusiv konfigurerede profiler. + ::: + +3. Kør kommandoen `/models` for at vælge den model, du ønsker. + + ```txt + /models + ``` + +:::note +For brugerdefinerede inferensprofiler, brug modellen og udbydernavnet i nøglen og sæt egenskaben `id` til arn. Dette sikrer korrekt caching: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. Når du har registreret dig, kør kommandoen `/connect` og vælg Anthropic. + + ```txt + /connect + ``` + +2. Her kan du vælge muligheden **Claude Pro/Max**, og det vil åbne din browser og bede dig om at godkende. + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. Nu skal alle de Anthropiske modeller være tilgængelige, når du bruger kommandoen `/models`. + + ```txt + /models + ``` + +:::info +At bruge dit Claude Pro/Max-abonnement i OpenCode understøttes ikke officielt af [Anthropic](https://anthropic.com). +::: + +##### Brug API-nøgler + +Du kan også vælge **Create an API Key**, hvis du ikke har et Pro/Max-abonnement. Det åbner også din browser og beder dig logge på Anthropic og giver dig en kode, du kan indsætte i din terminal. + +Eller hvis du allerede har en API-nøgle, kan du vælge **Manually enter API Key** og indsætte den i terminalen. + +--- + +### Azure OpenAI + +:::note +Hvis du støder på "Beklager, men jeg kan ikke hjælpe med den anmodning"-fejl, kan du prøve at ændre indholdsfilteret fra **DefaultV2** til **Default** i Azure-ressourcen. +::: + +1. Gå til [Azure-portalen](https://portal.azure.com/) og opret en **Azure OpenAI**-ressource. Du skal bruge: + - **Ressourcenavn**: Dette bliver en del af API-endpointet (`https://RESOURCE_NAME.openai.azure.com/`) + - **API-nøgle**: Enten `KEY 1` eller `KEY 2` fra din ressource + +2. Gå til [Azure AI Foundry](https://ai.azure.com/) og distribuer en model. + + :::note + Distributionsnavnet skal matche modelnavnet for at opencode skal fungere korrekt. + ::: + +3. Kør kommandoen `/connect` og søg efter **Azure**. + + ```txt + /connect + ``` + +4. Indtast API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Angiv dit ressourcenavn som en miljøvariabel: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + Eller tilføj den til din bash-profil: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. Kør kommandoen `/models` for at vælge den distribuerede model. + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. Gå til [Azure-portalen](https://portal.azure.com/) og opret en **Azure OpenAI**-ressource. Du skal bruge: + - **Ressourcenavn**: Dette bliver en del af API-endpointet (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) + - **API-nøgle**: Enten `KEY 1` eller `KEY 2` fra din ressource + +2. Gå til [Azure AI Foundry](https://ai.azure.com/) og distribuer en model. + + :::note + Distributionsnavnet skal matche modelnavnet for at opencode skal fungere korrekt. + ::: + +3. Kør kommandoen `/connect` og søg efter **Azure Cognitive Services**. + + ```txt + /connect + ``` + +4. Indtast API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Angiv dit ressourcenavn som en miljøvariabel: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + Eller tilføj den til din bash-profil: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. Kør kommandoen `/models` for at vælge den distribuerede model. + + ```txt + /models + ``` + +--- + +### Baseten + +1. Gå til [Baseten](https://app.baseten.co/), opret en konto og generer en API-nøgle. + +2. Kør kommandoen `/connect` og søg efter **Baseten**. + + ```txt + /connect + ``` + +3. Indtast din Baseten API-nøgle. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model. + + ```txt + /models + ``` + +--- + +### Cerebras + +1. Gå til [Cerebras-konsollen](https://inference.cerebras.ai/), opret en konto og generer en API-nøgle. + +2. Kør kommandoen `/connect` og søg efter **Cerebras**. + + ```txt + /connect + ``` + +3. Indtast Cerebras API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model som _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +Cloudflare AI Gateway lader dig få adgang til modeller fra OpenAI, Anthropic, Workers AI og flere gennem et samlet endpoint. Med [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) behøver du ikke separate API-nøgler for hver udbyder. + +1. Gå til [Cloudflare-dashboardet](https://dash.cloudflare.com/), naviger til **AI** > **AI Gateway**, og opret en ny gateway. + +2. Angiv konto-ID og gateway-ID som miljøvariabler. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. Kør kommandoen `/connect` og søg efter **Cloudflare AI Gateway**. + + ```txt + /connect + ``` + +4. Indtast din Cloudflare API-token. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + Eller angiv den som en miljøvariabel. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. Kør kommandoen `/models` for at vælge en model. + + ```txt + /models + ``` + + Du kan også tilføje modeller gennem opencode-konfigurationen. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +### Cortecs + +1. Gå til [Cortecs-konsollen](https://cortecs.ai/), opret en konto og generer en API-nøgle. + +2. Kør kommandoen `/connect` og søg efter **Cortecs**. + + ```txt + /connect + ``` + +3. Indtast Cortecs API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model som _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. Gå til [DeepSeek-konsollen](https://platform.deepseek.com/), opret en konto og klik på **Create API Key**. + +2. Kør kommandoen `/connect` og søg efter **DeepSeek**. + + ```txt + /connect + ``` + +3. Indtast DeepSeek API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en DeepSeek-model som _DeepSeek Reasoner_. + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. Gå til [Deep Infra-dashboardet](https://deepinfra.com/dash), opret en konto og generer en API-nøgle. + +2. Kør kommandoen `/connect` og søg efter **Deep Infra**. + + ```txt + /connect + ``` + +3. Indtast Deep Infra API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model. + + ```txt + /models + ``` + +--- + +### Firmware + +1. Gå til [Firmware dashboard](https://app.firmware.ai/signup), opret en konto og generer en API-nøgle. + +2. Kør kommandoen `/connect` og søg efter **Firmware**. + + ```txt + /connect + ``` + +3. Indtast firmware API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model. + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. Gå til [Fireworks AI-konsollen](https://app.fireworks.ai/), opret en konto og klik på **Create API Key**. + +2. Kør kommandoen `/connect` og søg efter **Fireworks AI**. + + ```txt + /connect + ``` + +3. Indtast Fireworks AI API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model som _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo giver AI-drevet agentchat med native værktøjskaldsfunktioner gennem GitLabs anthropiske proxy. + +1. Kør kommandoen `/connect` og vælg GitLab. + + ```txt + /connect + ``` + +2. Vælg din godkendelsesmetode: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ + ``` + + #### Brug OAuth (anbefalet) + + Vælg **OAuth** og din browser åbner for autorisation. + + #### Brug personlig adgangstoken + 1. Gå til [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens) + 2. Klik på **Add new token** + 3. Navn: `OpenCode`, omfang: `api` + 4. Kopier tokenet (starter med `glpat-`) + 5. Indtast den i terminalen + +3. Kør kommandoen `/models` for at se tilgængelige modeller. + + ```txt + /models + ``` + + Tre Claude-baserede modeller er tilgængelige: + - **duo-chat-haiku-4-5** (standard) - Hurtige svar til hurtige opgaver + - **duo-chat-sonnet-4-5** - Balanceret ydeevne til de fleste arbejdsgange + - **duo-chat-opus-4-5** - Mest egnet til kompleks analyse + +:::note +Du kan også specificere 'GITLAB_TOKEN' miljøvariabel, hvis du ikke vil +gemme tokenet i opencode auth-lagring. +::: + +##### Selvhostet GitLab + +:::note[overholdelsesbemærkning] +OpenCode bruger en lille model til nogle AI-opgaver som at generere sessionstitlen. +Den er konfigureret til at bruge gpt-5-nano som standard, hostet af Zen. For at låse OpenCode +til kun at bruge din egen GitLab-hostede instans, tilføj følgende i din +`opencode.json` fil. Det anbefales også at deaktivere sessionsdeling. + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +For selvhostede GitLab-instanser: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +Hvis din instans kører en brugerdefineret AI-gateway: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +Eller tilføj til din bash-profil: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +Din GitLab-administrator skal aktivere følgende: + +1. [Duo Agent Platform](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) for brugeren, gruppen eller instansen +2. Funktionsflag (via Rails-konsollen): + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: + +##### OAuth for selvhostede instanser + +For at få Oauth til at fungere for din selvhostede instans, skal du oprette +en ny applikation (Indstillinger → Applikationer) med +callback URL `http://127.0.0.1:8080/callback` og følgende omfang: + +- api (Få adgang til API på dine vegne) +- read_user (Læs din personlige information) +- read_repository (tillader skrivebeskyttet adgang til depotet) + +Udsæt derefter applikations-ID som miljøvariabel: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +Mere dokumentation på [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth) hjemmesiden. + +##### Konfiguration + +Tilpas gennem `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### GitLab API-værktøjer (valgfrit, men stærkt anbefalet) + +For at få adgang til GitLab-værktøjer (merge requests, problemer, pipelines, CI/CD, etc.): + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +Denne plugin giver omfattende GitLab-repository-administrationsfunktioner, inklusiv MR-anmeldelser, problemsporing, pipeline-overvågning og mere. + +--- + +### GitHub Copilot + +Sådan bruger du GitHub Copilot-abonnementet med OpenCode: + +:::note +Nogle modeller kan kræve et [Pro+ +abonnement](https://github.com/features/copilot/plans) at bruge. + +Nogle modeller skal aktiveres manuelt i [GitHub Copilot-indstillingerne](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use). +::: + +1. Kør kommandoen `/connect` og søg efter GitHub Copilot. + + ```txt + /connect + ``` + +2. Naviger til [github.com/login/device](https://github.com/login/device) og indtast koden. + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + │ Waiting for authorization... + ``` + +3. Kør nu kommandoen `/models` for at vælge modellen du ønsker. + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +Sådan bruger du Google Vertex AI med OpenCode: + +1. Gå til **Model Garden** i Google Cloud Console og tjek + modeller tilgængelig i din region. + + :::note + Du skal have et Google Cloud-projekt med Vertex AI API aktiveret. + ::: + +2. Angiv de nødvendige miljøvariabler: + - `GOOGLE_CLOUD_PROJECT`: Dit Google Cloud-projekt ID + - `VERTEX_LOCATION` (valgfrit): Regionen for Vertex AI (standard til `global`) + - Godkendelse (vælg en): + - `GOOGLE_APPLICATION_CREDENTIALS`: Sti til tjenestekontoens JSON-nøglefil + - Godkend med gcloud CLI: `gcloud auth application-default login` + + Sæt dem mens du kører opencode. + + ```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode + ``` + + Eller tilføj dem til din bash-profil. + + ```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`-regionen forbedrer tilgængeligheden og reducerer fejl uden ekstra omkostninger. Brug regionale endpoints (f.eks. `us-central1`) for krav til dataophold. [Læs mere](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. Kør kommandoen `/models` for at vælge modellen du ønsker. + + ```txt + /models + ``` + +--- + +### Groq + +1. Gå til [Groq-konsollen](https://console.groq.com/), klik på **Create API Key**, og kopier nøglen. + +2. Kør kommandoen `/connect` og søg efter Groq. + + ```txt + /connect + ``` + +3. Indtast API-nøglen for udbyderen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge den du ønsker. + + ```txt + /models + ``` + +--- + +### Hugging Face + +[Hugging Face Inference Providers](https://huggingface.co/docs/inference-providers) giver adgang til åbne modeller som støttes af 17+ udbydere. + +1. Gå til [Hugging Face-indstillinger](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained) for at oprette et token med tilladelse til at kalde inferensudbydere. + +2. Kør kommandoen `/connect` og søg efter **Hugging Face**. + + ```txt + /connect + ``` + +3. Indtast dit Hugging Face-token. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model som _Kimi-K2-Instruct_ eller _GLM-4.6_. + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) er en LLM observerbarhedsplatform som giver logning, overvågning og analyser for dine AI-applikationer. Helicone AI Gateway ruter dine anmodninger til den rigtige udbyder automatisk baseret på modellen. + +1. Gå til [Helicone](https://helicone.ai), opret en konto og generer en API-nøgle fra dashboardet. + +2. Kør kommandoen `/connect` og søg efter **Helicone**. + + ```txt + /connect + ``` + +3. Indtast Helicone API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model. + + ```txt + /models + ``` + +For flere udbydere og avancerede funktioner som caching og hastighedsbegrænsning, tjek [Helicone-dokumentationen](https://docs.helicone.ai). + +#### Valgfrie konfigurationer + +I tilfælde af at du ser en funktion eller model fra Helicone som ikke konfigureres automatisk gennem opencode, kan du altid konfigurere den selv. + +Her er [Helicone's Model Directory](https://helicone.ai/models), du skal bruge denne for at hente ID'erne til de modeller du vil tilføje. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### Brugerdefinerede headers + +Helicone understøtter tilpassede headers for funktioner som caching, brugersporing og sessionsadministration. Læg dem til din udbyderkonfiguration ved at bruge `options.headers`: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### Sessionssporing + +Helicones [Sessions](https://docs.helicone.ai/features/sessions) funktion lader dig gruppe relaterede LLM anmodninger sammen. Brug [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) plugin for automatisk at logge hver OpenCode-samtale som en session i Helicone. + +```bash +npm install -g opencode-helicone-session +``` + +Tilføj den til din konfiguration. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +Programmatisk injicerer `Helicone-Session-Id` og `Helicone-Session-Name` headers i dine anmodninger. På Helicones Sessions-side vil du se hver OpenCode-samtale opført som en separat session. + +##### Almindelige Helicone-headers + +| Header | Beskrivelse | +| -------------------------- | ------------------------------------------------------------------------- | +| `Helicone-Cache-Enabled` | Aktiver respons-caching (`true`/`false`) | +| `Helicone-User-Id` | Spor beregninger efter bruger | +| `Helicone-Property-[Name]` | Tilføj egendefinerede egenskaber (f.eks. `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | Knyt anmodninger til prompt-versioner | + +Se [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory) for alle tilgængelige headers. + +--- + +### llama.cpp + +Du kan konfigurere opencode til at bruge lokale modeller gennem [llama.cpps](https://github.com/ggml-org/llama.cpp) llama-server-værktøj + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +I dette eksempel: + +- `llama.cpp` er den tilpassede udbyder ID. Dette kan være hvilken som helst streng du vil. +- `npm` specificerer pakken som skal bruges for denne udbyder. Her bruges `@ai-sdk/openai-compatible` for enhver OpenAI-kompatibel API. +- `name` er visningsnavnet for udbyderen i UI. +- `options.baseURL` er endpointet for den lokale server. +- `models` er et kort over model-ID'er til deres konfigurationer. Modelnavnet vil vises i modelvalglisten. + +--- + +### IO.NET + +IO.NET tilbyder 17 modeller optimeret for forskellige brugstilfælde: + +1. Gå til [IO.NET-konsollen](https://ai.io.net/), opret en konto og generer en API-nøgle. + +2. Kør kommandoen `/connect` og søg efter **IO.NET**. + + ```txt + /connect + ``` + +3. Indtast nøglen IO.NET API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model. + + ```txt + /models + ``` + +--- + +### LM Studio + +Du kan konfigurere opencode til at bruge lokale modeller gennem LM Studio. + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +I dette eksempel: + +- `lmstudio` er den tilpassede udbyder ID. Dette kan være hvilken som helst streng du vil. +- `npm` specificerer pakken som skal bruges for denne udbyder. Her bruges `@ai-sdk/openai-compatible` for enhver OpenAI-kompatibel API. +- `name` er visningsnavnet for udbyderen i UI. +- `options.baseURL` er endpointet for den lokale server. +- `models` er et kort over model-ID'er til deres konfigurationer. Modelnavnet vil vises i modelvalglisten. + +--- + +### Moonshot AI + +Sådan bruger du Kimi K2 fra Moonshot AI: + +1. Gå til [Moonshot AI-konsollen](https://platform.moonshot.ai/console), opret en konto og klik på **Create API Key**. + +2. Kør kommandoen `/connect` og søg efter **Moonshot AI**. + + ```txt + /connect + ``` + +3. Indtast Moonshot API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge _Kimi K2_. + + ```txt + /models + ``` + +--- + +### MiniMax + +1. Gå til [MiniMax API-konsollen](https://platform.minimax.io/login), opret en konto og generer en API-nøgle. + +2. Kør kommandoen `/connect` og søg efter **MiniMax**. + + ```txt + /connect + ``` + +3. Indtast MiniMax API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model som _M2.1_. + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. Gå til [Nebius Token Factory-konsollen](https://tokenfactory.nebius.com/), opret en konto og klik på **Add Key**. + +2. Kør kommandoen `/connect` og søg efter **Nebius Token Factory**. + + ```txt + /connect + ``` + +3. Indtast Nebius Token Factory API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model som _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Ollama + +Du kan konfigurere opencode til at bruge lokale modeller gennem Ollama. + +:::tip +Ollama kan automatisk konfigurere sig selv for OpenCode. Se [Ollama-integrationsdokumenterne](https://docs.ollama.com/integrations/opencode) for detaljer. +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +I dette eksempel: + +- `ollama` er den tilpassede udbyder ID. Dette kan være hvilken som helst streng du vil. +- `npm` specificerer pakken som skal bruges for denne udbyder. Her bruges `@ai-sdk/openai-compatible` for enhver OpenAI-kompatibel API. +- `name` er visningsnavnet for udbyderen i UI. +- `options.baseURL` er endpointet for den lokale server. +- `models` er et kort over model-ID'er til deres konfigurationer. Modelnavnet vil vises i modelvalglisten. + +:::tip +Hvis værktøjskald ikke fungerer, prøv at øge `num_ctx` i Ollama. Start omkring 16k - 32k. +::: + +--- + +### Ollama Cloud + +Sådan bruger du Ollama Cloud med OpenCode: + +1. Gå til [https://ollama.com/](https://ollama.com/) og log på eller opret en konto. + +2. Naviger til **Settings** > **Keys** og klik på **Add API Key** for at generere en ny API-nøgle. + +3. Kopier API-nøglen til brug i OpenCode. + +4. Kør kommandoen `/connect` og søg efter **Ollama Cloud**. + + ```txt + /connect + ``` + +5. Indtast din Ollama Cloud API-nøgle. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **Vigtigt**: Før du bruger skymodeller i OpenCode, skal du hente modelinformationen lokalt: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. Kør kommandoen `/models` for at vælge din Ollama Cloud-model. + + ```txt + /models + ``` + +--- + +### OpenAI + +Vi anbefaler at du registrerer dig for [ChatGPT Plus eller Pro](https://chatgpt.com/pricing). + +1. Når du har registreret dig, kør kommandoen `/connect` og vælg OpenAI. + + ```txt + /connect + ``` + +2. Her kan du vælge muligheden **ChatGPT Plus/Pro** og det åbner din browser + og beder dig om at godkende. + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. Nu skal alle OpenAI-modellerne være tilgængelige, når du bruger kommandoen `/models`. + + ```txt + /models + ``` + +##### Brug API-nøgler + +Hvis du allerede har en API-nøgle, kan du vælge **Manually enter API Key** og indsætte den i terminalen. + +--- + +### OpenCode Zen + +OpenCode Zen er en liste over testede og verificerede modeller leveret af OpenCode-teamet. [Læs mere](/docs/zen). + +1. Log på **OpenCode Zen** og klik på **Create API Key**. + +2. Kør kommandoen `/connect` og søg efter **OpenCode Zen**. + + ```txt + /connect + ``` + +3. Indtast OpenCode API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model som _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### OpenRouter + +1. Gå til [OpenRouter-dashboardet](https://openrouter.ai/settings/keys), klik på **Create API Key**, og kopier nøglen. + +2. Kør kommandoen `/connect` og søg efter OpenRouter. + + ```txt + /connect + ``` + +3. Indtast API-nøglen for udbyderen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Mange OpenRouter-modeller er forudindlæst som standard, kør kommandoen `/models` for at vælge den du ønsker. + + ```txt + /models + ``` + + Du kan også tilføje flere modeller gennem opencode-konfigurationen. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +5. Du kan også tilpasse dem gennem opencode-konfigurationen. Her er et eksempel på at specificere en udbyder + + ```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 giver adgang til 40+ modeller fra OpenAI, Anthropic, Google, Amazon, Meta, Mistral og AI21 gennem en samlet platform. + +1. Gå til din [SAP BTP Cockpit](https://account.hana.ondemand.com/), naviger til din SAP AI kerne-tjenesteinstans, og opret en tjenestenøgle. + + :::tip + Tjenestenøglen er et JSON-objekt som indeholder `clientid`, `clientsecret`, `url` og `serviceurls.AI_API_URL`. Du finder din AI-kerneinstans under **Services** > **Instances and Subscriptions** i BTP cockpittet. + ::: + +2. Kør kommandoen `/connect` og søg efter **SAP AI Core**. + + ```txt + /connect + ``` + +3. Indtast tjenestenøglen JSON. + + ```txt + ┌ Service key + │ + │ + └ enter + ``` + + Eller angiv miljøvariablen `AICORE_SERVICE_KEY`: + + ```bash + AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode + ``` + + Eller tilføj den til din bash-profil: + + ```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' + ``` + +4. Angiv eventuelt deployment-ID og ressourcegruppe: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + Disse indstillinger er valgfrie og bør konfigureres i henhold til SAP AI kerne-opsætningen. + ::: + +5. Kør kommandoen `/models` for at vælge fra 40+ tilgængelige modeller. + + ```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**. + +2. Kør kommandoen `/connect` og søg efter **OVHcloud AI Endpoints**. + + ```txt + /connect + ``` + +3. Indtast OVHcloud AI Endpoints API-nøgle. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model som _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Scaleway + +Sådan bruger du [Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/) med OpenCode: + +1. Gå til [Scaleway Console IAM indstillinger](https://console.scaleway.com/iam/api-keys) for at generere en ny API-nøgle. + +2. Kør kommandoen `/connect` og søg efter **Scaleway**. + + ```txt + /connect + ``` + +3. Indtast Scaleway API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model som _devstral-2-123b-instruct-2512_ eller _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Together AI + +1. Gå til [Together AI-konsollen](https://api.together.ai), opret en konto og klik på **Add Key**. + +2. Kør kommandoen `/connect` og søg efter **Together AI**. + + ```txt + /connect + ``` + +3. Indtast Together AI API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model som _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Venice AI + +1. Gå til [Venice AI-konsollen](https://venice.ai), opret en konto og generer en API-nøgle. + +2. Kør kommandoen `/connect` og søg efter **Venice AI**. + + ```txt + /connect + ``` + +3. Indtast Venice AI API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model som _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + +### Vercel AI Gateway + +Vercel AI Gateway lader dig få adgang til modeller fra OpenAI, Anthropic, Google, xAI og mere gennem et samlet endpoint. Modeller tilbydes til listepris uden påslag. + +1. Gå til [Vercel dashboard](https://vercel.com/), naviger til fanen **AI Gateway**, og klik på **API Keys** for at oprette en ny API-nøgle. + +2. Kør kommandoen `/connect` og søg efter **Vercel AI Gateway**. + + ```txt + /connect + ``` + +3. Indtast Vercel AI Gateway API-nøgle. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model. + + ```txt + /models + ``` + +Du kan også tilpasse modeller gennem opencode-konfigurationen. Her er et eksempel på specificering af udbyder-rutingsrækkefølge. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "vercel": { + "models": { + "anthropic/claude-sonnet-4": { + "options": { + "order": ["anthropic", "vertex"] + } + } + } + } + } +} +``` + +Nogle nyttige rutealternativer: + +| Alternativ | Beskrivelse | +| ------------------- | -------------------------------------------------------- | +| `order` | Providersekvens for at prøve | +| `only` | Begræns til specifikke udbydere | +| `zeroDataRetention` | Brug kun udbydere med nul retningslinjer for datalagring | + +--- + +### xAI + +1. Gå til [xAI-konsollen](https://console.x.ai/), opret en konto og generer en API-nøgle. + +2. Kør kommandoen `/connect` og søg efter **xAI**. + + ```txt + /connect + ``` + +3. Indtast xAI API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model som _Grok Beta_. + + ```txt + /models + ``` + +--- + +### Z.AI + +1. Gå til [Z.AI API-konsollen](https://z.ai/manage-apikey/apikey-list), opret en konto og klik på **Create new API Key**. + +2. Kør kommandoen `/connect` og søg efter **Z.AI**. + + ```txt + /connect + ``` + + Hvis du abonnerer på **GLM Coding Plan**, vælg **Z.AI Coding Plan**. + +3. Indtast Z.AI API-nøglen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge en model som _GLM-4.7_. + + ```txt + /models + ``` + +--- + +### ZenMux + +1. Gå til [ZenMux-dashboardet](https://zenmux.ai/settings/keys), klik på **Create API Key**, og kopier nøglen. + +2. Kør kommandoen `/connect` og søg efter ZenMux. + + ```txt + /connect + ``` + +3. Indtast API-nøglen for udbyderen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Mange ZenMux-modeller er forudindlæst som standard, kør kommandoen `/models` for at vælge den du ønsker. + + ```txt + /models + ``` + + Du kan også tilføje flere modeller gennem opencode-konfigurationen. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "zenmux": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +--- + +## Brugerdefineret udbyder + +Sådan tilføjer du en **OpenAI-kompatibel** udbyder som ikke er opført i `/connect`-kommandoen: + +:::tip +Du kan bruge hvilken som helst OpenAI-kompatibel udbyder med opencode. De fleste moderne AI-udbydere tilbyder OpenAI-kompatible API'er. +::: + +1. Kør kommandoen `/connect` og rul ned til **Other**. + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. Indtast et unikt ID for udbyderen. + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::note + Vælg et mindeværdigt ID, du vil bruge dette i din konfigurationsfil. + ::: + +3. Indtast API-nøglen for udbyderen. + + ```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. Opret eller opdater `opencode.json`-filen i projektkataloget: + + ```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" + } + } + } + } + } + ``` + + Her er konfigurationsmulighederne: + - **npm**: AI SDK pakke at bruge, `@ai-sdk/openai-compatible` for OpenAI-kompatible udbydere + - **name**: Visningsnavn i UI. + - **models**: Tilgængelige modeller. + - **options.baseURL**: API endpoint URL. + - **options.apiKey**: Angiv API-nøglen hvis du ikke bruger auth. + - **options.headers**: Angiv egendefinerede headers. + + Mere om de avancerede muligheder i eksemplet nedenfor. + +5. Kør kommandoen `/models` og din egendefinerede udbyder og modeller vil vises i udvalgslisten. + +--- + +##### Eksempel + +Her er et eksempel på indstilling af mulighederne `apiKey`, `headers` og model `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 + } + } + } + } + } +} +``` + +Konfigurationsdetaljer: + +- **apiKey**: Angiv med `env` variabel syntaks, [læs mere](/docs/config#env-vars). +- **headers**: Egendefinerede headers sendt med hver anmodning. +- **limit.context**: Maksimalt input-tokens som modellen accepterer. +- **limit.output**: Maksimalt antal tokens modellen kan generere. + +`limit`-felterne lader OpenCode forstå hvor meget kontekst du har tilbage. Standardudbydere henter disse automatisk fra models.dev. + +--- + +## Fejlfinding + +Hvis du har problemer med at konfigurere en udbyder, tjek følgende: + +1. **Tjek godkendelsesopsætningen**: Kør `opencode auth list` for at se om legitimationsoplysningerne + for udbyderen er tilføjet til din konfiguration. + + Dette gælder ikke udbydere som Amazon Bedrock, som er afhængige af miljøvariabler for godkendelse. + +2. For tilpassede udbydere, tjek opencode-konfigurationen og: + - Sørg for at udbyderens ID som bruges i `/connect`-kommandoen matcher ID i opencode-konfigurationen. + - Den rigtige npm-pakke bruges for udbyderen. Brug for eksempel `@ai-sdk/cerebras` for Cerebras. Og for alle andre OpenAI-kompatible udbydere, brug `@ai-sdk/openai-compatible`. + - Kontroller at korrekt API-endpoint er brugt i `options.baseURL`-feltet. diff --git a/packages/web/src/content/docs/da/rules.mdx b/packages/web/src/content/docs/da/rules.mdx new file mode 100644 index 00000000000..8c7ccac9e8a --- /dev/null +++ b/packages/web/src/content/docs/da/rules.mdx @@ -0,0 +1,180 @@ +--- +title: Regler +description: Angiv tilpassede instruktioner til opencode. +--- + +Du kan gi tilpassede instruksjoner for at OpenCode ved at oprete en `AGENTS.md`-fil. Dette ligner på Cursors regler. Den inneholder instruksjoner som vil bli inkludert i LLMs kontekst for at tilpasse oppførselen til ditt spesifikke prosjekt. + +--- + +## Initialisering + +For at lage en ny `AGENTS.md` fil, kan du kjøre kommandoen `/init` i opencode. + +:::tip +Du bør overgi prosjektets `AGENTS.md`-fil til Git. +::: + +Dette vil skanne prosjektet og alt dets innhold for at forstå hva prosjektet handler om og generere en `AGENTS.md`-fil med det. Dette hjelper opencode at navigere i prosjektet bedre. + +Hvis du har en eksisterende `AGENTS.md`-fil, vil denne prøve at tilføje til den. + +--- + +## Eksempel + +Du kan også bare lage denne filen manuelt. Her er et eksempel på nogle ting du kan tilføje inn i en `AGENTS.md`-fil. + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +Vi tilføjer til prosjektspesifikke instruksjoner her, og dette vil bli delt på tvers av teamet ditt. + +--- + +## Typer + +opencode støtter også lesing av `AGENTS.md`-filen fra flere steder. Og dette tjener forskjellige formål. + +### Projekt + +Plasser en `AGENTS.md` i prosjektroten for prosjektspesifikke regler. Disse gjelder kun når du arbeider i denne katalogen eller dens underkataloger. + +### Globalt + +Du kan også ha globale regler i en `~/.config/opencode/AGENTS.md`-fil. Dette blir brugt på alle opencode-sessioner. + +Siden dette ikke er forpliktet til Git eller delt med teamet ditt, anbefaler vi at bruge dette til at spesifisere eventuelle personlige regler som LLM bør følge. + +### Claude Code-kompatibilitet + +For brugere som migrerer fra Claude Code, støtter OpenCode Claude Codes filkonvensjoner som fallbacks: + +- **Prosjektregler**: `CLAUDE.md` i prosjektkatalogen din (bruges hvis ingen `AGENTS.md` eksisterer) +- **Globale regler**: `~/.claude/CLAUDE.md` (bruges hvis ingen `~/.config/opencode/AGENTS.md` eksisterer) +- **Skills**: `~/.claude/skills/` — se [Agent Skills](/docs/skills/) for detaljer + +For at deaktivere Claude Code-kompatibilitet, sett en av disse miljøvariablene: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## Prioritet + +Når opencode starter, ser den etter regelfiler i denne rekkefølgen: + +1. **Lokale filer** ved at gå opp fra nuværende katalog (`AGENTS.md`, `CLAUDE.md`) +2. **Global fil** på `~/.config/opencode/AGENTS.md` +3. **Claude Code-fil** på `~/.claude/CLAUDE.md` (med mindre de er deaktivert) + +Den første matchende filen vinner i hver kategori. For eksempel, hvis du har både `AGENTS.md` og `CLAUDE.md`, bruges bare `AGENTS.md`. På samme måte har `~/.config/opencode/AGENTS.md` forrang over `~/.claude/CLAUDE.md`. + +--- + +## Brugerdefinerede instruktioner + +Du kan spesifisere egendefinerte instruksjonsfiler i din `opencode.json` eller den globale `~/.config/opencode/opencode.json`. Dette lar deg og teamet ditt gjenbruge eksisterende regler i stedet for at måtte duplisere dem til AGENTS.md. + +Eksempel: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Du kan også bruge eksterne URL-er for at laste instruksjoner fra nettet. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +Fjerninstruksjoner hentes med 5 sekunders tidsavbrudd. + +Alle instruksjonsfilene er kombinert med `AGENTS.md`-filene dine. + +--- + +## Reference til eksterne filer + +Selv om opencode ikke automatisk analyserer filreferanser i `AGENTS.md`, kan du oppnå lignende funksjonalitet på to måter: + +### Brug af opencode.json + +Den anbefalte tilnærmingen er at bruge feltet `instructions` i `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### Manuelle instruktioner i AGENTS.md + +Du kan lære opencode at lese eksterne filer ved at gi eksplisitte instruksjoner i `AGENTS.md`. Her er et praktisk eksempel: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +Denne tilnærmingen lar deg: + +- Lag modulære, gjenbrugbare regelfiler +- Del regler på tvers av prosjekter via symbolkoblinger eller git-undermoduler +- Hold AGENTS.md kortfattet mens du refererer til detaljerte retningslinjer +- Sørg for at opencode laster filer kun når det er nødvendig for den spesifikke oppgaven + +:::tip +For monorepos eller prosjekter med delte standarder er brug av `opencode.json` med glob-mønstre (som `packages/*/AGENTS.md`) mer vedlikeholdbart enn manuelle instruksjoner. +::: diff --git a/packages/web/src/content/docs/da/sdk.mdx b/packages/web/src/content/docs/da/sdk.mdx new file mode 100644 index 00000000000..3feff27b3b0 --- /dev/null +++ b/packages/web/src/content/docs/da/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: Typesikker JS-klient for åpen kodeserver. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +Åpenkoden JS/TS SDK gir en typesikker klient for samhandling med serveren. +Brug den til at bygge integrasjoner og kontrollere opencode programmatisk. + +[Finn ut mer](/docs/server) om hvordan serveren fungerer. For eksempler, tjek ut [prosjektene](/docs/ecosystem#projects) bygget av fellesskapet. + +--- + +## Installation + +Installer SDK fra npm: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## Opret klient + +Opret en forekomst av opencode: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +Dette starter både en server og en klient + +#### Indstillinger + +| Alternativ | Skriv | Beskrivelse | Standard | +| ---------- | ------------- | -------------------------------- | ----------- | +| `hostname` | `string` | Server vertsnavn | `127.0.0.1` | +| `port` | `number` | Serverport | `4096` | +| `signal` | `AbortSignal` | Avbryt signal for kansellering | `undefined` | +| `timeout` | `number` | Tidsavbrudd i ms for serverstart | `5000` | +| `config` | `Config` | Konfigurasjonsobjekt | `{}` | + +--- + +## Konfig + +Du kan sende et konfigurasjonsobjekt for at tilpasse virkemåten. Forekomsten henter fortsatt din `opencode.json`, men du kan overstyre eller tilføje til konfigurasjon inline: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## Kun klient + +Hvis du allerede har en kjørende forekomst av opencode, kan du oprete en klientforekomst for at koble til den: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### Indstillinger + +| Alternativ | Skriv inn | Beskrivelse | Standard | +| --------------- | ---------- | ---------------------------------- | ----------------------- | +| `baseUrl` | `string` | URL av serveren | `http://localhost:4096` | +| `fetch` | `function` | Egendefinert hentingimplementering | `globalThis.fetch` | +| `parseAs` | `string` | Svarparsingmetode | `auto` | +| `responseStyle` | `string` | Returstil: `data` eller `fields` | `fields` | +| `throwOnError` | `boolean` | Kast feil i stedet for retur | `false` | + +--- + +## Typer + +SDK inkluderer TypeScript-definisjoner for alle API-typer. Importer dem direkte: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +Alle typer er generert fra serverens OpenAPI-spesifikasjon og tilgængelig i types-filen. + +--- + +## Fejl + +SDK kan gi feil som du kan fange opp og håndtere: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## API'er + +SDK avslører alle server-APIer gjennom en typesikker klient. + +--- + +### Globalt + +| Metode | Beskrivelse | Svar | +| ----------------- | --------------------------- | ------------------------------------ | +| `global.health()` | Tjek serverhelse og versjon | `{ healthy: true, version: string }` | + +--- + +#### Eksempler + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### App + +| Metode | Beskrivelse | Svar | +| -------------- | ------------------------------- | ------------------------------------------- | +| `app.log()` | Skriv en loggoppføring | `boolean` | +| `app.agents()` | Liste alle tilgængelige agenter | Agent[] | + +--- + +#### Eksempler + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### Projekt + +| Metode | Beskrivelse | Svar | +| ------------------- | -------------------------- | ---------------------------------------------- | +| `project.list()` | Liste over alle prosjekter | Prosjekt[] | +| `project.current()` | Få nåværende prosjekt | Prosjekt | + +--- + +#### Eksempler + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### Sti + +| Metode | Beskrivelse | Svar | +| ------------ | ----------------- | ---------------------------------------- | +| `path.get()` | Få nuværende bane | Path | + +--- + +#### Eksempler + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### Konfiguration + +| Metode | Beskrivelse | Svar | +| -------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | Få konfigurasjonsinformasjon | Config | +| `config.providers()` | Liste leverandører og standardmodeller | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### Eksempler + +```javascript +const config = await client.config.get() + +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` | + +--- + +#### Eksempler + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### Filer + +| Metode | Beskrivelse | Svar | +| ------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------ | +| `find.text({ query })` | Søk etter tekst i filer | En rekke matchobjekter med `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `find.files({ query })` | Finn filer og kataloger etter navn | `string[]` (baner) | +| `find.symbols({ query })` | Finn arbeidsområdesymboler | Symbol[] | +| `file.read({ query })` | Les en fil | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | Få status for sporede filer | Fil[] | + +`find.files` støtter nogle få valgfrie søkefelt: + +- `type`: `"file"` eller `"directory"` +- `directory`: overstyr prosjektroten for søket +- `limit`: maksimalt antall resultater (1–200) + +--- + +#### Eksempler + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| Metode | Beskrivelse | Svar | +| ------------------------------ | ---------------------------- | --------- | +| `tui.appendPrompt({ body })` | Legg til tekst i ledeteksten | `boolean` | +| `tui.openHelp()` | Åpne hjelpedialogen | `boolean` | +| `tui.openSessions()` | Åpne sessionvelgeren | `boolean` | +| `tui.openThemes()` | Åpne temavelgeren | `boolean` | +| `tui.openModels()` | Åpne modellvelgeren | `boolean` | +| `tui.submitPrompt()` | Send inn nuværende ledetekst | `boolean` | +| `tui.clearPrompt()` | Fjern ledeteksten | `boolean` | +| `tui.executeCommand({ body })` | Utfør en kommando | `boolean` | +| `tui.showToast({ body })` | Vis toastvarsel | `boolean` | + +--- + +#### Eksempler + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### Godkendelse + +| Metode | Beskrivelse | Svar | +| ------------------- | ------------------------------- | --------- | +| `auth.set({ ... })` | Angi autentiseringslegitimasjon | `boolean` | + +--- + +#### Eksempler + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### Hændelser + +| Metode | Beskrivelse | Svar | +| ------------------- | ------------------------------ | ------------------------------ | +| `event.subscribe()` | Server-sendte hendelser stream | Server-sendte hendelser stream | + +--- + +#### Eksempler + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/da/server.mdx b/packages/web/src/content/docs/da/server.mdx new file mode 100644 index 00000000000..6eb74d946d8 --- /dev/null +++ b/packages/web/src/content/docs/da/server.mdx @@ -0,0 +1,287 @@ +--- +title: Server +description: Interager med opencode-serveren over HTTP. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +Kommandoen `opencode serve` kører en hovedløs HTTP-server, som afslører et OpenAPI-endpoint, som en opencode-klient kan bruge. + +--- + +### Brug + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### Indstillinger + +| Flag | Beskrivelse | Standard | +| --------------- | -------------------------------------------- | ---------------- | +| `--port` | Port at lytte på | `4096` | +| `--hostname` | Værtsnavn at lytte på | `127.0.0.1` | +| `--mdns` | Aktiver mDNS-opdagelse | `false` | +| `--mdns-domain` | Brugerdefineret domænenavn for mDNS-tjeneste | `opencode.local` | +| `--cors` | Yderligere browseroprindelse for at tillade | `[]` | + +`--cors` kan angives flere gange: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### Godkendelse + +Indstil `OPENCODE_SERVER_PASSWORD` for at beskytte serveren med HTTP grundlæggende godkendelse. Brugernavnet er som standard `opencode`, eller indstil `OPENCODE_SERVER_USERNAME` for at tilsidesætte det. Dette gælder både `opencode serve` og `opencode web`. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### Sådan fungerer det + +Når du kører `opencode` starter den en TUI og en server. Hvor TUI er +klient som taler med serveren. Serveren viser en OpenAPI 3.1-specifikation +endpoint. Dette endpoint bruges også til at generere en [SDK](/docs/sdk). + +:::tip +Brug opencode-serveren til at interagere med opencode programmatisk. +::: + +Denne arkitektur lader opencode understøtte flere klienter og lader dig interagere med opencode programmatisk. + +Du kan køre `opencode serve` for at starte en selvstændig server. Hvis du har +opencode TUI kørende, vil `opencode serve` starte en ny server. + +--- + +#### Opret forbindelse til en eksisterende server + +Når du starter TUI, tildeler den tilfældigt en port og et værtsnavn. Du kan i stedet sende `--hostname` og `--port` [flagene](/docs/cli). Brug derefter disse til at forbinde til serveren. + +[`/tui`](#tui) endpointet kan bruges til at køre TUI gennem serveren. Du kan for eksempel forududfylde eller køre en forespørgsel. Denne opsætning bruges af OpenCode [IDE](/docs/ide) plugins. + +--- + +## Specifikation + +Serveren publicerer en OpenAPI 3.1-specifikation som kan vises på: + +``` +http://:/doc +``` + +For eksempel `http://localhost:4096/doc`. Brug specifikationen til at generere klienter eller inspicere forespørgsels- og svartyper. Eller se den i en Swagger-utforsker. + +--- + +## API'er + +OpenCode-serveren viser følgende API'er. + +--- + +### Globalt + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ---------------- | -------------------------------- | ------------------------------------ | +| `GET` | `/global/health` | Få serverhelbred og version | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | Få globale hændelser (SSE strøm) | Eventstrøm | + +--- + +### Projekt + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------------------ | ------------------------- | --------------------------------------------- | +| `GET` | `/project` | Liste over alle projekter | Project[] | +| `GET` | `/project/current` | Få det nuværende projekt | Project | + +--- + +### Sti og VCS + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------- | --------------------------------- | ------------------------------------------- | +| `GET` | `/path` | Få nuværende sti | Path | +| `GET` | `/vcs` | Få VCS info for nuværende projekt | VcsInfo | + +--- + +### Instans + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------------------- | ------------------------ | --------- | +| `POST` | `/instance/dispose` | Kassér nuværende instans | `boolean` | + +--- + +### Konfiguration + +| Metode | Sti | Beskrivelse | Svar | +| ------- | ------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------- | +| `GET` | `/config` | Få konfigurationsinformation | Config | +| `PATCH` | `/config` | Opdater konfiguration | Config | +| `GET` | `/config/providers` | Liste udbydere og standardmodeller | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +### Udbyder + +| Metode | Sti | Beskrivelse | Svar | +| ------ | -------------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------- | +| `GET` | `/provider` | Liste alle udbydere | `{ all: `Provider[]`, default: {...}, connected: string[] }` | +| `GET` | `/provider/auth` | Få udbydergodkendelsesmetoder | `{ [providerID: string]: `ProviderAuthMethod[]` }` | +| `POST` | `/provider/{id}/oauth/authorize` | Autoriser en udbyder ved at bruge OAuth | ProviderAuthAuthorization | +| `POST` | `/provider/{id}/oauth/callback` | Håndter OAuth-callback for en udbyder | `boolean` | + +--- + +### Sessioner + +| Metode | Sti | Beskrivelse | Noter | +| -------- | ---------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------- | +| `GET` | `/session` | Liste alle sessioner | Returnerer Session[] | +| `POST` | `/session` | Opret en ny session | body: `{ parentID?, title? }`, returnerer Session | +| `GET` | `/session/status` | Få sessionstatus for alle sessioner | Returnerer `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | Få sessiondetaljer | Returnerer Session | +| `DELETE` | `/session/:id` | Slet en session og alle dens data | Returnerer `boolean` | +| `PATCH` | `/session/:id` | Opdater sessionegenskaber | body: `{ title? }`, returnerer Session | +| `GET` | `/session/:id/children` | Få en sessions undersessioner | Returnerer Session[] | +| `GET` | `/session/:id/todo` | Få to-do-listen for en session | Returnerer Todo[] | +| `POST` | `/session/:id/init` | Analyser appen og lav `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returnerer `boolean` | +| `POST` | `/session/:id/fork` | Fork en eksisterende session ved en besked | body: `{ messageID? }`, returnerer Session | +| `POST` | `/session/:id/abort` | Afbryd en kørende session | Returnerer `boolean` | +| `POST` | `/session/:id/share` | Del en session | Returnerer Session | +| `DELETE` | `/session/:id/share` | Stop med at dele en session | Returnerer Session | +| `GET` | `/session/:id/diff` | Få diff for denne session | query: `messageID?`, returnerer FileDiff[] | +| `POST` | `/session/:id/summarize` | Opsummér sessionen | body: `{ providerID, modelID }`, returnerer `boolean` | +| `POST` | `/session/:id/revert` | Tilbagestil en besked | body: `{ messageID, partID? }`, returnerer `boolean` | +| `POST` | `/session/:id/unrevert` | Gendan alle nulstillede beskeder | Returnerer `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | Svar på en tilladelsesforespørgsel | body: `{ response, remember? }`, returnerer `boolean` | + +--- + +### Beskeder + +| Metode | Sti | Beskrivelse | Noter | +| ------ | --------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `GET` | `/session/:id/message` | Liste beskeder i en session | query: `limit?`, returnerer `{ info: `Message`, parts: `Part[]`}[]` | +| `POST` | `/session/:id/message` | Send en besked og vent på svar | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, returnerer `{ info: `Message`, parts: `Part[]`}` | +| `GET` | `/session/:id/message/:messageID` | Få beskeddetaljer | Returnerer `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/prompt_async` | Send en besked asynkront (ingen vent) | body: samme som `/session/:id/message`, returnerer `204 No Content` | +| `POST` | `/session/:id/command` | Udfør en skråstregskommando | body: `{ messageID?, agent?, model?, command, arguments }`, returnerer `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/shell` | Kør en shell-kommando | body: `{ agent, model?, command }`, returnerer `{ info: `Message`, parts: `Part[]`}` | + +--- + +### Kommandoer + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ---------- | --------------------- | --------------------------------------------- | +| `GET` | `/command` | Liste alle kommandoer | Command[] | + +--- + +### Filer + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------------------------ | ------------------------------- | ------------------------------------------------------------------------------------------ | +| `GET` | `/find?pattern=` | Søg efter tekst i filer | En række matchobjekter med `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `GET` | `/find/file?query=` | Find filer og mapper efter navn | `string[]` (stier) | +| `GET` | `/find/symbol?query=` | Find arbejdsområdesymboler | Symbol[] | +| `GET` | `/file?path=` | Liste filer og mapper | FileNode[] | +| `GET` | `/file/content?path=

` | Læs en fil | FileContent | +| `GET` | `/file/status` | Få status for sporede filer | File[] | + +#### /find/file forespørgselsparametre + +- `query` (obligatorisk) - søgestreng (fuzzy match) +- `type` (valgfrit) - begræns resultaterne til `"file"` eller `"directory"` +- `directory` (valgfrit) — overstyr projektroden for søget +- `limit` (valgfrit) - maks. resultater (1–200) +- `dirs` (valgfrit) - ældre flag (`"false"` returnerer kun filer) + +--- + +### Værktøjer (eksperimentelt) + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------------------------------------------- | --------------------------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | Vis alle værktøjs-ID'er | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | Liste værktøjer med JSON-skemaer for en model | ToolList | + +--- + +### LSP, formattere og MCP + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------------ | -------------------------- | -------------------------------------------------------- | +| `GET` | `/lsp` | Få LSP serverstatus | LSPStatus[] | +| `GET` | `/formatter` | Få formateringsstatus | FormatterStatus[] | +| `GET` | `/mcp` | Få MCP serverstatus | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | Tilføj MCP server dynamisk | body: `{ name, config }`, returnerer MCP statusobjekt | + +--- + +### Agenter + +| Metode | Sti | Beskrivelse | Svar | +| ------ | -------- | ------------------------------- | ------------------------------------------- | +| `GET` | `/agent` | Liste alle tilgængelige agenter | Agent[] | + +--- + +### Logning + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------ | ---------------------------------------------------------- | --------- | +| `POST` | `/log` | Skriv logpost. Body: `{ service, level, message, extra? }` | `boolean` | + +--- + +### TUI + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ----------------------- | ------------------------------------------- | -------------------------- | +| `POST` | `/tui/append-prompt` | Tilføj tekst til prompten | `boolean` | +| `POST` | `/tui/open-help` | Åbn hjælp-dialogen | `boolean` | +| `POST` | `/tui/open-sessions` | Åbn sessionsvælgeren | `boolean` | +| `POST` | `/tui/open-themes` | Åbn temavælgeren | `boolean` | +| `POST` | `/tui/open-models` | Åbn modelvælgeren | `boolean` | +| `POST` | `/tui/submit-prompt` | Indsend nuværende prompt | `boolean` | +| `POST` | `/tui/clear-prompt` | Ryd prompten | `boolean` | +| `POST` | `/tui/execute-command` | Udfør en kommando (`{ command }`) | `boolean` | +| `POST` | `/tui/show-toast` | Vis toast (`{ title?, message, variant }`) | `boolean` | +| `GET` | `/tui/control/next` | Vent på næste kontrolforespørgsel | Kontrolforespørgselsobjekt | +| `POST` | `/tui/control/response` | Svar på en kontrolforespørgsel (`{ body }`) | `boolean` | + +--- + +### Godkendelse + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ----------- | ------------------------------------------------------------ | --------- | +| `PUT` | `/auth/:id` | Angiv godkendelsesoplysninger. Body skal matche udbyderskema | `boolean` | + +--- + +### Hændelser + +| Metode | Sti | Beskrivelse | Svar | +| ------ | -------- | ----------------------------------------------------------------------------------------- | --------------------------- | +| `GET` | `/event` | Server-sendt hændelsesstrøm. Første hændelse er `server.connected`, derefter bushændelser | Server-sendt hændelsesstrøm | + +--- + +### Dokumentation + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------ | ------------------------- | ----------------------------------- | +| `GET` | `/doc` | OpenAPI 3.1-specifikation | HTML side med OpenAPI-specifikation | diff --git a/packages/web/src/content/docs/da/share.mdx b/packages/web/src/content/docs/da/share.mdx new file mode 100644 index 00000000000..1ac2094ca70 --- /dev/null +++ b/packages/web/src/content/docs/da/share.mdx @@ -0,0 +1,128 @@ +--- +title: Deling +description: Del dine OpenCode-samtaler. +--- + +OpenCodes delingsfunksjon lar deg lage offentlige lenker til dine OpenCode-samtaler, slik at du kan samarbeide med lagkamerater eller få hjelp fra andre. + +:::note +Delte samtaler er offentlig tilgængelige for alle med linken. +::: + +--- + +## Sådan fungerer det + +Når du deler en samtale, OpenCode: + +1. Opreter en unik offentlig URL for sessionen din +2. Synkroniserer samtaleloggen din til serverne våre +3. Gør samtalen tilgængelig via den delbare lenken — `opncd.ai/s/` + +--- + +## Tilstande + +OpenCode støtter tre delingsmoduser som kontrollerer hvordan samtaler deles: + +--- + +### Manuel (standard) + +Som standard bruger OpenCode manuell delingsmodus. Sessioner deles ikke automatisk, men du kan dele dem manuelt ved at bruge kommandoen `/share`: + +``` +/share +``` + +Dette vil generere en unik URL som vil bli kopiert til utklippstavlen din. + +For at eksplisitt angi manuell modus i [konfigurasjonsfilen](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### Automatisk deling + +Du kan aktivere automatisk deling for alle nye samtaler ved at sette alternativet `share` til `"auto"` i [konfigurasjonsfilen](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +Med automatisk deling aktivert, vil hver nye samtale automatisk bli delt og en kobling vil bli generert. + +--- + +### Deaktiveret + +Du kan deaktivere deling helt ved at sette alternativet `share` til `"disabled"` i [konfigurasjonsfilen](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +For at håndheve dette på tvers av teamet ditt for et gitt prosjekt, tilføj det til `opencode.json` i prosjektet ditt og tjek inn i Git. + +--- + +## Ophæv deling + +Slik slutter du at dele en samtale og fjerner den fra offentlig tilgang: + +``` +/unshare +``` + +Dette vil fjerne delelinken og slette dataene knyttet til samtalen. + +--- + +## Privatliv + +Det er et par ting du må huske på når du deler en samtale. + +--- + +### Datalagring + +Delte samtaler forblir tilgængelige til du eksplisitt opphever deling av dem. Dette +inkluderer: + +- Full samtalehistorikk +- Alle meldinger og svar +- Metadata for sessioner + +--- + +### Anbefalinger + +- Del kun samtaler som ikke inneholder sensitiv informasjon. +- Se gjennom samtaleinnholdet før du deler. +- Opphev deling av samtaler når samarbeidet er fullført. +- Unngå at dele samtaler med proprietær kode eller konfidensielle data. +- For sensitive prosjekter, deaktiver deling helt. + +--- + +## For virksomheder + +For bedriftsimplementeringer kan delingsfunksjonen være: + +- **Deaktivert** helt for overholdelse av sikkerhet +- **Begrenset** til brugere som kun er autentisert gjennom SSO +- **Selvvert** på din egen infrastruktur + +[Finn ut mer](/docs/enterprise) om brug av opencode i organisasjonen din. diff --git a/packages/web/src/content/docs/da/skills.mdx b/packages/web/src/content/docs/da/skills.mdx new file mode 100644 index 00000000000..83badb3bf9a --- /dev/null +++ b/packages/web/src/content/docs/da/skills.mdx @@ -0,0 +1,222 @@ +--- +title: "Agentfærdigheder" +description: "Definer gjenbrugbar atferd via SKILL.md-definisjoner" +--- + +Agentferdigheter lar OpenCode oppdage gjenbrugbare instruksjoner fra repo- eller hjemmekatalogen din. +Ferdigheter lastes inn på forespørsel via det opprinnelige `skill`-verktøyet – agenter ser tilgængelige ferdigheter og kan laste inn hele innholdet når det er nødvendig. + +--- + +## Placer filer + +Opret én mappe per ferdighetsnavn og tilføj inn en `SKILL.md` i den. +OpenCode søker etter disse stedene: + +- Prosjektkonfigurasjon: `.opencode/skills//SKILL.md` +- Global konfigurasjon: `~/.config/opencode/skills//SKILL.md` +- Prosjekt Claude-kompatibel: `.claude/skills//SKILL.md` +- Global Claude-kompatibel: `~/.claude/skills//SKILL.md` +- Prosjektagent-kompatibel: `.agents/skills//SKILL.md` +- Global agent-kompatibel: `~/.agents/skills//SKILL.md` + +--- + +## Forstå opdagelsen + +For prosjektlokale stier går OpenCode opp fra din nåværende arbejdskatalog til den når git-arbeidstreet. +Den laster alle matchende `skills/*/SKILL.md` i `.opencode/` og alle matchende `.claude/skills/*/SKILL.md` eller `.agents/skills/*/SKILL.md` underveis. + +Globale definisjoner lastes også inn fra `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md` og `~/.agents/skills/*/SKILL.md`. + +--- + +## Skriv frontmatter + +Hver `SKILL.md` må starte med YAML frontmatter. +Bare disse feltene gjenkjennes: + +- `name` (påkrevd) +- `description` (påkrevd) +- `license` (valgfritt) +- `compatibility` (valgfritt) +- `metadata` (valgfritt, streng-til-streng kart) + +Ukjente frontmatter-felter ignoreres. + +--- + +## Bekræft navn + +`name` må: + +- Bestå av 1–64 tegn +- Vær alfanumerisk med små bokstaver med skilletegn med enkelt bindestrek +- Ikke begynne eller slutte med `-` +- Ikke inneholde påfølgende `--` +- Match katalognavnet som inneholder `SKILL.md` + +Ekvivalent regulært uttrykk: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## Følg længdereglerne + +`description` må bestå av 1-1024 tegn. +Hold det spesifikt nok til at agenten kan velge riktig. + +--- + +## Brug et eksempel + +Lag `.opencode/skills/git-release/SKILL.md` slik: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## Genkend værktøjsbeskrivelsen + +OpenCode viser tilgængelige ferdigheter i `skill` verktøybeskrivelsen. +Hver oppføring inneholder ferdighetsnavnet og beskrivelsen: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +Agenten laster inn en ferdighet ved at kalle verktøyet: + +``` +skill({ name: "git-release" }) +``` + +--- + +## Konfigurer tilladelser + +Kontroller hvilke ferdigheter agenter har tilgang til ved at bruge mønsterbaserte tillatelser i `opencode.json`: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| Tillatelse | Atferd | +| ---------- | ------------------------------------------ | +| `allow` | Ferdigheter lastes umiddelbart | +| `deny` | Ferdighet skjult for agent, tilgang avvist | +| `ask` | Bruger bedt om godkjenning før lasting | + +Mønstre støtter jokertegn: `internal-*` samsvarer med `internal-docs`, `internal-tools` osv. + +--- + +## Tilsidesættelse pr. agent + +Gi spesifikke agenter andre tillatelser enn de globale standardinnstillingene. + +**For egendefinerte agenter** (i agent frontmatter): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**For innebygde agenter** (i `opencode.json`): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## Deaktiver færdighedsværktøjet + +Deaktiver ferdigheter fullstendig for agenter som ikke bør bruge dem: + +**For egendefinerte agenter**: + +```yaml +--- +tools: + skill: false +--- +``` + +**For innebygde agenter**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +Når den er deaktivert, blir ``-delen utelatt helt. + +--- + +## Fejlfind indlæsning + +Hvis en ferdighet ikke vises: + +1. Kontroller at `SKILL.md` er stavet med store bokstaver +2. Tjek at frontmatter inkluderer `name` og `description` +3. Sørg for at ferdighetsnavnene er unike på alle steder +4. Tjek tillatelser – ferdigheter med `deny` er skjult for agenter diff --git a/packages/web/src/content/docs/da/themes.mdx b/packages/web/src/content/docs/da/themes.mdx new file mode 100644 index 00000000000..533bef30eb0 --- /dev/null +++ b/packages/web/src/content/docs/da/themes.mdx @@ -0,0 +1,369 @@ +--- +title: Temaer +description: Velg et innebygd tema eller definer ditt eget. +--- + +Med OpenCode kan du velge fra ett av flere innebygde temaer, bruge et tema som tilpasser seg terminaltemaet ditt, eller definere ditt eget tilpassede tema. + +Som standard bruger OpenCode vårt eget `opencode`-tema. + +--- + +## Terminalkrav + +For at temaer skal vises riktig med fullfarvepalett, må terminalen din støtte **truecolor** (24-biters farver). De fleste moderne terminaler støtter dette som standard, men du må kanskje aktivere det: + +- **Tjek støtte**: Kjør `echo $COLORTERM` - den skal gi ut `truecolor` eller `24bit` +- **Aktiver truecolor**: Sett miljøvariabelen `COLORTERM=truecolor` i shellprofilen din +- **Terminalkompatibilitet**: Sørg for at terminalemulatoren din støtter 24-bits farver (de fleste moderne terminaler som iTerm2, Alacritty, Kitty, Windows Terminal og nyere versioner av GNOME Terminal gør det) + +Uden truecolor-støtte kan temaer vises med redusert farvenøjagtighed eller falde tilbage til nærmeste 256-farvers tilnærming. + +--- + +## Indbyggede temaer + +OpenCode kommer med flere innebygde temaer. + +| Navn | Beskrivelse | +| ---------------------- | ------------------------------------------------------------------------- | +| `system` | Tilpasser seg terminalens bakgrunnsfarve | +| `tokyonight` | Basert på [Tokyonight](https://github.com/folke/tokyonight.nvim)-temaet | +| `everforest` | Basert på [Everforest](https://github.com/sainnhe/everforest)-temaet | +| `ayu` | Basert på [Ayu](https://github.com/ayu-theme) mørke tema | +| `catppuccin` | Basert på [Catppuccin](https://github.com/catppuccin)-temaet | +| `catppuccin-macchiato` | Basert på [Catppuccin](https://github.com/catppuccin)-temaet | +| `gruvbox` | Basert på [Gruvbox](https://github.com/morhetz/gruvbox)-temaet | +| `kanagawa` | Basert på [Kanagawa](https://github.com/rebelot/kanagawa.nvim)-temaet | +| `nord` | Basert på [Nord](https://github.com/nordtheme/nord)-temaet | +| `matrix` | Hacker-stil grønt på svart tema | +| `one-dark` | Basert på [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Mørkt tema | + +Og mer, vi tilføjer stadig til nye temaer. + +--- + +## Systemtema + +`system`-temaet er designet for at automatisk tilpasse seg terminalens farvevalg. I motsetning til tradisjonelle temaer som bruger faste farver, er _system_-temaet: + +- **Genererer gråskala**: Opreter en brugerdefineret gråskala basert på terminalens bakgrunnsfarve, og sikrer optimal kontrast. +- **Bruger ANSI farver**: Bruger standard ANSI farver (0-15) for syntaksutheving og UI elementer, som respekterer terminalens farvepalett. +- **Bevarer terminalens standardinnstillinger**: Bruger `none` for tekst- og bakgrunnsfarver for at opretholde terminalens opprinnelige utseende. + +Systemtemaet er for brugere som: + +- Vil at OpenCode skal matche terminalens utseende +- Brug tilpassede terminalfarveskjemaer +- Foretrekker et konsistent utseende på tvers av alle terminalapplikasjoner + +--- + +## 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). + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## Brugerdefinerede temaer + +OpenCode støtter et fleksibelt JSON-basert temasystem som lar brugere enkelt lage og tilpasse temaer. + +--- + +### Hierarki + +Temaer lastes inn fra flere kataloger i følgende rekkefølge der senere kataloger overstyrer tidligere: + +1. **Innebygde temaer** - Disse er innebygd i binæren +2. **Brugerkonfigurasjonskatalog** - Definert i `~/.config/opencode/themes/*.json` eller `$XDG_CONFIG_HOME/opencode/themes/*.json` +3. **Prosjektrotkatalog** - Definert i `/.opencode/themes/*.json` +4. **Nuværende arbejdskatalog** - Definert i `./.opencode/themes/*.json` + +Hvis flere kataloger inneholder et tema med samme navn, vil temaet fra katalogen med høyere prioritet bli brugt. + +--- + +### Oprettelse af et tema + +For at lage et brugerdefineret tema, lag en JSON-fil i en av temakatalogene. + +For brugeromfattende temaer: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +Og for prosjektspesifikke temaer. + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### JSON-format + +Temaer bruger et fleksibelt JSON-format med støtte for: + +- **Sekskantfarver**: `"#ffffff"` +- **ANSI farver**: `3` (0-255) +- **Farvereferanser**: `"primary"` eller egendefinerte definisjoner +- **Mørke/lyse varianter**: `{"dark": "#000", "light": "#fff"}` +- **Ingen farve**: `"none"` - Bruger terminalens standardfarve eller transparent + +--- + +### Farvedefinitioner + +`defs`-delen er valgfri, og den lar deg definere gjenbrugbare farver som kan refereres til i temaet. + +--- + +### Terminalstandarder + +Spesialverdien `"none"` kan bruges for hvilken som helst farve for at arve terminalens standardfarve. Dette er spesielt nyttig for at lage temaer som passer sømløst med terminalens farveskjema: + +- `"text": "none"` - Bruger terminalens standard forgrunnsfarve +- `"background": "none"` - Bruger terminalens standard bakgrunnsfarve + +--- + +### Eksempel + +Her er et eksempel på et brugerdefineret tema: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/da/tools.mdx b/packages/web/src/content/docs/da/tools.mdx new file mode 100644 index 00000000000..2b8b20b15c5 --- /dev/null +++ b/packages/web/src/content/docs/da/tools.mdx @@ -0,0 +1,379 @@ +--- +title: Værktøjer +description: Administrer de værktøjer, en LLM kan bruge. +--- + +Verktøy lar LLM utføre handlinger i kodebasen din. OpenCode kommer med et sett med innebygde verktøy, men du kan utvide det med [egendefinerte verktøy](/docs/custom-tools) eller [MCP servere](/docs/mcp-servers). + +Som standard er alle verktøy **aktivert** og trenger ikke tillatelse for at kjøre. Du kan kontrollere verktøyets oppførsel gjennom [tillatelser](/docs/permissions). + +--- + +## Konfiguration + +Brug feltet `permission` for at kontrollere verktøyets oppførsel. Du kan tillate, avslå eller kreve godkjenning for hvert verktøy. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +Du kan også bruge jokertegn for at kontrollere flere verktøy samtidig. For eksempel, for at kreve godkjenning for alle verktøy fra en MCP-server: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[Finn ut mer](/docs/permissions) om konfigurering av tillatelser. + +--- + +## Indbyggede + +Her er alle de innebygde verktøyene som er tilgængelige i OpenCode. + +--- + +### bash + +Utfør shellkommandoer i prosjektmiljøet ditt. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +Dette verktøyet lar LLM kjøre terminalkommandoer som `npm install`, `git status` eller en hvilken som helst annen shell-kommando. + +--- + +### edit + +Endre eksisterende filer ved at bruge eksakte strengerstatninger. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Dette verktøyet utfører nøyaktige redigeringer av filer ved at erstatte eksakte teksttreff. Det er den primære måten LLM endrer kode på. + +--- + +### write + +Opret nye filer eller overskriv eksisterende. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Brug denne for at la LLM lage nye filer. Den vil overskrive eksisterende filer hvis de allerede eksisterer. + +:::note +`write`-verktøyet kontrolleres av tillatelsen `edit`, som dekker alle filendringer (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### read + +Les filinnholdet fra kodebasen din. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +Dette verktøyet leser filer og returnerer innholdet. Den støtter lesing av spesifikke linjeområder for store filer. + +--- + +### grep + +Søk i filinnhold ved hjelp av regulære uttrykk. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +Rask innholdssøk på tvers av kodebasen din. Støtter full regex-syntaks og filmønsterfiltrering. + +--- + +### glob + +Finn filer etter mønstermatching. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +Søk etter filer ved at bruge glob-mønstre som `**/*.js` eller `src/**/*.ts`. Returnerer samsvarende filbaner sortert etter endringstid. + +--- + +### list + +List filer og kataloger i en gitt bane. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +Dette verktøyet viser kataloginnhold. Den aksepterer glob-mønstre for at filtrere resultater. + +--- + +### lsp (experimental) + +Samhandle med dine konfigurerte LSP-servere for at få kodeintelligensfunksjoner som definisjoner, referanser, sveveinformasjon og anropshierarki. + +:::note +Dette verktøyet er bare tilgængelig når `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (eller `OPENCODE_EXPERIMENTAL=true`). +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +Støttede operasjoner inkluderer `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls` og `outgoingCalls`. + +For at konfigurere hvilke LSP-servere som er tilgængelige for prosjektet ditt, se [LSP-servere](/docs/lsp). + +--- + +### patch + +Brug patcher på filer. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Dette verktøyet bruger opdateringsfiler til kodebasen din. Nyttig for at påføre diff og lapper fra forskjellige kilder. + +:::note +`patch`-verktøyet kontrolleres av tillatelsen `edit`, som dekker alle filendringer (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### skill + +Last inn en [ferdighet](/docs/skills) (en `SKILL.md` fil) og returner innholdet i samtalen. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +Administrer to-doslister under kodingssessioner. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +Opreter og opdaterer oppgavelister for at spore fremdrift under komplekse operasjoner. LLM bruger dette til at organisere flertrinnsoppgaver. + +:::note +Dette verktøyet er deaktivert for subagenter som standard, men du kan aktivere det manuelt. [Finn ut mer](/docs/agents/#permissions) +::: + +--- + +### todoread + +Les eksisterende to-doslister. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +Leser nuværende to-doslistestatus. Bruges av LLM for at spore hvilke oppgaver som venter eller er fullført. + +:::note +Dette verktøyet er deaktivert for subagenter som standard, men du kan aktivere det manuelt. [Finn ut mer](/docs/agents/#permissions) +::: + +--- + +### webfetch + +Hent nettinnhold. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +Lar LLM hente og lese nettsider. Nyttig for at slå opp dokumentasjon eller forske på nettressurser. + +--- + +### websearch + +Søk på nettet for informasjon. + +:::note +Dette verktøyet er bare tilgængelig når du bruger OpenCode-leverandøren eller når miljøvariabelen `OPENCODE_ENABLE_EXA` er satt til en sannverdi (f.eks. `true` eller `1`). + +Slik aktiverer du når du starter OpenCode: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +Utfører nettsøk med Exa AI for at finne relevant informasjon på nettet. Nyttig for at undersøke emner, finne aktuelle hendelser eller samle informasjon utover treningsdataavbruddet. + +Ingen API-nøgle kreves — verktøyet kobles direkte til Exa AIs vertsbaserte MCP-tjeneste uten autentisering. + +:::tip +Brug `websearch` når du trenger at finne informasjon (oppdagelse), og `webfetch` når du trenger at hente innhold fra en bestemt URL (henting). +::: + +--- + +### question + +Still brugeren spørsmål under utførelse. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +Dette verktøyet lar LLM stille spørsmål til brugeren under en oppgave. Det er nyttig for: + +- Samle brugerpreferanser eller krav +- Avklarende tvetydige instruksjoner +- Få beslutninger om gjennomføringsvalg +- Tilbyr valg om hvilken retning du skal ta + +Hvert spørsmål inkluderer en overskrift, spørsmålsteksten og en liste over alternativer. Brugere kan velge fra de angitte alternativene eller skrive inn et brugerdefineret svar. Når det er flere spørsmål, kan brugerne navigere mellom dem før de sender inn alle svarene. + +--- + +## Brugerdefinerede værktøjer + +Egendefinerte verktøy lar deg definere dine egne funksjoner som LLM kan kalle. Disse er definert i konfigurasjonsfilen din og kan kjøre vilkårlig kode. + +[Finn ut mer](/docs/custom-tools) om at lage tilpassede verktøy. + +--- + +## MCP-servere + +MCP (Model Context Protocol) servere lar deg integrere eksterne verktøy og tjenester. Dette inkluderer databasetilgang, API-integrasjoner og tredjepartstjenester. + +[Les mer](/docs/mcp-servers) om konfigurering av MCP-servere. + +--- + +## Interne + +Internt bruger verktøy som `grep`, `glob` og `list` [ripgrep](https://github.com/BurntSushi/ripgrep) under panseret. Som standard respekterer ripgrep `.gitignore`-mønstre, noe som betyr at filer og kataloger som er oppført i `.gitignore` vil bli ekskludert fra søk og lister. + +--- + +### Ignoreringsmønstre + +For at inkludere filer som normalt vil bli ignorert, lag en `.ignore`-fil i prosjektroten. Denne filen kan eksplisitt tillate visse stier. + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +For eksempel lar denne `.ignore` filen ripgrep søke i `node_modules/`, `dist/` og `build/` kataloger selv om de er oppført i `.gitignore`. diff --git a/packages/web/src/content/docs/da/troubleshooting.mdx b/packages/web/src/content/docs/da/troubleshooting.mdx new file mode 100644 index 00000000000..475c81f9f09 --- /dev/null +++ b/packages/web/src/content/docs/da/troubleshooting.mdx @@ -0,0 +1,300 @@ +--- +title: Fejlfinding +description: Almindelige problemer, og hvordan de løses. +--- + +For at fejlfinde problemer med OpenCode, start med at tjekke logfilerne og de lokale data, den gemmer på disken. + +--- + +## Logfiler + +Logfiler skrives til: + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: Tryk `WIN+R` og indsæt `%USERPROFILE%\.local\share\opencode\log` + +Logfiler navngives med tidsstempler (f.eks. `2025-01-09T123456.log`) og de sidste 10 logfiler beholdes. + +Du kan angive logniveauet med kommandolinjeflaget `--log-level` for at få mere detaljeret fejlfindingsinformation. For eksempel `opencode --log-level DEBUG`. + +--- + +## Lagring + +opencode gemmer sessionsdata og andre applikationsdata på disken på: + +- **macOS/Linux**: `~/.local/share/opencode/` +- **Windows**: Tryk `WIN+R` og indsæt `%USERPROFILE%\.local\share\opencode` + +Denne mappe indeholder: + +- `auth.json` - Godkendelsesdata som API-nøgler, OAuth-tokens +- `log/` - Applikationslogs +- `project/` - Projektspecifikke data som sessions- og beskeddata + - Hvis projektet er inden for et Git-repo, gemmes det i `.//storage/` + - Hvis det ikke er et Git-repo, gemmes det i `./global/storage/` + +--- + +## Desktop-app + +OpenCode Desktop kører en lokal OpenCode-server (`opencode-cli` sidevognen) i baggrunden. De fleste problemer er forårsaget af et plugin, der fungerer dårligt, en ødelagt cache eller en dårlig serverindstilling. + +### Hurtige tjek + +- Afslut og start appen på ny. +- Hvis appen viser en fejlskærm, klikker du på **Start på ny** og kopierer fejldetaljerne. +- Kun macOS: `OpenCode`-menu -> **Genindlæs webvisning** (hjælper hvis UI er tom/frosset). + +--- + +### Deaktiver plugins + +Hvis skrivebordsappen går ned ved opstart, hænger eller opfører sig mærkeligt, start med at deaktivere plugins. + +#### Tjek den globale konfiguration + +Åbn den globale konfigurationsfil og se efter en `plugin`-nøgle. + +- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (eller `~/.config/opencode/opencode.json`) +- **macOS/Linux** (ældre installationer): `~/.local/share/opencode/opencode.jsonc` +- **Windows**: Tryk `WIN+R` og indsæt `%USERPROFILE%\.config\opencode\opencode.jsonc` + +Hvis du har konfigureret plugins, deaktiver dem midlertidigt ved at fjerne nøglen eller sætte den til et tomt array: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### Tjek plugin-mapper + +OpenCode kan også indlæse lokale plugins fra disken. Flyt disse midlertidigt væk (eller giv mappen nyt navn) og start skrivebordsappen på ny: + +- **Globale plugins** + - **macOS/Linux**: `~/.config/opencode/plugins/` + - **Windows**: Tryk `WIN+R` og indsæt `%USERPROFILE%\.config\opencode\plugins` +- **Projektplugins** (kun hvis du bruger konfiguration per projekt) + - `/.opencode/plugins/` + +Hvis appen begynder at fungere igen, aktiverer du plugins én ad gangen for at finde ud af, hvilken som forårsager problemet. + +--- + +### Ryd cachen + +Hvis deaktivering af plugins ikke hjælper (eller en plugin-installation sidder fast), tøm cachen så OpenCode kan genopbygge den. + +1. Afslut OpenCode Desktop helt. +2. Slet cache-mappen: + +- **macOS**: Finder -> `Cmd+Shift+G` -> indsæt `~/.cache/opencode` +- **Linux**: slet `~/.cache/opencode` (eller kør `rm -rf ~/.cache/opencode`) +- **Windows**: Tryk `WIN+R` og indsæt `%USERPROFILE%\.cache\opencode` + +3. Start OpenCode Desktop på ny. + +--- + +### Løs problemer med serverforbindelse + +OpenCode Desktop kan enten starte sin egen lokale server (standard) eller forbinde til en server URL, du har konfigureret. + +Hvis du ser en **"Forbindelse mislykkedes"**-dialogboks (eller appen kommer aldrig forbi splash-skærmen), se efter en brugerdefineret server URL. + +#### Slet standardserveren for skrivebordet URL + +Fra startskærmen klikker du på servernavnet (med statusprikken) for at åbne servervælgeren. I delen **Standardserver** klikker du på **Slet**. + +#### Fjern `server.port` / `server.hostname` fra din konfiguration + +Hvis `opencode.json(c)` indeholder en `server`-del, fjern den midlertidigt og start skrivebordsappen på ny. + +#### Tjek miljøvariabler + +Hvis du har `OPENCODE_PORT` sat i dit miljø, vil skrivebordsappen prøve at bruge den port for den lokale server. + +- Deaktiver `OPENCODE_PORT` (eller vælg en ledig port) og start på ny. + +--- + +### Linux: Wayland / X11-problemer + +På Linux kan nogle Wayland-opsætninger forårsage tomme vinduer eller kompositorfejl. + +- Hvis du er på Wayland og appen er tom/crasher, prøv at starte med `OC_ALLOW_WAYLAND=1`. +- Hvis det gør ting værre, fjern det og prøv at starte under en X11-session i stedet. + +--- + +### Windows: WebView2-runtime + +På Windows kræver OpenCode Desktop Microsoft Edge **WebView2 Runtime**. Hvis appen åbnes i et tomt vindue eller ikke starter, installer/opdater WebView2 og prøv igen. + +--- + +### Windows: Generelle ydeevneproblemer + +Hvis du oplever langsom ydeevne, problemer med filadgang eller terminalproblemer på Windows, kan du prøve at bruge [WSL (Windows Subsystem for Linux)](/docs/windows-wsl). WSL giver et Linux-miljø som fungerer mere sømløst med funktionerne i OpenCode. + +--- + +### Meddelelser vises ikke + +OpenCode Desktop viser kun systemvarsler når: + +- varsler er aktiveret for OpenCode i dine OS-indstillinger, og +- appvinduet ikke er fokuseret. + +--- + +### Nulstil desktop-applagring (sidste udvej) + +Hvis appen ikke starter og du ikke kan slette indstillingerne fra UI, nulstil skrivebordsappens gemte tilstand. + +1. Afslut OpenCode Desktop. +2. Find og slet disse filer (de findes i OpenCode Desktop-appens datamappe): + +- `opencode.settings.dat` (skrivebordsstandardserver URL) +- `opencode.global.dat` og `opencode.workspace.*.dat` (UI tilstand som nylige servere/projekter) + +Sådan finder du mappen hurtigt: + +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (søg derefter efter filnavnene ovenfor) +- **Linux**: søg under `~/.local/share` efter filnavnene ovenfor +- **Windows**: Tryk `WIN+R` -> `%APPDATA%` (søg derefter efter filnavnene ovenfor) + +--- + +## Få hjælp + +Hvis du oplever problemer med OpenCode: + +1. **Rapporter problemer på GitHub** + + Den bedste måde at rapportere fejl eller bede om funktioner på er gennem vores GitHub-repo: + + [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + + Før du opretter et nyt issue, søg i eksisterende issues for at se om dit problem allerede er rapporteret. + +2. **Bliv en del af vores Discord** + + For hjælp i realtid og fællesskabsdiskussion, bliv en del af vores Discord-server: + + [**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## Almindelige problemer + +Her er nogle almindelige problemer og hvordan du kan løse dem. + +--- + +### OpenCode vil ikke starte + +1. Tjek logfilerne for fejlmeddelelser +2. Prøv at køre med `--print-logs` for at se output i terminalen +3. Sørg for at du har den nyeste version med `opencode upgrade` + +--- + +### Godkendelsesproblemer + +1. Prøv at godkende på ny med kommandoen `/connect` i TUI +2. Tjek at dine API-nøgler er gyldige +3. Sørg for at dit netværk tillader forbindelser til udbyderens API + +--- + +### Modellen er ikke tilgængelig + +1. Tjek at du har godkendt dig med udbyderen +2. Kontroller at modelnavnet i konfigurationen er rigtigt +3. Nogle modeller kan kræve specifik adgang eller abonnement + +Hvis du støder på `ProviderModelNotFoundError` refererer du mest sandsynligt forkert +til en model et sted. +Modeller skal refereres sådan: `/` + +Eksempler: + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +For at finde ud af hvilke modeller du har adgang til, kør `opencode models` + +--- + +### ProviderInitError + +Hvis du støder på en ProviderInitError, har du sandsynligvis en ugyldig eller ødelagt konfiguration. + +For at løse dette: + +1. Kontroller først at din udbyder er rigtigt konfigureret ved at følge [udbydervejledningen](/docs/providers) +2. Hvis problemet vedvarer, prøv at tømme den gemte konfiguration: + + ```bash + rm -rf ~/.local/share/opencode + ``` + + På Windows, tryk `WIN+R` og slet: `%USERPROFILE%\.local\share\opencode` + +3. Godkend på ny med din udbyder ved at bruge kommandoen `/connect` i TUI. + +--- + +### AI_APICallError og udbyderpakkeproblemer + +Hvis du støder på API-kaldsfejl, kan dette skyldes forældede udbyderpakker. opencode installerer dynamisk udbyderpakker (OpenAI, Anthropic, Google, etc.) efter behov og cacher dem lokalt. + +For at løse problemer med udbyderpakke: + +1. Tøm udbyderens pakkecache: + + ```bash + rm -rf ~/.cache/opencode + ``` + + På Windows, tryk `WIN+R` og slet: `%USERPROFILE%\.cache\opencode` + +2. Start opencode på ny for at installere de nyeste udbyderpakker på ny + +Dette vil tvinge opencode til at downloade de nyeste versioner af udbyderpakkerne, som ofte løser kompatibilitetsproblemer med modelparametre og API-ændringer. + +--- + +### Kopier/indsæt virker ikke på Linux + +Linux-brugere skal have et af følgende udklipsholderværktøjer installeret for at kopier/indsæt-funktionalitet skal fungere: + +**For X11-systemer:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**For Wayland-systemer:** + +```bash +apt install -y wl-clipboard +``` + +**For hovedløse miljøer:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +opencode vil opdage om du bruger Wayland og foretrække `wl-clipboard`, ellers vil den prøve at finde udklipsholderværktøjer i rækkefølgen: `xclip` og `xsel`. diff --git a/packages/web/src/content/docs/da/tui.mdx b/packages/web/src/content/docs/da/tui.mdx new file mode 100644 index 00000000000..21cdbe320e0 --- /dev/null +++ b/packages/web/src/content/docs/da/tui.mdx @@ -0,0 +1,387 @@ +--- +title: TUI +description: Brug af OpenCode-terminalbrugergrænsefladen. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode giver en interaktiv terminalgrænseflade eller TUI til at arbejde med dine projekter med en LLM. + +At køre OpenCode starter TUI for den nuværende mappe. + +```bash +opencode +``` + +Eller du kan starte den for en bestemt arbejdsmappe. + +```bash +opencode /path/to/project +``` + +Når du er i TUI, kan du spørge den med en besked. + +```text +Give me a quick summary of the codebase. +``` + +--- + +## Filreferencer + +Du kan referere til filer i dine beskeder med `@`. Det laver en fuzzy filsøgning i den nuværende arbejdsmappe. + +:::tip +Du kan også bruge `@` til at referere til filer i dine beskeder. +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +Indholdet i filen tilføjes automatisk til samtalen. + +--- + +## Bash-kommandoer + +Start en besked med `!` for at køre en shell-kommando. + +```bash frame="none" +!ls -la +``` + +Outputtet fra kommandoen tilføjes til samtalen som et værktøjsresultat. + +--- + +## Kommandoer + +Når du bruger OpenCode TUI, kan du skrive `/` efterfulgt af et kommandonavn for hurtigt at udføre handlinger. For eksempel: + +```bash frame="none" +/help +``` + +De fleste kommandoer har også genvejstaster som bruger `ctrl+x` som Leader-tast, hvor `ctrl+x` er standard Leader-tast. [Læs mere](/docs/keybinds). + +Her er alle tilgængelige skråstregskommandoer: + +--- + +### connect + +Tilføj en udbyder til OpenCode. Lader dig vælge fra tilgængelige udbydere og tilføje deres API-nøgler. + +```bash frame="none" +/connect +``` + +--- + +### compact + +Komprimer nuværende session. _Alias_: `/summarize` + +```bash frame="none" +/compact +``` + +**Genvejstast:** `ctrl+x c` + +--- + +### details + +Skift visning af værktøjsudførelsesdetaljer. + +```bash frame="none" +/details +``` + +**Genvejstast:** `ctrl+x d` + +--- + +### editor + +Åbn eksternt redigeringsprogram for at skrive beskeder. Bruger redigeringsprogrammet i miljøvariablen `EDITOR`. [Læs mere](#editor-setup). + +```bash frame="none" +/editor +``` + +**Genvejstast:** `ctrl+x e` + +--- + +### exit + +Afslut OpenCode. _Aliaser_: `/quit`, `/q` + +```bash frame="none" +/exit +``` + +**Genvejstast:** `ctrl+x q` + +--- + +### export + +Eksporter nuværende samtale til Markdown og åbn i standardredigeringsprogrammet. Bruger redigeringsprogrammet i miljøvariablen `EDITOR`. [Læs mere](#editor-setup). + +```bash frame="none" +/export +``` + +**Genvejstast:** `ctrl+x x` + +--- + +### help + +Vis hjælpedialogen. + +```bash frame="none" +/help +``` + +**Genvejstast:** `ctrl+x h` + +--- + +### init + +Opret eller opdater `AGENTS.md`-fil. [Læs mere](/docs/rules). + +```bash frame="none" +/init +``` + +**Genvejstast:** `ctrl+x i` + +--- + +### models + +Liste over tilgængelige modeller. + +```bash frame="none" +/models +``` + +**Genvejstast:** `ctrl+x m` + +--- + +### new + +Start en ny session. _Alias_: `/clear` + +```bash frame="none" +/new +``` + +**Genvejstast:** `ctrl+x n` + +--- + +### redo + +Gentag en tidligere fortrudt besked. Kun tilgængelig efter brug af `/undo`. + +:::tip +Eventuelle filændringer vil også blive genoprettet. +::: + +Internt bruger dette Git til at administrere filændringerne. Så dit projekt **skal være et Git-depot**. + +```bash frame="none" +/redo +``` + +**Genvejstast:** `ctrl+x r` + +--- + +### sessions + +List og skift mellem sessioner. _Aliaser_: `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +**Genvejstast:** `ctrl+x l` + +--- + +### share + +Del nuværende session. [Læs mere](/docs/share). + +```bash frame="none" +/share +``` + +**Genvejstast:** `ctrl+x s` + +--- + +### themes + +Liste over tilgængelige temaer. + +```bash frame="none" +/theme +``` + +**Genvejstast:** `ctrl+x t` + +--- + +### thinking + +Skift synligheden af tænke-/ræsonneringsblokke i samtalen. Når den er aktiveret, kan du se modellens ræsonneringsproces for modeller, som understøtter udvidet tænkning. + +:::note +Denne kommando kontrollerer bare om tænkeblokke **vises** - den aktiverer eller deaktiverer ikke modellens ræsonneringsmuligheder. For at skifte mellem faktiske ræsonneringsmuligheder, brug `ctrl+t` for at bladre gennem modelvarianter. +::: + +```bash frame="none" +/thinking +``` + +--- + +### undo + +Fortryd sidste besked i samtalen. Fjerner den sidste brugerbesked, alle efterfølgende svar og eventuelle filændringer. + +:::tip +Eventuelle filændringer vil også blive nulstillet. +::: + +Internt bruger dette Git til at administrere filændringerne. Så dit projekt **skal være et Git-depot**. + +```bash frame="none" +/undo +``` + +**Genvejstast:** `ctrl+x u` + +--- + +### unshare + +Ophæv deling af nuværende session. [Læs mere](/docs/share#un-sharing). + +```bash frame="none" +/unshare +``` + +--- + +## Opsætning af editor + +Både kommandoerne `/editor` og `/export` bruger editoren som er specificeret i miljøvariablen `EDITOR`. + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + + For at gøre det permanent, tilføj dette til din shellprofil; + `~/.bashrc`, `~/.zshrc` osv. + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + + For at gøre det permanent, brug **Systemegenskaber** > **Miljøvariabler**. + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + + For at gøre det permanent, tilføj dette til din PowerShell-profil. + + + + +Populære redigeringsalternativer inkluderer: + +- `code` - Visual Studio Code +- `cursor` - Cursor +- `windsurf` - Windsurf +- `nvim` - Neovim-editor +- `vim` - Vim editor +- `nano` - Nano-editor +- `notepad` - Windows Notesblok +- `subl` - Sublime Text + +:::note +Nogle editorer som VS Code skal startes med flaget `--wait`. +::: + +Nogle editorer kræver kommandolinjeargumenter for at køre i blokeringstilstand. `--wait`-flaget gør at redigeringsprocessen blokeres indtil den lukkes. + +--- + +## Konfigurer + +Du kan tilpasse TUI-adfærden gennem OpenCode-konfigurationsfilen. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### 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`.** + +--- + +## Tilpasning + +Du kan tilpasse forskellige aspekter af TUI-visningen ved at bruge kommandopaletten (`ctrl+x h` eller `/help`). Disse indstillinger gemmes ved genstart. + +--- + +#### Visning af brugernavn + +Skift om dit brugernavn vises i chat-beskeder. Få adgang til dette gennem: + +- Kommandopalet: Søg efter "brugernavn" eller "skjul brugernavn" +- Indstillingen gemmes automatisk og vil blive husket over TUI-sessioner diff --git a/packages/web/src/content/docs/da/web.mdx b/packages/web/src/content/docs/da/web.mdx new file mode 100644 index 00000000000..889045ca202 --- /dev/null +++ b/packages/web/src/content/docs/da/web.mdx @@ -0,0 +1,142 @@ +--- +title: Web +description: Brug af OpenCode i din browser. +--- + +OpenCode kan køre som en webapplikation i din browser, hvilket giver den samme kraftfulde AI-kodningsoplevelse uden behov for en terminal. + +![OpenCode Web - Ny session](../../../assets/web/web-homepage-new-session.png) + +## Kom godt i gang + +Start webgrænsefladen ved at køre: + +```bash +opencode web +``` + +Dette starter en lokal server på `127.0.0.1` med en tilfældig tilgængelig port og åbner automatisk OpenCode i din standardbrowser. + +:::caution +Hvis `OPENCODE_SERVER_PASSWORD` ikke er indstillet, vil serveren være usikret. Dette er fint til lokal brug, men bør indstilles til netværksadgang. +::: + +:::tip[Windows-brugere] +For den bedste oplevelse skal du køre `opencode web` fra [WSL](/docs/windows-wsl) i stedet for PowerShell. Dette sikrer korrekt filsystemadgang og terminalintegration. +::: + +--- + +## Konfiguration + +Du kan konfigurere webserveren ved hjælp af kommandolinjeflag eller i din [config-fil](/docs/config). + +### Port + +Som standard vælger OpenCode en tilgængelig port. Du kan angive en port: + +```bash +opencode web --port 4096 +``` + +### Værtsnavn + +Som standard binder serveren til `127.0.0.1` (kun lokal vært). Sådan gør du OpenCode tilgængelig på dit netværk: + +```bash +opencode web --hostname 0.0.0.0 +``` + +Når du bruger `0.0.0.0`, vil OpenCode vise både lokale adresser og netværksadresser: + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### mDNS-opdagelse + +Aktiver mDNS for at gøre din server synlig på det lokale netværk: + +```bash +opencode web --mdns +``` + +Dette indstiller automatisk værtsnavnet til `0.0.0.0` og annoncerer serveren som `opencode.local`. + +Du kan tilpasse mDNS-domænenavnet til at køre flere forekomster på det samme netværk: + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +For at tillade yderligere domæner til CORS (nyttigt til brugerdefinerede frontends): + +```bash +opencode web --cors https://example.com +``` + +### Godkendelse + +For at beskytte adgangen skal du angive en adgangskode ved hjælp af `OPENCODE_SERVER_PASSWORD` miljøvariablen: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +Brugernavnet er som standard `opencode`, men kan ændres med `OPENCODE_SERVER_USERNAME`. + +--- + +## Brug af webgrænsefladen + +Når den er startet, giver webgrænsefladen adgang til dine OpenCode-sessioner. + +### Sessioner + +Se og administrer dine sessioner fra hjemmesiden. Du kan se aktive sessioner og starte nye. + +![OpenCode Web - Active Session](../../../assets/web/web-homepage-active-session.png) + +### Serverstatus + +Klik på "Se servere" for at se tilsluttede servere og deres status. + +![OpenCode Web - Se servere](../../../assets/web/web-homepage-see-servers.png) + +--- + +## Tilslutning af en terminal + +Du kan vedhæfte en terminal TUI til en kørende webserver: + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +Dette giver dig mulighed for at bruge både webgrænsefladen og terminalen samtidigt og dele de samme sessioner og tilstand. + +--- + +## Konfigurationsfil + +Du kan også konfigurere serverindstillinger i din `opencode.json`-konfigurationsfil: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +Kommandolinjeflag har forrang over konfigurationsfilindstillinger. diff --git a/packages/web/src/content/docs/da/windows-wsl.mdx b/packages/web/src/content/docs/da/windows-wsl.mdx new file mode 100644 index 00000000000..37be0496385 --- /dev/null +++ b/packages/web/src/content/docs/da/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: Kør OpenCode på Windows med WSL for den bedste oplevelse. +--- + +import { Steps } from "@astrojs/starlight/components" + +Selvom OpenCode kan køre direkte på Windows, anbefaler vi at bruge [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) for den bedste oplevelse. WSL giver et Linux-miljø, der fungerer problemfrit med OpenCodes funktioner. + +:::tip[Hvorfor WSL?] +WSL giver bedre filsystemydelse, fuld terminalunderstøttelse og kompatibilitet med de udviklingsværktøjer, som OpenCode er afhængig af. +::: + +--- + +## Opsætning + + + +1. **Installer WSL** + + Hvis du ikke allerede har gjort det, så [installer WSL](https://learn.microsoft.com/en-us/windows/wsl/install) med Microsofts officielle vejledning. + +2. **Installer OpenCode i WSL** + + Når WSL er sat op, skal du åbne din WSL-terminal og installere OpenCode med en af [installationsmetoderne](/docs/). + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **Brug OpenCode fra WSL** + + Gå til din projektmappe (få adgang til Windows-filer via `/mnt/c/`, `/mnt/d/` osv.) og kør OpenCode. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## Desktop-app + WSL-server + +Hvis du foretrækker OpenCode Desktop-appen, men vil køre serveren i WSL: + +1. **Start serveren i WSL** med `--hostname 0.0.0.0` for at tillade eksterne forbindelser: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **Forbind Desktop-appen** til `http://localhost:4096` + +:::note +Hvis `localhost` ikke virker i din opsætning, så forbind i stedet med WSL-IP-adressen (fra WSL: `hostname -I`) og brug `http://:4096`. +::: + +:::caution +Når du bruger `--hostname 0.0.0.0`, skal du sætte `OPENCODE_SERVER_PASSWORD` for at sikre serveren. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## Webklient + WSL + +For den bedste weboplevelse på Windows: + +1. **Kør `opencode web` i WSL-terminalen** i stedet for PowerShell: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Åbn fra din Windows-browser** på `http://localhost:` (OpenCode udskriver URL'en) + +Når du kører `opencode web` fra WSL, får du korrekt filsystemadgang og terminalintegration, samtidig med at det stadig er tilgængeligt fra din Windows-browser. + +--- + +## Adgang til Windows-filer + +WSL kan få adgang til alle dine Windows-filer via `/mnt/`-mappen: + +- `C:`-drev → `/mnt/c/` +- `D:`-drev → `/mnt/d/` +- Og så videre... + +Eksempel: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +For den mest problemfri oplevelse kan du overveje at klone/kopiere dit repo ind i WSL-filsystemet (for eksempel under `~/code/`) og køre OpenCode derfra. +::: + +--- + +## Tips + +- Lad OpenCode køre i WSL for projekter, der ligger på Windows-drev - filadgangen er problemfri +- Brug VS Codes [WSL-udvidelse](https://code.visualstudio.com/docs/remote/wsl) sammen med OpenCode for et integreret udviklingsworkflow +- Din OpenCode-konfiguration og dine sessioner gemmes i WSL-miljøet i `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/da/zen.mdx b/packages/web/src/content/docs/da/zen.mdx new file mode 100644 index 00000000000..128583ad7ab --- /dev/null +++ b/packages/web/src/content/docs/da/zen.mdx @@ -0,0 +1,254 @@ +--- +title: Zen +description: Udvalgt liste over modeller leveret af OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen er en liste over testede og verificerede modeller leveret af OpenCode-teamet. + +:::note +OpenCode Zen er i øjeblikket i beta. +::: + +Zen fungerer som alle andre udbydere i OpenCode. Du logger på OpenCode Zen og får +din API-nøgle. Den er **helt valgfri** og du behøver ikke bruge den for at bruge +OpenCode. + +--- + +## Baggrund + +Der er et stort antal modeller derude, men kun få af dem +fungerer godt som kodeagenter. Derudover er de fleste udbydere +konfigureret meget forskelligt, så du får meget forskellig ydeevne og kvalitet. + +:::tip +Vi testede en udvalgt gruppe modeller og udbydere, der fungerer godt med OpenCode. +::: + +Så hvis du bruger en model gennem noget som OpenRouter, kan du aldrig være +sikker på, om du får den bedste version af modellen, du ønsker. + +For at fikse dette gjorde vi et par ting: + +1. Vi testede en udvalgt gruppe modeller og talte med deres teams om, hvordan + man bedst kører dem. +2. Vi samarbejdede derefter med nogle få udbydere for at sikre, at disse blev serveret + korrekt. +3. Til sidst benchmarkede vi kombinationen af model/udbyder og kom frem + til en liste, som vi har lyst til at anbefale. + +OpenCode Zen er en AI gateway, der giver dig adgang til disse modeller. + +--- + +## Sådan fungerer det + +OpenCode Zen fungerer som alle andre udbydere i OpenCode. + +1. Du logger på **OpenCode Zen**, tilføjer faktureringsoplysninger + og kopierer API-nøglen. +2. Du kører kommandoen `/connect` i TUI, vælger OpenCode Zen og indsætter API-nøglen. +3. Kør `/models` i TUI for at se listen over modeller, vi anbefaler. + +Du opkræves per anmodning, og du kan tilføje kredit til din konto. + +--- + +## Endpoints + +Du kan også få adgang til vores modeller gennem følgende API-endpoints. + +| Model | Model ID | Endpoint | AI SDK Pakke | +| ------------------- | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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` | +| 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.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 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` | +| Stor sylteagurk | big-pickle | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | + +[model-id](/docs/config/#models) i OpenCode-konfigurationen +bruger formatet `opencode/`. For eksempel, for GPT 5.2 Codex, ville du +bruge `opencode/gpt-5.2-codex` i din konfiguration. + +--- + +### Modeller + +Du kan hente hele listen over tilgængelige modeller og deres metadata fra: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## Priser + +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.1 | $0,30 | $1,20 | $0,10 | - | +| GLM 4.7 Gratis | Gratis | Gratis | Gratis | - | +| 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 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 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.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 | Gratis | Gratis | Gratis | - | + +Du bemærker måske _Claude Haiku 3.5_ i din brugshistorik. Dette er en [lavprismodel](/docs/config/#models), som bruges til at generere titlerne på dine sessioner. + +:::note +Kreditkortgebyrer overføres til kostpris (4,4 % + $0,30 per transaktion); vi opkræver ikke noget udover det. +::: + +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. +- 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. + +--- + +### Automatisk opfyldning + +Hvis din saldo går under $5, vil Zen automatisk laste $20 ind på nytt. + +Du kan ændre beløbet for automatisk påfyldning. Du kan også deaktivere automatisk genindlæsning helt. + +--- + +### Månedlige grænser + +Du kan også angive en månedlig brugsgrænse for hele arbejdsområdet og for hvert +medlem af dit team. + +Lad os for eksempel sige, at du sætter en månedlig brugsgrænse til $20, Zen vil ikke bruge +mere end $20 på en måned. Men hvis du har automatisk genindlæsning aktiveret, kan Zen ende med +at opkræve dig mere end $20, hvis din saldo går under $5. + +--- + +## Privatliv + +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. +- 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). + +--- + +## For teams + +Zen fungerer også fremragende for teams. Du kan invitere holdkammerater, tildele roller, kuratere +de modeller dit hold bruger, og mere. + +:::note +Arbejdsområder er i øjeblikket gratis for teams som en del af betaversionen. +::: + +At administrere dit arbejdsområde er i øjeblikket gratis for teams som en del af betaversionen. Vi vil +dele mere information om priserne snart. + +--- + +### Roller + +Du kan invitere holdkammerater til dit arbejdsområde og tildele roller: + +- **Admin**: Administrer modeller, medlemmer, API-nøgler og fakturering +- **Medlem**: Administrer kun sine egne API-nøgler + +Administratorer kan også sætte månedlige forbrugsgrænser for hvert medlem for at holde omkostningerne under kontrol. + +--- + +### Modeladgang + +Administratorer kan aktivere eller deaktivere specifikke modeller for arbejdsområdet. Anmodninger til en deaktiveret model vil returnere en fejl. + +Dette er nyttigt for tilfælde, hvor du ønsker at deaktivere brugen af en model, som +samler ind data. + +--- + +### Medbring din egen nøgle + +Du kan bruge dine egne OpenAI- eller Anthropic API-nøgler, mens du stadig har adgang til andre modeller i Zen. + +Når du bruger dine egne nøgler, faktureres tokens direkte af udbyderen, ikke af Zen. + +For eksempel kan din organisation allerede have en nøgle for OpenAI eller Anthropic +og du vil bruge det i stedet for det Zen giver. + +--- + +## Mål + +Vi oprettede OpenCode Zen for at: + +1. **Benchmarke** de bedste modeller/udbydere for kodningsagenter. +2. Have adgang til mulighederne for **højeste kvalitet** og ikke nedgradere ydeevnen eller rute til billigere udbydere. +3. Give videre eventuelle **prisfald** ved at sælge til kostpris; så den eneste mark-up er for at dække vores behandlingsgebyrer. +4. Have **ingen fastlåsning** ved at lade dig bruge den med en hvilken som helst anden kodeagent. Og lade dig altid bruge en hvilken som helst anden udbyder med OpenCode også. diff --git a/packages/web/src/content/docs/de/acp.mdx b/packages/web/src/content/docs/de/acp.mdx new file mode 100644 index 00000000000..d63a13c5277 --- /dev/null +++ b/packages/web/src/content/docs/de/acp.mdx @@ -0,0 +1,156 @@ +--- +title: ACP-Unterstützung +description: Verwenden Sie OpenCode in jedem ACP-kompatiblen Editor. +--- + +OpenCode unterstützt [Agent Client Protocol](https://agentclientprotocol.com) oder (ACP), sodass Sie es direkt in kompatiblen Editoren und IDEs verwenden können. + +:::tip +Eine Liste der Editoren und Tools, die ACP unterstützen, finden Sie unter [ACP progress report](https://zed.dev/blog/acp-progress-report#available-now). +::: + +ACP ist ein offenes Protokoll, das die Kommunikation zwischen Code-Editoren und AI-Coding-Agenten standardisiert. + +--- + +## Konfiguration + +Um OpenCode über ACP zu verwenden, konfigurieren Sie Ihren Editor für die Ausführung des Befehls `opencode acp`. + +Der Befehl startet OpenCode als ACP-kompatiblen Unterprozess, der über stdio über JSON-RPC mit Ihrem Editor kommuniziert. + +Nachfolgend finden Sie Beispiele für beliebte Editoren, die ACP unterstützen. + +--- + +### Zed + +Fügen Sie Ihrer [Zed](https://zed.dev)-Konfiguration (`~/.config/zed/settings.json`) Folgendes hinzu: + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +Um es zu öffnen, verwenden Sie die Aktion `agent: new thread` in der **Befehlspalette**. + +Sie können auch eine Tastenkombination binden, indem Sie Ihren `keymap.json` bearbeiten: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### JetBrains IDEs + +Fügen Sie zu Ihrem [JetBrains IDE](https://www.jetbrains.com/) acp.json gemäß [Dokumentation](https://www.jetbrains.com/help/ai-assistant/acp.html) hinzu: + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +Um es zu öffnen, verwenden Sie den neuen Agenten „OpenCode“ in der AI Chat Agent Selector. + +--- + +### Avante.nvim + +Fügen Sie Ihrer [Avante.nvim](https://github.com/yetone/avante.nvim)-Konfiguration Folgendes hinzu: + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +Wenn Sie Umgebungsvariablen übergeben müssen: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +Um OpenCode als ACP-Agent in [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim) zu verwenden, fügen Sie Folgendes zu Ihrer Neovim-Konfiguration hinzu: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +Diese Konfiguration richtet CodeCompanion so ein, dass OpenCode als ACP-Agent für den Chat verwendet wird. + +Wenn Sie Umgebungsvariablen (wie `OPENCODE_API_KEY`) übergeben müssen, finden Sie ausführliche Informationen zu [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) in der Dokumentation zu CodeCompanion.nvim. + +## Unterstützung + +OpenCode funktioniert über ACP genauso wie im Terminal. Alle Funktionen werden unterstützt: + +:::note +Einige integrierte Slash-Befehle wie `/undo` und `/redo` werden derzeit nicht unterstützt. +::: + +- Integrierte Tools (Dateioperationen, Terminalbefehle usw.) +- Benutzerdefinierte Tools und Slash-Befehle +- MCP-Server, die in Ihrer OpenCode-Konfiguration konfiguriert sind +- Projektspezifische Regeln von `AGENTS.md` +- Benutzerdefinierte Formatierer und Linters +- Agenten- und Berechtigungssystem diff --git a/packages/web/src/content/docs/de/agents.mdx b/packages/web/src/content/docs/de/agents.mdx new file mode 100644 index 00000000000..289b113cf64 --- /dev/null +++ b/packages/web/src/content/docs/de/agents.mdx @@ -0,0 +1,733 @@ +--- +title: Agenten +description: Konfigurieren und verwenden Sie spezielle Agenten. +--- + +Agenten sind spezialisierte AI-Assistenten, die für bestimmte Aufgaben und Arbeitsabläufe konfiguriert werden können. Sie ermöglichen Ihnen die Erstellung gezielter Werkzeuge mit benutzerdefinierten Eingabeaufforderungen, Modellen und Werkzeugzugriff. + +:::tip +Verwenden Sie den Planagenten, um Code zu analysieren und Vorschläge zu überprüfen, ohne Codeänderungen vorzunehmen. +::: + +Sie können während einer Sitzung zwischen Agenten wechseln oder sie mit der Erwähnung `@` aufrufen. + +--- + +## Typen + +Es gibt zwei Arten von Agenten in OpenCode; Primäragenten und Subagenten. + +--- + +### Primäragenten + +Primäragenten sind die Hauptassistenten, mit denen Sie direkt interagieren. Sie können sie mit der **Tabulatortaste** oder Ihrer konfigurierten Tastenkombination `switch_agent` durchblättern. Diese Agenten kümmern sich um Ihr Hauptgespräch. Der Werkzeugzugriff wird über Berechtigungen konfiguriert – zum Beispiel sind bei „Build“ alle Werkzeuge aktiviert, während „Plan“ eingeschränkt ist. + +:::tip +Sie können die **Tabulatortaste** verwenden, um während einer Sitzung zwischen primären Agenten zu wechseln. +::: + +OpenCode verfügt über zwei integrierte Primäragenten: **Build** und **Plan**. Auch +Schauen wir uns diese unten an. + +--- + +### Build + +_Modus_: `primary` + +Build ist der **Standard**-Primäragent mit allen aktivierten Tools. Dies ist der Standardagent für Entwicklungsarbeiten, bei dem Sie vollen Zugriff auf Dateioperationen und Systembefehle benötigen. + +--- + +### Plan + +_Modus_: `primary` + +Ein eingeschränkter Agent, der für Planung und Analyse entwickelt wurde. Wir verwenden ein Berechtigungssystem, um Ihnen mehr Kontrolle zu geben und unbeabsichtigte Änderungen zu verhindern. +Standardmäßig sind alle folgenden Elemente auf `ask` gesetzt: + +- `file edits`: Alle Schreibvorgänge, Patches und Bearbeitungen +- `bash`: Alle Bash-Befehle + +Dieser Agent ist nützlich, wenn Sie möchten, dass LLM Code analysiert, Änderungen vorgeschlagen oder Pläne erstellt werden, ohne tatsächliche Änderungen an Ihrer Codebasis vorzunehmen. + +--- + +### General + +_Modus_: `subagent` + +Ein Allzweckagent zur Recherche komplexerer Fragen und zur Ausführung mehrstufiger Aufgaben. Verfügt über vollständigen Zugriff auf das Tool (außer Todo), sodass bei Bedarf Dateiänderungen vorgenommen werden können. Verwenden Sie Matrizen, um mehrere Arbeitseinheiten parallel auszuführen. + +--- + +### Explore + +_Modus_: `subagent` + +Ein schneller, schreibgeschützter Agent zum Erkunden von Codebasen. Dateien können nicht geändert werden. Verwenden Sie dies, wenn Sie Dateien schnell anhand von Mustern finden, Code nach Schlüsselwörtern durchsuchen oder Fragen zur Codebasis beantworten müssen. + +--- + +### Compaction + +_Modus_: `primary` + +Versteckter Systemagent, der lange Kontext in einer kleineren Zusammenfassung komprimiert. Es wird bei Bedarf automatisch ausgeführt und ist im UI nicht auswählbar. + +--- + +### Title + +_Modus_: `primary` + +Versteckter Systemagent, der kurze Sitzungstitel generiert. Es läuft automatisch und ist im UI nicht auswählbar. + +--- + +### Summary + +_Modus_: `primary` + +Versteckter Systemagent, der Sitzungszusammenfassungen erstellt. Es läuft automatisch und ist im UI nicht auswählbar. + +--- + +## Verwendung + +1. Verwenden Sie für primäre Agenten die **Tabulatortaste**, um während einer Sitzung durch sie zu blättern. Sie können auch Ihre konfigurierte `switch_agent`-Tastenkombination verwenden. + +2. Subagenten können aufgerufen werden: + - **Automatisch** durch primäre Agenten für spezielle Aufgaben basierend auf ihren Beschreibungen. + - Manuell durch **@ Erwähnung** eines Subagenten in Ihrer Nachricht. Zum Beispiel. + + ```txt frame="none" + @general help me search for this function + ``` + +3. **Navigation zwischen Sitzungen**: Wenn Subagenten ihre eigenen untergeordneten Sitzungen erstellen, können Sie zwischen der übergeordneten Sitzung und allen untergeordneten Sitzungen sorgfältig handeln, indem Sie Folgendes verwenden: + - **\+Rechts** (oder Ihre konfigurierte `session_child_cycle`-Tastenkombination), um vorwärts durch Parent → Child1 → Child2 → ... → Parent zu blättern + - **\+Links** (oder Ihre konfigurierte `session_child_cycle_reverse`-Tastenkombination), um rückwärts durch Parent ← Child1 ← Child2 ← ... ← Parent zu blättern + + Dadurch können Sie nahtlos zwischen der Hauptkonversation und der spezialisierten Subagentenarbeit wechseln. + +--- + +## Konfiguration + +Sie können die integrierten Agenten anpassen oder über die Konfiguration eigene erstellen. Agenten können auf zwei Arten konfiguriert werden: + +--- + +### JSON + +Konfigurieren Sie Agenten in Ihrer `opencode.json`-Konfigurationsdatei: + +```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 + +Sie können Agenten auch mithilfe von Markdown-Dateien definieren. Platzieren Sie sie in: + +- Global: `~/.config/opencode/agents/` +- Pro Projekt: `.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. +``` + +Der Name der Markdown-Datei wird zum Agentennamen. Beispielsweise erstellte `review.md` einen `review`-Agenten. + +--- + +## Optionen + +Schauen wir uns diese Konfigurationsmöglichkeiten im Detail an. + +--- + +### Beschreibung + +Verwenden Sie die Option `description`, um eine kurze Beschreibung darüber bereitzustellen, was der Agent tut und wann er verwendet werden soll. + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +Dies ist eine **erforderliche** Konfigurationsoption. + +--- + +### Temperatur + +Steuern Sie die Zufälligkeit und Kreativität der Antworten von LLM mit der `temperature`-Konfiguration. + +Höchste Werte machen die Antworten fokussierter und deterministischer, während höhere Werte die Kreativität und Variabilität steigern. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Temperaturwerte liegen typischerweise zwischen 0.0 und 1.0: + +- **0.0-0.2**: Sehr fokussierte und deterministische Antworten, ideal für Code-Analyse und Planung +- **0.3-0.5**: Ausgewogene Antworten mit etwas Kreativität, gut für allgemeine Entwicklungsaufgaben +- **0.6-1.0**: Kreativere und vielfältigere Antworten, nützlich für Brainstorming und Erkundung + +```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}" + } + } +} +``` + +Wenn keine Temperatur angegeben ist, verwendet OpenCode modellspezifische Standardwerte; typischerweise 0 für die meisten Modelle, 0.55 für Qwen-Modelle. + +--- + +### Schritte + +Steuern Sie die maximale Anzahl an Agenteniterationen, die ein Agent durchführen kann, bevor er gezwungen wird, nur mit Text zu antworten. Dadurch können Benutzer, die die Kosten kontrollieren möchten, ein Limit für Agentenaktionen festlegen. + +Wenn dies nicht festgelegt ist, iteriert der Agent weiter, bis das Modell den Stopp beschließt oder der Benutzer die Sitzung unterbricht. + +```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 + } + } +} +``` + +Wenn das Limit erreicht ist, erhält der Agent eine spezielle Systemaufforderung, die ihn anweist, mit einer Zusammenfassung seiner Arbeit und empfohlenen verbleibenden Aufgaben zu antworten. + +:::caution +Das alte Feld `maxSteps` ist veraltet. Verwenden Sie stattdessen `steps`. +::: + +--- + +### Deaktivieren + +Auf `true` setzen, um den Agenten zu deaktivieren. + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### Prompt + +Geben Sie mit der `prompt`-Konfiguration eine benutzerdefinierte Systemaufforderungsdatei für diese Agenten an. Die Eingabeaufforderungsdatei sollte Anweisungen enthalten, die speziell auf den Zweck des Agenten zugeschnitten sind. + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Dieser Pfad ist relativ zum Speicherort der Konfigurationsdatei. Dies funktioniert sowohl für die globale OpenCode-Konfiguration als auch für die projektspezifische Konfiguration. + +--- + +### Modell + +Verwenden Sie die `model`-Konfiguration, um das Modell für diese Agenten zu überschreiben. Nützlich für die Verwendung verschiedener Modelle, die für verschiedene Aufgaben optimiert sind. Zum Beispiel ein schnelleres Modell für die Planung, ein leistungsfähigeres Modell für die Umsetzung. + +:::tip +Wenn Sie kein Modell angeben, verwenden Sie den primären Agenten [model globally configured](/docs/config#models), während die Subagenten das Modell des primären Agenten verwenden, der den Subagenten aufgerufen hat. +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +Die Modell-ID in Ihrer OpenCode-Konfiguration verwendet das Format `provider/model-id`. Wenn Sie beispielsweise [OpenCode Zen](/docs/zen) verwenden, würden Sie `opencode/gpt-5.1-codex` für GPT 5.1 Codex verwenden. + +--- + +### Werkzeuge + +Steuern Sie mit der `tools`-Konfiguration, welche Tools in diesem Agent verfügbar sind. Sie können bestimmte Tools aktivieren oder deaktivieren, indem Sie sie auf `true` oder `false` setzen. + +```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 +Die agentenspezifische Konfiguration überschreibt die globale Konfiguration. +::: + +Sie können Platzhalter auch verwenden, um mehrere Werkzeuge gleichzeitig zu steuern. So deaktivieren Sie beispielsweise alle Tools von einem MCP-Server: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[Learn more about tools](/docs/tools). + +--- + +### Berechtigungen + +Sie können Berechtigungen konfigurieren, um zu verwalten, welche Aktionen ein Agent ausführen kann. Derzeit können die Berechtigungen für die Tools `edit`, `bash` und `webfetch` wie folgt konfiguriert werden: + +- `"ask"` – Bitten Sie um Genehmigung, bevor Sie das Tool ausführen +- `"allow"` – Alle Vorgänge ohne Genehmigung zulassen +- `"deny"` – Deaktivieren Sie das Tool + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +Sie können diese Berechtigungen pro Agent überschreiben. + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +Sie können Berechtigungen auch in Markdown-Agenten festlegen. + +```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. +``` + +Sie können Berechtigungen für bestimmte Bash-Befehle festlegen. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +Dies kann ein Glob-Muster annehmen. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +Und Sie können den Platzhalter `*` auch verwenden, um Berechtigungen für alle Befehle zu verwalten. +Da die letzte übereinstimmende Regel Vorrang hat, setzen Sie zuerst den Platzhalter `*` und danach bestimmte Regeln. + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[Learn more about permissions](/docs/permissions). + +--- + +### Modus + +Steuern Sie den Modus des Agenten mit der `mode`-Konfiguration. Mit der Option `mode` wird festgelegt, wie der Agent verwendet werden kann. + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +Die Option `mode` kann auf `primary`, `subagent` oder `all` gesetzt werden. Wenn kein `mode` angegeben ist, wird standardmäßig `all` verwendet. + +--- + +### Versteckt + +Verstecken Sie einen Subagenten im Autovervollständigungsmenü `@` mit `hidden: true`. Nützlich für interne Subagenten, die nur programmgesteuert von anderen Agenten über das Task-Tool aufgerufen werden sollten. + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +Dies wirkt sich nur auf die Benutzersichtbarkeit im Autovervollständigungsmenü aus. Versteckte Agenten können weiterhin vom Modell über das Aufgabentool aufgerufen werden, sofern die Berechtigungen dies zulassen. + +:::note +Gilt nur für `mode: subagent`-Agenten. +::: + +--- + +### Task-Berechtigungen + +Steuern Sie, welche Subagenten ein Agent über das Task-Tool mit `permission.task` aufrufen kann. Verwendet Glob-Muster für eine flexible Zuordnung. + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +Bei der Einstellung `deny` wird der Subagent vollständig aus der Beschreibung des Aufgabentools entfernt, sodass das Modell nicht versucht, ihn aufzurufen. + +:::tip +Die Regeln werden der Reihe nach ausgewertet und die **letzte übereinstimmende Regel gewinnt**. Im obigen Beispiel entspricht `orchestrator-planner` sowohl `*` (verweigern) als auch `orchestrator-*` (zulassen), aber da `orchestrator-*` nach `*` kommt, ist das Ergebnis `allow`. +::: + +:::tip +Benutzer können jeden Subagenten immer direkt über das Autovervollständigungsmenü `@` aufrufen, auch wenn die Aufgabenberechtigungen des Agenten dies verweigern würden. +::: + +--- + +### Farbe + +Passen Sie das visuelle Erscheinungsbild des Agenten im UI mit der Option `color` an. Dies wirkt sich darauf aus, wie der Agent in der Benutzeroberfläche angezeigt wird. + +Verwenden Sie eine gültige Hex-Farbe (z. B. `#FF5733`) oder Themenfarbe: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +Steuern Sie die Antwortvielfalt mit der Option `top_p`. Alternative zur Temperatur zur Kontrolle des Zufalls. + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +Die Werte reichen von 0.0 bis 1.0. Niedrigere Werte sind fokussierter, höhere Werte vielfältiger. + +--- + +### Zusätzliche Optionen + +Alle anderen Optionen, die Sie in Ihrer Agentenkonfiguration angeben, werden als Modelloptionen **direkt** an den Anbieter weitergeleitet. Dadurch können Sie anbieterspezifische Funktionen und Parameter nutzen. + +Mit den Argumentationsmodellen von OpenAI können Sie beispielsweise den Argumentationsaufwand steuern: + +```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" + } + } +} +``` + +Diese zusätzlichen Optionen sind modell- und anbieterspezifisch. Überprüfen Sie die Dokumentation Ihres Anbieters auf verfügbare Parameter. + +:::tip +Führen Sie `opencode models` aus, um eine Liste der verfügbaren Modelle anzubieten. +::: + +--- + +## Agenten erstellen + +Mit dem folgenden Befehl können Sie neue Agenten erstellen: + +```bash +opencode agent create +``` + +Dieser interaktive Befehl führt zu Folgendem: + +1. Fragen Sie, wo der Agent gespeichert werden soll. global oder projektspezifisch. +2. Beschreibung dessen, was der Agent tun soll. +3. Generieren Sie eine entsprechende Systemaufforderung und -kennung. +4. Hier können Sie auswählen, auf welche Tools der Agent zugreifen kann. +5. Erstellen Sie abschließend eine Markdown-Datei mit der Agentenkonfiguration. + +--- + +## Anwendungsfälle + +Hier sind einige häufige Anwendungsfälle für verschiedene Agenten. + +- **Build-Agent**: Vollständige Entwicklungsarbeit mit allen aktivierten Tools +- **Planagent**: Analyse und Planung ohne Änderungen +- **Review-Agent**: Codeüberprüfung mit schreibgeschütztem Zugriff plus Dokumentationstools +- **Debug-Agent**: Konzentriert sich auf die Untersuchung mit aktivierten Bash- und Lesetools +- **Docs-Agent**: Schreiben von Dokumentationen mit Dateioperationen, aber ohne Systembefehle + +--- + +## Beispiele + +Hier sind einige Beispielagenten, die für Sie nützlich sein könnten. + +:::tip +Haben Sie einen Agenten, den Sie gerne teilen möchten? [Reichen Sie einen PR ein](https://github.com/anomalyco/opencode). +::: + +--- + +### Dokumentationsagent + +```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 +``` + +--- + +### Sicherheitsprüfer + +```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/de/cli.mdx b/packages/web/src/content/docs/de/cli.mdx new file mode 100644 index 00000000000..650e75d31f7 --- /dev/null +++ b/packages/web/src/content/docs/de/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: OpenCode CLI Optionen und Befehle. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +Der OpenCode CLI startet standardmäßig das [TUI](/docs/tui), wenn er ohne Argumente ausgeführt wird. + +```bash +opencode +``` + +Es akzeptiert aber auch Befehle, wie auf dieser Seite dokumentiert. Dadurch können Sie programmgesteuert mit OpenCode interagieren. + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +Starten Sie die Terminalbenutzeroberfläche OpenCode. + +```bash +opencode [project] +``` + +#### Optionen + +| Flag | Kurz | Beschreibung | +| ------------ | ---- | ---------------------------------------------------------------------- | +| `--continue` | `-c` | Setzen Sie die letzte Sitzung fort | +| `--session` | `-s` | Session-ID zum Fortfahren | +| `--fork` | | Sitzung beim Fortsetzen verzweigen (mit `--continue` oder `--session`) | +| `--prompt` | | Prompt zur Verwendung | +| `--model` | `-m` | Zu verwendendes Modell in der Form provider/model | +| `--agent` | | Zu verwendender Agent | +| `--port` | | Port zum Abhören | +| `--hostname` | | Hostname zum Abhören | + +--- + +## Befehle + +Der OpenCode CLI verfügt außerdem über die folgenden Befehle. + +--- + +### agent + +Agenten für OpenCode verwalten. + +```bash +opencode agent [command] +``` + +--- + +### attach + +Schließen Sie ein Terminal an einen bereits laufenden OpenCode-Backend-Server an, der über die Befehle `serve` oder `web` gestartet wurde. + +```bash +opencode attach [url] +``` + +Dies ermöglicht die Verwendung von TUI mit einem Remote-Backend OpenCode. Zum Beispiel: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### Optionen + +| Flag | Kurz | Beschreibung | +| ----------- | ---- | ----------------------------------------- | +| `--dir` | | Arbeitsverzeichnis zum Starten von TUI in | +| `--session` | `-s` | Session-ID zum Fortfahren | + +--- + +#### create + +Erstellen Sie einen neuen Agenten mit benutzerdefinierter Konfiguration. + +```bash +opencode agent create +``` + +Dieser Befehl führt Sie durch die Erstellung eines neuen Agenten mit einer benutzerdefinierten Systemeingabeaufforderung und Toolkonfiguration. + +--- + +#### list + +Listen Sie alle verfügbaren Agenten auf. + +```bash +opencode agent list +``` + +--- + +### auth + +Befehl zum Verwalten von Anmeldeinformationen und Anmelden für Anbieter. + +```bash +opencode auth [command] +``` + +--- + +#### login + +OpenCode wird von der Anbieterliste bei [Models.dev](https://models.dev) unterstützt, sodass Sie `opencode auth login` verwenden können, um API-Schlüssel für jeden Anbieter zu konfigurieren, den Sie verwenden möchten. Dies wird in `~/.local/share/opencode/auth.json` gespeichert. + +```bash +opencode auth login +``` + +Wenn OpenCode startet, lädt es den Anbieter aus der Anmeldeinformationsdatei. Und ob in Ihren Umgebungen Schlüssel sind oder in Ihrem Projekt eine `.env`-Datei vorhanden ist. + +--- + +#### list + +Listet alle authentifizierten Anbieter auf, wie in der Anmeldeinformationsdatei gespeichert. + +```bash +opencode auth list +``` + +Oder die Kurzversion. + +```bash +opencode auth ls +``` + +--- + +#### logout + +Melden Sie sich von einem Anbieter ab, indem Sie ihn aus der Anmeldeinformationsdatei löschen. + +```bash +opencode auth logout +``` + +--- + +### github + +Verwalten Sie den GitHub-Agenten für die Repository-Automatisierung. + +```bash +opencode github [command] +``` + +--- + +#### install + +Installieren Sie den GitHub-Agenten in Ihrem Repository. + +```bash +opencode github install +``` + +Dadurch wird der erforderliche GitHub-Aktionsworkflow eingerichtet und Sie durch den Konfigurationsprozess geführt. [Learn more](/docs/github). + +--- + +#### run + +Führen Sie den GitHub-Agenten aus. Dies wird normalerweise in GitHub-Aktionen verwendet. + +```bash +opencode github run +``` + +##### Optionen + +| Flag | Beschreibung | +| --------- | --------------------------------------------------- | +| `--event` | GitHub Scheinereignis zum Ausführen des Agenten für | +| `--token` | GitHub persönliches Zugriffstoken | + +--- + +### mcp + +Verwalten Sie Model Context Protocol-Server. + +```bash +opencode mcp [command] +``` + +--- + +#### add + +Fügen Sie Ihrer Konfiguration einen MCP-Server hinzu. + +```bash +opencode mcp add +``` + +Dieser Befehl führt Sie durch das Hinzufügen eines lokalen oder Remote-MCP-Servers. + +--- + +#### list + +Listen Sie alle konfigurierten MCP-Server und deren Verbindungsstatus auf. + +```bash +opencode mcp list +``` + +Oder nutzen Sie die Kurzversion. + +```bash +opencode mcp ls +``` + +--- + +#### auth + +Authentifizieren Sie sich mit einem OAuth-fähigen MCP-Server. + +```bash +opencode mcp auth [name] +``` + +Wenn Sie keinen Servernamen angeben, werden Sie aufgefordert, einen der verfügbaren OAuth-fähigen Server auszuwählen. + +Sie können auch OAuth-fähige Server und deren Authentifizierungsstatus auflisten. + +```bash +opencode mcp auth list +``` + +Oder nutzen Sie die Kurzversion. + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +Entfernen Sie OAuth-Anmeldeinformationen für einen MCP-Server. + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +Beheben Sie OAuth-Verbindungsprobleme für einen MCP-Server. + +```bash +opencode mcp debug +``` + +--- + +### models + +Listen Sie alle verfügbaren Modelle der konfigurierten Anbieter auf. + +```bash +opencode models [provider] +``` + +Dieser Befehl zeigt alle bei Ihren konfigurierten Anbietern verfügbaren Modelle im Format `provider/model` an. + +Dies ist nützlich, um die genauen Modellnamen herauszufinden, die in [Ihrer Konfiguration](/docs/config/) verwendet werden sollen. + +Sie können optional eine Anbieter-ID übergeben, um Modelle nach diesem Anbieter zu filtern. + +```bash +opencode models anthropic +``` + +#### Optionen + +| Flag | Beschreibung | +| ----------- | ------------------------------------------------------------------------------------- | +| `--refresh` | Aktualisieren Sie den Modellcache von models.dev | +| `--verbose` | Verwenden Sie eine ausführlichere Modellausgabe (einschließlich Metadaten wie Kosten) | + +Verwenden Sie das Flag `--refresh`, um die zwischengespeicherte Modellliste zu aktualisieren. Dies ist nützlich, wenn einem Anbieter neue Modelle hinzugefügt wurden und Sie diese in OpenCode sehen möchten. + +```bash +opencode models --refresh +``` + +--- + +### run + +Führen Sie OpenCode im nicht interaktiven Modus aus, indem Sie direkt eine Eingabeaufforderung übergeben. + +```bash +opencode run [message..] +``` + +Dies ist nützlich für die Skripterstellung, die Automatisierung oder wenn Sie eine schnelle Antwort wünschen, ohne das vollständige TUI zu starten. Zum Beispiel: + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +Sie können auch eine Verbindung zu einer laufenden `opencode serve`-Instanz herstellen, um bei jedem Lauf Kaltstartzeiten für den MCP-Server zu vermeiden: + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### Optionen + +| Flag | Kurz | Beschreibung | +| ------------ | ---- | --------------------------------------------------------------------------------------------------- | +| `--command` | | Der auszuführende Befehl, Argumente als Nachricht verwenden | +| `--continue` | `-c` | Setzen Sie die letzte Sitzung fort | +| `--session` | `-s` | Session-ID zum Fortfahren | +| `--fork` | | Sitzung beim Fortsetzen verzweigen (mit `--continue` oder `--session` verwenden) | +| `--share` | | Teilen Sie die Sitzung | +| `--model` | `-m` | Zu verwendendes Modell in der Form provider/model | +| `--agent` | | Zu verwendender Agent | +| `--file` | `-f` | Datei(en) zum Anhängen an die Nachricht | +| `--format` | | Format: default (formatiert) oder json (rohe JSON-Ereignisse) | +| `--title` | | Titel für die Sitzung (verwendet eine verkürzte Eingabeaufforderung, wenn kein Wert angegeben wird) | +| `--attach` | | An einen laufenden OpenCode-Server anschließen (z.B. http://localhost:4096) | +| `--port` | | Port für den lokalen Server (standardmäßig zufälliger Port) | + +--- + +### serve + +Starten Sie einen Headless-OpenCode-Server für den API-Zugriff. Sehen Sie sich die [Server-Dokumentation](/docs/server) für die vollständige HTTP-Schnittstelle an. + +```bash +opencode serve +``` + +Dadurch wird ein HTTP-Server gestartet, der API-Zugriff auf OpenCode-Funktionalität ohne die TUI-Schnittstelle bietet. Legen Sie `OPENCODE_SERVER_PASSWORD` fest, um die HTTP-Basisauthentifizierung zu aktivieren (Benutzername ist standardmäßig `opencode`). + +#### Optionen + +| Flag | Beschreibung | +| ------------ | ----------------------------------------------- | +| `--port` | Port zum Abhören | +| `--hostname` | Hostname zum Abhören | +| `--mdns` | mDNS-Discovery aktivieren | +| `--cors` | Zusätzliche Browser-Ursprünge für CORS zulassen | + +--- + +### session + +OpenCode-Sitzungen verwalten. + +```bash +opencode session [command] +``` + +--- + +#### list + +Listen Sie alle OpenCode-Sitzungen auf. + +```bash +opencode session list +``` + +##### Optionen + +| Flag | Kurz | Beschreibung | +| ------------- | ---- | ---------------------------------------- | +| `--max-count` | `-n` | Beschränken auf die N neuesten Sitzungen | +| `--format` | | Ausgabeformat: table oder json (table) | + +--- + +### stats + +Zeigen Sie Token-Nutzungs- und Kostenstatistiken für Ihre OpenCode-Sitzungen an. + +```bash +opencode stats +``` + +#### Optionen + +| Flag | Beschreibung | +| ----------- | ------------------------------------------------------------------------------------------------------------------------------ | +| `--days` | Statistiken für die letzten N Tage anzeigen (alle Zeiten) | +| `--tools` | Anzahl der angebotenen Werkzeuge (alle) | +| `--models` | Aufschlüsselung der Modellnutzung anzeigen (standardmäßig ausgeblendet). Übergeben Sie eine Zahl, um die obersten N anzuzeigen | +| `--project` | Nach Projekt filtern (alle Projekte, leere Zeichenfolge: aktuelles Projekt) | + +--- + +### export + +Sitzungsdaten als JSON exportieren. + +```bash +opencode export [sessionID] +``` + +Wenn Sie keine Sitzungs-ID angeben, werden Sie aufgefordert, eine der verfügbaren Sitzungen auszuwählen. + +--- + +### import + +Importieren Sie Sitzungsdaten aus einer JSON-Datei oder einer OpenCode-Freigabe-URL. + +```bash +opencode import +``` + +Sie können aus einer lokalen Datei oder einer OpenCode-Freigabe-URL importieren. + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +Starten Sie einen Headless-OpenCode-Server mit einer Weboberfläche. + +```bash +opencode web +``` + +Dadurch wird ein HTTP-Server gestartet und ein Webbrowser geöffnet, um über eine Webschnittstelle auf OpenCode zuzugreifen. Legen Sie `OPENCODE_SERVER_PASSWORD` fest, um die HTTP-Basisauthentifizierung zu aktivieren (Benutzername ist standardmäßig `opencode`). + +#### Optionen + +| Flag | Beschreibung | +| ------------ | ----------------------------------------------- | +| `--port` | Port zum Abhören | +| `--hostname` | Hostname zum Abhören | +| `--mdns` | mDNS-Discovery aktivieren | +| `--cors` | Zusätzliche Browser-Ursprünge für CORS zulassen | + +--- + +### acp + +Starten Sie einen ACP (Agent Client Protocol) Server. + +```bash +opencode acp +``` + +Dieser Befehl startet einen ACP-Server, der über stdin/stdout unter Verwendung von nd-JSON kommuniziert. + +#### Optionen + +| Flag | Beschreibung | +| ------------ | -------------------- | +| `--cwd` | Arbeitsverzeichnis | +| `--port` | Port zum Abhören | +| `--hostname` | Hostname zum Abhören | + +--- + +### uninstall + +Deinstallieren Sie OpenCode und entfernen Sie alle zugehörigen Dateien. + +```bash +opencode uninstall +``` + +#### Optionen + +| Flag | Kurz | Beschreibung | +| --------------- | ---- | --------------------------------------------------- | +| `--keep-config` | `-c` | Konfigurationsdateien behalten | +| `--keep-data` | `-d` | Sitzungsdaten und Snapshots aufbewahren | +| `--dry-run` | | Zeigt, was entfernt werden würde, ohne zu entfernen | +| `--force` | `-f` | Bestätigungsaufforderungen überspringen | + +--- + +### upgrade + +Aktualisiert OpenCode auf die neueste Version oder eine bestimmte Version. + +```bash +opencode upgrade [target] +``` + +Um auf die neueste Version zu aktualisieren: + +```bash +opencode upgrade +``` + +Um auf eine bestimmte Version zu aktualisieren. + +```bash +opencode upgrade v0.1.48 +``` + +#### Optionen + +| Flag | Kurz | Beschreibung | +| ---------- | ---- | ------------------------------------------------------------------- | +| `--method` | `-m` | Die zu verwendende Installationsmethode; curl, npm, pnpm, bun, brew | + +--- + +## Globale Flags + +Der OpenCode CLI akzeptiert die folgenden globalen Flags. + +| Flag | Kurz | Beschreibung | +| -------------- | ---- | ----------------------------------------- | +| `--help` | `-h` | Hilfe anzeigen | +| `--version` | `-v` | Versionsnummer drucken | +| `--print-logs` | | Protokolle nach stderr drucken | +| `--log-level` | | Protokollebene (DEBUG, INFO, WARN, ERROR) | + +--- + +## Umgebungsvariablen + +OpenCode kann mithilfe von Umgebungsvariablen konfiguriert werden. + +| Variable | Typ | Beschreibung | +| ------------------------------------- | --------------- | -------------------------------------------------------------------------------- | +| `OPENCODE_AUTO_SHARE` | boolescher Wert | Sitzungen automatisch teilen | +| `OPENCODE_GIT_BASH_PATH` | Zeichenfolge | Pfad zur ausführbaren Git Bash-Datei unter Windows | +| `OPENCODE_CONFIG` | Zeichenfolge | Pfad zur Konfigurationsdatei | +| `OPENCODE_CONFIG_DIR` | Zeichenfolge | Pfad zum Konfigurationsverzeichnis | +| `OPENCODE_CONFIG_CONTENT` | Zeichenfolge | Inline-JSON-Konfigurationsinhalt | +| `OPENCODE_DISABLE_AUTOUPDATE` | boolescher Wert | Automatische Update-Prüfungen deaktivieren | +| `OPENCODE_DISABLE_PRUNE` | boolescher Wert | Bereinigung alter Daten deaktivieren | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolescher Wert | Deaktivieren Sie die automatische Aktualisierung von Terminaltiteln | +| `OPENCODE_PERMISSION` | Zeichenfolge | Inline-JSON-Berechtigungskonfiguration | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolescher Wert | Standard-Plugins deaktivieren | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolescher Wert | Automatische LSP-Server-Downloads deaktivieren | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolescher Wert | Experimentelle Modelle aktivieren | +| `OPENCODE_DISABLE_AUTOCOMPACT` | boolescher Wert | Automatische Kontextkomprimierung deaktivieren | +| `OPENCODE_DISABLE_CLAUDE_CODE` | boolescher Wert | Deaktivieren Sie das Lesen von `.claude` (Prompt + Skills) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolescher Wert | Deaktivieren Sie das Lesen von `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolescher Wert | Deaktivieren Sie das Laden von `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | boolescher Wert | Deaktivieren Sie das Abrufen von Modellen aus Remote-Quellen | +| `OPENCODE_FAKE_VCS` | Zeichenfolge | Gefälschter VCS-Anbieter zu Testzwecken | +| `OPENCODE_DISABLE_FILETIME_CHECK` | boolescher Wert | Dateizeitprüfung zur Optimierung deaktivieren | +| `OPENCODE_CLIENT` | Zeichenfolge | Client-ID (standardmäßig `cli`) | +| `OPENCODE_ENABLE_EXA` | boolescher Wert | Exa-Websuchtools aktivieren | +| `OPENCODE_SERVER_PASSWORD` | Zeichenfolge | Aktivieren Sie die Basisauthentifizierung für `serve`/`web` | +| `OPENCODE_SERVER_USERNAME` | Zeichenfolge | Benutzernamen für die Basisauthentifizierung überschreiben (Standard `opencode`) | +| `OPENCODE_MODELS_URL` | Zeichenfolge | Benutzerdefinierte URL zum Abrufen der Modellkonfiguration | + +--- + +### Experimentell + +Diese Umgebungsvariablen ermöglichen experimentelle Funktionen, die sich ändern oder entfernt werden können. + +| Variable | Typ | Beschreibung | +| ----------------------------------------------- | --------------- | ------------------------------------------------------- | +| `OPENCODE_EXPERIMENTAL` | boolescher Wert | Alle experimentellen Funktionen aktivieren | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolescher Wert | Symbolerkennung aktivieren | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolescher Wert | Kopieren bei Auswahl in TUI deaktivieren | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | Zahl | Standard-Timeout für Bash-Befehle in ms | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | Zahl | Maximale Ausgabetokens für LLM-Antworten | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolescher Wert | Dateiüberwachung für das gesamte Verzeichnis aktivieren | +| `OPENCODE_EXPERIMENTAL_OXFMT` | boolescher Wert | Oxfmt-Formatierer aktivieren | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolescher Wert | Experimentelles LSP-Tool aktivieren | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolescher Wert | Dateiüberwachung deaktivieren | +| `OPENCODE_EXPERIMENTAL_EXA` | boolescher Wert | Experimentelle Exa-Funktionen aktivieren | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolescher Wert | Experimentelle LSP-Typprüfung aktivieren | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolescher Wert | Experimentelle Markdown-Funktionen aktivieren | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolescher Wert | Planmodus aktivieren | diff --git a/packages/web/src/content/docs/de/commands.mdx b/packages/web/src/content/docs/de/commands.mdx new file mode 100644 index 00000000000..5c795fba0c5 --- /dev/null +++ b/packages/web/src/content/docs/de/commands.mdx @@ -0,0 +1,323 @@ +--- +title: Befehle +description: Erstellen Sie benutzerdefinierte Befehle für sich wiederholende Aufgaben. +--- + +Mit benutzerdefinierten Befehlen können Sie eine Eingabeaufforderung angeben, die ausgeführt werden soll, wenn dieser Befehl im TUI ausgeführt wird. + +```bash frame="none" +/my-command +``` + +Benutzerdefinierte Befehle gibt es zusätzlich zu den integrierten Befehlen wie `/init`, `/undo`, `/redo`, `/share`, `/help`. [Mehr erfahren](/docs/tui#commands). + +--- + +## Befehlsdateien erstellen + +Erstellen Sie Markdown-Dateien im Verzeichnis `commands/`, um benutzerdefinierte Befehle zu definieren. + +Erstellen Sie `.opencode/commands/test.md`: + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Der Frontmatter definiert Befehlseigenschaften. Der Inhalt wird zur Vorlage. + +Verwenden Sie den Befehl, indem Sie `/` folgen vom Befehlsnamen eingeben. + +```bash frame="none" +"/test" +``` + +--- + +## Konfiguration + +Sie können benutzerdefinierte Befehle über die OpenCode-Konfiguration hinzufügen oder indem Sie Markdown-Dateien im Verzeichnis `commands/` erstellen. + +--- + +### JSON + +Verwenden Sie die Option `command` in Ihrem OpenCode [config](/docs/config): + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Jetzt können Sie diesen Befehl im TUI ausführen: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +Sie können Befehle auch mithilfe von Markdown-Dateien definieren. Platzieren Sie sie in: + +- Global: `~/.config/opencode/commands/` +- Pro Projekt: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Der Name der Markdown-Datei wird zum Befehlsnamen. Zum Beispiel `test.md` lässt +Du läufst: + +```bash frame="none" +/test +``` + +--- + +## Prompt-Konfiguration + +Die Eingabeaufforderungen für die benutzerdefinierten Befehle unterstützen mehrere spezielle Platzhalter und Syntax. + +--- + +### Argumente + +Übergeben Sie Argumente an Befehle mithilfe des Platzhalters `$ARGUMENTS`. + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +Führen Sie den Befehl mit Argumenten aus: + +```bash frame="none" +/component Button +``` + +Und `$ARGUMENTS` wird durch `Button` ersetzt. + +Sie können auch über Positionsparameter auf einzelne Argumente zugreifen: + +- `$1` – Erstes Argument +- `$2` – Zweites Argument +- `$3` – Drittes Argument +- Und so weiter... + +Zum Beispiel: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +Führen Sie den Befehl aus: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +Dies ersetzt: + +- `$1` mit `config.json` +- `$2` mit `src` +- `$3` mit `{ "key": "value" }` + +--- + +### Shell-Ausgabe + +Verwenden Sie _!`command`_, um die Ausgabe [bash command](/docs/tui#bash-commands) in Ihre Eingabeaufforderung einzufügen. + +So erstellen Sie beispielsweise einen benutzerdefinierten Befehl, der die Testabdeckung analysiert: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +Oder um die letzten Änderungen zu überprüfen: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +Befehle werden im Stammverzeichnis Ihres Projekts ausgeführt und ihre Ausgabe wird Teil der Eingabeaufforderung. + +--- + +### Dateiverweise + +Fügen Sie Dateien in Ihren Befehl ein, indem Sie `@` folgend vom Dateinamen verwenden. + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +Der Dateiinhalt wird automatisch in die Eingabeaufforderung einbezogen. + +--- + +## Optionen + +Schauen wir uns die Konfigurationsmöglichkeiten im Detail an. + +--- + +### Template + +Die Option `template` die Eingabeaufforderung, die an LLM gesendet wird, wenn der Befehl ausgeführt wird. + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +Dies ist eine **erforderliche** Konfigurationsoption. + +--- + +### Description + +Verwenden Sie die Option `description`, um eine kurze Beschreibung der Funktion des Befehls bereitzustellen. + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +Dies wird als Beschreibung im TUI angezeigt, wenn Sie den Befehl eingeben. + +--- + +### Agent + +Verwenden Sie die `agent`-Konfiguration, um optional anzugeben, welche [agent](/docs/agents) diesen Befehl ausführen soll. +Wenn es sich um einen [subagent](/docs/agents/#subagents) handelt, löst der Befehl standardmäßig einen Subagentenaufruf aus. +Um dieses Verhalten zu deaktivieren, setzen Sie `subtask` auf `false`. + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +Dies ist eine **optionale** Konfigurationsoption. Wenn nicht angegeben, wird standardmäßig Ihr aktueller Agent verwendet. + +--- + +### Subtask + +Verwenden Sie den booleschen Wert `subtask`, um zu erzwingen, dass der Befehl einen [subagent](/docs/agents/#subagents)-Aufruf auslöst. +Dies ist nützlich, wenn Sie möchten, dass der Befehl Ihren primären Kontext nicht verunreinigt und den Agenten dazu zwingt, als Subagent zu fungieren. +auch wenn `mode` in der [agent](/docs/agents)-Konfiguration auf `primary` gesetzt ist. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +Dies ist eine **optionale** Konfigurationsoption. + +--- + +### Model + +Verwenden Sie die `model`-Konfiguration, um das Standardmodell für diesen Befehl zu überschreiben. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Dies ist eine **optionale** Konfigurationsoption. + +--- + +## Integriert + +OpenCode enthält mehrere integrierte Befehle wie `/init`, `/undo`, `/redo`, `/share`, `/help`; [mehr erfahren](/docs/tui#commands). + +:::note +Benutzerdefinierte Befehle können integrierte Befehle überschreiben. +::: + +Wenn Sie einen benutzerdefinierten Befehl mit demselben Namen definieren, überschreibt dieser den integrierten Befehl. diff --git a/packages/web/src/content/docs/de/config.mdx b/packages/web/src/content/docs/de/config.mdx new file mode 100644 index 00000000000..0a2040be7a1 --- /dev/null +++ b/packages/web/src/content/docs/de/config.mdx @@ -0,0 +1,684 @@ +--- +title: Konfiguration +description: Verwenden Sie die Konfiguration OpenCode JSON. +--- + +Sie können OpenCode mithilfe einer JSON-Konfigurationsdatei konfigurieren. + +--- + +## Format + +OpenCode unterstützt die Formate **JSON** und **JSONC** (JSON mit Kommentaren). + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + // Theme configuration + "theme": "opencode", + "model": "anthropic/claude-sonnet-4-5", + "autoupdate": true, +} +``` + +--- + +## Speicherorte + +Sie können Ihre Konfiguration an verschiedenen Orten platzieren und sie haben eine +andere Rangfolge. + +:::note +Konfigurationsdateien werden **zusammengeführt**, nicht ersetzt. +::: + +Konfigurationsdateien werden zusammengeführt und nicht ersetzt. Einstellungen aus den folgenden Konfigurationsspeicherorten werden kombiniert. Spätere Konfigurationen überschreiben frühere nur bei Schlüsselkonflikten. Es bleiben keine widersprüchlichen Einstellungen aus allen Konfigurationen erhalten. + +Wenn Ihre globale Konfiguration beispielsweise `theme: "opencode"` und `autoupdate: true` und Ihre Projektkonfiguration `model: "anthropic/claude-sonnet-4-5"` festlegt, umfasst die endgültige Konfiguration alle drei Einstellungen. + +--- + +### Rangfolge + +Konfigurationsquellen werden in dieser Reihenfolge geladen (spätere Quellen überschreiben frühere): + +1. **Remote-Konfiguration** (von `.well-known/opencode`) – Organisationsstandards +2. **Globale Konfiguration** (`~/.config/opencode/opencode.json`) – Benutzereinstellungen +3. **Benutzerdefinierte Konfiguration** (`OPENCODE_CONFIG` env var) – benutzerdefinierte Überschreibungen +4. **Projektkonfiguration** (`opencode.json` im Projekt) – projektspezifische Einstellungen +5. **`.opencode` Verzeichnisse** – Agenten, Befehle, Plugins +6. **Inline-Konfiguration** (`OPENCODE_CONFIG_CONTENT` env var) – Laufzeitüberschreibungen + +Dies bedeutet, dass Projektkonfigurationen globale Standardeinstellungen überschreiben können und globale Konfigurationen Remote-Organisationsstandards überschreiben können. + +:::note +Die Verzeichnisse `.opencode` und `~/.config/opencode` verwenden **Pluralnamen** für Unterverzeichnisse: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/` und `themes/`. Aus Gründen der Abwärtskompatibilität werden auch einzelne Namen (z. B. `agent/`) unterstützt. +::: + +--- + +### Remote + +Organisationen können die Standardkonfiguration über den Endpunkt `.well-known/opencode` bereitstellen. Dieser wird automatisch abgerufen, wenn Sie sich bei einem Anbieter authentifizieren, der dies unterstützt. + +Zuerst wird die Remote-Konfiguration geladen, die als Basisschicht dient. Alle anderen Konfigurationsquellen (global, Projekt) können diese Standardeinstellungen überschreiben. + +Wenn Ihre Organisation beispielsweise MCP-Server bereitstellt, sind die standardmäßig deaktiviert: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +Sie können bestimmte Server in Ihrer lokalen Konfiguration aktivieren: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### Global + +Platzieren Sie Ihre globale OpenCode-Konfiguration in `~/.config/opencode/opencode.json`. Verwenden Sie die globale Konfiguration für benutzerweite Einstellungen wie Themen, Anbieter oder Tastenkombinationen. + +Die globale Konfiguration überschreibt die Standardeinstellungen der Remote-Organisation. + +--- + +### Pro Projekt + +Fügen Sie `opencode.json` in Ihrem Projektstamm hinzu. Die Projektkonfiguration hat unter den Standardkonfigurationsdateien die höchste Priorität – sie überschreibt sowohl globale als auch Remote-Konfigurationen. + +:::tip +Platzieren Sie die projektspezifische Konfiguration im Stammverzeichnis Ihres Projekts. +::: + +Wenn OpenCode gestartet wird, sucht es im aktuellen Verzeichnis nach einer Konfigurationsdatei oder durchsucht das nächstgelegene Git-Verzeichnis. + +Dies kann auch sicher in Git eingecheckt werden und dasselbe Schema wie das globale verwenden. + +--- + +### Benutzerdefinierter Pfad + +Geben Sie mithilfe der Umgebungsvariablen `OPENCODE_CONFIG` einen benutzerdefinierten Konfigurationsdateipfad an. + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +Die benutzerdefinierte Konfiguration wird in der Rangfolge zwischen globalen und Projektkonfigurationen geladen. + +--- + +### Benutzerdefiniertes Verzeichnis + +Geben Sie mit `OPENCODE_CONFIG_DIR` ein benutzerdefiniertes Konfigurationsverzeichnis an. +Umgebungsvariable. Dieses Verzeichnis wird nach Agenten, Befehlen, +Modi und Plugins genau wie das Standardverzeichnis `.opencode` und sollten +folgen der gleichen Struktur. + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +Das benutzerdefinierte Verzeichnis wird nach den Verzeichnissen global config und `.opencode` geladen, sodass es deren Einstellungen **überschreiben** kann. + +--- + +## Schema + +Die Konfigurationsdatei verfügt über ein Schema, das in [**`opencode.ai/config.json`**](https://opencode.ai/config.json) definiert ist. + +Ihr Editor sollte in der Lage sein, basierend auf dem Schema zu validieren und automatisch zu vervollständigen. + +--- + +### TUI + +Sie können TUI-spezifische Einstellungen über die Option `tui` konfigurieren. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +Verfügbare Optionen: + +- `scroll_acceleration.enabled` – Scrollbeschleunigung im macOS-Stil aktivieren. **Hat Vorrang vor `scroll_speed`.** +- `scroll_speed` – Benutzerdefinierter Scrollgeschwindigkeitsmultiplikator (Standard: `3`, Minimum: `1`). Wird ignoriert, wenn `scroll_acceleration.enabled` gleich `true` ist. +- `diff_style` – Steuern Sie das Diff-Rendering. `"auto"` passt sich der Terminalbreite an, `"stacked"` zeigt immer eine einzelne Spalte an. + +[Erfahren Sie hier mehr über die Verwendung der TUI](/docs/tui). + +--- + +### Server + +Sie können Servereinstellungen für die Befehle `opencode serve` und `opencode web` über die Option `server` konfigurieren. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +Verfügbare Optionen: + +- `port` – Port zum Abhören. +- `hostname` – Hostname zum Abhören. Wenn `mdns` aktiviert ist und kein Hostname festgelegt ist, wird standardmäßig `0.0.0.0` verwendet. +- `mdns` – mDNS-Diensterkennung aktivieren. Dadurch können andere Geräte im Netzwerk Ihres OpenCode-Servers erkannt werden. +- `mdnsDomain` – Benutzerdefinierter Domänenname für den mDNS-Dienst. Standardmäßig ist `opencode.local`. Nützlich für die Ausführung mehrerer Instanzen im selben Netzwerk. +- `cors` – Zusätzliche Ursprünge, um CORS zu ermöglichen, wenn der HTTP-Server von einem browserbasierten Client aus verwendet wird. Die Werte müssen vollständige Ursprünge haben (Schema + Host + optionaler Port), z. B. `https://app.example.com`. + +[Erfahren Sie hier mehr über den Server](/docs/server). + +--- + +### Werkzeuge + +Sie können die Tools, die ein LLM verwenden kann, über die Option `tools` verwalten. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[Erfahren Sie hier mehr über Tools](/docs/tools). + +--- + +### Modelle + +Sie können die Anbieter und Modelle, die Sie in Ihrer OpenCode-Konfiguration verwenden möchten, über die Optionen `provider`, `model` und `small_model` konfigurieren. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +Die Option `small_model` konfiguriert ein separates Modell für einfache Aufgaben wie die Titelgenerierung. Standardmäßig versucht OpenCode, ein günstigeres Modell zu verwenden, sofern eines bei Ihrem Anbieter verfügbar ist, andernfalls greift es auf Ihr Hauptmodell zurück. + +Zu den Anbieteroptionen können `timeout` und `setCacheKey` gehören: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` – Anforderungszeitlimit in Millisekunden (Standard: 300000). Zum Deaktivieren auf `false` setzen. +- `setCacheKey` – Stellen Sie sicher, dass immer ein Cache-Schlüssel für den angegebenen Anbieter festgelegt ist. + +Sie können auch [lokale Modelle](/docs/models#local) konfigurieren. [Mehr erfahren](/docs/models). + +--- + +#### Anbieterspezifische Optionen + +Einige Anbieter unterstützen zusätzliche Konfigurationsoptionen über die allgemeinen Einstellungen `timeout` und `apiKey` hinaus. + +##### Amazon Bedrock + +Amazon Bedrock unterstützt AWS-spezifische Konfigurationen: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` – AWS-Region für Bedrock (standardmäßig `AWS_REGION` env var oder `us-east-1`) +- `profile` – AWS benanntes Profil von `~/.aws/credentials` (standardmäßig `AWS_PROFILE` Umgebungsvariable) +- `endpoint` – Benutzerdefinierter Endpunkt URL für VPC-Endpunkte. Dies ist ein Alias ​​​​für die generische Option `baseURL` unter Verwendung der AWS-spezifischen Terminologie. Wenn beide angegeben sind, hat `endpoint` Vorrang. + +:::note +Inhabertoken (`AWS_BEARER_TOKEN_BEDROCK` oder `/connect`) haben Vorrang vor der profilbasierten Authentifizierung. Weitere Informationen finden Sie unter [Authentifizierungs-Rangfolge](/docs/providers#authentication-precedence). +::: + +[Erfahren Sie mehr über die Amazon Bedrock-Konfiguration](/docs/providers#amazon-bedrock). + +--- + +### Themen + +Sie können das Thema, das Sie in Ihrer OpenCode-Konfiguration verwenden möchten, über die Option `theme` konfigurieren. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[Mehr erfahren](/docs/themes). + +--- + +### Agenten + +Über die Option `agent` können Sie spezielle Agenten für bestimmte Aufgaben konfigurieren. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +Sie können Agenten auch mithilfe von Markdown-Dateien in `~/.config/opencode/agents/` oder `.opencode/agents/` definieren. [Mehr erfahren](/docs/agents). + +--- + +### Standardagent + +Sie können den Standardagenten mit der Option `default_agent` festlegen. Dadurch wird bestimmt, welcher Agent verwendet wird, wenn keiner explizit angegeben wird. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +Der Standardagent muss ein Primäragent (kein Subagent) sein. Dies kann ein integrierter Agent wie `"build"` oder `"plan"` oder ein von Ihnen definierter [custom agent](/docs/agents) sein. Wenn der angegebene Agent nicht existiert oder ein Subagent ist, greift OpenCode mit einer Warnung auf `"build"` zurück. + +Diese Einstellung gilt für alle Schnittstellen: TUI, CLI (`opencode run`), Desktop-App und GitHub Aktion. + +--- + +### Teilen + +Sie können die Funktion [share](/docs/share) über die Option `share` konfigurieren. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +Dazu braucht es: + +- `"manual"` – Manuelles Teilen über Befehle zulassen (Standard) +- `"auto"` – Neue Konversationen automatisch teilen +- `"disabled"` – Teile vollständig deaktivieren + +Standardmäßig ist die Freigabe auf den manuellen Modus eingestellt, in dem Sie Konversationen explizit mit dem Befehl `/share` teilen müssen. + +--- + +### Befehle + +Sie können benutzerdefinierte Befehle für sich wiederholende Aufgaben über die Option `command` konfigurieren. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +Sie können Befehle auch mithilfe von Markdown-Dateien in `~/.config/opencode/commands/` oder `.opencode/commands/` definieren. [Mehr erfahren](/docs/commands). + +--- + +### Tastenkombinationen + +Sie können Ihre Tastenkombinationen über die Option `keybinds` anpassen. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[Mehr erfahren](/docs/keybinds). + +--- + +### Automatisches Update + +OpenCode lädt beim Start automatisch alle neuen Updates herunter. Sie können dies mit der Option `autoupdate` deaktivieren. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +Wenn Sie keine Updates wünschen, aber dringend möchten, wenn eine neue Version verfügbar ist, setzen Sie `autoupdate` auf `"notify"`. +Beachten Sie, dass dies nur funktioniert, wenn es nicht mit einem Paketmanager wie Homebrew installiert wurde. + +--- + +### Formatierer + +Sie können Codeformatierer über die Option `formatter` konfigurieren. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[Erfahren Sie hier mehr über Formatierer](/docs/formatters). + +--- + +### Berechtigungen + +OpenCode erlaubt standardmäßig alle Vorgänge, ohne dass eine ausdrückliche Genehmigung erforderlich ist. Sie können dies mit der Option `permission` ändern. + +Um beispielsweise sicherzustellen, dass die Tools `edit` und `bash` eine Benutzergenehmigung erfordern: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[Erfahren Sie hier mehr über Berechtigungen](/docs/permissions). + +--- + +### Komprimierung + +Sie können das Verhalten der Kontextkomprimierung über die Option `compaction` steuern. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto` – Die Sitzung wird automatisch komprimieren, wenn der Kontext voll ist (Standard: `true`). +- `prune` – Alte Tool-Ausgaben entfernen, um Token zu sparen (Standard: `true`). + +--- + +### Dateiüberwachung + +Sie können Datei-Watcher-Ignoriermuster über die Option `watcher` konfigurieren. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +Muster folgen der Glob-Syntax. Verwenden Sie diese Option, um verrauschte Verzeichnisse von der Dateiüberwachung auszuschließen. + +--- + +### MCP + +Sie können den MCP-Server, den Sie verwenden möchten, über die Option `mcp` konfigurieren. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[Mehr erfahren](/docs/mcp-servers). + +--- + +### Plugins + +[Plugins](/docs/plugins) erweitert OpenCode mit benutzerdefinierten Tools, Hooks und Integrationen. + +Platzieren Sie Ihre Plugin-Dateien in `.opencode/plugins/` oder `~/.config/opencode/plugins/`. Sie können Plugins auch über die Option `plugin` von npm laden. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[Mehr erfahren](/docs/plugins). + +--- + +### Anweisungen + +Sie können die Anweisungen für das von Ihnen verwendete Modell über die Option `instructions` konfigurieren. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Dies erfordert eine Reihe von Pfaden und Glob-Mustern zu Anweisungsdateien. [Erfahren Sie hier mehr über Regeln](/docs/rules). + +--- + +### Deaktivierte Anbieter + +Sie können Anbieter, die automatisch geladen werden, über die Option `disabled_providers` deaktivieren. Dies ist nützlich, wenn Sie verhindern möchten, dass bestimmte Anbieter geladen werden, selbst wenn deren Anmeldeinformationen verfügbar sind. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +Der `disabled_providers` hat Vorrang vor `enabled_providers`. +::: + +Die Option `disabled_providers` akzeptiert ein Array des Anbieters IDs. Wenn ein Anbieter deaktiviert ist: + +- Es wird nicht geladen, selbst wenn Umgebungsvariablen festgelegt sind. +- Es wird nicht geladen, selbst wenn API-Schlüssel über den Befehl `/connect` konfiguriert werden. +- Die Modelle des Anbieters erscheinen nicht in der Modellauswahlliste. + +--- + +### Aktivierte Anbieter + +Sie können über die Option `enabled_providers` eine Zulassungsliste für Anbieter angeben. Wenn diese Option festgelegt ist, werden nur die angegebenen Anbieter aktiviert und alle anderen werden ignoriert. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +Dies ist nützlich, wenn Sie OpenCode darauf beschränken möchten, nur bestimmte Anbieter zu verwenden, anstatt sie einzeln zu deaktivieren. + +:::note +Der `disabled_providers` hat Vorrang vor `enabled_providers`. +::: + +Wenn ein Anbieter sowohl in `enabled_providers` als auch in `disabled_providers` vorkommt, hat `disabled_providers` aus Gründen der Abwärtskompatibilität Vorrang. + +--- + +### Experimentell + +Der Schlüssel `experimental` enthält Optionen, die sich in der aktiven Entwicklung befinden. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +Experimentelle Optionen sind nicht stabil. Sie können ohne vorherige Ankündigung geändert oder entfernt werden. +::: + +--- + +## Variablen + +Sie können die Variablenersetzung in Ihren Konfigurationsdateien verwenden, um auf Umgebungsvariablen und Dateiinhalte zu verweisen. + +--- + +### Umgebungsvariablen + +Verwenden Sie `{env:VARIABLE_NAME}`, um Umgebungsvariablen zu ersetzen: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +Wenn die Umgebungsvariable nicht gesetzt ist, wird sie durch eine leere Zeichenfolge ersetzt. + +--- + +### Dateien + +Verwenden Sie `{file:path/to/file}`, um den Inhalt einer Datei zu ersetzen: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +Dateipfade können sein: + +- Relativ zum Konfigurationsdateiverzeichnis +- Oder absolute Pfade beginnend mit `/` oder `~` + +Diese sind nützlich für: + +- Bewahren Sie vertrauliche Daten wie API-Schlüssel in separaten Dateien auf. +- Einschließlich große Anweisungsdateien, ohne Ihre Konfiguration zu überladen. +- Gemeinsame Nutzung gemeinsamer Konfigurationsausschnitte über mehrere Konfigurationsdateien hinweg. diff --git a/packages/web/src/content/docs/de/custom-tools.mdx b/packages/web/src/content/docs/de/custom-tools.mdx new file mode 100644 index 00000000000..a6dfd64d5ab --- /dev/null +++ b/packages/web/src/content/docs/de/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: Benutzerdefinierte Tools +description: Erstellen Sie Tools, die der LLM in OpenCode aufrufen kann. +--- + +Benutzerdefinierte Tools sind von Ihnen erstellte Funktionen, die der LLM während Gesprächen aufrufen kann. Sie arbeiten neben [built-in tools](/docs/tools) von OpenCode wie `read`, `write` und `bash`. + +--- + +## Ein Tool erstellen + +Tools werden als **TypeScript**- oder **JavaScript**-Dateien definiert. Die Tooldefinition kann jedoch Skripte aufrufen, die in **jeder Sprache** geschrieben sind – TypeScript oder JavaScript wird nur für die Tooldefinition selbst verwendet. + +--- + +### Speicherort + +Sie können wie folgt definiert werden: + +- Lokal, indem Sie sie im Verzeichnis `.opencode/tools/` Ihres Projekts platzieren. +- Oder global, indem Sie sie in `~/.config/opencode/tools/` platzieren. + +--- + +### Struktur + +Der einfachste Weg, Tools zu erstellen, ist die Verwendung des `tool()`-Helfers, der Typsicherheit und Validierung bietet. + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +Der **Dateiname** wird zum **Toolnamen**. Das Obige erstellt ein `database`-Tool. + +--- + +#### Mehrere Werkzeuge pro Datei + +Sie können auch mehrere Tools aus einer einzigen Datei exportieren. Jeder Export wird zu **einem separaten Tool** mit dem Namen **`_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +Dadurch werden zwei Tools erstellt: `math_add` und `math_multiply`. + +--- + +### Argumente + +Sie können `tool.schema` verwenden, was nur [Zod](https://zod.dev) ist, um Argumenttypen zu definieren. + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +Sie können [Zod](https://zod.dev) auch direkt importieren und ein ähnliches Objekt zurückgeben: + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### Kontext + +Tools erhalten Kontext zur aktuellen Sitzung: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +Verwenden Sie `context.directory` für das Sitzungsarbeitsverzeichnis. +Verwenden Sie `context.worktree` für das Stammverzeichnis des Git-Arbeitsbaums. + +--- + +## Beispiele + +### Ein Tool in Python schreiben + +Sie können Ihre Tools in jeder gewünschten Sprache schreiben. Hier ist ein Beispiel, das mit Python zwei Zahlen addiert. + +Erstellen Sie zunächst das Tool als Python-Skript: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +Erstellen Sie dann die Werkzeugdefinition, die es aufruft: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +Hier verwenden wir das Dienstprogramm [`Bun.$`](https://bun.com/docs/runtime/shell), um das Python-Skript auszuführen. diff --git a/packages/web/src/content/docs/de/ecosystem.mdx b/packages/web/src/content/docs/de/ecosystem.mdx new file mode 100644 index 00000000000..ea1bc589a4b --- /dev/null +++ b/packages/web/src/content/docs/de/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: Ökosystem +description: Mit OpenCode erstellte Projekte und Integrationen. +--- + +Eine Sammlung von Community-Projekten, die auf OpenCode basieren. + +:::note +Möchten Sie Ihr OpenCode-bezogenes Projekt zu dieser Liste hinzufügen? Senden Sie einen PR. +::: + +Sie können sich auch [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) und [opencode.cafe](https://opencode.cafe) ansehen, eine Community, die das Ökosystem und die Community zusammenfasst. + +--- + +## Plugins + +| Name | Beschreibung | +| --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | Führen Sie OpenCode-Sitzungen automatisch in isolierten Daytona-Sandboxes mit Git-Synchronisierung und Live-Vorschauen aus | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | Helicone-Sitzungsheader für die Anforderungsgruppierung automatisch einfügen | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | TypeScript/Svelte-Typen mit Suchtools automatisch in Dateilesevorgänge einfügen | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | Verwenden Sie Ihr ChatGPT Plus/Pro-Abonnement anstelle von API Credits | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | Verwenden Sie Ihren bestehenden Gemini-Plan anstelle der API-Abrechnung | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | Nutzen Sie die kostenlosen Modelle von Antigravity anstelle der API-Abrechnung | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Multi-Branch-Devcontainer-Isolierung mit flachen Klonen und automatisch zugewiesenen Ports | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Google Antigravity OAuth-Plugin mit Unterstützung für die Google-Suche und robustere API-Verarbeitung | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Optimieren Sie die Token-Nutzung, indem Sie veraltete Tool-Ausgaben bereinigen | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Fügen Sie native Websuchunterstützung für unterstützte Anbieter mit Google Grounded Style hinzu | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Ermöglicht AI-Agenten, Hintergrundprozesse in einem PTY auszuführen und ihnen interaktive Eingaben zu senden. | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Anweisungen für nicht interaktive Shell-Befehle – verhindert Abstürze bei TTY-abhängigen Vorgängen | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Verfolgen Sie die Nutzung von OpenCode mit Wakatime | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Von LLMs erstellte Abschriftentabellen bereinigen | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | 10x schnellere Codebearbeitung mit Morph Fast Apply API und Lazy-Edit-Markern | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Hintergrundagenten, vorgefertigte LSP/AST/MCP-Tools, kuratierte Agenten, Claude Code-kompatibel | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | Desktop-Benachrichtigungen und akustische Warnungen für OpenCode-Sitzungen | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Desktop-Benachrichtigungen und akustische Warnungen für Berechtigungs-, Abschluss- und Fehlerereignisse | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | AI-gestützte automatische Benennung von Zellij-Sitzungen basierend auf dem OpenCode-Kontext | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Ermöglichen Sie OpenCode-Agenten das verzögerte Laden von Eingabeaufforderungen bei Bedarf mit Skill-Erkennung und -Injektion | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Persistenter Speicher über Sitzungen hinweg mit Supermemory | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Interaktive Planüberprüfung mit visueller Anmerkung und private/offline-Freigabe | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Erweitern Sie OpenCode /commands zu einem leistungsstarken Orchestrierungssystem mit granularer Flusskontrolle | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | Planen Sie wiederkehrende Jobs mit launchd (Mac) oder systemd (Linux) mit Cron-Syntax | +| [micode](https://github.com/vtemian/micode) | Strukturiertes Brainstorming → Planen → Workflow mit Sitzungskontinuität Implementierung | +| [octto](https://github.com/vtemian/octto) | Interaktiver Browser UI für AI Brainstorming mit Formularen mit mehreren Fragen | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | Hintergrundagenten im Claude Code-Stil mit asynchroner Delegation und Kontextpersistenz | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | Native OS-Benachrichtigungen für OpenCode – wissen, wann Aufgaben erledigt sind | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | Gebündelter Multi-Agent-Orchestrierungs-Harness – 16 Komponenten, eine Installation | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | Reibungslose Git-Arbeitsbäume für OpenCode | + +--- + +## Projekte + +| Name | Beschreibung | +| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------- | +| [kimaki](https://github.com/remorses/kimaki) | Discord-Bot zur Steuerung von OpenCode-Sitzungen, basierend auf SDK | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Neovim-Plugin für editorfähige Eingabeaufforderungen, basierend auf API | +| [portal](https://github.com/hosenur/portal) | Mobile-First-Web UI für OpenCode über Tailscale/VPN | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | Vorlage zum Erstellen von OpenCode-Plugins | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Neovim-Frontend für OpenCode – ein terminalbasierter AI-Coding-Agent | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Vercel AI SDK Anbieter für die Verwendung von OpenCode über @opencode-ai/sdk | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | Web-/Desktop-App und VS Code-Erweiterung für OpenCode | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Obsidian-Plugin, das OpenCode in Obsidians UI einbettet | +| [OpenWork](https://github.com/different-ai/openwork) | Eine Open-Source-Alternative zu Claude Cowork, unterstützt von OpenCode | +| [ocx](https://github.com/kdcokenny/ocx) | OpenCode Erweiterungsmanager mit portablen, isolierten Profilen. | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | Desktop-, Web-, Mobil- und Remote-Client-App für OpenCode | + +--- + +## Agenten + +| Name | Beschreibung | +| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | +| [Agentic](https://github.com/Cluster444/agentic) | Modulare AI-Agenten und -Befehle für strukturierte Entwicklung | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | Konfigurationen, Eingabeaufforderungen, Agenten und Plugins für verbesserte Arbeitsabläufe | diff --git a/packages/web/src/content/docs/de/enterprise.mdx b/packages/web/src/content/docs/de/enterprise.mdx new file mode 100644 index 00000000000..a01c71ae60c --- /dev/null +++ b/packages/web/src/content/docs/de/enterprise.mdx @@ -0,0 +1,170 @@ +--- +title: Unternehmen +description: Sichere Verwendung von OpenCode in Ihrem Unternehmen. +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +OpenCode Enterprise ist für Organisationen gedacht, die sicherstellen möchten, dass ihr Code und ihre Daten niemals ihre Infrastruktur verlassen. Dies kann durch die Verwendung einer zentralen Konfiguration erreicht werden, die in Ihr SSO- und internes AI-Gateway integriert ist. + +:::note +OpenCode speichert keine Ihrer Code- oder Kontextdaten. +::: + +So starten Sie mit OpenCode Enterprise: + +1. Führen Sie einen internen Test mit Ihrem Team durch. +2. **Kontaktieren Sie uns**, um Preise und Implementierungsoptionen zu besprechen. + +--- + +## Testphase + +OpenCode ist Open Source und speichert keine Ihrer Code- oder Kontextdaten, sodass Ihr Entwickler einfach [get started](/docs/) und eine Testversion durchführen kann. + +--- + +### Datenverarbeitung + +**OpenCode speichert Ihren Code oder Ihre Kontextdaten nicht.** Die gesamte Verarbeitung erfolgt lokal oder durch direkte API-Aufrufe an Ihren AI-Anbieter. + +Das heißt, solange Sie einen Anbieter Ihres Vertrauens oder einen internen nutzen +AI-Gateway können Sie OpenCode sicher verwenden. + +Die einzige Einschränkung hier ist die optionale Funktion `/share`. + +--- + +#### Gespräche teilen + +Wenn ein Benutzer die Funktion `/share` aktiviert, werden die Konversation und die damit verbundenen Daten an den Dienst gesendet, den wir zum Hosten dieser Freigabeseiten unter opencode.ai verwenden. + +Die Daten werden derzeit über das Edge-Netzwerk unseres CDN bereitgestellt und am Edge in der Nähe Ihres Benutzers zwischengespeichert. + +Wir empfehlen Ihnen, dies für Ihre Testversion zu deaktivieren. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[Learn more about sharing](/docs/share). + +--- + +### Code-Besitz + +**Der gesamte von OpenCode erstellte Code gehört Ihnen.** Es bestehen keine Lizenzbeschränkungen oder Eigentumsansprüche. + +--- + +## Preise + +Für OpenCode Enterprise verwenden wir ein Pro-Sitz-Modell. Wenn Sie über ein eigenes LLM-Gateway verfügen, berechnen wir keine Gebühren für die verwendeten Token. Für weitere Informationen zu Preisen und Implementierungsoptionen **kontaktieren Sie uns**. + +--- + +## Bereitstellung + +Sobald Sie Ihre Testversion abgeschlossen haben und bereit sind, OpenCode unter zu verwenden +Für Ihre Organisation können Sie **uns kontaktieren**, um dies zu besprechen +Preisgestaltung und Umsetzungsmöglichkeiten. + +--- + +### Zentrale Konfiguration + +Wir können OpenCode so einrichten, dass eine einzige zentrale Konfiguration für Ihre gesamte Organisation verwendet wird. + +Diese zentralisierte Konfiguration kann in Ihren SSO-Anbieter integriert werden und stellt sicher, dass alle Benutzer nur auf Ihr internes AI-Gateway zugreifen. + +--- + +### SSO-Integration + +Über die zentrale Konfiguration kann OpenCode zur Authentifizierung in den SSO-Anbieter Ihrer Organisation integriert werden. + +Dadurch kann OpenCode Anmeldeinformationen für Ihr internes AI-Gateway über Ihr eigenes Identitätsverwaltungssystem abrufen. + +--- + +### Internes AI-Gateway + +Mit der zentralen Konfiguration kann OpenCode auch so konfiguriert werden, dass nur Ihr internes AI-Gateway verwendet wird. + +Sie können auch alle anderen AI-Anbieter deaktivieren und so sicherstellen, dass alle Anfragen über die genehmigte Infrastruktur Ihrer Organisation laufen. + +--- + +### Self-Hosting + +Wir empfehlen jedoch, die Freigabeseiten zu deaktivieren, um sicherzustellen, dass Ihre Daten niemals verloren gehen +In Ihrer Organisation können wir Ihnen auch dabei helfen, sie selbst in Ihrer Infrastruktur zu hosten. + +Dies steht derzeit auf unserer Roadmap. Wenn Sie Interesse haben, **lassen Sie es uns wissen**. + +--- + +## FAQ + +

+Was ist OpenCode Enterprise? + +OpenCode Enterprise ist für Organisationen gedacht, die sicherstellen möchten, dass ihr Code und ihre Daten niemals ihre Infrastruktur verlassen. Dies kann durch die Verwendung einer zentralen Konfiguration erreicht werden, die in Ihr SSO- und internes AI-Gateway integriert ist. + +
+ +
+Wie fange ich mit OpenCode Enterprise an? + +Beginnen Sie einfach mit einem internen Test mit Ihrem Team. OpenCode speichert standardmäßig weder Ihren Code noch Ihre Kontextdaten, was den Einstieg erleichtert. + +Dann **kontaktieren Sie uns**, um Preise und Implementierungsoptionen zu besprechen. + +
+ +
+Wie funktioniert die Preisgestaltung für Unternehmen? + +Wir bieten Enterprise-Preise pro Sitzplatz an. Wenn Sie über ein eigenes LLM-Gateway verfügen, berechnen wir keine Gebühren für die verwendeten Token. Für weitere Informationen **kontaktieren Sie uns** für ein individuelles Angebot, das auf die Bedürfnisse Ihrer Organisation zugeschnitten ist. + +
+ +
+Sind meine Daten bei OpenCode Enterprise sicher? + +Ja. OpenCode speichert Ihren Code oder Ihre Kontextdaten nicht. Die gesamte Verarbeitung erfolgt lokal oder durch direkte API-Anrufe an Ihren AI-Anbieter. Dank zentraler Konfiguration und SSO-Integration bleiben Ihre Daten innerhalb der Infrastruktur Ihres Unternehmens sicher. + +
+ +
+Können wir unsere eigene private NPM-Registry verwenden? + +OpenCode unterstützt private NPM-Registrierungen durch Buns native `.npmrc`-Dateiunterstützung. Wenn Ihre Organisation eine private Registrierung wie JFrog Artifactory, Nexus oder ähnliches verwendet, stellen Sie sicher, dass der Entwickler authentifiziert ist, bevor Sie OpenCode ausführen. + +So richten Sie die Authentifizierung mit Ihrer privaten Registrierung ein: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +Dadurch wird `~/.npmrc` mit Authentifizierungsdetails erstellt. OpenCode wird automatisch +Hebe das auf. + +:::caution +Sie müssen bei der privaten Registrierung angemeldet sein, bevor Sie OpenCode ausführen. +::: + +Alternativ können Sie eine `.npmrc`-Datei manuell konfigurieren: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +Entwickler müssen vor der Ausführung von OpenCode bei der privaten Registrierung angemeldet sein, um sicherzustellen, dass Pakete aus Ihrer Unternehmensregistrierung installiert werden können. + +
diff --git a/packages/web/src/content/docs/de/formatters.mdx b/packages/web/src/content/docs/de/formatters.mdx new file mode 100644 index 00000000000..f953f16cb71 --- /dev/null +++ b/packages/web/src/content/docs/de/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: Formatierer +description: OpenCode verwendet sprachspezifische Formatierer. +--- + +OpenCode formatiert Dateien automatisch, nachdem sie mit sprachspezifischen Formatierern geschrieben oder bearbeitet wurden. Dadurch wird sichergestellt, dass der generierte Code dem Codestil Ihres Projekts entspricht. + +--- + +## Integriert + +OpenCode verfügt über mehrere integrierte Formatierer für gängige Sprachen und Frameworks. Nachfolgend finden Sie eine Liste der Formatierer, unterstützten Dateierweiterungen und benötigten Befehle oder Konfigurationsoptionen. + +| Formatierer | Erweiterungen | Anforderungen | +| -------------------- | -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | +| gofmt | .go | `gofmt`-Befehl verfügbar | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | `mix`-Befehl verfügbar | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, und [more](https://prettier.io/docs/en/index.html) | `prettier`-Abhängigkeit in `package.json` | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, und [more](https://biomejs.dev/) | `biome.json(c)` Konfigurationsdatei | +| zig | .zig, .zon | `zig`-Befehl verfügbar | +| clang-format | .c, .cpp, .h, .hpp, .ino und [more](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` Konfigurationsdatei | +| ktlint | .kt, .kts | `ktlint`-Befehl verfügbar | +| ruff | .py, .pyi | `ruff`-Befehl verfügbar mit config | +| rustfmt | .rs | `rustfmt`-Befehl verfügbar | +| cargofmt | .rs | `cargo fmt`-Befehl verfügbar | +| uv | .py, .pyi | `uv`-Befehl verfügbar | +| rubocop | .rb, .rake, .gemspec, .ru | `rubocop`-Befehl verfügbar | +| standardrb | .rb, .rake, .gemspec, .ru | `standardrb`-Befehl verfügbar | +| htmlbeautifier | .erb, .html.erb | `htmlbeautifier`-Befehl verfügbar | +| air | .R | `air`-Befehl verfügbar | +| dart | .dart | `dart`-Befehl verfügbar | +| ocamlformat | .ml, .mli | `ocamlformat` Befehl verfügbar und `.ocamlformat` Konfigurationsdatei | +| terraform | .tf, .tfvars | `terraform`-Befehl verfügbar | +| gleam | .gleam | `gleam`-Befehl verfügbar | +| nixfmt | .nix | `nixfmt`-Befehl verfügbar | +| shfmt | .sh, .bash | `shfmt`-Befehl verfügbar | +| pint | .php | `laravel/pint`-Abhängigkeit in `composer.json` | +| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | `oxfmt`-Abhängigkeit in `package.json` und einer [experimental env variable flag](/docs/cli/#experimental) | +| Ormolu | .hs | `ormolu`-Befehl verfügbar | + +Wenn Ihr Projekt auch `prettier` in Ihrem `package.json` hat, wird OpenCode automatisch verwendet. + +--- + +## Funktionsweise + +Wenn OpenCode eine Datei schreibt oder bearbeitet, geschieht Folgendes: + +1. Überprüft die Dateierweiterung anhand aller aktivierten Formatierer. +2. Führt den entsprechenden Formatierungsbefehl für die Datei aus. +3. Wendet die Formatierungsänderungen automatisch an. + +Dieser Prozess findet im Hintergrund statt und stellt sicher, dass Ihr Codestile ohne manuelle Schritte beibehalten werden. + +--- + +## Konfiguration + +Sie können Formatierer über den Abschnitt `formatter` in Ihrer OpenCode-Konfiguration anpassen. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +Jede Formatierungskonfiguration unterstützt Folgendes: + +| Eigenschaft | Typ | Beschreibung | +| ------------- | --------------- | -------------------------------------------------------------------------------- | +| `disabled` | boolescher Wert | Setzen Sie dies auf `true`, um den Formatierer zu deaktivieren | +| `command` | string[] | Der zum Formatieren auszuführende Befehl | +| `environment` | Objekt | Umgebungsvariablen, die beim Ausführen des Formatierers festgelegt werden sollen | +| `extensions` | string[] | Dateierweiterungen, die dieser Formatierer verarbeiten soll | + +Schauen wir uns einige Beispiele an. + +--- + +### Formatierer deaktivieren + +Um **alle** Formatierer global zu deaktivieren, setzen Sie `formatter` auf `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +Um einen **bestimmten** Formatierer zu deaktivieren, setzen Sie `disabled` auf `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### Benutzerdefinierter Formatierer + +Sie können den integrierten Formatierer überschreiben oder neu hinzufügen, indem Sie den Befehl, Umgebungsvariablen und Dateierweiterungen angeben: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +Der Platzhalter **`$FILE`** im Befehl wird durch den Pfad zur zu formatierenden Datei ersetzt. diff --git a/packages/web/src/content/docs/de/github.mdx b/packages/web/src/content/docs/de/github.mdx new file mode 100644 index 00000000000..71881c333f5 --- /dev/null +++ b/packages/web/src/content/docs/de/github.mdx @@ -0,0 +1,321 @@ +--- +title: GitHub +description: Verwenden Sie OpenCode in GitHub-Problemen und Pull-Requests. +--- + +OpenCode lässt sich in Ihren GitHub-Workflow integrieren. Erwähnen Sie `/opencode` oder `/oc` in Ihrem Kommentar, und OpenCode führt Aufgaben in Ihrem GitHub Actions-Runner aus. + +--- + +## Funktionen + +- **Issue Triage**: Bitten Sie OpenCode, ein Problem zu untersuchen und es Ihnen zu erklären. +- **Reparieren und implementieren**: Bitten Sie OpenCode, ein Problem zu beheben oder eine Funktion zu implementieren. Und es funktioniert in einem neuen Branch und sendet ein PR mit allen Änderungen. +- **Sicher**: OpenCode läuft in den Runners Ihres GitHub. + +--- + +## Installation + +Führen Sie den folgenden Befehl in einem Projekt aus, das sich in einem GitHub-Repository befindet: + +```bash +opencode github install +``` + +Dies führt Sie durch die Installation der GitHub-App, das Erstellen des Workflows und das Einrichten von Secrets. + +--- + +### Manuelle Einrichtung + +Oder Sie können es manuell einrichten. + +1. **Installieren Sie die GitHub-App** + + Gehen Sie zu [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). Stellen Sie sicher, dass es im Ziel-Repository installiert ist. + +2. **Den Workflow hinzufügen** + + Fügen Sie die folgende Workflowdatei zu `.github/workflows/opencode.yml` in Ihrem Repository hinzu. Stellen Sie sicher, dass Sie in `env` die passenden Werte für `model` und `api_key` setzen. + + ```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx + ``` + +3. **Speichern Sie die API-Schlüssel in Secrets** + + Erweitern Sie in den **Einstellungen** Ihrer Organisation oder Ihres Projekts links **Secrets und Variablen** und wählen Sie **Aktionen** aus. Und fügen Sie die erforderlichen API-Schlüssel hinzu. + +--- + +## Konfiguration + +- `model`: Das mit OpenCode zu verwendende Modell. Nimmt das Format `provider/model` an. Dies ist **erforderlich**. +- `agent`: Der zu verwendende Agent. Muss ein Hauptagent sein. Fällt aus der Konfiguration auf `default_agent` oder `"build"` zurück, wenn es nicht gefunden wird. +- `share`: Ob die OpenCode-Sitzung geteilt werden soll. Der Standardwert ist **true** für öffentliche Repositorys. +- `prompt`: Optionale benutzerdefinierte Eingabeaufforderung zum Überschreiben des Standardverhaltens. Verwenden Sie dies, um anzupassen, wie OpenCode Anfragen verarbeitet. +- `token`: Optionales GitHub-Zugriffstoken zum Ausführen von Vorgängen wie dem Erstellen von Kommentaren, dem Festschreiben von Änderungen und dem Öffnen von Pull Requests. Standardmäßig verwendet OpenCode das Installation Access Token der OpenCode GitHub-App, sodass Commits, Kommentare und Pull Requests so aussehen, als würden sie von der App kommen. + + Alternativ können Sie [built-in `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) des GitHub Action Runners verwenden, ohne die OpenCode GitHub App zu installieren. Stellen Sie einfach sicher, dass Sie in Ihrem Workflow die erforderlichen Berechtigungen erteilen: + + ```yaml + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + ``` + + Sie können bei Bedarf auch einen [personal access tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) verwenden. + +--- + +## Unterstützte Events + +OpenCode kann durch die folgenden GitHub-Events ausgelöst werden: + +| Ereignistyp | Ausgelöst durch | Einzelheiten | +| ----------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `issue_comment` | Kommentieren Sie ein Problem oder PR | Erwähnen Sie `/opencode` oder `/oc` in Ihrem Kommentar. OpenCode liest den Kontext und kann Branches erstellen, PRs öffnen oder antworten. | +| `pull_request_review_comment` | Kommentieren Sie bestimmte Codezeilen in einem PR | Erwähnen Sie `/opencode` oder `/oc` beim Überprüfen des Codes. OpenCode empfängt Dateipfad, Zeilennummern und Diff Context. | +| `issues` | Problem geöffnet oder bearbeitet | Lösen Sie OpenCode automatisch aus, wenn Probleme erstellt oder geändert werden. Erfordert `prompt`-Eingabe. | +| `pull_request` | PR geöffnet oder aktualisiert | Lösen Sie OpenCode automatisch aus, wenn PRs geöffnet, synchronisiert oder erneut geöffnet werden. Nützlich für automatisierte Bewertungen. | +| `schedule` | Cron-basierter Zeitplan | Führen Sie OpenCode nach einem Zeitplan aus. Erfordert `prompt`-Eingabe. Die Ausgabe geht an Protokolle und PRs (kein Kommentar zu diesem Problem). | +| `workflow_dispatch` | Manueller Trigger von GitHub UI | Lösen Sie OpenCode bei Bedarf über die Actions Tab aus. Erfordert `prompt`-Eingabe. Die Ausgabe erfolgt an Protokolle und PRs. | + +### Beispiel für einen Zeitplan + +Führen Sie OpenCode nach einem Zeitplan aus, um automatisierte Aufgaben auszuführen: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +Für geplante Ereignisse ist die Eingabe `prompt` **erforderlich**, da es keinen Kommentar gibt, aus dem Anweisungen extrahiert werden können. Geplante Workflows werden ohne Benutzerkontext zur Berechtigungsprüfung ausgeführt. Daher muss der Workflow `contents: write` und `pull-requests: write` gewähren, wenn Sie erwarten, dass OpenCode Branches oder PRs erstellt. + +--- + +### Pull-Request-Beispiel + +Überprüfen Sie PRs automatisch, wenn sie geöffnet oder aktualisiert werden: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Wenn für `pull_request`-Ereignisse kein `prompt` bereitgestellt wird, überprüft OpenCode standardmäßig die Pull-Anfrage. + +--- + +### Beispiel für eine Issue-Triage + +Neue Probleme automatisch selektieren. In diesem Beispiel wird nach Konten gefiltert, die älter als 30 Tage sind, um Spam zu reduzieren: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +Für `issues`-Ereignisse ist die Eingabe `prompt` **erforderlich**, da es keinen Kommentar gibt, aus dem Anweisungen extrahiert werden können. + +--- + +## Benutzerdefinierte Prompts + +Überschreiben Sie die Standardaufforderung, um das Verhalten von OpenCode für Ihren Workflow anzupassen. + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Dies ist nützlich, um bestimmte Prüfkriterien, Kodierungsstandards oder Schwerpunktbereiche durchzusetzen, die für Ihr Projekt relevant sind. + +--- + +## Beispiele + +Hier sind einige Beispiele, wie Sie OpenCode in GitHub verwenden können. + +- **Erklären Sie ein Problem** + + Fügen Sie diesen Kommentar in einer GitHub-Ausgabe hinzu. + + ``` + /opencode explain this issue + ``` + + OpenCode liest den gesamten Thread, einschließlich aller Kommentare, und antwortet mit einer klaren Erklärung. + +- **Ein Problem beheben** + + Sagen Sie in einer GitHub-Ausgabe: + + ``` + /opencode fix this + ``` + + Und OpenCode erstellt einen neuen Branch, implementiert die Änderungen und öffnet ein PR mit den Änderungen. + +- **PRs überprüfen und Änderungen vornehmen** + + Hinterlassen Sie den folgenden Kommentar auf einem GitHub PR. + + ``` + Delete the attachment from S3 when the note is removed /oc + ``` + + OpenCode implementiert die angeforderte Änderung und schreibt sie an denselben PR fest. + +- **Überprüfen Sie bestimmte Codezeilen** + + Hinterlassen Sie einen Kommentar direkt zu den Codezeilen auf der Files Tab von PR. OpenCode erkennt automatisch die Datei, Zeilennummern und den Diff Context, um präzise Antworten bereitzustellen. + + ``` + [Comment on specific lines in Files tab] + /oc add error handling here + ``` + + Beim Kommentieren bestimmter Zeilen erhält OpenCode: + - Die genaue Datei, die überprüft wird + - Die spezifischen Codezeilen + - Der umgebende Diff Context + - Informationen zur Zeilennummer + + Dies ermöglicht gezieltere Anfragen, ohne dass Dateipfade oder Zeilennummern manuell angegeben werden müssen. diff --git a/packages/web/src/content/docs/de/gitlab.mdx b/packages/web/src/content/docs/de/gitlab.mdx new file mode 100644 index 00000000000..28289d4fbe9 --- /dev/null +++ b/packages/web/src/content/docs/de/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: Verwenden Sie OpenCode in GitLab-Issues und Merge Requests. +--- + +OpenCode lässt sich über Ihre GitLab CI/CD-Pipeline oder mit GitLab Duo in Ihren GitLab-Workflow integrieren. + +In beiden Fällen läuft OpenCode auf Ihren GitLab Runners. + +--- + +## GitLab CI + +OpenCode funktioniert in einer regulären GitLab-Pipeline. Sie können es als [CI component](https://docs.gitlab.com/ee/ci/components/) in eine Pipeline einbauen. + +Hier verwenden wir eine von der Community erstellte CI/CD-Komponente für OpenCode – [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### Funktionen + +- **Benutzerdefinierte Konfiguration pro Job verwenden**: Konfigurieren Sie OpenCode mit einem benutzerdefinierten Konfigurationsverzeichnis, zum Beispiel `./config/#custom-directory`, um die Funktionalität pro OpenCode-Aufruf zu aktivieren oder zu deaktivieren. +- **Minimale Einrichtung**: Die CI-Komponente richtet OpenCode im Hintergrund ein. Sie müssen lediglich die OpenCode-Konfiguration und die erste Eingabeaufforderung erstellen. +- **Flexibel**: Die CI-Komponente unterstützt mehrere Eingaben zum Anpassen ihres Verhaltens + +--- + +### Einrichtung + +1. Speichern Sie Ihre OpenCode-Authentifizierung JSON als Umgebungsvariablen vom Dateityp CI unter **Einstellungen** > **CI/CD** > **Variablen**. Stellen Sie sicher, dass Sie sie als „Maskiert und ausgeblendet“ markieren. +2. Fügen Sie Folgendes zu Ihrer `.gitlab-ci.yml`-Datei hinzu. + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # Die variable name für ihre OpenCode authentifizierung JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +Weitere Eingaben und Anwendungsfälle finden Sie unter [check out the docs](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) für diese Komponente. + +--- + +## GitLab Duo + +OpenCode lässt sich in Ihren GitLab-Workflow integrieren. +Erwähnen Sie `@opencode` in einem Kommentar und OpenCode führt Aufgaben innerhalb Ihrer GitLab CI-Pipeline aus. + +--- + +### Funktionen + +- **Issue Triage**: Bitten Sie OpenCode, ein Problem zu untersuchen und es Ihnen zu erklären. +- **Reparieren und implementieren**: Bitten Sie OpenCode, ein Problem zu beheben oder eine Funktion zu implementieren. + Es wird ein neuer Branch erstellt und eine Merge Request mit den Änderungen ausgelöst. +- **Sicher**: OpenCode läuft auf Ihren GitLab Runners. + +--- + +### Einrichtung + +OpenCode wird in Ihrer GitLab CI/CD-Pipeline ausgeführt. Folgendes müssen Sie zum Einrichten benötigen: + +:::tip +Aktuelle Anweisungen finden Sie im [**GitLab docs**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/). +::: + +1. Konfigurieren Sie Ihre GitLab-Umgebung +2. CI/CD einrichten +3. Holen Sie sich einen AI-Modellanbieterschlüssel API +4. Erstellen Sie ein Dienstkonto +5. Konfigurieren Sie CI/CD-Variablen +6. Erstellen Sie eine Flow-Konfigurationsdatei, hier ist ein Beispiel: + +
+ + Flow-Konfiguration + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +Ausführliche Anweisungen finden Sie unter [GitLab CLI agents docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/). + +--- + +### Beispiele + +Hier sind einige Beispiele, wie Sie OpenCode in GitLab verwenden können. + +:::tip +Sie können die Verwendung einer anderen Triggerphrase als `@opencode` konfigurieren. +::: + +- **Erklären Sie ein Problem** + + Fügen Sie diesen Kommentar in einer GitLab-Ausgabe hinzu. + + ``` + @opencode explain this issue + ``` + + OpenCode liest das Problem und antwortet mit einer klaren Erklärung. + +- **Ein Problem beheben** + + Sagen Sie in einer GitLab-Ausgabe: + + ``` + @opencode fix this + ``` + + OpenCode erstellt einen neuen Branch, implementiert die Änderungen und öffnet eine Merge Request mit den Änderungen. + +- **Merge Requests prüfen** + + Hinterlassen Sie den folgenden Kommentar zu einer GitLab Merge Request. + + ``` + @opencode review this merge request + ``` + + OpenCode prüft die Merge Request und gibt Feedback. diff --git a/packages/web/src/content/docs/de/ide.mdx b/packages/web/src/content/docs/de/ide.mdx new file mode 100644 index 00000000000..dcc28239578 --- /dev/null +++ b/packages/web/src/content/docs/de/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: Die OpenCode-Erweiterung für VS Code, Cursor und andere IDEs +--- + +OpenCode lässt sich in VS Code, Cursor oder jede IDE integrieren, die ein Terminal unterstützt. Führen Sie einfach `opencode` im Terminal aus, um zu beginnen. + +--- + +## Verwendung + +- **Schnellstart**: Verwenden Sie `Cmd+Esc` (Mac) oder `Ctrl+Esc` (Windows/Linux), um OpenCode in einer geteilten Terminalansicht zu öffnen, oder fokussieren Sie eine dieser Terminalsitzung, falls bereits eine ausgeführt wird. +- **Neue Sitzung**: Verwenden Sie `Cmd+Shift+Esc` (Mac) oder `Ctrl+Shift+Esc` (Windows/Linux), um eine neue OpenCode-Terminalsitzung zu starten, auch wenn eine bereits geöffnet ist. Sie können auch auf die OpenCode-Schaltfläche im UI klicken. +- **Kontextbewusstsein**: Teilen Sie Ihre aktuelle Auswahl oder Registerkarte automatisch mit OpenCode. +- **Verknüpfungen zu Dateiverweisen**: Verwenden Sie `Cmd+Option+K` (Mac) oder `Alt+Ctrl+K` (Linux/Windows), um Dateiverweisen einzufügen. Beispiel: `@File#L37-42`. + +--- + +## Installation + +So installieren Sie OpenCode in VS Code und beliebten Forks wie Cursor, Windsurf, VSCodium: + +1. Öffnen Sie VS Code +2. Öffnen Sie das integrierte Terminal +3. Führen Sie `opencode` aus – die Erweiterung wird automatisch installiert + +Wenn Sie andererseits Ihre eigene IDE verwenden möchten, wenn Sie `/editor` oder `/export` von TUI ausführen, müssen Sie `export EDITOR="code --wait"` festlegen. [Learn more](/docs/tui/#editor-setup). + +--- + +### Manuelle Installation + +Suchen Sie im Extension Marketplace nach **OpenCode** und klicken Sie auf **Installieren**. + +--- + +### Fehlerbehebung + +Wenn die Erweiterung nicht automatisch installiert werden kann: + +- Stellen Sie sicher, dass Sie `opencode` im integrierten Terminal ausführen. +- Bestätigen Sie, dass CLI für Ihre IDE installiert ist: + - Für VS Code: `code` Befehl + - Für Cursor: Befehl `cursor` + - Für Windsurf: Befehl `windsurf` + - Für VSCodium: Befehl `codium` + - Wenn nicht, führen Sie `Cmd+Shift+P` (Mac) oder `Ctrl+Shift+P` (Windows/Linux) aus und suchen Sie nach „Shell Command: Install 'code' command in PATH“ (oder dem Äquivalent für Ihre IDE). +- Stellen Sie sicher, dass VS Code über die Berechtigung zum Installieren von Erweiterungen verfügt diff --git a/packages/web/src/content/docs/de/index.mdx b/packages/web/src/content/docs/de/index.mdx new file mode 100644 index 00000000000..e1337254df2 --- /dev/null +++ b/packages/web/src/content/docs/de/index.mdx @@ -0,0 +1,355 @@ +--- +title: Einführung +description: Beginnen Sie mit OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**OpenCode**](/) ist ein Open-Source-Coding-Agent für AI. Es ist als terminalbasierte Schnittstelle, Desktop-App oder IDE-Erweiterung verfügbar. + +![OpenCode TUI with the opencode theme](../../../assets/lander/screenshot.png) + +Fangen wir an. + +--- + +#### Voraussetzungen + +Um OpenCode in Ihrem Terminal verwenden zu können, benötigen Sie: + +1. Ein moderner Terminal-Emulator, zum Beispiel: + - [WezTerm](https://wezterm.org), cross-platform + - [Alacritty](https://alacritty.org), plattformübergreifend + - [Ghostty](https://ghostty.org), Linux und macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux und macOS + +2. API-Schlüssel für die LLM-Anbieter, die Sie verwenden möchten. + +--- + +## Installation + +Der einfachste Weg, OpenCode zu installieren, ist über das Installationsskript. + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +Sie können es auch mit den folgenden Befehlen installieren: + +- **Mit Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **Homebrew unter macOS und Linux verwenden** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > Wir empfehlen die Verwendung des OpenCode-Taps für die aktuellsten Versionen. Die offizielle `brew install opencode`-Formel wird vom Homebrew-Team gepflegt und seltener aktualisiert. + +- **Verwendung von Paru unter Arch Linux** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[Empfohlen: Verwenden Sie WSL] +Für das beste Erlebnis unter Windows empfehlen wir die Verwendung von [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Es bietet eine bessere Leistung und vollständige Kompatibilität mit den Funktionen von OpenCode. +::: + +- **Verwendung von Chocolatey** + + ```bash + choco install opencode + ``` + +- **Scoop verwenden** + + ```bash + scoop install opencode + ``` + +- **Mit NPM** + + ```bash + npm install -g opencode-ai + ``` + +- **Mit Mise** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **Verwendung von Docker** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +Die Unterstützung für die Installation von OpenCode unter Windows mit Bun ist derzeit in Arbeit. + +Sie können die Binärdatei auch aus [Releases](https://github.com/anomalyco/opencode/releases) abrufen. + +--- + +## Konfiguration + +Mit OpenCode können Sie jeden LLM-Anbieter verwenden, indem Sie dessen API-Schlüssel konfigurieren. + +Wenn Sie mit der Verwendung von LLM-Anbietern noch nicht vertraut sind, empfehlen wir die Verwendung von [OpenCode Zen](/docs/zen). +Es handelt sich um eine kuratierte Liste von Modellen, die vom OpenCode Team getestet und verifiziert wurden. + +1. Führen Sie den Befehl `/connect` in TUI aus, wählen Sie OpenCode aus und gehen Sie zu [opencode.ai/auth](https://opencode.ai/auth). + + ```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 + ``` + +Alternativ können Sie auch einen der anderen Anbieter auswählen. [Mehr erfahren](/docs/providers#directory). + +--- + +## Initialisierung + +Nachdem Sie nun einen Anbieter konfiguriert haben, können Sie zu einem Projekt navigieren +an dem Sie arbeiten möchten. + +```bash +cd /path/to/project +``` + +Und führen Sie OpenCode aus. + +```bash +opencode +``` + +Als nächstes initialisieren Sie OpenCode für das Projekt, indem Sie den folgenden Befehl ausführen. + +```bash frame="none" +/init +``` + +Dadurch wird OpenCode dazu veranlasst, Ihr Projekt zu analysieren und eine `AGENTS.md`-Datei im Projektstammverzeichnis zu erstellen. + +:::tip +Sie sollten die `AGENTS.md`-Datei Ihres Projekts an Git übergeben. +::: + +Dies hilft OpenCode, die Projektstruktur und die Codierungsmuster zu verstehen +die verwendet werden. + +--- + +## Verwendung + +Sie können nun OpenCode verwenden, um an Ihrem Projekt zu arbeiten. Fragen Sie ruhig nach +allem! + +Wenn Sie mit der Verwendung eines AI-Codierungsagenten noch nicht vertraut sind, finden Sie hier einige Beispiele, die hilfreich sein könnten. + +--- + +### Fragen stellen + +Sie können OpenCode bitten, Ihnen die Codebasis zu erklären. + +:::tip +Verwenden Sie die Taste `@`, um eine Fuzzy-Suche nach Dateien im Projekt durchzuführen. +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +Dies ist hilfreich, wenn es einen Teil der Codebasis gibt, an dem Sie nicht gearbeitet haben. + +--- + +### Funktionen hinzufügen + +Sie können OpenCode bitten, Ihrem Projekt neue Funktionen hinzuzufügen. Wir empfehlen jedoch, es zunächst um die Erstellung eines Plans zu bitten. + +1. **Erstellen Sie einen Plan** + + OpenCode verfügt über einen _Plan Mode_, der seine Fähigkeit, Änderungen vorzunehmen, deaktiviert + Schlagen Sie stattdessen vor, wie die Funktion implementiert wird. + + Wechseln Sie mit der **Tabulatortaste** dorthin. In der unteren rechten Ecke sehen Sie einen Indikator dafür. + + ```bash frame="none" title="In den Plan-Modus wechseln" + + ``` + + Beschreiben wir nun, was es tun soll. + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + Sie möchten OpenCode genügend Details geben, um zu verstehen, was Sie wollen. Es hilft + mit ihm zu sprechen, als ob Sie mit einem Junior-Entwickler in Ihrem Team sprechen würden. + + :::tip + Geben Sie OpenCode reichlich Kontext und Beispiele, damit es versteht, was Sie + wollen. + ::: + +2. **Den Plan überarbeiten** + + Sobald Sie einen Plan erhalten, können Sie ihm Feedback geben oder weitere Details hinzufügen. + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + + :::tip + Ziehen Sie Bilder per Drag-and-Drop in das Terminal, um sie zur Eingabeaufforderung hinzuzufügen. + ::: + + OpenCode kann alle von Ihnen bereitgestellten Bilder scannen und zur Eingabeaufforderung hinzufügen. Du kannst + Ziehen Sie dazu ein Bild per Drag & Drop in das Terminal. + +3. **Funktion erstellen** + + Wenn Sie mit dem Plan zufrieden sind, wechseln Sie zurück in den _Build Mode_ + indem Sie erneut die **Tabulatortaste** drücken. + + ```bash frame="none" + + ``` + + Und es bitten, die Änderungen vorzunehmen. + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### Änderungen vornehmen + +Für einfachere Änderungen können Sie OpenCode bitten, es direkt zu erstellen +ohne den Plan vorher überprüfen zu müssen. + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +Sie möchten sicherstellen, dass Sie viele Details bereitstellen, damit OpenCode die richtigen +Änderungen vornimmt. + +--- + +### Änderungen rückgängig machen + +Nehmen wir an, Sie bitten OpenCode, einige Änderungen vorzunehmen. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Aber Sie erkennen, dass es nicht das ist, was Sie wollten. Sie können die Änderungen **rückgängig machen** +mit dem Befehl `/undo`. + +```bash frame="none" +/undo +``` + +OpenCode macht nun die von Ihnen vorgenommenen Änderungen rückgängig und zeigt Ihre ursprüngliche Nachricht +wieder an. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Von hier aus können Sie die Eingabeaufforderung anpassen und OpenCode bitten, es erneut zu versuchen. + +:::tip +Sie können `/undo` mehrmals ausführen, um mehrere Änderungen rückgängig zu machen. +::: + +Oder Sie **können** die Änderungen mit dem Befehl `/redo` wiederholen. + +```bash frame="none" +/redo +``` + +--- + +## Teilen + +Die Gespräche, die Sie mit OpenCode führen, können [mit Ihrem Team](/docs/share) geteilt werden. + +```bash frame="none" +/share +``` + +Dadurch wird ein Link zur aktuellen Konversation erstellt und in Ihre Zwischenablage kopiert. + +:::note +Gespräche werden standardmäßig nicht geteilt. +::: + +Hier ist ein [Beispielgespräch](https://opencode.ai/s/4XP1fce5) mit OpenCode. + +--- + +## Anpassung + +Und das ist es! Sie sind jetzt ein Profi im Umgang mit OpenCode. + +Um es zu Ihrem eigenen zu machen, empfehlen wir [ein Theme auszuwählen](/docs/themes), [Keybinds anzupassen](/docs/keybinds), [Code-Formatter zu konfigurieren](/docs/formatters), [eigene Commands zu erstellen](/docs/commands) oder mit der [OpenCode-Konfiguration](/docs/config) zu experimentieren. diff --git a/packages/web/src/content/docs/de/keybinds.mdx b/packages/web/src/content/docs/de/keybinds.mdx new file mode 100644 index 00000000000..d5758008057 --- /dev/null +++ b/packages/web/src/content/docs/de/keybinds.mdx @@ -0,0 +1,192 @@ +--- +title: Tastenkombinationen +description: Passen Sie Ihre Tastenkombinationen an. +--- + +OpenCode verfügt über eine Liste von Tastenkombinationen, die Sie über die OpenCode-Konfiguration anpassen können. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## Leader Key + +OpenCode verwendet für die meisten Keybinds einen `leader`-Schlüssel. Dies vermeidet Konflikte in Ihrem Terminal. + +Standardmäßig ist `ctrl+x` der Leader Key und bei den meisten Aktionen müssen Sie zuerst den Leader Key und dann die Tastenkombination drücken. Um beispielsweise eine neue Sitzung zu starten, drücken Sie zuerst `ctrl+x` und dann `n`. + +Sie müssen für Ihre Keybinds keinen Leader Key verwenden, wir empfehlen jedoch, dies zu tun. + +--- + +## Keybind deaktivieren + +Sie können eine Keybind deaktivieren, indem Sie den Schlüssel mit dem Wert „none“ zu Ihrer Konfiguration hinzufügen. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## Desktop-Prompt-Shortcuts + +Die Eingabeaufforderungseingabe der OpenCode-Desktop-App unterstützt gängige Readline/Emacs-style-Verknüpfungen zum Bearbeiten von Text. Diese sind integriert und derzeit nicht über `opencode.json` konfigurierbar. + +| Keybind | Aktion | +| -------- | ----------------------------------------------------- | +| `ctrl+a` | Zum Anfang der aktuellen Zeile gehen | +| `ctrl+e` | Zum Ende der aktuellen Zeile gehen | +| `ctrl+b` | Cursor um ein Zeichen zurückbewegen | +| `ctrl+f` | Cursor um ein Zeichen vorwärts bewegen | +| `alt+b` | Cursor um ein Wort zurückbewegen | +| `alt+f` | Bewegen Sie den Cursor ein Wort vorwärts | +| `ctrl+d` | Zeichen unter dem Cursor löschen | +| `ctrl+k` | Bis zum Zeilenende löschen (Kill) | +| `ctrl+u` | Bis zum Zeilenanfang löschen (Kill) | +| `ctrl+w` | Vorheriges Wort löschen (Kill) | +| `alt+d` | Nächstes Wort löschen (Kill) | +| `ctrl+t` | Zeichen transponieren | +| `ctrl+g` | Popovers abbrechen / Ausführung der Antwort abbrechen | + +--- + +## Shift+Enter + +Einige Terminals senden standardmäßig keine Zusatztasten mit der Eingabetaste. Möglicherweise müssen Sie Ihr Terminal so konfigurieren, dass es `Shift+Enter` als Escape-Sequenz sendet. + +### Windows Terminal + +Öffnen Sie Ihr `settings.json` unter: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +Fügen Sie dies dem `actions`-Array auf Stammebene hinzu: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Fügen Sie dies dem `keybindings`-Array auf Stammebene hinzu: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Speichern Sie die Datei und starten Sie das Windows-Terminal neu oder öffnen Sie einen neuen Tab. diff --git a/packages/web/src/content/docs/de/lsp.mdx b/packages/web/src/content/docs/de/lsp.mdx new file mode 100644 index 00000000000..60f8316c6b6 --- /dev/null +++ b/packages/web/src/content/docs/de/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: LSP Server +description: OpenCode lässt sich in Ihren LSP-Server integrieren. +--- + +OpenCode lässt sich in Ihr Language Server Protocol (LSP) integrieren, um die Interaktion von LLM mit Ihrer Codebasis zu unterstützen. Es verwendet Diagnosefunktionen, um dem LLM Feedback zu geben. + +--- + +## Integriert + +OpenCode verfügt über mehrere integrierte LSP-Server für gängige Sprachen: + +| LSP Server | Erweiterungen | Anforderungen | +| ------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| astro | .astro | Automatische Installation für Astro-Projekte | +| bash | .sh, .bash, .zsh, .ksh | Installiert den bash-language-server automatisch | +| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | Automatische Installation für C/C++-Projekte | +| csharp | .cs | `.NET SDK` installed | +| clojure-lsp | .clj, .cljs, .cljc, .edn | `clojure-lsp`-Befehl verfügbar | +| dart | .dart | `dart`-Befehl verfügbar | +| deno | .ts, .tsx, .js, .jsx, .mjs | `deno`-Befehl verfügbar (automatische Erkennung von deno.json/deno.jsonc) | +| elixir-ls | .ex, .exs | `elixir`-Befehl verfügbar | +| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | `eslint` dependency in project | +| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` installed | +| gleam | .gleam | `gleam`-Befehl verfügbar | +| gopls | .go | `go`-Befehl verfügbar | +| hls | .hs, .lhs | `haskell-language-server-wrapper`-Befehl verfügbar | +| jdtls | .java | `Java SDK (version 21+)` installiert | +| kotlin-ls | .kt, .kts | Automatische Installation für Kotlin-Projekte | +| lua-ls | .lua | Automatische Installation für Lua-Projekte | +| nixd | .nix | `nixd`-Befehl verfügbar | +| ocaml-lsp | .ml, .mli | `ocamllsp`-Befehl verfügbar | +| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | `oxlint` dependency in project | +| php intelephense | .php | Automatische Installation für PHP-Projekte | +| prisma | .prisma | `prisma`-Befehl verfügbar | +| pyright | .py, .pyi | `pyright` dependency installed | +| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | Befehle `ruby` und `gem` verfügbar | +| rust | .rs | `rust-analyzer`-Befehl verfügbar | +| sourcekit-lsp | .swift, .objc, .objcpp | `swift` installed (`xcode` on macOS) | +| svelte | .svelte | Automatische Installation für Svelte-Projekte | +| terraform | .tf, .tfvars | Automatische Installation von GitHub-Releases | +| tinymist | .typ, .typc | Automatische Installation von GitHub-Releases | +| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` dependency in project | +| vue | .vue | Automatische Installation für Vue-Projekte | +| yaml-ls | .yaml, .yml | Installiert den Red Hat yaml-language-server automatisch | +| zls | .zig, .zon | `zig`-Befehl verfügbar | + +LSP-Server werden automatisch aktiviert, wenn eine der oben genannten Dateierweiterungen erkannt wird und die Anforderungen erfüllt sind. + +:::note +Sie können LSP-Server-Downloads automatisch deaktivieren, indem Sie die Umgebungsvariable `OPENCODE_DISABLE_LSP_DOWNLOAD` auf `true` setzen. +::: + +--- + +## Funktionsweise + +Wenn OpenCode eine Datei öffnet, geschieht Folgendes: + +1. Überprüft die Dateierweiterung anhand aller aktivierten LSP-Server. +2. Startet den entsprechenden LSP-Server, falls er noch nicht ausgeführt wird. + +--- + +## Konfiguration + +Sie können LSP-Server über den Abschnitt `lsp` in Ihrer OpenCode-Konfiguration anpassen. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +Jeder LSP-Server unterstützt Folgendes: + +| Eigentum | Geben Sie | ein Beschreibung | +| ---------------- | --------------- | ------------------------------------------------------------------ | +| `disabled` | boolescher Wert | Setzen Sie dies auf `true`, um den LSP-Server zu deaktivieren | +| `command` | string[] | Der Befehl zum Starten des LSP-Servers | +| `extensions` | string[] | Dateierweiterungen, die dieser LSP-Server verarbeiten soll | +| `env` | Objekt | Umgebungsvariablen, die beim Starten des Servers festgelegt werden | +| `initialization` | Objekt | Initialisierungsoptionen zum Senden an den LSP-Server | + +Schauen wir uns einige Beispiele an. + +--- + +### Umgebungsvariablen + +Verwenden Sie die Eigenschaft `env`, um Umgebungsvariablen festzulegen, wenn Sie den Server LSP starten: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### Initialisierungsoptionen + +Verwenden Sie die Eigenschaft `initialization`, um Initialisierungsoptionen an den Server LSP zu übergeben. Dies sind serverspezifische Einstellungen, die während der LSP `initialize`-Anfrage gesendet werden: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +Die Initialisierungsoptionen variieren je nach LSP-Server. Überprüfen Sie die Dokumentation Ihres LSP-Servers auf verfügbare Optionen. +::: + +--- + +### Deaktivieren von LSP-Servern + +Um **alle** LSP-Server global zu deaktivieren, setzen Sie `lsp` auf `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +Um einen **bestimmten** LSP-Server zu deaktivieren, setzen Sie `disabled` auf `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### Benutzerdefinierter LSP-Server + +Sie können einen benutzerdefinierten LSP-Server hinzufügen, indem Sie den Befehl und die Dateierweiterungen angeben: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## Weitere Informationen + +### PHP Intelephense + +PHP Intelepense bietet Premium-Funktionen über einen Lizenzschlüssel. Sie können einen Lizenzschlüssel bereitstellen, indem Sie (nur) den Schlüssel in eine Textdatei einfügen unter: + +- Auf macOS/Linux: `$HOME/intelephense/license.txt` +- Unter Windows: `%USERPROFILE%/intelephense/license.txt` + +Die Datei sollte nur den Lizenzschlüssel ohne zusätzlichen Inhalt enthalten. diff --git a/packages/web/src/content/docs/de/mcp-servers.mdx b/packages/web/src/content/docs/de/mcp-servers.mdx new file mode 100644 index 00000000000..d53ae00f708 --- /dev/null +++ b/packages/web/src/content/docs/de/mcp-servers.mdx @@ -0,0 +1,511 @@ +--- +title: MCP Server +description: Fügen Sie lokale und Remote-MCP-Tools hinzu. +--- + +Sie können externe Tools zu OpenCode hinzufügen, indem Sie das _Model Context Protocol_ oder MCP verwenden. OpenCode unterstützt sowohl lokale als auch Remote-Server. + +Nach dem Hinzufügen stehen MCP-Tools automatisch neben den integrierten Tools für LLM zur Verfügung. + +--- + +#### Hinweise + +Wenn Sie einen MCP-Server verwenden, wird dieser zum Kontext hinzugefügt. Wenn Sie viele Werkzeuge haben, können Sie das schnell zusammenfassen. Wir empfehlen daher, vorsichtig zu sein, welchen MCP-Server Sie verwenden. + +:::tip +MCP-Server ergänzen Ihren Kontext, daher sollten Sie vorsichtig sein, welchen Server Sie aktivieren. +::: + +Bestimmte MCP-Server, wie der GitHub-Server MCP, neigen dazu, viele Token hinzuzufügen und können leicht das Kontextlimit überschreiten. + +--- + +## Aktivierung + +Sie können den MCP-Server in Ihrem [OpenCode Config](https://opencode.ai/docs/config/) unter `mcp` definieren. Fügen Sie jedem MCP einen eindeutigen Namen hinzu. Sie können bei der Eingabe von LLM namentlich auf diesen MCP verweisen. + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +Sie können einen Server auch deaktivieren, indem Sie `enabled` auf `false` setzen. Dies ist nützlich, wenn Sie einen Server vorübergehend deaktivieren möchten, ohne ihn aus Ihrer Konfiguration zu entfernen. + +--- + +### Überschreiben von Remote-Standardwerten + +Organisationen können über ihren `.well-known/opencode`-Endpunkt Standard-MCP-Server bereitstellen. Diese Server sind möglicherweise standardmäßig deaktiviert, sodass Benutzer sich für den Server entscheiden können, die sie benötigen. + +Um einen bestimmten Server aus der Remote-Konfiguration Ihrer Organisation zu aktivieren, fügen Sie ihn mit `enabled: true` zu Ihrer lokalen Konfiguration hinzu: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +Ihre lokalen Konfigurationswerte überschreiben die Remote-Standardwerte. Weitere Einzelheiten finden Sie unter [config precedence](/docs/config#precedence-order). + +--- + +## Lokal + +Fügen Sie lokale MCP-Server mit `type` bis `"local"` innerhalb des MCP-Objekts hinzu. + +```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", + }, + }, + }, +} +``` + +Mit dem Befehl wird der lokale MCP-Server gestartet. Sie können auch eine Liste von Umgebungsvariablen übergeben. + +So können Sie beispielsweise den Testserver [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) MCP hinzufügen. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "mcp_everything": { + "type": "local", + "command": ["npx", "-y", "@modelcontextprotocol/server-everything"], + }, + }, +} +``` + +Und um es zu verwenden, kann ich `use the mcp_everything tool` zu meinen Eingabeaufforderungen hinzufügen. + +```txt "mcp_everything" +use the mcp_everything tool to add the number 3 and 4 +``` + +--- + +#### Optionen + +Hier finden Sie alle Optionen zum Konfigurieren eines lokalen MCP-Servers. + +| Option | Geben Sie | ein Erforderlich | Beschreibung | +| ------------- | --------------- | ---------------- | -------------------------------------------------------------------------------------------- | +| `type` | Zeichenfolge | Y | Typ der MCP-Serververbindung, muss `"local"` sein. | +| `command` | Array | Y | Befehl und Argumente zum Ausführen des MCP-Servers. | +| `environment` | Objekt | | Umgebungsvariablen, die beim Ausführen des Servers festgelegt werden sollen. | +| `enabled` | Boolescher Wert | | Aktivieren oder deaktivieren Sie den MCP-Server beim Start. | +| `timeout` | Nummer | | Timeout in ms für das Abrufen von Tools vom MCP-Server. Standardmäßig ist 5000 (5 Sekunden). | + +--- + +## Remote + +Fügen Sie den Remote-MCP-Server hinzu, indem Sie `type` auf `"remote"` setzen. + +```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" + } + } + } +} +``` + +Der `url` ist der URL des Remote-Servers MCP und mit der Option `headers` können Sie eine Liste von Headern übergeben. + +--- + +#### Optionen + +| Option | Geben Sie | ein Erforderlich | Beschreibung | +| --------- | --------------- | ---------------- | -------------------------------------------------------------------------------------------- | +| `type` | Zeichenfolge | Y | Typ der MCP-Serververbindung, muss `"remote"` sein. | +| `url` | Zeichenfolge | Y | URL des Remote-Servers MCP. | +| `enabled` | Boolescher Wert | | Aktivieren oder deaktivieren Sie den MCP-Server beim Start. | +| `headers` | Objekt | | Header, die mit der Anfrage gesendet werden sollen. | +| `oauth` | Objekt | | OAuth-Authentifizierungskonfiguration. Siehe Abschnitt [OAuth](#oauth) unten. | +| `timeout` | Nummer | | Timeout in ms für das Abrufen von Tools vom MCP-Server. Standardmäßig ist 5000 (5 Sekunden). | + +--- + +## OAuth + +OpenCode übernimmt automatisch die OAuth-Authentifizierung für Remote-MCP-Server. Wenn ein Server eine Authentifizierung erfordert, wird OpenCode Folgendes tun: + +1. Erkennen Sie die 401-Antwort und initiieren Sie den OAuth-Fluss +2. Verwenden Sie **Dynamische Client-Registrierung (RFC 7591)**, sofern vom Server unterstützt +3. Bewahren Sie Token sicher für zukünftige Anfragen auf + +--- + +### Automatisch + +Für die meisten OAuth-fähigen MCP-Server ist keine spezielle Konfiguration erforderlich. Konfigurieren Sie einfach den Remote-Server: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "my-oauth-server": { + "type": "remote", + "url": "https://mcp.example.com/mcp" + } + } +} +``` + +Wenn der Server eine Authentifizierung erfordert, werden Sie von OpenCode beim ersten Versuch, ihn zu verwenden, zur Authentifizierung autorisiert. Wenn nicht, können Sie [manually trigger the flow](#authenticating) mit `opencode mcp auth ` verwenden. + +--- + +### Vorregistriert + +Wenn Sie über Client-Anmeldeinformationen vom Serveranbieter MCP verfügen, können Sie diese konfigurieren: + +```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" + } + } + } +} +``` + +--- + +### Authentifizieren + +Sie können die Authentifizierung manuell auslösen oder Anmeldeinformationen verwalten. + +Authentifizieren Sie sich bei einem bestimmten MCP-Server: + +```bash +opencode mcp auth my-oauth-server +``` + +Hören Sie alle MCP-Server und ihren Authentifizierungsstatus auf: + +```bash +opencode mcp list +``` + +Gespeicherte Zugangsdaten entfernen: + +```bash +opencode mcp logout my-oauth-server +``` + +Der Befehl `mcp auth` öffnet Ihren Browser zur Autorisierung. Nach der Autorisierung speichert OpenCode die Token sicher in `~/.local/share/opencode/mcp-auth.json`. + +--- + +#### OAuth deaktivieren + +Wenn Sie automatisches OAuth für einen Server deaktivieren möchten (e.g., für Server, die stattdessen API-Schlüssel verwenden), setzen Sie `oauth` auf `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-Optionen + +| Option | Geben Sie | ein Beschreibung | +| -------------- | --------------- | --------------------------------------------------------------------------------------------- | +| `oauth` | Object \| false | OAuth-Konfigurationsobjekt oder `false`, um die automatische OAuth-Erkennung zu deaktivieren. | +| `clientId` | Zeichenfolge | OAuth-Client ID. Wenn nicht angegeben, wird eine dynamische Client-Registrierung versucht. | +| `clientSecret` | Zeichenfolge | OAuth-Client-Geheimnis, falls vom Autorisierungsserver erforderlich. | +| `scope` | Zeichenfolge | OAuth-Bereiche, die während der Autorisierung angefordert werden sollen. | + +#### Debugging + +Wenn die Authentifizierung eines Remote-Servers MCP fehlschlägt, können Sie Probleme diagnostizieren mit: + +```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 +``` + +Der Befehl `mcp debug` zeigt den aktuellen Authentifizierungsstatus an, testet die HTTP-Konnektivität und versucht den OAuth-Erkennungsfluss. + +--- + +## Verwaltung + +Ihre MCPs sind neben integrierten Tools auch als Tools in OpenCode verfügbar. Sie können sie also wie jedes andere Tool über die OpenCode-Konfiguration verwalten. + +--- + +### Global + +Das bedeutet, dass Sie sie global aktivieren oder deaktivieren können. + +```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 + } +} +``` + +Wir können auch ein Glob-Muster verwenden, um alle passenden MCPs zu deaktivieren. + +```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 + } +} +``` + +Hier verwenden wir das Glob-Muster `my-mcp*`, um alle MCPs zu deaktivieren. + +--- + +### Pro Agent + +Wenn Sie über eine große Anzahl von MCP-Servern verfügen, möchten Sie diese möglicherweise nur pro Agent aktivieren und global deaktivieren. Gehen Sie dazu wie folgt vor: + +1. Deaktivieren Sie es global als Tool. +2. Aktivieren Sie in Ihrem [agent config](/docs/agents#tools) den MCP-Server als Tool. + +```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 + } + } + } +} +``` + +--- + +#### Glob-Muster + +Das Glob-Muster verwendet einfache Regex-Globbing-Muster: + +- `*` entspricht null oder mehr Zeichen (e.g., `"my-mcp*"` entspricht `my-mcp_search`, `my-mcp_list` usw.) +- `?` matches exactly one character +- Alle anderen Zeichen stimmen wörtlich überein + +:::note +MCP-Servertools werden mit dem Servernamen als Präfix registriert. Um alle Tools für einen Server zu deaktivieren, verwenden Sie einfach Folgendes: + +``` +"mymcpservername_*": false +``` + +::: + +--- + +## Beispiele + +Nachfolgend finden Sie Beispiele einiger gängiger MCP-Server. Sie können ein PR einreichen, wenn Sie einen anderen Server dokumentieren möchten. + +--- + +### Sentry + +Fügen Sie [Sentry MCP server](https://mcp.sentry.dev) hinzu, um mit Ihren Sentry-Projekten und -Problemen zu interagieren. + +```json title="opencode.json" {4-8} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "sentry": { + "type": "remote", + "url": "https://mcp.sentry.dev/mcp", + "oauth": {} + } + } +} +``` + +Authentifizieren Sie sich nach dem Hinzufügen der Konfiguration mit Sentry: + +```bash +opencode mcp auth sentry +``` + +Dadurch wird ein Browserfenster geöffnet, um den OAuth-Ablauf abzuschließen und OpenCode mit Ihrem Sentry-Konto zu verbinden. + +Nach der Authentifizierung können Sie Sentry-Tools in Ihren Eingabeaufforderungen verwenden, um Probleme, Projekte und Fehlerdaten abzufragen. + +```txt "use sentry" +Show me the latest unresolved issues in my project. use sentry +``` + +--- + +### Context7 + +Fügen Sie [Context7 MCP server](https://github.com/upstash/context7) hinzu, um Dokumente zu durchsuchen. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "context7": { + "type": "remote", + "url": "https://mcp.context7.com/mcp" + } + } +} +``` + +Wenn Sie sich für ein kostenloses Konto angemeldet haben, können Sie Ihren API-Schlüssel verwenden und höhere Ratenlimits erhalten. + +```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}" + } + } + } +} +``` + +Hier gehen wir davon aus, dass Sie die Umgebungsvariable `CONTEXT7_API_KEY` festgelegt haben. + +Fügen Sie `use context7` zu Ihren Eingabeaufforderungen hinzu, um den Context7 MCP-Server zu verwenden. + +```txt "use context7" +Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 +``` + +Alternativ können Sie so etwas zu Ihrem [AGENTS.md](/docs/rules/) hinzufügen. + +```md title="AGENTS.md" +When you need to search docs, use `context7` tools. +``` + +--- + +### Grep by Vercel + +Fügen Sie den Server [Grep by Vercel](https://grep.app) MCP hinzu, um Codefragmente auf GitHub zu durchsuchen. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "gh_grep": { + "type": "remote", + "url": "https://mcp.grep.app" + } + } +} +``` + +Da wir unseren MCP-Server `gh_grep` genannt haben, können Sie `use the gh_grep tool` zu Ihren Eingabeaufforderungen hinzufügen, um den Agenten dazu zu bringen, ihn zu verwenden. + +```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 +``` + +Alternativ können Sie so etwas zu Ihrem [AGENTS.md](/docs/rules/) hinzufügen. + +```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/de/models.mdx b/packages/web/src/content/docs/de/models.mdx new file mode 100644 index 00000000000..075296c4876 --- /dev/null +++ b/packages/web/src/content/docs/de/models.mdx @@ -0,0 +1,223 @@ +--- +title: Modelle +description: Konfigurieren eines LLM-Anbieters und -Modells. +--- + +OpenCode verwendet [AI SDK](https://ai-sdk.dev/) und [Models.dev](https://models.dev) zur Unterstützung von **75+ LLM-Anbietern** und unterstützt die Ausführung lokaler Modelle. + +--- + +## Anbieter + +Die meisten gängigen Anbieter sind standardmäßig vorinstalliert. Wenn Sie die Anmeldeinformationen für einen Anbieter über den Befehl `/connect` hinzugefügt haben, sind diese verfügbar, wenn Sie OpenCode starten. + +Erfahren Sie mehr über [providers](/docs/providers). + +--- + +## Modell auswählen + +Sobald Sie Ihren Anbieter konfiguriert haben, können Sie das gewünschte Modell auswählen, indem Sie Folgendes eingeben: + +```bash frame="none" +/models +``` + +--- + +## Empfohlene Modelle + +Es gibt viele Modelle da draußen und jede Woche kommen neue Modelle heraus. + +:::tip +Erwägen Sie die Verwendung eines der von uns empfohlenen Modelle. +::: + +Allerdings gibt es nur wenige von ihnen, die sowohl gut darin sind, Code zu generieren als auch Tools aufzurufen. + +Hier sind mehrere Modelle, die gut mit OpenCode funktionieren, in keiner bestimmten Reihenfolge. (Dies ist weder eine vollständige noch eine unbedingt aktuelle Liste): + +- GPT 5.2 +- GPT 5.1 Kodex +- Claude Opus 4.5 +- Claude Sonett 4.5 +- Minimax M2.1 +- Gemini 3 Pro + +--- + +## Standard festlegen + +Um eines davon als Standardmodell festzulegen, können Sie den Schlüssel `model` in Ihrem festlegen +OpenCode config. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +Hier ist der vollständige ID `provider_id/model_id`. Wenn Sie beispielsweise [OpenCode Zen](/docs/zen) verwenden, würden Sie `opencode/gpt-5.1-codex` für GPT 5.1 Codex verwenden. + +Wenn Sie einen [custom provider](/docs/providers#custom) konfiguriert haben, ist `provider_id` der Schlüssel aus dem `provider`-Teil Ihrer Konfiguration und `model_id` der Schlüssel aus `provider.models`. + +--- + +## Modelle konfigurieren + +Sie können die Optionen eines Modells global über die Konfiguration konfigurieren. + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +Hier konfigurieren wir globale Einstellungen für zwei integrierte Modelle: `gpt-5` bei Zugriff über den `openai`-Anbieter und `claude-sonnet-4-20250514` bei Zugriff über den `anthropic`-Anbieter. +Die integrierten Anbieter- und Modellnamen finden Sie unter [Models.dev](https://models.dev). + +Sie können diese Optionen auch für alle von Ihnen verwendeten Agenten konfigurieren. Die Agentenkonfiguration beschreibt hier alle globalen Optionen. [Learn more](/docs/agents/#additional). + +Sie können auch benutzerdefinierte Varianten definieren, die integrierte Varianten erweitern. Mit Varianten können Sie unterschiedliche Einstellungen für dasselbe Modell konfigurieren, ohne doppelte Einträge zu erstellen: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## Varianten + +Viele Modelle unterstützen mehrere Varianten mit unterschiedlichen Konfigurationen. OpenCode wird mit integrierten Standardvarianten für beliebte Anbieter ausgeliefert. + +### Integrierte Varianten + +OpenCode wird für viele Anbieter mit Standardvarianten ausgeliefert: + +**Anthropic**: + +- `high` – Budget für hohes Denken (Standard) +- `max` – Maximales Denkbudget + +**OpenAI**: + +Variiert je nach Modell, aber ungefähr: + +- `none` – Keine Begründung +- `minimal` – Minimaler Argumentationsaufwand +- `low` – Geringer Denkaufwand +- `medium` – Mittlerer Denkaufwand +- `high` – Hoher Denkaufwand +- `xhigh` – Extra hoher Argumentationsaufwand + +**Google**: + +- `low` – Beliebtestes effort/token-Budget +- `high` – Höheres effort/token-Budget + +:::tip +Diese Liste ist nicht vollständig. Viele andere Anbieter verfügen ebenfalls über integrierte Standardeinstellungen. +::: + +### Benutzerdefinierte Varianten + +Sie können vorhandene Varianten überschreiben oder eigene hinzufügen: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### Varianten durchwechseln + +Verwenden Sie die Tastenkombination `variant_cycle`, um schnell zwischen Varianten zu wechseln. [Learn more](/docs/keybinds). + +--- + +## Laden von Modellen + +Wenn OpenCode startet, sucht es nach Modellen in der folgenden Prioritätsreihenfolge: + +1. Das Befehlszeilenflag `--model` oder `-m`. Das Format ist das gleiche wie in der Konfigurationsdatei: `provider_id/model_id`. + +2. Die Modellliste in der OpenCode-Konfiguration. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + + Das Format hier ist `provider/model`. + +3. Das zuletzt verwendete Modell. + +4. Das erste Modell, das eine interne Priorität verwendet. diff --git a/packages/web/src/content/docs/de/modes.mdx b/packages/web/src/content/docs/de/modes.mdx new file mode 100644 index 00000000000..b0d93930731 --- /dev/null +++ b/packages/web/src/content/docs/de/modes.mdx @@ -0,0 +1,331 @@ +--- +title: Modi +description: Verschiedene Modi für unterschiedliche Anwendungsfälle. +--- + +:::caution +Modi werden jetzt über die Option `agent` in der OpenCode-Konfiguration konfiguriert. Der +Die Option `mode` ist jetzt veraltet. [Learn more](/docs/agents). +::: + +Mit den Modi in OpenCode können Sie das Verhalten, die Tools und die Eingabeaufforderungen für verschiedene Anwendungsfälle anpassen. + +Es verfügt über zwei integrierte Modi: **Build** und **Plan**. Sie können anpassen +diese oder konfigurieren Sie Ihre eigenen über die OpenCode-Konfiguration. + +Sie können während einer Sitzung zwischen den Modi wechseln oder diese in Ihrer Konfigurationsdatei konfigurieren. + +--- + +## Integriert + +OpenCode verfügt über zwei integrierte Modi. + +--- + +### Build + +Build ist der **Standardmodus**, bei dem alle Tools aktiviert sind. Dies ist der Standardmodus für Entwicklungsarbeiten, bei dem Sie vollen Zugriff auf Dateioperationen und Systembefehle benötigen. + +--- + +### Plan + +Ein eingeschränkter Modus für Planung und Analyse. Im Planmodus sind die folgenden Tools standardmäßig deaktiviert: + +- `write` – Es können keine neuen Dateien erstellt werden +- `edit` – Vorhandene Dateien können nicht geändert werden, mit Ausnahme der Dateien unter `.opencode/plans/*.md`, um den Plan selbst detailliert darzustellen +- `patch` – Patches können nicht angewendet werden +- `bash` – Shell-Befehle können nicht ausgeführt werden + +Dieser Modus ist nützlich, wenn Sie möchten, dass AI Code analysiert, Änderungen vorschlägt oder Pläne erstellt, ohne tatsächliche Änderungen an Ihrer Codebasis vorzunehmen. + +--- + +## Wechseln + +Sie können während einer Sitzung mit der _Tab_-Taste zwischen den Modi wechseln. Oder Ihre konfigurierte `switch_mode`-Tastenkombination. + +Siehe auch: [Formatters](/docs/formatters) für Informationen zur Codeformatierungskonfiguration. + +--- + +## Konfiguration + +Sie können die integrierten Modi anpassen oder über die Konfiguration eigene erstellen. Modi können auf zwei Arten konfiguriert werden: + +### JSON-Konfiguration + +Konfigurieren Sie Modi in Ihrer `opencode.json`-Konfigurationsdatei: + +```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-Konfiguration + +Sie können Modi auch mithilfe von Markdown-Dateien definieren. Platzieren Sie sie in: + +- Global: `~/.config/opencode/modes/` +- Projekt: `.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. +``` + +Der Name der Markdown-Datei wird zum Modusnamen (e.g., `review.md` erstellt einen `review`-Modus). + +Schauen wir uns diese Konfigurationsmöglichkeiten im Detail an. + +--- + +### Model + +Verwenden Sie die `model`-Konfiguration, um das Standardmodell für diesen Modus zu überschreiben. Nützlich für die Verwendung verschiedener Modelle, die für verschiedene Aufgaben optimiert sind. Zum Beispiel ein schnelleres Modell für die Planung, ein leistungsfähigeres Modell für die Umsetzung. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### Temperatur + +Steuern Sie die Zufälligkeit und Kreativität der Antworten von AI mit der `temperature`-Konfiguration. Niedrigere Werte machen die Antworten fokussierter und deterministischer, während höhere Werte die Kreativität und Variabilität steigern. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Temperaturwerte liegen typischerweise zwischen 0.0 und 1.0: + +- **0.0-0.2**: Sehr fokussierte und deterministische Antworten, ideal für Code-Analyse und Planung +- **0.3-0.5**: Ausgewogene Antworten mit etwas Kreativität, gut für allgemeine Entwicklungsaufgaben +- **0.6-1.0**: Kreativere und vielfältigere Antworten, nützlich für Brainstorming und Erkundung + +```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}" + } + } +} +``` + +Wenn keine Temperatur angegeben ist, verwendet OpenCode modellspezifische Standardwerte (normalerweise 0 für die meisten Modelle, 0.55 für Qwen-Modelle). + +--- + +### Prompt + +Geben Sie mit der `prompt`-Konfiguration eine benutzerdefinierte Systemaufforderungsdatei für diesen Modus an. Die Eingabeaufforderungsdatei sollte spezifische Anweisungen für den Zweck des Modus enthalten. + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Dieser Pfad ist relativ zum Speicherort der Konfigurationsdatei. Das funktioniert also +sowohl die globale OpenCode-Konfiguration als auch die projektspezifische Konfiguration. + +--- + +### Werkzeuge + +Steuern Sie mit der `tools`-Konfiguration, welche Tools in diesem Modus verfügbar sind. Sie können bestimmte Tools aktivieren oder deaktivieren, indem Sie sie auf `true` oder `false` setzen. + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +Wenn keine Tools angegeben sind, sind alle Tools standardmäßig aktiviert. + +--- + +#### Verfügbare Tools + +Hier sind alle Tools aufgeführt, die über den Konfigurationsmodus gesteuert werden können. + +| Werkzeug | Beschreibung | +| ----------- | ---------------------------- | +| `bash` | Shell-Befehle ausführen | +| `edit` | Vorhandene Dateien ändern | +| `write` | Neue Dateien erstellen | +| `read` | Dateiinhalt lesen | +| `grep` | Dateiinhalte durchsuchen | +| `glob` | Dateien nach Muster suchen | +| `list` | Verzeichnisinhalte auflisten | +| `patch` | Patches auf Dateien anwenden | +| `todowrite` | Aufgabenlisten verwalten | +| `todoread` | Aufgabenlisten lesen | +| `webfetch` | Webinhalte abrufen | + +--- + +## Benutzerdefinierte Modi + +Sie können Ihre eigenen benutzerdefinierten Modi erstellen, indem Sie diese zur Konfiguration hinzufügen. Hier sind Beispiele für beide Ansätze: + +### Verwenden der JSON-Konfiguration + +```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 + } + } + } +} +``` + +### Verwendung von Markdown-Dateien + +Erstellen Sie Modusdateien in `.opencode/modes/` für projektspezifische Modi oder `~/.config/opencode/modes/` für globale Modi: + +```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 +``` + +--- + +### Anwendungsfälle + +Hier sind einige häufige Anwendungsfälle für verschiedene Modi. + +- **Build-Modus**: Vollständige Entwicklungsarbeit mit allen aktivierten Tools +- **Planmodus**: Analyse und Planung ohne Änderungen +- **Überprüfungsmodus**: Codeüberprüfung mit schreibgeschütztem Zugriff plus Dokumentationstools +- **Debug-Modus**: Konzentriert sich auf die Untersuchung mit aktivierten Bash- und Lesetools +- **Docs-Modus**: Dokumentationsschreiben mit Dateioperationen, aber ohne Systembefehle + +Möglicherweise stellen Sie auch fest, dass unterschiedliche Modelle für unterschiedliche Anwendungsfälle geeignet sind. diff --git a/packages/web/src/content/docs/de/network.mdx b/packages/web/src/content/docs/de/network.mdx new file mode 100644 index 00000000000..34d2e5bd074 --- /dev/null +++ b/packages/web/src/content/docs/de/network.mdx @@ -0,0 +1,57 @@ +--- +title: Netzwerk +description: Konfigurieren Sie Proxys und benutzerdefinierte Zertifikate. +--- + +OpenCode unterstützt Standard-Proxy-Umgebungsvariablen und benutzerdefinierte Zertifikate für Unternehmensnetzwerkumgebungen. + +--- + +## Proxy + +OpenCode respektiert Standard-Proxy-Umgebungsvariablen. + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +Der TUI kommuniziert mit einem lokalen HTTP-Server. Sie müssen den Proxy für diese Verbindung umgehen, um Routing-Schleifen zu verhindern. +::: + +Sie können den Port und den Hostnamen des Servers mit [CLI flags](/docs/cli#run) konfigurieren. + +--- + +### Authentifizierung + +Wenn Ihr Proxy eine Basisauthentifizierung erfordert, geben Sie Anmeldeinformationen in URL ein. + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +Vermeiden Sie hartkodierte Passwörter. Verwenden Sie Umgebungsvariablen oder einen sicheren Speicher für Anmeldeinformationen. +::: + +Für Proxys, die eine erweiterte Authentifizierung wie NTLM oder Kerberos erfordern, sollten Sie die Verwendung eines LLM-Gateways in Betracht ziehen, das Ihre Authentifizierungsmethode unterstützt. + +--- + +## Benutzerdefinierte Zertifikate + +Wenn Ihr Unternehmen benutzerdefinierte Zertifizierungsstellen für HTTPS-Verbindungen verwendet, konfigurieren Sie OpenCode so, dass es ihnen vertraut. + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +Dies funktioniert sowohl für Proxy-Verbindungen als auch für den direkten API-Zugriff. diff --git a/packages/web/src/content/docs/de/permissions.mdx b/packages/web/src/content/docs/de/permissions.mdx new file mode 100644 index 00000000000..0fb23831aa4 --- /dev/null +++ b/packages/web/src/content/docs/de/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: Berechtigungen +description: Steuern Sie, für welche Aktionen eine Genehmigung erforderlich ist. +--- + +OpenCode verwendet die `permission`-Konfiguration, um zu entscheiden, ob eine bestimmte Aktion automatisch ausgeführt werden soll, Sie dazu auffordern oder blockiert werden soll. + +Ab `v1.1.1` ist die alte boolesche Konfiguration `tools` veraltet und wurde in `permission` zusammengeführt. Die alte `tools`-Konfiguration wird aus Gründen der Abwärtskompatibilität weiterhin unterstützt. + +--- + +## Aktionen + +Jede Berechtigungsregel wird zu einem der folgenden aufgelöst: + +- `"allow"` – ohne Genehmigung ausführen +- `"ask"` — um Genehmigung bitten +- `"deny"` – Aktion blockieren + +--- + +## Konfiguration + +Sie können Berechtigungen global festlegen (mit `*`) und bestimmte Tools überschreiben. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +Sie können auch alle Berechtigungen auf einmal festlegen: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## Granulare Regeln (Objektsyntax) + +Bei den meisten Berechtigungen können Sie ein Objekt verwenden, um basierend auf der Werkzeugeingabe verschiedene Aktionen anzuwenden. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +Regeln werden nach Musterübereinstimmung ausgewertet, wobei die **letzte übereinstimmende Regel gewinnt**. Ein gängiges Muster besteht darin, zuerst die Catch-All-Regel `"*"` und danach spezifischere Regeln zu platzieren. + +### Platzhalter + +Berechtigungsmuster verwenden einen einfachen Platzhalterabgleich: + +- `*` matches zero or more of any character +- `?` matches exactly one character +- Alle anderen Zeichen stimmen wörtlich überein + +### Erweiterung des Home-Verzeichnisses + +Sie können `~` oder `$HOME` am Anfang eines Musters verwenden, um auf Ihr Home-Verzeichnis zu verweisen. Dies ist besonders nützlich für [`external_directory`](#external-directories)-Regeln. + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### Externe Verzeichnisse + +Verwenden Sie `external_directory`, um Toolaufrufe zuzulassen, die Pfade außerhalb des Arbeitsverzeichnisses berühren, in dem OpenCode gestartet wurde. Dies gilt für jedes Werkzeug, das einen Pfad als Eingabe verwendet (z. B. `read`, `edit`, `list`, `glob`, `grep` und viele `bash`-Befehle). + +Die Home-Erweiterung (wie `~/...`) wirkt sich nur darauf aus, wie ein Muster geschrieben wird. Dadurch wird ein externer Pfad nicht zum Teil des aktuellen Arbeitsbereichs, daher müssen Pfade außerhalb des Arbeitsverzeichnisses weiterhin über `external_directory` zulässig sein. + +Dies ermöglicht beispielsweise den Zugriff auf alles unter `~/projects/personal/`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +Jedes hier zulässige Verzeichnis erbt dieselben Standardeinstellungen wie der aktuelle Arbeitsbereich. Seit [`read` defaults to `allow`](#defaults) sind Lesevorgänge auch für Einträge unter `external_directory` zulässig, sofern sie nicht überschrieben werden. Fügen Sie explizite Regeln hinzu, wenn ein Tool in diesen Pfaden eingeschränkt werden soll, z. B. das Blockieren von Bearbeitungen, während Lesevorgänge beibehalten werden: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +Konzentrieren Sie sich in der Liste auf vertrauenswürdige Pfade und fügen Sie bei Bedarf zusätzliche Zulassungs- oder Ablehnungsregeln für andere Tools hinzu (z. B. `bash`). + +--- + +## Verfügbare Berechtigungen + +OpenCode-Berechtigungen basieren auf Tool-Namen sowie einigen Sicherheitsvorkehrungen: + +- `read` – eine Datei lesen (entspricht dem Dateipfad) +- `edit` – alle Dateiänderungen (umfasst `edit`, `write`, `patch`, `multiedit`) +- `glob` – Datei-Globbing (entspricht dem Glob-Muster) +- `grep` – Inhaltssuche (entspricht dem Regex-Muster) +- `list` – Auflistung der Dateien in einem Verzeichnis (entspricht dem Verzeichnispfad) +- `bash` – Ausführen von Shell-Befehlen (entspricht analysierten Befehlen wie `git status --porcelain`) +- `task` – Subagenten starten (entspricht dem Subagententyp) +- `skill` – Laden einer Fertigkeit (entspricht dem Fertigkeitsnamen) +- `lsp` – Ausführen von LSP-Abfragen (derzeit nicht granular) +- `todoread`, `todowrite` – lesen/aktualisieren der Aufgabenliste +- `webfetch` – Abrufen eines URL (entspricht dem URL) +- `websearch`, `codesearch` – web/code Suche (entspricht der Abfrage) +- `external_directory` – wird ausgelöst, wenn ein Tool Pfade außerhalb des Projektarbeitsverzeichnisses berührt +- `doom_loop` – wird ausgelöst, wenn derselbe Werkzeugaufruf dreimal mit identischer Eingabe wiederholt wird + +--- + +## Standardwerte + +Wenn Sie nichts angeben, beginnt OpenCode mit zulässigen Standardeinstellungen: + +- Die meisten Berechtigungen sind standardmäßig auf `"allow"` eingestellt. +- `doom_loop` und `external_directory` sind standardmäßig `"ask"`. +- `read` ist `"allow"`, aber `.env`-Dateien werden standardmäßig verweigert: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## Was „Fragen“ bewirkt + +Wenn OpenCode zur Genehmigung auffordert, bietet UI drei Ergebnisse: + +- `once` – nur diese Anfrage genehmigen +- `always` – zukünftige Anfragen genehmigen, die den vorgeschlagenen Mustern entsprechen (für den Rest der aktuellen OpenCode-Sitzung) +- `reject` – die Anfrage ablehnen + +Der Satz von Mustern, die `always` genehmigen würde, wird vom Tool bereitgestellt (Beispiel: Bash-Genehmigungen setzen normalerweise ein sicheres Befehlspräfix wie `git status*` auf die Whitelist). + +--- + +## Agenten + +Sie können Berechtigungen pro Agent überschreiben. Agentenberechtigungen werden mit der globalen Konfiguration zusammengeführt und Agentenregeln haben Vorrang. [Learn more](/docs/agents#permissions) über Agentenberechtigungen. + +:::note +Ausführlichere Mustervergleichsbeispiele finden Sie oben im Abschnitt [Granular Rules (Object Syntax)](#granular-rules-object-syntax). +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +Sie können Agentenberechtigungen auch in Markdown konfigurieren: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +Verwenden Sie den Mustervergleich für Befehle mit Argumenten. `"grep *"` erlaubt `grep pattern file.txt`, während `"grep"` allein es blockieren würde. Befehle wie `git status` funktionieren für das Standardverhalten, erfordern jedoch eine explizite Erlaubnis (wie `"git status *"`), wenn Argumente übergeben werden. +::: diff --git a/packages/web/src/content/docs/de/plugins.mdx b/packages/web/src/content/docs/de/plugins.mdx new file mode 100644 index 00000000000..57fcdbba6e8 --- /dev/null +++ b/packages/web/src/content/docs/de/plugins.mdx @@ -0,0 +1,384 @@ +--- +title: Plugins +description: Schreiben Sie Ihre eigenen Plugins, um OpenCode zu erweitern. +--- + +Mit Plugins können Sie OpenCode erweitern, indem Sie verschiedene Ereignisse einbinden und das Verhalten anpassen. Sie können Plugins erstellen, um neue Funktionen hinzuzufügen, externe Dienste zu integrieren oder das Standardverhalten von OpenCode zu ändern. + +Beispiele finden Sie im von der Community erstellten [plugins](/docs/ecosystem#plugins). + +--- + +## Plugins verwenden + +Es gibt zwei Möglichkeiten, Plugins zu laden. + +--- + +### Aus lokalen Dateien + +Platzieren Sie JavaScript- oder TypeScript-Dateien im Plugin-Verzeichnis. + +- `.opencode/plugins/` – Plugins auf Projektebene +- `~/.config/opencode/plugins/` – Globale Plugins + +Dateien in diesen Verzeichnissen werden beim Start automatisch geladen. + +--- + +### Von npm + +Geben Sie npm-Pakete in Ihrer Konfigurationsdatei an. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +Es werden sowohl reguläre als auch bereichsbezogene NPM-Pakete unterstützt. + +Durchsuchen Sie die verfügbaren Plugins im [ecosystem](/docs/ecosystem#plugins). + +--- + +### Plugin-Installation + +**NPM-Plugins** werden beim Start automatisch mit Bun installiert. Pakete und ihre Abhängigkeiten werden in `~/.cache/opencode/node_modules/` zwischengespeichert. + +**Lokale Plugins** werden direkt aus dem Plugin-Verzeichnis geladen. Um externe Pakete zu verwenden, müssen Sie ein `package.json` in Ihrem Konfigurationsverzeichnis erstellen (siehe [Dependencies](#dependencies)) oder das Plugin auf npm und [add it to your config](/docs/config#plugins) veröffentlichen. + +--- + +### Ladereihenfolge + +Plugins werden aus allen Quellen geladen und alle Hooks werden nacheinander ausgeführt. Die Ladereihenfolge lautet: + +1. Globale Konfiguration (`~/.config/opencode/opencode.json`) +2. Projektkonfiguration (`opencode.json`) +3. Globales Plugin-Verzeichnis (`~/.config/opencode/plugins/`) +4. Projekt-Plugin-Verzeichnis (`.opencode/plugins/`) + +Doppelte npm-Pakete mit demselben Namen und derselben Version werden einmal geladen. Allerdings werden ein lokales Plugin und ein NPM-Plugin mit ähnlichen Namen beide separat geladen. + +--- + +## Plugins erstellen + +Ein Plugin ist ein **JavaScript/TypeScript-Modul**, das eine oder mehrere Plugin-Funktionen exportiert. Jede Funktion empfängt ein Kontextobjekt und gibt ein Hooks-Objekt zurück. + +--- + +### Abhängigkeiten + +Lokale Plugins und benutzerdefinierte Tools können externe npm-Pakete verwenden. Fügen Sie Ihrem Konfigurationsverzeichnis ein `package.json` mit den benötigten Abhängigkeiten hinzu. + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +OpenCode führt beim Start `bun install` aus, um diese zu installieren. Ihre Plugins und Tools können sie dann importieren. + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### Grundstruktur + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +Die Plugin-Funktion erhält: + +- `project`: Die aktuellen Projektinformationen. +- `directory`: Das aktuelle Arbeitsverzeichnis. +- `worktree`: Der Git-Worktree-Pfad. +- `client`: Ein OpenCode-SDK-Client für die Interaktion mit AI. +- `$`: Buns [shell API](https://bun.com/docs/runtime/shell) zum Ausführen von Befehlen. + +--- + +### TypeScript-Unterstützung + +Für TypeScript-Plugins können Sie Typen aus dem Plugin-Paket importieren: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### Ereignisse + +Plugins können Ereignisse abonnieren, wie unten im Abschnitt „Beispiele“ gezeigt. Hier finden Sie eine Liste der verschiedenen verfügbaren Veranstaltungen. + +#### Befehlsereignisse + +- `command.executed` + +#### Dateiereignisse + +- `file.edited` +- `file.watcher.updated` + +#### Installationsereignisse + +- `installation.updated` + +#### LSP-Ereignisse + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### Nachrichtenereignisse + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### Berechtigungsereignisse + +- `permission.asked` +- `permission.replied` + +#### Serverereignisse + +- `server.connected` + +#### Sitzungsereignisse + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### Todo-Ereignisse + +- `todo.updated` + +#### Shell-Ereignisse + +- `shell.env` + +#### Tool-Ereignisse + +- `tool.execute.after` +- `tool.execute.before` + +#### TUI-Ereignisse + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## Beispiele + +Hier sind einige Beispiele für Plugins, mit denen Sie OpenCode erweitern können. + +--- + +### Benachrichtigungen senden + +Senden Sie Benachrichtigungen, wenn bestimmte Ereignisse eintreten: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +Wir verwenden `osascript`, um AppleScript unter macOS auszuführen. Hier verwenden wir es zum Versenden von Benachrichtigungen. + +:::note +Wenn Sie die OpenCode-Desktop-App verwenden, kann diese automatisch Systembenachrichtigungen senden, wenn eine Antwort bereit ist oder wenn in einer Sitzung ein Fehler auftritt. +::: + +--- + +### .env-Schutz + +Verhindern Sie, dass OpenCode `.env`-Dateien liest: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### Umgebungsvariablen einfügen + +Fügen Sie Umgebungsvariablen in alle Shell-Ausführungen ein (AI-Tools und Benutzerterminals): + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### Benutzerdefinierte Tools + +Plugins können OpenCode auch benutzerdefinierte Tools hinzufügen: + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +Der `tool`-Helfer erstellt ein benutzerdefiniertes Tool, das OpenCode aufrufen kann. Es verwendet eine Zod-Schemafunktion und gibt eine Tooldefinition zurück mit: + +- `description`: Was das Tool macht +- `args`: Zod-Schema für die Argumente des Tools +- `execute`: Funktion, die ausgeführt wird, wenn das Tool aufgerufen wird + +Ihre benutzerdefinierten Tools stehen neben den integrierten Tools für OpenCode zur Verfügung. + +--- + +### Protokollierung + +Verwenden Sie `client.app.log()` anstelle von `console.log` für die strukturierte Protokollierung: + +```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" }, + }, + }) +} +``` + +Ebenen: `debug`, `info`, `warn`, `error`. Weitere Informationen finden Sie unter [SDK documentation](https://opencode.ai/docs/sdk). + +--- + +### Compaction-Hooks + +Passen Sie den Kontext an, der beim Komprimieren einer Sitzung einbezogen wird: + +```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 +`) + }, + } +} +``` + +Der Hook `experimental.session.compacting` wird ausgelöst, bevor der Hook LLM eine Fortsetzungszusammenfassung generiert. Verwenden Sie es, um domänenspezifischen Kontext einzufügen, der der standardmäßigen Komprimierungsaufforderung entgehen würde. + +Sie können die Komprimierungsaufforderung auch vollständig ersetzen, indem Sie `output.prompt` festlegen: + +```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. +` + }, + } +} +``` + +Wenn `output.prompt` festgelegt ist, ersetzt es die standardmäßige Komprimierungsaufforderung vollständig. Das Array `output.context` wird in diesem Fall ignoriert. diff --git a/packages/web/src/content/docs/de/providers.mdx b/packages/web/src/content/docs/de/providers.mdx new file mode 100644 index 00000000000..d72ac5af3de --- /dev/null +++ b/packages/web/src/content/docs/de/providers.mdx @@ -0,0 +1,1889 @@ +--- +title: Anbieter +description: Verwendung eines beliebigen LLM-Anbieters in OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console + +OpenCode verwendet [AI SDK](https://ai-sdk.dev/) und [Models.dev](https://models.dev) zur Unterstützung von **75+ LLM-Anbietern** und unterstützt die Ausführung lokaler Modelle. + +Um einen Anbieter hinzuzufügen, müssen Sie: + +1. Fügen Sie die API-Schlüssel für den Anbieter mit dem Befehl `/connect` hinzu. +2. Konfigurieren Sie den Anbieter in Ihrer OpenCode-Konfiguration. + +--- + +### Anmeldeinformationen + +Wenn Sie die API-Schlüssel eines Anbieters mit dem Befehl `/connect` hinzufügen, werden diese gespeichert +in `~/.local/share/opencode/auth.json`. + +--- + +### Konfiguration + +Sie können die Anbieter über den Abschnitt `provider` in Ihrem OpenCode anpassen +config. + +--- + +#### Base URL + +Sie können die Base URL für jeden Anbieter anpassen, indem Sie die Option `baseURL` festlegen. Das ist nuetzlich, wenn Sie Proxy-Dienste oder benutzerdefinierte Endpunkte verwenden. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen ist eine Liste von Modellen, die vom OpenCode-Team bereitgestellt wurden +Getestet und verifiziert, dass es gut mit OpenCode funktioniert. [Learn more](/docs/zen). + +:::tip +Wenn Sie neu sind, empfehlen wir Ihnen, mit OpenCode Zen zu beginnen. +::: + +1. Führen Sie den Befehl `/connect` in TUI aus, wählen Sie OpenCode aus und gehen Sie zu [opencode.ai/auth](https://opencode.ai/auth). + + ```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 TUI aus, um die Liste der von uns empfohlenen Modelle anzuzeigen. + + ```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 +Liste, zögern Sie nicht, ein PR zu öffnen. + +:::note +Sehen Sie hier keinen Anbieter? Senden Sie einen PR. +::: + +--- + +### 302.AI + +1. Gehen Sie zu [302.AI console](https://302.ai/), erstellen Sie ein Konto und generieren Sie einen API-Schlüssel. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **302.AI**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren 302.AI API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell auszuwählen. + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +So verwenden Sie Amazon Bedrock mit OpenCode: + +1. Gehen Sie zum **Modellkatalog** in der Amazon Bedrock-Konsole und fordern Sie an + Zugriff auf die gewünschten Modelle. + + :::tip + Sie müssen Zugriff auf das gewünschte Modell in Amazon Bedrock haben. + ::: + +2. **Konfigurieren Sie die Authentifizierung** mit einer der folgenden Methoden: + + #### Umgebungsvariablen (Schnellstart) + + Legen Sie eine dieser Umgebungsvariablen fest, während Sie OpenCode ausführen: + + ```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode + ``` + + Oder fügen Sie sie Ihrem Bash-Profil hinzu: + + ```bash title="~/.bash_profile" + export AWS_PROFILE=my-dev-profile + export AWS_REGION=us-east-1 + ``` + + #### Konfigurationsdatei (empfohlen) + + Für eine projektspezifische oder dauerhafte Konfiguration verwenden Sie `opencode.json`: + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile" + } + } + } + } + ``` + + **Verfügbare Optionen:** + - `region` - AWS region (e.g., `us-east-1`, `eu-west-1`) + - `profile` - AWS named profile from `~/.aws/credentials` + - `endpoint` – Benutzerdefinierter Endpunkt URL für VPC-Endpunkte (Alias ​​für generische `baseURL`-Option) + + :::tip + Konfigurationsdateioptionen haben Vorrang vor Umgebungsvariablen. + ::: + + #### Erweitert: VPC Endpunkte + + Wenn Sie VPC-Endpunkte für Bedrock verwenden: + + ```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 + Die Option `endpoint` ist ein Alias ​​für die generische Option `baseURL` und verwendet AWS-spezifische Terminologie. Wenn sowohl `endpoint` als auch `baseURL` angegeben sind, hat `endpoint` Vorrang. + ::: + + #### Authentifizierungsmethoden + - **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: Erstellen Sie einen IAM-Benutzer und generieren Sie Zugriffsschlüssel in der AWS-Konsole + - **`AWS_PROFILE`**: Benannte Profile von `~/.aws/credentials` verwenden. Zuerst mit `aws configure --profile my-profile` oder `aws sso login` konfigurieren + - **`AWS_BEARER_TOKEN_BEDROCK`**: Generieren Sie langfristige API-Schlüssel aus der Amazon Bedrock-Konsole + - **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: Für EKS IRSA (IAM Rollen für Dienstkonten) oder andere Kubernetes-Umgebungen mit OIDC-Verbund. Diese Umgebungsvariablen werden von Kubernetes automatisch eingefügt, wenn Dienstkontoanmerkungen verwendet werden. + + #### Authentifizierungspriorität + + Amazon Bedrock verwendet die folgende Authentifizierungspriorität: + 1. **Bearer-Token** – `AWS_BEARER_TOKEN_BEDROCK`-Umgebungsvariable oder Token aus dem `/connect`-Befehl + 2. **AWS Anmeldeinformationskette** – Profil, Zugriffsschlüssel, gemeinsame Anmeldeinformationen, IAM Rollen, Web-Identitätstoken (EKS IRSA), Instanzmetadaten + + :::note + Wenn ein Inhabertoken festgelegt ist (über `/connect` oder `AWS_BEARER_TOKEN_BEDROCK`), hat es Vorrang vor allen AWS-Anmeldeinformationsmethoden, einschließlich konfigurierter Profile. + ::: + +3. Führen Sie den Befehl `/models` aus, um das gewünschte Modell auszuwählen. + + ```txt + /models + ``` + +:::note +Verwenden Sie für benutzerdefinierte Inferenzprofile den Modell- und Anbieternamen im Schlüssel und legen Sie die Eigenschaft `id` auf den Arn fest. Dadurch wird ein korrektes Caching sichergestellt: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. Sobald Sie sich angemeldet haben, führen Sie den Befehl `/connect` aus und wählen Sie Anthropic aus. + + ```txt + /connect + ``` + +2. Hier können Sie die Option **Claude Pro/Max** auswählen und Ihr Browser wird geöffnet + und bitten Sie, sich zu authentifizieren. + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. Jetzt sollten alle Anthropic-Modelle verfügbar sein, wenn Sie den Befehl `/models` verwenden. + + ```txt + /models + ``` + +:::info +Die Verwendung Ihres Claude Pro/Max-Abonnements in OpenCode wird von [Anthropic](https://anthropic.com) nicht offiziell unterstützt. +::: + +##### Verwendung von API-Keys + +Sie können auch **Erstellen eines API-Schlüssels** auswählen, wenn Sie kein Pro/Max-Abonnement haben. Außerdem wird Ihr Browser geöffnet, Sie werden aufgefordert, sich bei Anthropic anzumelden, und Sie erhalten einen Code, den Sie in Ihr Terminal einfügen können. + +Wenn Sie bereits über einen API-Schlüssel verfügen, können Sie **API-Schlüssel manuell eingeben** auswählen und ihn in Ihr Terminal einfügen. + +--- + +### Azure OpenAI + +:::note +Wenn Sie auf die Fehlermeldung „Es tut mir leid, aber ich kann Ihnen bei dieser Anfrage nicht weiterhelfen“ stoßen, versuchen Sie, den Inhaltsfilter in Ihrer Azure-Ressource von **DefaultV2** in **Default** zu ändern. +::: + +1. Gehen Sie zu [Azure portal](https://portal.azure.com/) und erstellen Sie eine **Azure OpenAI**-Ressource. Sie benötigen: + - **Ressourcenname**: Dies wird Teil Ihres API-Endpunkts (`https://RESOURCE_NAME.openai.azure.com/`) + - **API-Schlüssel**: Entweder `KEY 1` oder `KEY 2` aus Ihrer Ressource + +2. Gehen Sie zu [Azure AI Foundry](https://ai.azure.com/) und stellen Sie ein Modell bereit. + + :::note + Der Bereitstellungsname muss mit dem Modellnamen übereinstimmen, damit OpenCode ordnungsgemäß funktioniert. + ::: + +3. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Azure**. + + ```txt + /connect + ``` + +4. Geben Sie Ihren API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Legen Sie Ihren Ressourcennamen als Umgebungsvariable fest: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + Oder fügen Sie es Ihrem Bash-Profil hinzu: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. Führen Sie den Befehl `/models` aus, um Ihr bereitgestelltes Modell auszuwählen. + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. Gehen Sie zu [Azure portal](https://portal.azure.com/) und erstellen Sie eine **Azure OpenAI**-Ressource. Sie benötigen: + - **Ressourcenname**: Dies wird Teil Ihres API-Endpunkts (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) + - **API-Schlüssel**: Entweder `KEY 1` oder `KEY 2` aus Ihrer Ressource + +2. Gehen Sie zu [Azure AI Foundry](https://ai.azure.com/) und stellen Sie ein Modell bereit. + + :::note + Der Bereitstellungsname muss mit dem Modellnamen übereinstimmen, damit OpenCode ordnungsgemäß funktioniert. + ::: + +3. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Azure Cognitive Services**. + + ```txt + /connect + ``` + +4. Geben Sie Ihren API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Legen Sie Ihren Ressourcennamen als Umgebungsvariable fest: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + Oder fügen Sie es Ihrem Bash-Profil hinzu: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. Führen Sie den Befehl `/models` aus, um Ihr bereitgestelltes Modell auszuwählen. + + ```txt + /models + ``` + +--- + +### Baseten + +1. Gehen Sie zu [Baseten](https://app.baseten.co/), erstellen Sie ein Konto und generieren Sie einen API-Schlüssel. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Baseten**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Baseten API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell auszuwählen. + + ```txt + /models + ``` + +--- + +### Cerebras + +1. Gehen Sie zu [Cerebras console](https://inference.cerebras.ai/), erstellen Sie ein Konto und generieren Sie einen API-Schlüssel. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Cerebras**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Cerebras-API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell wie _Qwen 3 Coder 480B_ auszuwählen. + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +Mit dem Cloudflare AI Gateway können Sie über einen einheitlichen Endpunkt auf Modelle von OpenAI, Anthropic, Workers AI und mehr zugreifen. Mit [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) benötigen Sie nicht für jeden Anbieter separate API-Schlüssel. + +1. Gehen Sie zu [Cloudflare dashboard](https://dash.cloudflare.com/), navigieren Sie zu **AI** > **AI Gateway** und erstellen Sie ein neues Gateway. + +2. Legen Sie Ihr Konto ID und Ihr Gateway ID als Umgebungsvariablen fest. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Cloudflare AI Gateway**. + + ```txt + /connect + ``` + +4. Geben Sie Ihr Cloudflare-API-Token ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + Oder legen Sie es als Umgebungsvariable fest. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. Führen Sie den Befehl `/models` aus, um ein Modell auszuwählen. + + ```txt + /models + ``` + + Sie können Modelle auch über Ihre OpenCode-Konfiguration hinzufügen. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +### Cortecs + +1. Gehen Sie zu [Cortecs console](https://cortecs.ai/), erstellen Sie ein Konto und generieren Sie einen API-Schlüssel. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Cortecs**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Cortecs-API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell wie _Kimi K2 Instruct_ auszuwählen. + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. Gehen Sie zu [DeepSeek console](https://platform.deepseek.com/), erstellen Sie ein Konto und klicken Sie auf **Neuen API-Schlüssel erstellen**. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **DeepSeek**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren DeepSeek API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein DeepSeek-Modell wie _DeepSeek Reasoner_ auszuwählen. + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. Gehen Sie zu [Deep Infra dashboard](https://deepinfra.com/dash), erstellen Sie ein Konto und generieren Sie einen API-Schlüssel. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Deep Infra**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Deep Infra API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell auszuwählen. + + ```txt + /models + ``` + +--- + +### Firmware + +1. Gehen Sie zu [Firmware dashboard](https://app.firmware.ai/signup), erstellen Sie ein Konto und generieren Sie einen API-Schlüssel. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Firmware**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Firmware API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell auszuwählen. + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. Gehen Sie zu [Fireworks AI console](https://app.fireworks.ai/), erstellen Sie ein Konto und klicken Sie auf **API-Schlüssel erstellen**. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Fireworks AI**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Fireworks AI API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell wie _Kimi K2 Instruct_ auszuwählen. + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo bietet AI-gestützten Agenten-Chat mit nativen Tool-Aufruffunktionen über den Anthropic-Proxy von GitLab. + +1. Führen Sie den Befehl `/connect` aus und wählen Sie GitLab aus. + + ```txt + /connect + ``` + +2. Wählen Sie Ihre Authentifizierungsmethode: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ + ``` + + #### Verwendung von OAuth (empfohlen) + + Wählen Sie **OAuth** und Ihr Browser wird zur Autorisierung geöffnet. + + #### Verwendung eines persönlichen Zugriffstokens + 1. Gehe zu [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens) + 2. Klicken Sie auf **Neues Token hinzufügen** + 3. Name: `OpenCode`, Bereiche: `api` + 4. Kopieren Sie das Token (beginnt mit `glpat-`) + 5. Geben Sie es im Terminal ein + +3. Führen Sie den Befehl `/models` aus, um verfügbare Modelle anzuzeigen. + + ```txt + /models + ``` + + Es stehen drei Claude-basierte Modelle zur Verfügung: + - **duo-chat-haiku-4-5** (Standard) – Schnelle Antworten für schnelle Aufgaben + - **duo-chat-sonnet-4-5** – Ausgewogene Leistung für die meisten Arbeitsabläufe + - **duo-chat-opus-4-5** – Am besten geeignet für komplexe Analysen + +:::note +Sie können auch die Umgebungsvariable „GITLAB_TOKEN“ angeben, wenn Sie dies nicht möchten +um das Token im OpenCode-Authentifizierungsspeicher zu speichern. +::: + +##### Selbstgehostetes GitLab + +:::note[Compliance-Hinweis] +OpenCode verwendet ein kleines Modell für einige AI-Aufgaben wie das Generieren des Sitzungstitels. +Es ist standardmäßig für die Verwendung von gpt-5-nano konfiguriert und wird von Zen gehostet. Zum Sperren von OpenCode +Um nur Ihre eigene von GitLab gehostete Instanz zu verwenden, fügen Sie Folgendes zu Ihrer hinzu +`opencode.json`-Datei. Es wird außerdem empfohlen, die Sitzungsfreigabe zu deaktivieren. + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +Für selbstgehostete GitLab-Instanzen: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +Wenn Ihre Instanz ein benutzerdefiniertes AI-Gateway ausführt: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +Oder fügen Sie zu Ihrem Bash-Profil hinzu: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +Ihr GitLab-Administrator muss Folgendes aktivieren: + +1. [Duo Agent Platform](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) für den Benutzer, die Gruppe oder die Instanz +2. Feature-Flags (über die Rails-Konsole): + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: + +##### OAuth für selbstgehostete Instanzen + +Damit OAuth für Ihre selbst gehostete Instanz funktioniert, müssen Sie eine erstellen +eine neue Anwendung (Einstellungen → Anwendungen) mit dem +Rückruf URL `http://127.0.0.1:8080/callback` und folgende Bereiche: + +- API (Greifen Sie in Ihrem Namen auf API zu) +- read_user (Lesen Sie Ihre persönlichen Daten) +- read_repository (Ermöglicht schreibgeschützten Zugriff auf das Repository) + +Stellen Sie dann die Anwendung ID als Umgebungsvariable bereit: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +Weitere Dokumentation auf der [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth)-Homepage. + +##### Konfiguration + +Anpassen über `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### GitLab API Tools (Optional, aber dringend empfohlen) + +So greifen Sie auf GitLab-Tools zu (Zusammenführungsanfragen, Probleme, Pipelines, CI/CD usw.): + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +Dieses Plugin bietet umfassende GitLab-Repository-Verwaltungsfunktionen, einschließlich MR-Überprüfungen, Problemverfolgung, Pipeline-Überwachung und mehr. + +--- + +### GitHub Copilot + +So verwenden Sie Ihr GitHub Copilot-Abonnement mit OpenCode: + +:::note +Einige Modelle benötigen möglicherweise ein [Pro+ +Abonnement](https://github.com/features/copilot/plans) zur Verwendung. + +Einige Modelle müssen in Ihrem [GitHub Copilot settings](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use) manuell aktiviert werden. +::: + +1. Führen Sie den Befehl `/connect` aus und suchen Sie nach GitHub Copilot. + + ```txt + /connect + ``` + +2. Navigieren Sie zu [github.com/login/device](https://github.com/login/device) und geben Sie den Code ein. + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + └ Waiting for authorization... + ``` + +3. Führen Sie nun den Befehl `/models` aus, um das gewünschte Modell auszuwählen. + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +So verwenden Sie Google Vertex AI mit OpenCode: + +1. Gehen Sie zum **Model Garden** in der Google Cloud Console und überprüfen Sie die + Modelle, die in Ihrer Region verfügbar sind. + + :::note + Sie benötigen ein Google Cloud-Projekt mit aktiviertem Vertex AI API. + ::: + +2. Legen Sie die erforderlichen Umgebungsvariablen fest: + - `GOOGLE_CLOUD_PROJECT`: Ihr Google Cloud-Projekt ID + - `VERTEX_LOCATION` (optional): Die Region für Vertex AI (standardmäßig `global`) + - Authentifizierung (wählen Sie eine aus): + - `GOOGLE_APPLICATION_CREDENTIALS`: Pfad zur Schlüsseldatei Ihres Dienstkontos JSON + - Authentifizieren Sie sich mit gcloud CLI: `gcloud auth application-default login` + + Legen Sie sie fest, während Sie OpenCode ausführen. + + ```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode + ``` + + Oder fügen Sie sie Ihrem Bash-Profil hinzu. + + ```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 +Die Region `global` verbessert die Verfügbarkeit und reduziert Fehler ohne zusätzliche Kosten. Verwenden Sie regionale Endpunkte (e.g., `us-central1`) für Datenresidenzanforderungen. [Learn more](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. Führen Sie den Befehl `/models` aus, um das gewünschte Modell auszuwählen. + + ```txt + /models + ``` + +--- + +### Groq + +1. Gehen Sie zu [Groq console](https://console.groq.com/), klicken Sie auf **Create API Key** und kopieren Sie den Schlüssel. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach Groq. + + ```txt + /connect + ``` + +3. Geben Sie den Schlüssel API für den Anbieter ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um das gewünschte auszuwählen. + + ```txt + /models + ``` + +--- + +### Hugging Face + +[Hugging Face Inference Providers](https://huggingface.co/docs/inference-providers) bietet Zugriff auf offene Modelle, die von 17+-Anbietern unterstützt werden. + +1. Gehen Sie zu [Hugging Face settings](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained), um ein Token mit der Berechtigung zum Aufrufen von Inferenzanbietern zu erstellen. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Hugging Face**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Hugging Face-Token ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell wie _Kimi-K2-Instruct_ oder _GLM-4.6_ auszuwählen. + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) ist eine LLM-Beobachtbarkeitsplattform, die Protokollierung, Überwachung und Analyse für Ihre AI-Anwendungen bietet. Das Helicone AI Gateway leitet Ihre Anfragen basierend auf dem Modell automatisch an den entsprechenden Anbieter weiter. + +1. Gehen Sie zu [Helicone](https://helicone.ai), erstellen Sie ein Konto und generieren Sie einen API-Schlüssel über Ihr Dashboard. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Helicone**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Helicone-API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell auszuwählen. + + ```txt + /models + ``` + +Weitere Anbieter und erweiterte Funktionen wie Caching und Ratenbegrenzung finden Sie unter [Helicone documentation](https://docs.helicone.ai). + +#### Optionale Konfigurationen + +Falls Sie eine Funktion oder ein Modell von Helicone sehen, das nicht automatisch über OpenCode konfiguriert wird, können Sie es jederzeit selbst konfigurieren. + +Hier ist [Helicone's Model Directory](https://helicone.ai/models). Sie benötigen dies, um die IDs der Modelle abzurufen, die Sie hinzufügen möchten. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### Benutzerdefinierte Header + +Helicone unterstützt benutzerdefinierte Header für Funktionen wie Caching, Benutzerverfolgung und Sitzungsverwaltung. Fügen Sie sie mit `options.headers` zu Ihrer Anbieterkonfiguration hinzu: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### Sitzungsverfolgung + +Mit der [Sessions](https://docs.helicone.ai/features/sessions)-Funktion von Helicone können Sie zusammengehörige LLM-Anfragen gruppieren. Verwenden Sie das [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session)-Plugin, um jede OpenCode-Konversation automatisch als Sitzung in Helicone zu protokollieren. + +```bash +npm install -g opencode-helicone-session +``` + +Fügen Sie es Ihrer Konfiguration hinzu. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +Das Plugin fügt `Helicone-Session-Id`- und `Helicone-Session-Name`-Header in Ihre Anfragen ein. Auf der Seite „Sitzungen“ von Helicone wird jede OpenCode-Konversation als separate Sitzung aufgeführt. + +##### Gängige Helicone-Header + +| Kopfzeile | Beschreibung | +| -------------------------- | ----------------------------------------------------------------------------------- | +| `Helicone-Cache-Enabled` | Antwort-Caching aktivieren (`true`/`false`) | +| `Helicone-User-Id` | Verfolgen Sie Metriken nach Benutzer | +| `Helicone-Property-[Name]` | Benutzerdefinierte Eigenschaften hinzufügen (e.g., `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | Anfragen mit Eingabeaufforderungsversionen verknüpfen | + +Alle verfügbaren Header finden Sie unter [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory). + +--- + +### llama.cpp + +Sie können OpenCode für die Verwendung lokaler Modelle über das Dienstprogramm [llama.cpp's](https://github.com/ggml-org/llama.cpp) llama-server konfigurieren + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +In diesem Beispiel: + +- `llama.cpp` ist der benutzerdefinierte Anbieter ID. Dies kann eine beliebige Zeichenfolge sein. +- `npm` gibt das Paket an, das für diesen Anbieter verwendet werden soll. Hier wird `@ai-sdk/openai-compatible` für jeden OpenAI-kompatiblen API verwendet. +- `name` ist der Anzeigename für den Anbieter im UI. +- `options.baseURL` ist der Endpunkt für den lokalen Server. +- `models` ist eine Zuordnung von Modell-IDs zu ihren Konfigurationen. Der Modellname wird in der Modellauswahlliste angezeigt. + +--- + +### IO.NET + +IO.NET bietet 17-Modelle, die für verschiedene Anwendungsfälle optimiert sind: + +1. Gehen Sie zu [IO.NET console](https://ai.io.net/), erstellen Sie ein Konto und generieren Sie einen API-Schlüssel. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **IO.NET**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren IO.NET API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell auszuwählen. + + ```txt + /models + ``` + +--- + +### LM Studio + +Sie können OpenCode über LM Studio für die Verwendung lokaler Modelle konfigurieren. + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +In diesem Beispiel: + +- `lmstudio` ist der benutzerdefinierte Anbieter ID. Dies kann eine beliebige Zeichenfolge sein. +- `npm` gibt das Paket an, das für diesen Anbieter verwendet werden soll. Hier wird `@ai-sdk/openai-compatible` für jeden OpenAI-kompatiblen API verwendet. +- `name` ist der Anzeigename für den Anbieter im UI. +- `options.baseURL` ist der Endpunkt für den lokalen Server. +- `models` ist eine Zuordnung von Modell-IDs zu ihren Konfigurationen. Der Modellname wird in der Modellauswahlliste angezeigt. + +--- + +### Moonshot AI + +So verwenden Sie Kimi K2 von Moonshot AI: + +1. Gehen Sie zu [Moonshot AI console](https://platform.moonshot.ai/console), erstellen Sie ein Konto und klicken Sie auf **Schlüssel API erstellen**. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Moonshot AI**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Moonshot API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um _Kimi K2_ auszuwählen. + + ```txt + /models + ``` + +--- + +### MiniMax + +1. Gehen Sie zu [MiniMax API Console](https://platform.minimax.io/login), erstellen Sie ein Konto und generieren Sie einen API-Schlüssel. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **MiniMax**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren MiniMax API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell wie _M2.1_ auszuwählen. + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. Gehen Sie zu [Nebius Token Factory console](https://tokenfactory.nebius.com/), erstellen Sie ein Konto und klicken Sie auf **Schlüssel hinzufügen**. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Nebius Token Factory**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Nebius Token Factory API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell wie _Kimi K2 Instruct_ auszuwählen. + + ```txt + /models + ``` + +--- + +### Ollama + +Sie können OpenCode über Ollama für die Verwendung lokaler Modelle konfigurieren. + +:::tip +Ollama kann sich automatisch für OpenCode konfigurieren. Weitere Informationen finden Sie unter [Ollama integration docs](https://docs.ollama.com/integrations/opencode). +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +In diesem Beispiel: + +- `ollama` ist der benutzerdefinierte Anbieter ID. Dies kann eine beliebige Zeichenfolge sein. +- `npm` gibt das Paket an, das für diesen Anbieter verwendet werden soll. Hier wird `@ai-sdk/openai-compatible` für jeden OpenAI-kompatiblen API verwendet. +- `name` ist der Anzeigename für den Anbieter im UI. +- `options.baseURL` ist der Endpunkt für den lokalen Server. +- `models` ist eine Zuordnung von Modell-IDs zu ihren Konfigurationen. Der Modellname wird in der Modellauswahlliste angezeigt. + +:::tip +Wenn Toolaufrufe nicht funktionieren, versuchen Sie, `num_ctx` in Ollama zu erhöhen. Beginnen Sie bei ca. 16.000 – 32.000 km. +::: + +--- + +### Ollama Cloud + +So verwenden Sie Ollama Cloud mit OpenCode: + +1. Gehen Sie zu [https://ollama.com/](https://ollama.com/) und melden Sie sich an oder erstellen Sie ein Konto. + +2. Navigieren Sie zu **Einstellungen** > **Schlüssel** und klicken Sie auf **Add API Key**, um einen neuen API-Schlüssel zu generieren. + +3. Kopieren Sie den API-Schlüssel zur Verwendung in OpenCode. + +4. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Ollama Cloud**. + + ```txt + /connect + ``` + +5. Geben Sie Ihren Ollama Cloud API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **Wichtig**: Bevor Sie Cloud-Modelle in OpenCode verwenden, müssen Sie die Modellinformationen lokal abrufen: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. Führen Sie den Befehl `/models` aus, um Ihr Ollama Cloud-Modell auszuwählen. + + ```txt + /models + ``` + +--- + +### OpenAI + +Wir empfehlen, sich für [ChatGPT Plus or Pro](https://chatgpt.com/pricing) anzumelden. + +1. Führen Sie nach der Anmeldung den Befehl `/connect` aus und wählen Sie OpenAI aus. + + ```txt + /connect + ``` + +2. Hier können Sie die Option **ChatGPT Plus/Pro** auswählen und Ihr Browser wird geöffnet + und bitten Sie, sich zu authentifizieren. + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. Jetzt sollten alle OpenAI-Modelle verfügbar sein, wenn Sie den Befehl `/models` verwenden. + + ```txt + /models + ``` + +##### Verwendung von API-Keys + +Wenn Sie bereits über einen API-Schlüssel verfügen, können Sie **API-Schlüssel manuell eingeben** auswählen und ihn in Ihr Terminal einfügen. + +--- + +### OpenCode Zen + +OpenCode Zen ist eine Liste getesteter und verifizierter Modelle, die vom OpenCode-Team bereitgestellt werden. [Learn more](/docs/zen). + +1. Melden Sie sich bei **OpenCode Zen** an und klicken Sie auf **Create API Key**. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **OpenCode Zen**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren OpenCode API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell wie _Qwen 3 Coder 480B_ auszuwählen. + + ```txt + /models + ``` + +--- + +### OpenRouter + +1. Gehen Sie zu [OpenRouter dashboard](https://openrouter.ai/settings/keys), klicken Sie auf **Create API Key** und kopieren Sie den Schlüssel. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach OpenRouter. + + ```txt + /connect + ``` + +3. Geben Sie den Schlüssel API für den Anbieter ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Viele OpenRouter-Modelle sind standardmäßig vorinstalliert. Führen Sie den Befehl `/models` aus, um das gewünschte Modell auszuwählen. + + ```txt + /models + ``` + + Sie können auch zusätzliche Modelle über Ihre OpenCode-Konfiguration hinzufügen. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +5. Sie können sie auch über Ihre OpenCode-Konfiguration anpassen. Hier ist ein Beispiel für die Angabe eines Anbieters + + ```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 bietet Zugriff auf 40+ Modelle von OpenAI, Anthropic, Google, Amazon, Meta, Mistral und AI21 über eine einheitliche Plattform. + +1. Gehen Sie zu Ihrem [SAP BTP Cockpit](https://account.hana.ondemand.com/), navigieren Sie zu Ihrer SAP AI Core-Dienstinstanz und erstellen Sie einen Dienstschlüssel. + + :::tip + Der Dienstschlüssel ist ein JSON-Objekt, das `clientid`, `clientsecret`, `url` und `serviceurls.AI_API_URL` enthält. Sie finden Ihre AI Core-Instanz unter **Dienste** > **Instanzen und Abonnements** im BTP Cockpit. + ::: + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **SAP AI Core**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren JSON-Service-Account-Key ein. + + ```txt + ┌ Service key + │ + │ + └ enter + ``` + + Oder legen Sie die Umgebungsvariable `AICORE_SERVICE_KEY` fest: + + ```bash + AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode + ``` + + Oder fügen Sie es Ihrem Bash-Profil hinzu: + + ```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' + ``` + +4. Legen Sie optional die Bereitstellung ID und die Ressourcengruppe fest: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + Diese Einstellungen sind optional und sollten entsprechend Ihrem SAP AI Core-Setup konfiguriert werden. + ::: + +5. Führen Sie den Befehl `/models` aus, um aus 40+ verfügbaren Modellen 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**. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **OVHcloud AI Endpoints**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren OVHcloud AI Endpoints API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell wie _gpt-oss-120b_ auszuwählen. + + ```txt + /models + ``` + +--- + +### Scaleway + +So verwenden Sie [Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/) mit OpenCode: + +1. Gehen Sie zu [Scaleway Console IAM settings](https://console.scaleway.com/iam/api-keys), um einen neuen API-Schlüssel zu generieren. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Scaleway**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Scaleway-API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell wie _devstral-2-123b-instruct-2512_ oder _gpt-oss-120b_ auszuwählen. + + ```txt + /models + ``` + +--- + +### Together AI + +1. Gehen Sie zu [Together AI console](https://api.together.ai), erstellen Sie ein Konto und klicken Sie auf **Schlüssel hinzufügen**. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Together AI**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Together AI API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell wie _Kimi K2 Instruct_ auszuwählen. + + ```txt + /models + ``` + +--- + +### Venice AI + +1. Gehen Sie zu [Venice AI console](https://venice.ai), erstellen Sie ein Konto und generieren Sie einen API-Schlüssel. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Venice AI**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Venice AI API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell wie _Llama 3.3 70B_ auszuwählen. + + ```txt + /models + ``` + +--- + +### Vercel AI Gateway + +Mit dem Vercel AI Gateway können Sie über einen einheitlichen Endpunkt auf Modelle von OpenAI, Anthropic, Google, xAI und mehr zugreifen. Die Modelle werden zum Listenpreis ohne Aufschlag angeboten. + +1. Gehen Sie zum [Vercel dashboard](https://vercel.com/), navigieren Sie zur Registerkarte **AI Gateway** und klicken Sie auf **API-Schlüssel**, um einen neuen API-Schlüssel zu erstellen. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Vercel AI Gateway**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren Vercel AI Gateway API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell auszuwählen. + + ```txt + /models + ``` + +Sie können Modelle auch über Ihre OpenCode-Konfiguration anpassen. Hier ist ein Beispiel für die Angabe der Provider-Routing-Reihenfolge. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "vercel": { + "models": { + "anthropic/claude-sonnet-4": { + "options": { + "order": ["anthropic", "vertex"] + } + } + } + } + } +} +``` + +Einige nützliche Routing-Optionen: + +| Option | Beschreibung | +| ------------------- | ----------------------------------------------------------------- | +| `order` | Anbietersequenz zum Ausprobieren | +| `only` | Auf bestimmte Anbieter beschränken | +| `zeroDataRetention` | Verwenden Sie nur Anbieter mit Null-Datenaufbewahrungsrichtlinien | + +--- + +### xAI + +1. Gehen Sie zu [xAI console](https://console.x.ai/), erstellen Sie ein Konto und generieren Sie einen API-Schlüssel. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **xAI**. + + ```txt + /connect + ``` + +3. Geben Sie Ihren xAI API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell wie _Grok Beta_ auszuwählen. + + ```txt + /models + ``` + +--- + +### Z.AI + +1. Gehen Sie zu [Z.AI API console](https://z.ai/manage-apikey/apikey-list), erstellen Sie ein Konto und klicken Sie auf **Neuen API-Schlüssel erstellen**. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **Z.AI**. + + ```txt + /connect + ``` + + Wenn Sie den **GLM Coding Plan** abonniert haben, wählen Sie **Z.AI Coding Plan**. + +3. Geben Sie Ihren Z.AI API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um ein Modell wie _GLM-4.7_ auszuwählen. + + ```txt + /models + ``` + +--- + +### ZenMux + +1. Gehen Sie zu [ZenMux dashboard](https://zenmux.ai/settings/keys), klicken Sie auf **Create API Key** und kopieren Sie den Schlüssel. + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach ZenMux. + + ```txt + /connect + ``` + +3. Geben Sie den Schlüssel API für den Anbieter ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Viele ZenMux-Modelle sind standardmäßig vorinstalliert. Führen Sie den Befehl `/models` aus, um das gewünschte Modell auszuwählen. + + ```txt + /models + ``` + + Sie können auch zusätzliche Modelle über Ihre OpenCode-Konfiguration hinzufügen. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "zenmux": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +--- + +## Benutzerdefinierter Anbieter + +So fügen Sie einen **OpenAI-kompatiblen** Anbieter hinzu, der nicht im Befehl `/connect` aufgeführt ist: + +:::tip +Sie können jeden OpenAI-kompatiblen Anbieter mit OpenCode verwenden. Die meisten modernen AI-Anbieter bieten OpenAI-kompatible APIs an. +::: + +1. Führen Sie den Befehl `/connect` aus und scrollen Sie nach unten zu **Andere**. + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. Geben Sie einen eindeutigen ID für den Anbieter ein. + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::note + Wählen Sie einen einprägsamen ID, den Sie in Ihrer Konfigurationsdatei verwenden. + ::: + +3. Geben Sie Ihren API-Schlüssel für den Anbieter ein. + + ```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. Erstellen oder aktualisieren Sie Ihre `opencode.json`-Datei in Ihrem Projektverzeichnis: + + ```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" + } + } + } + } + } + ``` + + Hier sind die Konfigurationsmöglichkeiten: + - **npm**: AI SDK zu verwendendes Paket, `@ai-sdk/openai-compatible` für OpenAI-kompatible Anbieter + - **Name**: Anzeigename in UI. + - **Modelle**: Verfügbare Modelle. + - **options.baseURL**: API endpoint URL. + - **Optionen.apiKey**: Legen Sie optional den Schlüssel API fest, wenn Sie keine Authentifizierung verwenden. + - **options.headers**: Optional benutzerdefinierte Header festlegen. + + Mehr zu den erweiterten Optionen im Beispiel unten. + +5. Führen Sie den Befehl `/models` aus und Ihr benutzerdefinierter Anbieter und Ihre Modelle werden in der Auswahlliste angezeigt. + +--- + +##### Beispiel + +Hier ist ein Beispiel für die Einstellung der Optionen `apiKey`, `headers` und Modell `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 + } + } + } + } + } +} +``` + +Konfigurationsdetails: + +- **apiKey**: Wird mit der Variablensyntax `env`, [learn more](/docs/config#env-vars), festgelegt. +- **Header**: Benutzerdefinierte Header, die mit jeder Anfrage gesendet werden. +- **limit.context**: Maximale Eingabetokens, die das Modell akzeptiert. +- **limit.output**: Maximale Token, die das Modell generieren kann. + +Mithilfe der `limit`-Felder kann OpenCode erkennen, wie viel Kontext Sie noch haben. Standardanbieter beziehen diese automatisch von models.dev. + +--- + +## Fehlerbehebung + +Wenn Sie Probleme beim Konfigurieren eines Anbieters haben, überprüfen Sie Folgendes: + +1. **Überprüfen Sie die Authentifizierungseinrichtung**: Führen Sie `opencode auth list` aus, um zu sehen, ob die Anmeldeinformationen vorhanden sind + für den Anbieter werden Ihrer Konfiguration hinzugefügt. + + Dies gilt nicht für Anbieter wie Amazon Bedrock, die für ihre Authentifizierung auf Umgebungsvariablen angewiesen sind. + +2. Überprüfen Sie bei benutzerdefinierten Anbietern die OpenCode-Konfiguration und: + - Stellen Sie sicher, dass der im Befehl `/connect` verwendete Anbieter ID mit dem ID in Ihrer OpenCode-Konfiguration übereinstimmt. + - Für den Anbieter wird das richtige npm-Paket verwendet. Verwenden Sie beispielsweise `@ai-sdk/cerebras` für Cerebras. Und für alle anderen OpenAI-kompatiblen Anbieter verwenden Sie `@ai-sdk/openai-compatible`. + - Überprüfen Sie, ob im Feld `options.baseURL` der richtige Endpunkt API verwendet wird. diff --git a/packages/web/src/content/docs/de/rules.mdx b/packages/web/src/content/docs/de/rules.mdx new file mode 100644 index 00000000000..ef446d09bd7 --- /dev/null +++ b/packages/web/src/content/docs/de/rules.mdx @@ -0,0 +1,190 @@ +--- +title: Regeln +description: Lege eigene Anweisungen fuer opencode fest. +--- + +Du kannst opencode ueber eine `AGENTS.md`-Datei mit eigenen Anweisungen steuern. +Das ist aehnlich zu den Regeln in Cursor und wird direkt in den LLM-Kontext geladen. + +--- + +## Initialisierung + +Um eine neue `AGENTS.md` zu erstellen, fuehre in opencode den Befehl `/init` aus. + +:::tip +Du solltest die `AGENTS.md` deines Projekts in Git committen. +::: + +Der Befehl scannt dein Projekt und erzeugt daraus eine passende `AGENTS.md`. +So kann opencode sich in deinem Code besser orientieren. + +Wenn bereits eine `AGENTS.md` existiert, versucht opencode sie zu erweitern. + +--- + +## Beispiel + +Du kannst die Datei auch manuell anlegen. +Hier ist ein Beispiel, was in einer `AGENTS.md` stehen kann. + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +Hier hinterlegst du projektspezifische Regeln, die dein Team gemeinsam nutzt. + +--- + +## Typen + +opencode kann `AGENTS.md` aus mehreren Orten lesen. +Die Orte haben unterschiedliche Zwecke. + +### Projekt + +Lege eine `AGENTS.md` im Projekt-Root ab, um projektspezifische Regeln zu definieren. +Diese gelten nur in diesem Verzeichnis und seinen Unterordnern. + +### Global + +Du kannst auch globale Regeln in `~/.config/opencode/AGENTS.md` speichern. +Diese gelten in allen opencode-Sitzungen. + +Da diese Datei nicht in Git landet und nicht mit dem Team geteilt wird, eignet sie sich fuer persoenliche Regeln. + +### Claude Code-Kompatibilität + +Wenn du von Claude Code kommst, unterstuetzt OpenCode dessen Dateikonventionen als Fallback: + +- **Projektregeln**: `CLAUDE.md` im Projekt (wenn keine `AGENTS.md` existiert) +- **Globale Regeln**: `~/.claude/CLAUDE.md` (wenn keine `~/.config/opencode/AGENTS.md` existiert) +- **Skills**: `~/.claude/skills/` - siehe [Agent Skills](/docs/skills/) fuer Details + +Um die Claude-Code-Kompatibilitaet zu deaktivieren, setze eine dieser Umgebungsvariablen: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## Rangfolge + +Beim Start sucht opencode in dieser Reihenfolge nach Regeldateien: + +1. **Lokale Dateien** beim Hochlaufen ab dem aktuellen Verzeichnis (`AGENTS.md`, `CLAUDE.md`) +2. **Globale Datei** unter `~/.config/opencode/AGENTS.md` +3. **Claude-Code-Datei** unter `~/.claude/CLAUDE.md` (falls nicht deaktiviert) + +Pro Kategorie gewinnt die zuerst passende Datei. +Wenn sowohl `AGENTS.md` als auch `CLAUDE.md` existieren, wird nur `AGENTS.md` verwendet. + +--- + +## Eigene Anweisungen + +Du kannst zusaetzliche Anweisungsdateien in deiner `opencode.json` oder in `~/.config/opencode/opencode.json` angeben. +So kann dein Team bestehende Regeln wiederverwenden, statt Inhalte in `AGENTS.md` zu duplizieren. + +Beispiel: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Du kannst auch Remote-URLs nutzen, um Regeln aus dem Web zu laden. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +Remote-Anweisungen werden mit 5 Sekunden Timeout geladen. + +Alle Anweisungsdateien werden mit deinen `AGENTS.md`-Dateien kombiniert. + +--- + +## Externe Dateien referenzieren + +opencode parst Datei-Referenzen in `AGENTS.md` nicht automatisch. +Du erreichst aehnliches Verhalten auf zwei Wegen. + +### Mit opencode.json + +Empfohlen ist das `instructions`-Feld in der `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### Manuelle Anweisungen in AGENTS.md + +Du kannst opencode explizit anweisen, externe Dateien zu lesen. +Hier ein praxisnahes Beispiel: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +Damit kannst du: + +- Modulare, wiederverwendbare Regeldateien erstellen +- Regeln projektuebergreifend per Symlink oder Git-Submodule teilen +- `AGENTS.md` kurz halten und auf Detailregeln verweisen +- Sicherstellen, dass Dateien nur bei Bedarf geladen werden + +:::tip +Fuer Monorepos oder gemeinsame Standards ist `opencode.json` mit Glob-Mustern (z. B. `packages/*/AGENTS.md`) oft wartbarer als manuelle Anweisungen. +::: diff --git a/packages/web/src/content/docs/de/sdk.mdx b/packages/web/src/content/docs/de/sdk.mdx new file mode 100644 index 00000000000..21791db05de --- /dev/null +++ b/packages/web/src/content/docs/de/sdk.mdx @@ -0,0 +1,393 @@ +--- +title: SDK +description: Typsicherer JS-Client fuer den opencode-Server. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +Das opencode JS/TS SDK bietet einen typsicheren Client fuer die Server-API. +Damit kannst du Integrationen bauen und opencode programmatisch steuern. + +[Mehr zum Server](/docs/server). Beispiele findest du in den [Community-Projekten](/docs/ecosystem#projects). + +--- + +## Installation + +Installiere das SDK ueber npm: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## Client erstellen + +Erstelle eine opencode-Instanz: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +Das startet Server und Client. + +#### Optionen + +| Option | Type | Description | Default | +| ---------- | ------------- | ------------------------------ | ----------- | +| `hostname` | `string` | Server hostname | `127.0.0.1` | +| `port` | `number` | Server port | `4096` | +| `signal` | `AbortSignal` | Abort signal for cancellation | `undefined` | +| `timeout` | `number` | Timeout in ms for server start | `5000` | +| `config` | `Config` | Configuration object | `{}` | + +--- + +## Config + +Du kannst ein Konfigurationsobjekt uebergeben, um das Verhalten anzupassen. +`opencode.json` wird weiterhin geladen, kann aber inline ueberschrieben oder erweitert werden: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## Nur Client + +Wenn opencode bereits laeuft, kannst du nur einen Client erstellen und verbinden: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### Optionen + +| Option | Type | Description | Default | +| --------------- | ---------- | -------------------------------- | ----------------------- | +| `baseUrl` | `string` | URL of the server | `http://localhost:4096` | +| `fetch` | `function` | Custom fetch implementation | `globalThis.fetch` | +| `parseAs` | `string` | Response parsing method | `auto` | +| `responseStyle` | `string` | Return style: `data` or `fields` | `fields` | +| `throwOnError` | `boolean` | Throw errors instead of return | `false` | + +--- + +## Typen + +Das SDK bringt TypeScript-Definitionen fuer alle API-Typen mit. +Du kannst sie direkt importieren: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +Alle Typen werden aus der OpenAPI-Spezifikation des Servers generiert und sind in der Typdatei verfuegbar. + +--- + +## Fehler + +Das SDK kann Fehler werfen, die du abfangen und behandeln kannst: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## APIs + +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 }` | + +--- + +#### Beispiele + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### App + +| Method | Description | Response | +| -------------- | ------------------------- | ------------------------------------------- | +| `app.log()` | Write a log entry | `boolean` | +| `app.agents()` | List all available agents | Agent[] | + +--- + +#### Beispiele + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### Project + +| Method | Description | Response | +| ------------------- | ------------------- | --------------------------------------------- | +| `project.list()` | List all projects | Project[] | +| `project.current()` | Get current project | Project | + +--- + +#### Beispiele + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### Path + +| Method | Description | Response | +| ------------ | ---------------- | ---------------------------------------- | +| `path.get()` | Get current path | Path | + +--- + +#### Beispiele + +```javascript +// Get current path information +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 } }` | + +--- + +#### Beispiele + +```javascript +const config = await client.config.get() + +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` | + +--- + +#### Beispiele + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### 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[] | + +`find.files` supports a few optional query fields: + +- `type`: `"file"` or `"directory"` +- `directory`: override the project root for the search +- `limit`: max results (1–200) + +--- + +#### Beispiele + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### 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` | + +--- + +#### Beispiele + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### Auth + +| Method | Description | Response | +| ------------------- | ------------------------------ | --------- | +| `auth.set({ ... })` | Set authentication credentials | `boolean` | + +--- + +#### Beispiele + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### Events + +| Method | Description | Response | +| ------------------- | ------------------------- | ------------------------- | +| `event.subscribe()` | Server-sent events stream | Server-sent events stream | + +--- + +#### Beispiele + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/de/server.mdx b/packages/web/src/content/docs/de/server.mdx new file mode 100644 index 00000000000..dd4a565faff --- /dev/null +++ b/packages/web/src/content/docs/de/server.mdx @@ -0,0 +1,291 @@ +--- +title: Server +description: Nutze den opencode-Server ueber HTTP. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +Der Befehl `opencode serve` startet einen headless HTTP-Server. +Er stellt einen OpenAPI-Endpunkt bereit, den ein opencode-Client nutzen kann. + +--- + +### Nutzung + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### Optionen + +| Flag | Description | Default | +| --------------- | ----------------------------------- | ---------------- | +| `--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 | `[]` | + +`--cors` kann mehrfach angegeben werden: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### Authentifizierung + +Setze `OPENCODE_SERVER_PASSWORD`, um den Server mit HTTP Basic Auth zu schuetzen. +Der Benutzername ist standardmaessig `opencode`, kann aber mit `OPENCODE_SERVER_USERNAME` ueberschrieben werden. Das gilt fuer `opencode serve` und `opencode web`. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### Funktionsweise + +Wenn du `opencode` startest, werden TUI und Server gestartet. +Die TUI ist dabei der Client, der mit dem Server spricht; dessen OpenAPI-3.1-Endpunkt dient auch zur Generierung des [SDK](/docs/sdk). + +:::tip +Nutze den opencode-Server, um opencode programmatisch anzusteuern. +::: + +Diese Architektur erlaubt mehrere Clients und programmatische Nutzung. + +Mit `opencode serve` startest du einen eigenstaendigen Server. +Laeuft bereits eine TUI, startet `opencode serve` trotzdem eine neue Serverinstanz. + +--- + +#### Mit bestehendem Server verbinden + +Beim TUI-Start werden Port und Hostname zufaellig gewaehlt. +Alternativ gibst du `--hostname` und `--port` als [Flags](/docs/cli) vor und verbindest dich dann gezielt damit. + +Der Endpunkt [`/tui`](#tui) kann die TUI ueber den Server steuern, etwa zum Vorbelegen oder Abschicken von Prompts. +Dieses Muster nutzen auch die OpenCode-[IDE](/docs/ide)-Plugins. + +--- + +## Spec + +Der Server veroeffentlicht eine OpenAPI-3.1-Spezifikation unter: + +``` +http://:/doc +``` + +Zum Beispiel `http://localhost:4096/doc`. +Nutze die Spec zum Generieren von Clients, zum Pruefen von Request/Response-Typen oder in einem Swagger-Explorer. + +--- + +## APIs + +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 | + +--- + +### Project + +| Method | Path | Description | Response | +| ------ | ------------------ | ----------------------- | --------------------------------------------- | +| `GET` | `/project` | List all projects | Project[] | +| `GET` | `/project/current` | Get the current project | Project | + +--- + +### Path & VCS + +| Method | Path | Description | Response | +| ------ | ------- | ------------------------------------ | ------------------------------------------- | +| `GET` | `/path` | Get the current path | Path | +| `GET` | `/vcs` | Get VCS info for the current project | VcsInfo | + +--- + +### Instanz + +| Method | Path | Description | Response | +| ------ | ------------------- | ---------------------------- | --------- | +| `POST` | `/instance/dispose` | Dispose the current instance | `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 } }` | + +--- + +### 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` | + +--- + +### 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` | + +--- + +### 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[]`}` | + +--- + +### Befehle + +| Method | Path | Description | Response | +| ------ | ---------- | ----------------- | --------------------------------------------- | +| `GET` | `/command` | List all commands | 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[] | + +#### `/find/file` Abfrageparameter + +- `query` (erforderlich) — Suchbegriff (Fuzzy-Suche) +- `type` (optional) — Ergebnisse auf `"file"` oder `"directory"` beschränken +- `directory` (optional) — Projektstammverzeichnis für die Suche überschreiben +- `limit` (optional) — Maximale Ergebnisse (1–200) +- `dirs` (optional) — Legacy-Flag (`"false"` gibt nur Dateien zurück) + +--- + +### 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 | + +--- + +### 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 | + +--- + +### Agenten + +| Method | Path | Description | Response | +| ------ | -------- | ------------------------- | ------------------------------------------- | +| `GET` | `/agent` | List all available agents | Agent[] | + +--- + +### Logging + +| Method | Path | Description | Response | +| ------ | ------ | ------------------------------------------------------------ | --------- | +| `POST` | `/log` | Write log entry. 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` | + +--- + +### Authentifizierung + +| Method | Path | Description | Response | +| ------ | ----------- | --------------------------------------------------------------- | --------- | +| `PUT` | `/auth/:id` | Set authentication credentials. Body must match provider schema | `boolean` | + +--- + +### Events + +| Method | Path | Description | Response | +| ------ | -------- | ----------------------------------------------------------------------------- | ------------------------- | +| `GET` | `/event` | Server-sent events stream. First event is `server.connected`, then bus events | Server-sent events stream | + +--- + +### Dokumentation + +| Method | Path | Description | Response | +| ------ | ------ | ------------------------- | --------------------------- | +| `GET` | `/doc` | OpenAPI 3.1 specification | HTML page with OpenAPI spec | diff --git a/packages/web/src/content/docs/de/share.mdx b/packages/web/src/content/docs/de/share.mdx new file mode 100644 index 00000000000..99fad21099b --- /dev/null +++ b/packages/web/src/content/docs/de/share.mdx @@ -0,0 +1,130 @@ +--- +title: Teilen +description: Teile OpenCode-Unterhaltungen per oeffentlichem Link. +--- + +Mit der Share-Funktion erstellst du oeffentliche Links zu OpenCode-Unterhaltungen. +So kannst du einfacher mit dem Team zusammenarbeiten oder Hilfe einholen. + +:::note +Geteilte Unterhaltungen sind fuer alle mit dem Link oeffentlich zugaenglich. +::: + +--- + +## Funktionsweise + +Wenn du eine Unterhaltung teilst, macht OpenCode Folgendes: + +1. Erstellt eine eindeutige oeffentliche URL fuer deine Sitzung +2. Synchronisiert den Verlauf auf unsere Server +3. Stellt die Unterhaltung unter `opncd.ai/s/` bereit + +--- + +## Teilen + +OpenCode hat drei Modi, die das Teilen steuern: + +--- + +### Manuell (Standard) + +Standardmaessig nutzt OpenCode den manuellen Modus. +Sitzungen werden nicht automatisch geteilt, du kannst sie aber mit `/share` veroeffentlichen: + +``` +/share +``` + +Dabei wird eine eindeutige URL erzeugt und in die Zwischenablage kopiert. + +Um den manuellen Modus explizit in der [Konfiguration](/docs/config) zu setzen: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### Auto-Share + +Du kannst automatisches Teilen fuer neue Unterhaltungen aktivieren, indem du in der [Konfiguration](/docs/config) `share` auf `"auto"` setzt: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +Mit aktiviertem Auto-Share wird jede neue Unterhaltung automatisch geteilt und ein Link erstellt. + +--- + +### Deaktiviert + +Du kannst Teilen komplett deaktivieren, indem du in der [Konfiguration](/docs/config) `share` auf `"disabled"` setzt: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +Wenn das fuer ein Projekt teamweit gelten soll, lege es in der Projekt-`opencode.json` fest und committe die Datei. + +--- + +## Teilen aufheben + +Um das Teilen zu beenden und den oeffentlichen Zugriff zu entfernen: + +``` +/unshare +``` + +Dadurch wird der Share-Link entfernt und die zugehoerigen Daten werden geloescht. + +--- + +## Datenschutz + +Beim Teilen solltest du ein paar Punkte beachten. + +--- + +### Datenaufbewahrung + +Geteilte Unterhaltungen bleiben veroeffentlicht, bis du sie explizit aufhebst. +Das umfasst: + +- Vollstaendigen Unterhaltungsverlauf +- Alle Nachrichten und Antworten +- Sitzungsmetadaten + +--- + +### Empfehlungen + +- Teile nur Unterhaltungen ohne sensible Informationen. +- Pruefe Inhalte vor dem Teilen. +- Hebe das Teilen wieder auf, wenn die Zusammenarbeit beendet ist. +- Teile keine proprietaeren Codes oder vertraulichen Daten. +- Deaktiviere Teilen komplett bei sensiblen Projekten. + +--- + +## Für Unternehmen + +In Enterprise-Umgebungen kann die Share-Funktion: + +- **Deaktiviert** werden, um Compliance-Vorgaben einzuhalten +- Auf **SSO-authentifizierte** Nutzer eingeschraenkt werden +- **Self-hosted** auf eigener Infrastruktur betrieben werden + +[Mehr dazu](/docs/enterprise), wie du opencode in deiner Organisation einsetzt. diff --git a/packages/web/src/content/docs/de/skills.mdx b/packages/web/src/content/docs/de/skills.mdx new file mode 100644 index 00000000000..63dbb126bbe --- /dev/null +++ b/packages/web/src/content/docs/de/skills.mdx @@ -0,0 +1,222 @@ +--- +title: Agenten-Skills +description: "Definiere wiederverwendbares Verhalten ueber SKILL.md" +--- + +Agent Skills erlauben OpenCode, wiederverwendbare Anweisungen aus deinem Repo oder Home-Verzeichnis zu finden. +Sie werden bei Bedarf ueber das native `skill`-Tool geladen, wenn ein Agent sie wirklich braucht. + +--- + +## Dateien platzieren + +Erstelle pro Skill-Namen einen Ordner und lege dort eine `SKILL.md` ab. +OpenCode sucht in folgenden Pfaden: + +- Project config: `.opencode/skills//SKILL.md` +- Global config: `~/.config/opencode/skills//SKILL.md` +- Project Claude-compatible: `.claude/skills//SKILL.md` +- Global Claude-compatible: `~/.claude/skills//SKILL.md` +- Project agent-compatible: `.agents/skills//SKILL.md` +- Global agent-compatible: `~/.agents/skills//SKILL.md` + +--- + +## Discovery verstehen + +Bei projektlokalen Pfaden laeuft OpenCode vom aktuellen Verzeichnis nach oben bis zum Git-Worktree. +Dabei werden passende `skills/*/SKILL.md` in `.opencode/` sowie passende Dateien unter `.claude/skills/*/SKILL.md` und `.agents/skills/*/SKILL.md` geladen. + +Globale Definitionen kommen zusaetzlich aus `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md` und `~/.agents/skills/*/SKILL.md`. + +--- + +## Frontmatter schreiben + +Jede `SKILL.md` muss mit YAML-Frontmatter beginnen. +Nur diese Felder werden ausgewertet: + +- `name` (required) +- `description` (required) +- `license` (optional) +- `compatibility` (optional) +- `metadata` (optional, string-to-string map) + +Unbekannte Frontmatter-Felder werden ignoriert. + +--- + +## Namen validieren + +`name` muss: + +- 1-64 Zeichen lang sein +- nur Kleinbuchstaben und Ziffern mit einzelnen Bindestrichen enthalten +- nicht mit `-` beginnen oder enden +- kein `--` enthalten +- zum Verzeichnisnamen passen, in dem `SKILL.md` liegt + +Entsprechender Regex: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## Längenregeln beachten + +`description` muss 1-1024 Zeichen lang sein. +Formuliere sie so konkret, dass Agenten den Skill eindeutig auswaehlen koennen. + +--- + +## Beispiel verwenden + +Erstelle `.opencode/skills/git-release/SKILL.md` zum Beispiel so: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## Tool-Beschreibung erkennen + +OpenCode listet verfuegbare Skills in der Beschreibung des `skill`-Tools. +Jeder Eintrag enthaelt Namen und Beschreibung: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +Der Agent laedt einen Skill per Tool-Aufruf: + +``` +skill({ name: "git-release" }) +``` + +--- + +## Berechtigungen konfigurieren + +Steuere in `opencode.json` per Muster, auf welche Skills Agenten zugreifen duerfen: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| Berechtigung | Verhalten | +| ------------ | ---------------------------------------- | +| `allow` | Skill wird sofort geladen | +| `deny` | Skill ist fuer Agenten versteckt | +| `ask` | Vor dem Laden wird nach Freigabe gefragt | + +Muster unterstuetzen Wildcards: `internal-*` passt z. B. auf `internal-docs` oder `internal-tools`. + +--- + +## Pro Agent überschreiben + +Du kannst einzelnen Agenten andere Berechtigungen als die globalen Defaults geben. + +**Fuer benutzerdefinierte Agenten** (im Frontmatter): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**Fuer eingebaute Agenten** (in `opencode.json`): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## Skill-Tool deaktivieren + +Deaktiviere Skills komplett fuer Agenten, die sie nicht nutzen sollen: + +**Fuer benutzerdefinierte Agenten**: + +```yaml +--- +tools: + skill: false +--- +``` + +**Fuer eingebaute Agenten**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +Wenn deaktiviert, wird der Abschnitt `` komplett weggelassen. + +--- + +## Fehlerbehebung beim Laden + +Wenn ein Skill nicht auftaucht: + +1. Pruefe, ob `SKILL.md` exakt in Grossbuchstaben geschrieben ist +2. Pruefe, ob Frontmatter `name` und `description` enthaelt +3. Stelle sicher, dass Skill-Namen ueber alle Orte hinweg eindeutig sind +4. Pruefe Berechtigungen - Skills mit `deny` sind fuer Agenten unsichtbar diff --git a/packages/web/src/content/docs/de/themes.mdx b/packages/web/src/content/docs/de/themes.mdx new file mode 100644 index 00000000000..b97816801d6 --- /dev/null +++ b/packages/web/src/content/docs/de/themes.mdx @@ -0,0 +1,372 @@ +--- +title: Themes +description: Waehle ein eingebautes Theme oder erstelle eins. +--- + +Mit OpenCode kannst du ein eingebautes Theme waehlen, ein an dein Terminal angepasstes Theme nutzen oder ein eigenes Theme definieren. + +Standardmaessig verwendet OpenCode das `opencode`-Theme. + +--- + +## Terminal-Anforderungen + +Damit Themes mit voller Farbpalette korrekt angezeigt werden, muss dein Terminal **truecolor** (24-Bit-Farben) unterstuetzen. +Die meisten modernen Terminals koennen das bereits, eventuell musst du es aber aktivieren: + +- **Support pruefen**: Fuehre `echo $COLORTERM` aus - erwartet ist `truecolor` oder `24bit` +- **Truecolor aktivieren**: Setze in deinem Shell-Profil `COLORTERM=truecolor` +- **Terminal-Kompatibilitaet**: Stelle sicher, dass dein Terminal-Emulator 24-Bit-Farben unterstuetzt + +Ohne truecolor werden Farben weniger exakt dargestellt oder auf eine 256-Farben-Naeherung reduziert. + +--- + +## Eingebaute Themes + +OpenCode liefert mehrere eingebaute Themes mit. + +| Name | Description | +| ---------------------- | ---------------------------------------------------------------------------- | +| `system` | Adapts to your terminal’s background color | +| `tokyonight` | Based on the [Tokyonight](https://github.com/folke/tokyonight.nvim) theme | +| `everforest` | Based on the [Everforest](https://github.com/sainnhe/everforest) theme | +| `ayu` | Based on the [Ayu](https://github.com/ayu-theme) dark theme | +| `catppuccin` | Based on the [Catppuccin](https://github.com/catppuccin) theme | +| `catppuccin-macchiato` | Based on the [Catppuccin](https://github.com/catppuccin) theme | +| `gruvbox` | Based on the [Gruvbox](https://github.com/morhetz/gruvbox) theme | +| `kanagawa` | Based on the [Kanagawa](https://github.com/rebelot/kanagawa.nvim) theme | +| `nord` | Based on the [Nord](https://github.com/nordtheme/nord) theme | +| `matrix` | Hacker-style green on black theme | +| `one-dark` | Based on the [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark theme | + +Und es kommen laufend weitere dazu. + +--- + +## System-Theme + +Das `system`-Theme passt sich automatisch an das Farbschema deines Terminals an. +Im Gegensatz zu Themes mit festen Farben gilt beim _system_-Theme: + +- **Generiert Graustufen**: Basierend auf deiner Terminal-Hintergrundfarbe fuer guten Kontrast +- **Nutzt ANSI-Farben**: Verwendet Standardfarben (0-15), die dein Terminalschema respektieren +- **Behaelt Terminal-Defaults**: Verwendet `none` fuer Text und Hintergruende + +Das System-Theme ist ideal fuer Nutzer, die: + +- OpenCode optisch ans Terminal anpassen wollen +- eigene Terminal-Farbschemata nutzen +- ein konsistentes Erscheinungsbild in Terminal-Apps bevorzugen + +--- + +## Theme verwenden + +Du kannst ein Theme ueber `/theme` auswaehlen oder direkt in der [Konfiguration](/docs/config) setzen. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## Eigene Themes + +OpenCode unterstuetzt ein flexibles JSON-basiertes Theme-System. +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: + +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` + +If multiple directories contain a theme with the same name, the theme from the directory with higher priority will be used. + +--- + +### Theme erstellen + +To create a custom theme, create a JSON file in one of the theme directories. + +For user-wide themes: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +And for project-specific themes. + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### JSON-Format + +Themes use a flexible JSON format with support for: + +- **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 + +--- + +### Farbdefinitionen + +The `defs` section is optional and it allows you to define reusable colors that can be referenced in the theme. + +--- + +### 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: + +- `"text": "none"` - Uses terminal's default foreground color +- `"background": "none"` - Uses terminal's default background color + +--- + +### Beispiel + +Here's an example of a custom theme: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/de/tools.mdx b/packages/web/src/content/docs/de/tools.mdx new file mode 100644 index 00000000000..b7a41d87bb7 --- /dev/null +++ b/packages/web/src/content/docs/de/tools.mdx @@ -0,0 +1,390 @@ +--- +title: Tools +description: Verwalte, welche Tools ein LLM nutzen darf. +--- + +Tools erlauben dem LLM Aktionen in deiner Codebasis. +OpenCode bringt eingebaute Tools mit und laesst sich ueber [Custom Tools](/docs/custom-tools) oder [MCP-Server](/docs/mcp-servers) erweitern. + +Standardmaessig sind alle Tools **aktiviert** und brauchen keine Freigabe. +Das Verhalten steuerst du ueber [Berechtigungen](/docs/permissions). + +--- + +## Konfiguration + +Nutze das Feld `permission`, um Tool-Verhalten zu steuern. +Pro Tool kannst du erlauben, verbieten oder eine Rueckfrage verlangen. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +Mit Wildcards kannst du mehrere Tools auf einmal steuern. +Zum Beispiel, um fuer alle Tools eines MCP-Servers eine Freigabe zu verlangen: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[Mehr dazu](/docs/permissions), wie du Berechtigungen konfigurierst. + +--- + +## Eingebaut + +Hier sind alle in OpenCode verfuegbaren eingebauten Tools. + +--- + +### bash + +Fuehrt Shell-Befehle in deiner Projektumgebung aus. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +Damit kann das LLM Terminal-Befehle wie `npm install`, `git status` oder andere Shell-Kommandos ausfuehren. + +--- + +### edit + +Bearbeitet bestehende Dateien ueber exakte String-Ersetzungen. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Dieses Tool fuehrt praezise Aenderungen per exakter Textsuche aus. +Es ist der zentrale Weg, wie das LLM Code aendert. + +--- + +### write + +Erstellt neue Dateien oder ueberschreibt bestehende Dateien. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Damit erlaubst du dem LLM, neue Dateien anzulegen. +Bestehende Dateien werden dabei ueberschrieben. + +:::note +Das Tool `write` wird ueber die Berechtigung `edit` gesteuert. +`edit` gilt fuer alle Datei-Aenderungen (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### read + +Read file contents from your codebase. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +This tool reads files and returns their contents. It supports reading specific line ranges for large files. + +--- + +### grep + +Search file contents using regular expressions. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +Fast content search across your codebase. Supports full regex syntax and file pattern filtering. + +--- + +### glob + +Find files by pattern matching. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +Search for files using glob patterns like `**/*.js` or `src/**/*.ts`. Returns matching file paths sorted by modification time. + +--- + +### list + +List files and directories in a given path. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +This tool lists directory contents. It accepts glob patterns to filter results. + +--- + +### lsp (experimental) + +Interact with your configured LSP servers to get code intelligence features like definitions, references, hover info, and call hierarchy. + +:::note +This tool is only available when `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (or `OPENCODE_EXPERIMENTAL=true`). +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +Supported operations include `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls`, and `outgoingCalls`. + +To configure which LSP servers are available for your project, see [LSP Servers](/docs/lsp). + +--- + +### patch + +Apply patches to files. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +This tool applies patch files to your codebase. Useful for applying diffs and patches from various sources. + +:::note +The `patch` tool is controlled by the `edit` permission, which covers all file modifications (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### skill + +Load a [skill](/docs/skills) (a `SKILL.md` file) and return its content in the conversation. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +Manage todo lists during coding sessions. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +Creates and updates task lists to track progress during complex operations. The LLM uses this to organize multi-step tasks. + +:::note +This tool is disabled for subagents by default, but you can enable it manually. [Learn more](/docs/agents/#permissions) +::: + +--- + +### todoread + +Read existing todo lists. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +Reads the current todo list state. Used by the LLM to track what tasks are pending or completed. + +:::note +This tool is disabled for subagents by default, but you can enable it manually. [Learn more](/docs/agents/#permissions) +::: + +--- + +### webfetch + +Fetch web content. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +Allows the LLM to fetch and read web pages. Useful for looking up documentation or researching online resources. + +--- + +### websearch + +Search the web for information. + +:::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`). + +To enable when launching OpenCode: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +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. + +No API key is required — the tool connects directly to Exa AI's hosted MCP service without authentication. + +:::tip +Use `websearch` when you need to find information (discovery), and `webfetch` when you need to retrieve content from a specific URL (retrieval). +::: + +--- + +### question + +Ask the user questions during execution. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +This tool allows the LLM to ask the user questions during a task. It's useful for: + +- Gathering user preferences or requirements +- Clarifying ambiguous instructions +- Getting decisions on implementation choices +- Offering choices about what direction to take + +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. + +--- + +## Benutzerdefinierte Tools + +Mit Custom Tools definierst du eigene Funktionen, die das LLM aufrufen kann. +Sie werden in der Konfigurationsdatei definiert und koennen beliebigen Code ausfuehren. + +[Mehr dazu](/docs/custom-tools), wie du Custom Tools erstellst. + +--- + +## MCP-Server + +MCP-Server (Model Context Protocol) binden externe Tools und Dienste ein. +Dazu gehoeren Datenbanken, API-Integrationen und Drittanbieter-Services. + +[Mehr dazu](/docs/mcp-servers), wie du MCP-Server konfigurierst. + +--- + +## Interna + +Intern verwenden Tools wie `grep`, `glob` und `list` [ripgrep](https://github.com/BurntSushi/ripgrep). +Standardmaessig beachtet ripgrep `.gitignore`, daher werden dort aufgefuehrte Dateien und Ordner nicht durchsucht. + +--- + +### Ignorier-Muster + +Wenn du normalerweise ignorierte Dateien einschliessen willst, lege im Projekt-Root eine `.ignore`-Datei an. +Dort kannst du Pfade explizit erlauben. + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +Dieses Beispiel erlaubt ripgrep, in `node_modules/`, `dist/` und `build/` zu suchen, auch wenn sie in `.gitignore` stehen. diff --git a/packages/web/src/content/docs/de/troubleshooting.mdx b/packages/web/src/content/docs/de/troubleshooting.mdx new file mode 100644 index 00000000000..076200cbd95 --- /dev/null +++ b/packages/web/src/content/docs/de/troubleshooting.mdx @@ -0,0 +1,301 @@ +--- +title: Fehlerbehebung +description: Haeufige Probleme und schnelle Loesungen. +--- + +Wenn OpenCode Probleme macht, starte mit Logs und lokal gespeicherten Daten auf der Festplatte. + +--- + +## Logs + +Logdateien werden hier gespeichert: + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.local\share\opencode\log` + +Dateinamen enthalten Zeitstempel (z. B. `2025-01-09T123456.log`) und es bleiben die letzten 10 Logs erhalten. + +Mit `--log-level` bekommst du detailliertere Diagnoseinfos, z. B. `opencode --log-level DEBUG`. + +--- + +## Speicher + +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` + +Dieses Verzeichnis enthaelt: + +- `auth.json` - Authentifizierungsdaten wie API-Keys und OAuth-Tokens +- `log/` - Anwendungslogs +- `project/` - Projektspezifische Daten wie Sitzungen und Nachrichten + - In Git-Repositories unter `.//storage/` + - Ohne Git unter `./global/storage/` + +--- + +## Desktop-App + +OpenCode Desktop startet im Hintergrund einen lokalen OpenCode-Server (`opencode-cli`-Sidecar). +Viele Probleme kommen von fehlerhaften Plugins, kaputtem Cache oder falschen Server-Einstellungen. + +### Schnellchecks + +- App komplett beenden und neu starten +- Bei Fehlerbildschirm **Restart** klicken und Details kopieren +- Nur macOS: `OpenCode`-Menue -> **Reload Webview** (hilft bei leerer/eingefrorener UI) + +--- + +### Plugins deaktivieren + +If the desktop app is crashing on launch, hanging, or behaving strangely, start by disabling plugins. + +#### Globale Konfiguration prüfen + +Open your global config file and look for a `plugin` key. + +- **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` + +If you have plugins configured, temporarily disable them by removing the key or setting it to an empty array: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### 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: + +- **Global 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) + - `/.opencode/plugins/` + +If the app starts working again, re-enable plugins one at a time to find which one is causing the issue. + +--- + +### Cache leeren + +If disabling plugins doesn't help (or a plugin install is stuck), clear the cache so OpenCode can rebuild it. + +1. Quit OpenCode Desktop completely. +2. Delete the cache directory: + +- **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` + +3. Restart OpenCode Desktop. + +--- + +### Server-Verbindungsprobleme beheben + +OpenCode Desktop can either start its own local server (default) or connect to a server URL you configured. + +If you see a **"Connection Failed"** dialog (or the app never gets past the splash screen), check for a custom 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**. + +#### `server.port` / `server.hostname` aus Konfiguration entfernen + +If your `opencode.json(c)` contains a `server` section, temporarily remove it and restart the desktop app. + +#### 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. + +- Unset `OPENCODE_PORT` (or pick a free port) and restart. + +--- + +### Linux: Wayland / X11-Probleme + +On Linux, some Wayland setups can cause blank windows or compositor errors. + +- 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. + +--- + +### 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. + +--- + +### 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. + +--- + +### Benachrichtigungen werden nicht angezeigt + +OpenCode Desktop only shows system notifications when: + +- notifications are enabled for OpenCode in your OS settings, and +- the app window is not focused. + +--- + +### 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. + +1. Quit OpenCode Desktop. +2. Find and delete these files (they live in the OpenCode Desktop app data directory): + +- `opencode.settings.dat` (desktop default server URL) +- `opencode.global.dat` and `opencode.workspace.*.dat` (UI state like recent servers/projects) + +To find the directory quickly: + +- **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) + +--- + +## Hilfe bekommen + +Wenn du Probleme mit OpenCode hast: + +1. **Probleme auf GitHub melden** + + Bugs und Feature-Wuensche meldest du am besten im GitHub-Repository: + + [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + + Suche vor dem Erstellen nach bestehenden Issues, damit Duplikate vermieden werden. + +2. **Unserem Discord beitreten** + + Fuer schnelle Hilfe und Austausch in der Community: + + [**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## Haeufige Probleme + +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` + +--- + +### 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 + +--- + +### 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 + +If you encounter `ProviderModelNotFoundError` you are most likely incorrectly +referencing a model somewhere. +Models should be referenced like so: `/` + +Examples: + +- `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` + +--- + +### ProviderInitError + +If you encounter a ProviderInitError, you likely have an invalid or corrupted configuration. + +To resolve this: + +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: + + ```bash + rm -rf ~/.local/share/opencode + ``` + + On Windows, press `WIN+R` and delete: `%USERPROFILE%\.local\share\opencode` + +3. Re-authenticate with your provider using the `/connect` command in the 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. + +To resolve provider package issues: + +1. Clear the provider package cache: + + ```bash + rm -rf ~/.cache/opencode + ``` + + On Windows, press `WIN+R` and delete: `%USERPROFILE%\.cache\opencode` + +2. Restart opencode to reinstall the latest provider packages + +This will force opencode to download the most recent versions of provider packages, which often resolves compatibility issues with model parameters and API changes. + +--- + +### Copy/Paste funktioniert nicht unter Linux + +Linux users need to have one of the following clipboard utilities installed for copy/paste functionality to work: + +**For X11 systems:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**For Wayland systems:** + +```bash +apt install -y wl-clipboard +``` + +**For headless environments:** + +```bash +apt install -y xvfb +# and run: +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`. diff --git a/packages/web/src/content/docs/de/tui.mdx b/packages/web/src/content/docs/de/tui.mdx new file mode 100644 index 00000000000..ebd16fa76aa --- /dev/null +++ b/packages/web/src/content/docs/de/tui.mdx @@ -0,0 +1,393 @@ +--- +title: TUI +description: Arbeite mit OpenCode in der Terminal-Oberflaeche. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode bietet eine interaktive Terminaloberflaeche (TUI), um mit einem LLM an deinen Projekten zu arbeiten. + +Ohne weitere Argumente startet OpenCode die TUI im aktuellen Verzeichnis. + +```bash +opencode +``` + +Oder du startest sie fuer ein bestimmtes Arbeitsverzeichnis. + +```bash +opencode /path/to/project +``` + +In der TUI kannst du direkt mit einer Nachricht prompten. + +```text +Give me a quick summary of the codebase. +``` + +--- + +## Datei-Referenzen + +Mit `@` kannst du Dateien in Nachrichten referenzieren. +Dabei wird im aktuellen Verzeichnis eine unscharfe Dateisuche genutzt. + +:::tip +Du kannst `@` in Nachrichten fuer Datei-Referenzen verwenden. +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +Der Dateiinhalt wird automatisch zur Unterhaltung hinzugefuegt. + +--- + +## Bash-Befehle + +Beginne eine Nachricht mit `!`, um einen Shell-Befehl auszufuehren. + +```bash frame="none" +!ls -la +``` + +Die Ausgabe landet als Tool-Ergebnis in der Unterhaltung. + +--- + +## Befehle + +In der OpenCode-TUI kannst du `/` plus Befehlsnamen eingeben, um Aktionen schnell auszufuehren. +Zum Beispiel: + +```bash frame="none" +/help +``` + +Viele Befehle haben auch Tastenkombinationen mit `ctrl+x` als Leader-Key. +[Mehr dazu](/docs/keybinds). + +Hier sind alle verfuegbaren Slash-Commands: + +--- + +### connect + +Add a provider to OpenCode. Allows you to select from available providers and add their API keys. + +```bash frame="none" +/connect +``` + +--- + +### compact + +Compact the current session. _Alias_: `/summarize` + +```bash frame="none" +/compact +``` + +**Keybind:** `ctrl+x c` + +--- + +### details + +Toggle tool execution details. + +```bash frame="none" +/details +``` + +**Keybind:** `ctrl+x d` + +--- + +### editor + +Open external editor for composing messages. Uses the editor set in your `EDITOR` environment variable. [Learn more](#editor-setup). + +```bash frame="none" +/editor +``` + +**Keybind:** `ctrl+x e` + +--- + +### exit + +Exit OpenCode. _Aliases_: `/quit`, `/q` + +```bash frame="none" +/exit +``` + +**Keybind:** `ctrl+x 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). + +```bash frame="none" +/export +``` + +**Keybind:** `ctrl+x x` + +--- + +### help + +Show the help dialog. + +```bash frame="none" +/help +``` + +**Keybind:** `ctrl+x h` + +--- + +### init + +Create or update `AGENTS.md` file. [Learn more](/docs/rules). + +```bash frame="none" +/init +``` + +**Keybind:** `ctrl+x i` + +--- + +### models + +List available models. + +```bash frame="none" +/models +``` + +**Keybind:** `ctrl+x m` + +--- + +### new + +Start a new session. _Alias_: `/clear` + +```bash frame="none" +/new +``` + +**Keybind:** `ctrl+x n` + +--- + +### redo + +Redo a previously undone message. Only available after using `/undo`. + +:::tip +Any file changes will also be restored. +::: + +Internally, this uses Git to manage the file changes. So your project **needs to +be a Git repository**. + +```bash frame="none" +/redo +``` + +**Keybind:** `ctrl+x r` + +--- + +### sessions + +List and switch between sessions. _Aliases_: `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +**Keybind:** `ctrl+x l` + +--- + +### share + +Share current session. [Learn more](/docs/share). + +```bash frame="none" +/share +``` + +**Keybind:** `ctrl+x s` + +--- + +### themes + +List available themes. + +```bash frame="none" +/theme +``` + +**Keybind:** `ctrl+x t` + +--- + +### 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. + +:::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. +::: + +```bash frame="none" +/thinking +``` + +--- + +### undo + +Undo last message in the conversation. Removes the most recent user message, all subsequent responses, and any file changes. + +:::tip +Any file changes made will also be reverted. +::: + +Internally, this uses Git to manage the file changes. So your project **needs to +be a Git repository**. + +```bash frame="none" +/undo +``` + +**Keybind:** `ctrl+x u` + +--- + +### unshare + +Unshare current session. [Learn more](/docs/share#un-sharing). + +```bash frame="none" +/unshare +``` + +--- + +## Editor-Einrichtung + +Both the `/editor` and `/export` commands use the editor specified in your `EDITOR` environment variable. + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + + To make it permanent, add this to your shell profile; + `~/.bashrc`, `~/.zshrc`, etc. + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + + To make it permanent, use **System Properties** > **Environment + Variables**. + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + + To make it permanent, add this to your PowerShell profile. + + + + +Popular editor options include: + +- `code` - Visual Studio Code +- `cursor` - Cursor +- `windsurf` - Windsurf +- `nvim` - Neovim editor +- `vim` - Vim editor +- `nano` - Nano editor +- `notepad` - Windows Notepad +- `subl` - Sublime Text + +:::note +Some editors like VS Code need to be started with the `--wait` flag. +::: + +Some editors need command-line arguments to run in blocking mode. The `--wait` flag makes the editor process block until closed. + +--- + +## Konfiguration + +You can customize TUI behavior through your OpenCode config file. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### 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`.** + +--- + +## Anpassung + +You can customize various aspects of the TUI view using the command palette (`ctrl+x h` or `/help`). These settings persist across restarts. + +--- + +#### Benutzername-Anzeige + +Toggle whether your username appears in chat messages. Access this through: + +- Command palette: Search for "username" or "hide username" +- The setting persists automatically and will be remembered across TUI sessions diff --git a/packages/web/src/content/docs/de/web.mdx b/packages/web/src/content/docs/de/web.mdx new file mode 100644 index 00000000000..f334e7c436e --- /dev/null +++ b/packages/web/src/content/docs/de/web.mdx @@ -0,0 +1,142 @@ +--- +title: Web +description: Verwenden Sie OpenCode in Ihrem Browser. +--- + +OpenCode kann als Webanwendung in Ihrem Browser ausgeführt werden und bietet das gleiche leistungsstarke KI-Codierungserlebnis, ohne dass ein Terminal erforderlich ist. + +![OpenCode Web – Neue Sitzung](../../../assets/web/web-homepage-new-session.png) + +## Erste Schritte + +Starten Sie die Weboberfläche, indem Sie Folgendes ausführen: + +```bash +opencode web +``` + +Dadurch wird ein lokaler Server auf `127.0.0.1` mit einem zufällig verfügbaren Port gestartet und OpenCode automatisch in Ihrem Standardbrowser geöffnet. + +:::caution +Wenn `OPENCODE_SERVER_PASSWORD` nicht gesetzt ist, ist der Server ungesichert. Dies ist für den lokalen Gebrauch in Ordnung, sollte aber für den Netzwerkzugriff eingestellt werden. +::: + +:::tip[Windows-Nutzer] +Um die beste Erfahrung zu erzielen, führen Sie `opencode web` über [WSL](/docs/windows-wsl) und nicht über PowerShell aus. Dies gewährleistet den ordnungsgemäßen Zugriff auf das Dateisystem und die Terminalintegration. +::: + +--- + +## Konfiguration + +Sie können den Webserver mithilfe von Befehlszeilen-Flags oder in Ihrer [Konfigurationsdatei](/docs/config) konfigurieren. + +### Port + +Standardmäßig wählt OpenCode einen verfügbaren Port aus. Sie können einen Port angeben: + +```bash +opencode web --port 4096 +``` + +### Hostname + +Standardmäßig bindet der Server an `127.0.0.1` (nur localhost). So machen Sie OpenCode in Ihrem Netzwerk zugänglich: + +```bash +opencode web --hostname 0.0.0.0 +``` + +Bei Verwendung von `0.0.0.0` zeigt OpenCode sowohl lokale als auch Netzwerkadressen an: + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### mDNS-Erkennung + +Aktivieren Sie mDNS, um Ihren Server im lokalen Netzwerk erkennbar zu machen: + +```bash +opencode web --mdns +``` + +Dadurch wird der Hostname automatisch auf `0.0.0.0` gesetzt und der Server als `opencode.local` angekündigt. + +Sie können den mDNS-Domänennamen anpassen, um mehrere Instanzen im selben Netzwerk auszuführen: + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +So erlauben Sie zusätzliche Domänen für CORS (nützlich für benutzerdefinierte Frontends): + +```bash +opencode web --cors https://example.com +``` + +### Authentifizierung + +Um den Zugriff zu schützen, legen Sie mithilfe der Umgebungsvariablen `OPENCODE_SERVER_PASSWORD` ein Passwort fest: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +Der Benutzername ist standardmäßig `opencode`, kann aber mit `OPENCODE_SERVER_USERNAME` geändert werden. + +--- + +## Verwenden der Weboberfläche + +Nach dem Start bietet die Weboberfläche Zugriff auf Ihre OpenCode-Sitzungen. + +### Sitzungen + +Zeigen Sie Ihre Sitzungen auf der Startseite an und verwalten Sie sie. Sie können aktive Sitzungen sehen und neue starten. + +![OpenCode Web – Aktive Sitzung](../../../assets/web/web-homepage-active-session.png) + +### Serverstatus + +Klicken Sie auf „Server anzeigen“, um verbundene Server und deren Status anzuzeigen. + +![OpenCode Web – Siehe Server](../../../assets/web/web-homepage-see-servers.png) + +--- + +## Anschließen eines Terminals + +Sie können eine Terminal-TUI an einen laufenden Webserver anschließen: + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +Dadurch können Sie sowohl die Weboberfläche als auch das Terminal gleichzeitig verwenden und dieselben Sitzungen und denselben Status teilen. + +--- + +## Konfigurationsdatei + +Sie können Servereinstellungen auch in Ihrer `opencode.json`-Konfigurationsdatei konfigurieren: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +Befehlszeilenflags haben Vorrang vor Konfigurationsdateieinstellungen. diff --git a/packages/web/src/content/docs/de/windows-wsl.mdx b/packages/web/src/content/docs/de/windows-wsl.mdx new file mode 100644 index 00000000000..29c4d1f7373 --- /dev/null +++ b/packages/web/src/content/docs/de/windows-wsl.mdx @@ -0,0 +1,115 @@ +--- +title: Windows (WSL) +description: Nutze OpenCode unter Windows am besten mit WSL. +--- + +import { Steps } from "@astrojs/starlight/components" + +OpenCode laeuft zwar direkt unter Windows, die beste Erfahrung bekommst du aber mit [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install). +WSL bietet eine Linux-Umgebung, die mit den OpenCode-Features nahtlos funktioniert. + +:::tip[Warum WSL?] +WSL bietet bessere Dateisystem-Performance, vollstaendige Terminal-Unterstuetzung und hohe Kompatibilitaet mit den Entwicklungswerkzeugen, die OpenCode nutzt. +::: + +--- + +## Einrichtung + + + +1. **Install WSL** + + Falls noch nicht geschehen, installiere [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) mit der offiziellen Microsoft-Anleitung. + +2. **Install OpenCode in WSL** + + Wenn WSL eingerichtet ist, oeffne dein WSL-Terminal und installiere OpenCode mit einer der [Installationsmethoden](/docs/). + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **OpenCode über WSL verwenden** + + Wechsle in dein Projektverzeichnis (Windows-Dateien erreichst du ueber `/mnt/c/`, `/mnt/d/` usw.) und starte OpenCode. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## Desktop-App + WSL-Server + +Wenn du die OpenCode-Desktop-App nutzen willst, den Server aber in WSL betreiben moechtest: + +1. **Starte den Server in WSL** mit `--hostname 0.0.0.0`, damit externe Verbindungen moeglich sind: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **Verbinde die Desktop-App** mit `http://localhost:4096` + +:::note +Wenn `localhost` in deiner Umgebung nicht funktioniert, nutze stattdessen die WSL-IP-Adresse (in WSL: `hostname -I`) und verbinde dich mit `http://:4096`. +::: + +:::caution +Wenn du `--hostname 0.0.0.0` verwendest, setze `OPENCODE_SERVER_PASSWORD`, um den Server zu schuetzen. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## Web-Client + WSL + +Fuer die beste Web-Erfahrung unter Windows: + +1. **Fuehre `opencode web` im WSL-Terminal aus**, nicht in PowerShell: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Rufe die URL im Windows-Browser auf** unter `http://localhost:` (OpenCode zeigt die URL an) + +Wenn du `opencode web` aus WSL startest, bleiben Dateizugriff und Terminal-Integration sauber. +Gleichzeitig ist die Weboberflaeche weiterhin im Windows-Browser erreichbar. + +--- + +## Zugriff auf Windows-Dateien + +WSL kann ueber das Verzeichnis `/mnt/` auf alle Windows-Dateien zugreifen: + +- Laufwerk `C:` -> `/mnt/c/` +- Laufwerk `D:` -> `/mnt/d/` +- usw. + +Beispiel: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +Fuer die beste Performance kannst du dein Repo direkt in das WSL-Dateisystem klonen/kopieren (z. B. nach `~/code/`) und OpenCode dort starten. +::: + +--- + +## Tipps + +- Lass OpenCode in WSL laufen, auch wenn das Projekt auf einem Windows-Laufwerk liegt +- Nutze die [WSL-Extension](https://code.visualstudio.com/docs/remote/wsl) von VS Code fuer einen integrierten Workflow +- OpenCode-Konfiguration und Sitzungen liegen in WSL unter `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/de/zen.mdx b/packages/web/src/content/docs/de/zen.mdx new file mode 100644 index 00000000000..f52ed5f363f --- /dev/null +++ b/packages/web/src/content/docs/de/zen.mdx @@ -0,0 +1,247 @@ +--- +title: Zen +description: Kuratierte Modellliste direkt von OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen ist eine vom OpenCode-Team getestete und verifizierte Modellliste. + +:::note +OpenCode Zen befindet sich aktuell in der Beta. +::: + +Zen funktioniert wie jeder andere Provider in OpenCode. +Du meldest dich bei OpenCode Zen an, holst dir deinen API-Key und nutzt ihn optional. + +--- + +## Hintergrund + +Es gibt sehr viele Modelle, aber nur ein Teil davon eignet sich wirklich gut als Coding-Agent. +Ausserdem konfigurieren Provider Modelle sehr unterschiedlich, was die Qualitaet stark beeinflusst. + +:::tip +Wir haben eine Auswahl aus Modellen und Providern getestet, die gut mit OpenCode funktionieren. +::: + +Wenn du Modelle ueber Gateways wie OpenRouter nutzt, ist oft unklar, ob du die beste Ausfuehrung eines Modells bekommst. + +Um das zu verbessern, haben wir: + +1. Eine Auswahl an Modellen getestet und mit den Teams ueber optimale Laufzeit-Setups gesprochen +2. Mit Providern zusammengearbeitet, damit diese Modelle korrekt ausgeliefert werden +3. Modell/Provider-Kombinationen gebenchmarkt und eine empfehlenswerte Liste erstellt + +OpenCode Zen ist ein AI-Gateway, das dir Zugriff auf genau diese Modelle gibt. + +--- + +## Funktionsweise + +OpenCode Zen funktioniert wie jeder andere Provider in OpenCode. + +1. Melde dich bei **OpenCode Zen** an, hinterlege Zahlungsdaten und kopiere deinen API-Key. +2. Fuehre in der TUI `/connect` aus, waehle OpenCode Zen und fuege den API-Key ein. +3. Starte `/models` in der TUI, um empfohlene Modelle zu sehen. + +Abgerechnet wird pro Anfrage, Guthaben kannst du jederzeit aufladen. + +--- + +## Endpunkte + +Du kannst unsere Modelle auch ueber die folgenden API-Endpunkte aufrufen. + +| Model | Model ID | Endpoint | AI SDK Package | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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` | + +Die [Model-ID](/docs/config/#models) in deiner OpenCode-Konfiguration hat das Format `opencode/`. +Fuer GPT 5.2 Codex verwendest du zum Beispiel `opencode/gpt-5.2-codex`. + +--- + +### Models + +Die komplette Liste verfuegbarer Modelle inklusive Metadaten findest du unter: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## Preisgestaltung + +Wir nutzen ein Pay-as-you-go-Modell. +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.1 | $0.30 | $1.20 | $0.10 | - | +| GLM 4.7 Free | Free | Free | Free | - | +| 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 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 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.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 | Free | Free | Free | - | + +In deinem Verlauf siehst du eventuell _Claude Haiku 3.5_. +Das ist ein [guenstiges Modell](/docs/config/#models), das fuer Session-Titel verwendet wird. + +:::note +Kreditkartengebuehren geben wir zum Selbstkostenpreis weiter (4,4 % + $0.30 pro Transaktion), ohne Aufschlag. +::: + +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. + +Wenn du Fragen hast, kontaktiere uns. + +--- + +### Auto-reload + +Wenn dein Guthaben unter $5 faellt, laedt Zen automatisch $20 nach. + +Du kannst den Betrag anpassen oder Auto-Reload komplett deaktivieren. + +--- + +### Monatslimits + +Du kannst monatliche Limits fuer den gesamten Workspace und pro Teammitglied festlegen. + +Wenn du z. B. ein Monatslimit von $20 setzt, verbraucht Zen nicht mehr als $20 pro Monat. +Mit aktiviertem Auto-Reload kann die Abrechnung dennoch darueber liegen, falls das Guthaben unter $5 sinkt. + +--- + +## Datenschutz + +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). + +--- + +## Für Teams + +Zen eignet sich auch gut fuer Teams. +Du kannst Mitglieder einladen, Rollen vergeben und den Modellzugriff fuer dein Team steuern. + +:::note +Workspaces sind fuer Teams waehrend der Beta derzeit kostenlos. +::: + +Workspace-Verwaltung ist in der Beta kostenlos. +Details zur spaeteren Preisgestaltung folgen. + +--- + +### Rollen + +Du kannst Teammitglieder einladen und Rollen vergeben: + +- **Admin**: Verwalten Modelle, Mitglieder, API-Keys und Abrechnung +- **Member**: Verwalten nur eigene API-Keys + +Admins koennen zusaetzlich monatliche Ausgabenlimits pro Mitglied setzen. + +--- + +### Modellzugriff + +Admins koennen einzelne Modelle fuer den Workspace aktivieren oder deaktivieren. +Anfragen an deaktivierte Modelle liefern einen Fehler. + +Das ist hilfreich, wenn bestimmte datenverarbeitende Modelle ausgeschlossen werden sollen. + +--- + +### Eigenen Key mitbringen + +Du kannst eigene OpenAI- oder Anthropic-API-Keys verwenden und trotzdem andere Zen-Modelle nutzen. + +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. + +--- + +## Ziele + +Wir haben OpenCode Zen entwickelt, um: + +1. Die besten Modell/Provider-Kombinationen fuer Coding-Agenten zu **benchmarken** +2. Stets **hohe Qualitaet** ohne Downgrades oder versteckte Umleitungen auf billigere Provider zu liefern +3. **Preissenkungen** zum Selbstkostenpreis weiterzugeben, mit Aufschlag nur fuer Zahlungsgebuehren +4. **Kein Lock-in** zu erzwingen, damit du Zen mit anderen Coding-Agents und OpenCode weiter mit anderen Providern nutzen kannst diff --git a/packages/web/src/content/docs/es/acp.mdx b/packages/web/src/content/docs/es/acp.mdx new file mode 100644 index 00000000000..6cc14669a98 --- /dev/null +++ b/packages/web/src/content/docs/es/acp.mdx @@ -0,0 +1,156 @@ +--- +title: Soporte ACP +description: Utilice OpenCode en cualquier editor compatible con ACP. +--- + +OpenCode admite el [Agent Client Protocol](https://agentclientprotocol.com) o (ACP), lo que le permite usarlo directamente en editores e IDE compatibles. + +:::tip +Para obtener una lista de editores y herramientas compatibles con ACP, consulte el [informe de progreso de ACP](https://zed.dev/blog/acp-progress-report#available-now). +::: + +ACP es un protocolo abierto que estandariza la comunicación entre editores de código y agentes de codificación de IA. + +--- + +## Configuración + +Para usar OpenCode a través de ACP, configure su editor para ejecutar el comando `opencode acp`. + +El comando inicia OpenCode como un subproceso compatible con ACP que se comunica con su editor a través de JSON-RPC a través de stdio. + +A continuación se muestran ejemplos de editores populares que admiten ACP. + +--- + +### Zed + +Agregue a su configuración [Zed](https://zed.dev) (`~/.config/zed/settings.json`): + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +Para abrirlo, use la acción `agent: new thread` en la **Paleta de comandos**. + +También puedes vincular un atajo de teclado editando tu `keymap.json`: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### JetBrains IDEs + +Agregue a su [JetBrains IDE](https://www.jetbrains.com/) acp.json de acuerdo con la [documentación](https://www.jetbrains.com/help/ai-assistant/acp.html): + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +Para abrirlo, use el nuevo agente 'OpenCode' en el selector de agentes de AI Chat. + +--- + +### Avante.nvim + +Agregue a su configuración [Avante.nvim](https://github.com/yetone/avante.nvim): + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +Si necesita pasar variables de entorno: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +Para usar OpenCode como agente ACP en [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim), agregue lo siguiente a su configuración de Neovim: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +Esta configuración configura CodeCompanion para usar OpenCode como agente ACP para el chat. + +Si necesita pasar variables de entorno (como `OPENCODE_API_KEY`), consulte [Configuración de adaptadores: variables de entorno](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) en la documentación de CodeCompanion.nvim para obtener detalles completos. + +## Soporte + +OpenCode funciona igual a través de ACP que en la terminal. Todas las funciones son compatibles: + +:::note +Algunos comandos de barra integrados como `/undo` y `/redo` no son compatibles actualmente. +::: + +- Herramientas integradas (operaciones de archivos, comandos de terminal, etc.) +- Herramientas personalizadas y comandos de barra +- Servidores MCP configurados en su configuración OpenCode +- Reglas específicas del proyecto de `AGENTS.md` +- Formateadores y linters personalizados +- Sistema de agentes y permisos. diff --git a/packages/web/src/content/docs/es/agents.mdx b/packages/web/src/content/docs/es/agents.mdx new file mode 100644 index 00000000000..0b2736ac373 --- /dev/null +++ b/packages/web/src/content/docs/es/agents.mdx @@ -0,0 +1,747 @@ +--- +title: Agentes +description: Configurar y utilizar agentes especializados. +--- + +Los agentes son asistentes de IA especializados que se pueden configurar para tareas y flujos de trabajo específicos. Le permiten crear herramientas enfocadas con indicaciones, modelos y acceso a herramientas personalizados. + +:::tip +Utilice el agente del plan para analizar el código y revisar sugerencias sin realizar ningún cambio en el código. +::: + +Puede cambiar entre agentes durante una sesión o invocarlos con la mención `@`. + +--- + +## Tipos + +Hay dos tipos de agentes en OpenCode; agentes primarios y subagentes. + +--- + +### Agentes primarios + +Los agentes primarios son los asistentes principales con los que interactúas directamente. Puede recorrerlos usando la tecla **Tab** o la combinación de teclas `switch_agent` configurada. Estos agentes manejan su conversación principal. El acceso a las herramientas se configura mediante permisos; por ejemplo, Build tiene todas las herramientas habilitadas mientras que Plan está restringido. + +:::tip +Puede utilizar la tecla **Tab** para cambiar entre agentes principales durante una sesión. +::: + +OpenCode viene con dos agentes principales integrados, **Build** y **Plan**. Bien +mira estos a continuación. + +--- + +### Subagentes + +Los subagentes son asistentes especializados que los agentes principales pueden invocar para tareas específicas. También puedes invocarlos manualmente **@ mencionándolos** en tus mensajes. + +OpenCode viene con dos subagentes integrados, **General** y **Explore**. Veremos esto a continuación. + +--- + +## Integrados + +OpenCode viene con dos agentes primarios integrados y dos subagentes integrados. + +--- + +### Build + +_Modo_: `primary` + +Build es el agente principal **predeterminado** con todas las herramientas habilitadas. Este es el agente estándar para trabajos de desarrollo en los que necesita acceso completo a las operaciones de archivos y comandos del sistema. + +--- + +### Plan + +_Modo_: `primary` + +Un agente restringido diseñado para la planificación y el análisis. Utilizamos un sistema de permisos para brindarle más control y evitar cambios no deseados. +De forma predeterminada, todo lo siguiente está configurado en `ask`: + +- `file edits`: todas las escrituras, parches y ediciones. +- `bash`: Todos los comandos bash + +Este agente es útil cuando desea que LLM analice código, sugiera cambios o cree planes sin realizar modificaciones reales a su base de código. + +--- + +### General + +_Modo_: `subagent` + +Un agente de uso general para investigar preguntas complejas y ejecutar tareas de varios pasos. Tiene acceso completo a las herramientas (excepto tareas pendientes), por lo que puede realizar cambios en los archivos cuando sea necesario. Utilícelo para ejecutar varias unidades de trabajo en paralelo. + +--- + +### Explore + +_Modo_: `subagent` + +Un agente rápido y de solo lectura para explorar bases de código. No se pueden modificar archivos. Úselo cuando necesite buscar rápidamente archivos por patrones, buscar palabras clave en el código o responder preguntas sobre el código base. + +--- + +### Compactación + +_Modo_: `primary` + +Agente de sistema oculto que compacta un contexto largo en un resumen más pequeño. Se ejecuta automáticamente cuando es necesario y no se puede seleccionar en la interfaz de usuario. + +--- + +### Título + +_Modo_: `primary` + +Agente del sistema oculto que genera títulos de sesión cortos. Se ejecuta automáticamente y no se puede seleccionar en la interfaz de usuario. + +--- + +### Resumen + +_Modo_: `primary` + +Agente del sistema oculto que crea resúmenes de sesiones. Se ejecuta automáticamente y no se puede seleccionar en la interfaz de usuario. + +--- + +## Uso + +1. Para los agentes principales, use la tecla **Tab** para recorrerlos durante una sesión. También puede utilizar su combinación de teclas `switch_agent` configurada. + +2. Se pueden invocar subagentes: + - **Automáticamente** por agentes principales para tareas especializadas según sus descripciones. + - Manualmente **@ mencionando** un subagente en tu mensaje. Por ejemplo. + + ```txt frame="none" + @general help me search for this function + ``` + +3. **Navegación entre sesiones**: cuando los subagentes crean sus propias sesiones secundarias, puede navegar entre la sesión principal y todas las sesiones secundarias usando: + - **\+Right** (or su combinación de teclas `session_child_cycle` configurada) para avanzar a través de padre → hijo1 → hijo2 → ... → padre + - **\+Left** (or su combinación de teclas `session_child_cycle_reverse` configurada) para retroceder entre padre ← hijo1 ← hijo2 ← ... ← padre + + Esto le permite cambiar sin problemas entre la conversación principal y el trabajo de subagente especializado. + +--- + +## Configuración + +Puede personalizar los agentes integrados o crear los suyos propios mediante la configuración. Los agentes se pueden configurar de dos maneras: + +--- + +### JSON + +Configure agentes en su archivo de configuración `opencode.json`: + +```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 + +También puede definir agentes utilizando archivos de Markdown. Colócalos en: + +- Global: `~/.config/opencode/agents/` +- Por proyecto: `.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. +``` + +El nombre del archivo de Markdown se convierte en el nombre del agente. Por ejemplo, `review.md` crea un agente `review`. + +--- + +## Opciones + +Veamos estas opciones de configuración en detalle. + +--- + +### Descripción + +Utilice la opción `description` para proporcionar una breve descripción de lo que hace el agente y cuándo usarlo. + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +Esta es una opción de configuración **obligatoria**. + +--- + +### Temperatura + +Controle la aleatoriedad y la creatividad de las respuestas de LLM con la configuración `temperature`. + +Los valores más bajos hacen que las respuestas sean más centradas y deterministas, mientras que los valores más altos aumentan la creatividad y la variabilidad. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Los valores de temperatura suelen oscilar entre 0,0 y 1,0: + +- **0.0-0.2**: Respuestas muy enfocadas y deterministas, ideales para análisis y planificación de código. +- **0,3-0,5**: respuestas equilibradas con algo de creatividad, buenas para tareas de desarrollo general. +- **0.6-1.0**: respuestas más creativas y variadas, útiles para la lluvia de ideas y la exploración. + +```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}" + } + } +} +``` + +Si no se especifica ninguna temperatura, OpenCode utiliza valores predeterminados específicos del modelo; normalmente 0 para la mayoría de los modelos, 0,55 para los modelos Qwen. + +--- + +### Pasos máximos + +Controle la cantidad máxima de iteraciones agentes que un agente puede realizar antes de verse obligado a responder solo con texto. Esto permite a los usuarios que desean controlar los costos establecer un límite a las acciones de agencia. + +Si no se establece esto, el agente continuará iterando hasta que el modelo decida detenerse o el usuario interrumpa la sesión. + +```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 + } + } +} +``` + +Cuando se alcanza el límite, el agente recibe un mensaje especial del sistema que le indica que responda con un resumen de su trabajo y las tareas restantes recomendadas. + +:::caution +El campo heredado `maxSteps` está en desuso. Utilice `steps` en su lugar. +::: + +--- + +### Deshabilitar + +Establezca en `true` para deshabilitar el agente. + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### Indicación + +Especifique un archivo de aviso del sistema personalizado para este agente con la configuración `prompt`. El archivo de aviso debe contener instrucciones específicas para el propósito del agente. + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Esta ruta es relativa a donde se encuentra el archivo de configuración. Entonces esto funciona tanto para la configuración global OpenCode como para la configuración específica del proyecto. + +--- + +### Modelo + +Utilice la configuración `model` para anular el modelo de este agente. Útil para utilizar diferentes modelos optimizados para diferentes tareas. Por ejemplo, un modelo más rápido de planificación, un modelo más capaz de implementación. + +:::tip +Si no especifica un modelo, los agentes primarios usarán el [modelo configurado globalmente](/docs/config#models), mientras que los subagentes usarán el modelo del agente primario que invocó al subagente. +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +El ID del modelo en su configuración OpenCode usa el formato `provider/model-id`. Por ejemplo, si usa [OpenCode Zen](/docs/zen), usaría `opencode/gpt-5.1-codex` para GPT 5.1 Codex. + +--- + +### Herramientas + +Controle qué herramientas están disponibles en este agente con la configuración `tools`. Puede habilitar o deshabilitar herramientas específicas configurándolas en `true` o `false`. + +```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 +La configuración específica del agente anula la configuración global. +::: + +También puedes utilizar comodines para controlar varias herramientas a la vez. Por ejemplo, para desactivar todas las herramientas de un servidor MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[Más información sobre herramientas](/docs/tools). + +--- + +### Permisos + +Puede configurar permisos para administrar qué acciones puede realizar un agente. Actualmente, los permisos para las herramientas `edit`, `bash` y `webfetch` se pueden configurar para: + +- `"ask"`: solicitar aprobación antes de ejecutar la herramienta +- `"allow"` — Permitir todas las operaciones sin aprobación +- `"deny"` — Desactiva la herramienta + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +Puede anular estos permisos por agente. + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +También puede establecer permisos en los agentes de Markdown. + +```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. +``` + +Puede establecer permisos para comandos bash específicos. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +Esto puede tomar un patrón global. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +Y también puedes usar el comodín `*` para administrar los permisos de todos los comandos. +Dado que la última regla de coincidencia tiene prioridad, coloque el comodín `*` primero y las reglas específicas después. + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[Más información sobre permisos](/docs/permissions). + +--- + +### Modo + +Controle el modo del agente con la configuración `mode`. La opción `mode` se utiliza para determinar cómo se puede utilizar el agente. + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +La opción `mode` se puede configurar en `primary`, `subagent` o `all`. Si no se especifica `mode`, el valor predeterminado es `all`. + +--- + +### Oculto + +Oculte un subagente del menú de autocompletar `@` con `hidden: true`. Útil para subagentes internos que solo deben ser invocados mediante programación por otros agentes a través de la herramienta Tarea. + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +Esto sólo afecta la visibilidad del usuario en el menú de autocompletar. El modelo aún puede invocar agentes ocultos a través de la herramienta Tarea si los permisos lo permiten. + +:::note +Sólo aplica para agentes `mode: subagent`. +::: + +--- + +### Permisos de tarea + +Controle qué subagentes puede invocar un agente a través de la herramienta Tarea con `permission.task`. Utiliza patrones globales para una combinación flexible. + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +Cuando se establece en `deny`, el subagente se elimina por completo de la descripción de la herramienta Tarea, por lo que el modelo no intentará invocarlo. + +:::tip +Las reglas se evalúan en orden y la **última regla coincidente gana**. En el ejemplo anterior, `orchestrator-planner` coincide con `*` (denegar) y `orchestrator-*` (permitir), pero como `orchestrator-*` viene después de `*`, el resultado es `allow`. +::: + +:::tip +Los usuarios siempre pueden invocar cualquier subagente directamente a través del menú de autocompletar `@`, incluso si los permisos de tarea del agente lo niegan. +::: + +--- + +### Color + +Personalice la apariencia visual del agente en la interfaz de usuario con la opción `color`. Esto afecta la forma en que aparece el agente en la interfaz. + +Utilice un color hexadecimal válido (por ejemplo, `#FF5733`) o un color de tema: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +Controle la diversidad de respuestas con la opción `top_p`. Alternativa a la temperatura para controlar la aleatoriedad. + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +Los valores oscilan entre 0,0 y 1,0. Los valores más bajos están más enfocados, los valores más altos son más diversos. + +--- + +### Adicional + +Cualquier otra opción que especifique en la configuración de su agente se **pasará directamente** al proveedor como opciones de modelo. Esto le permite utilizar funciones y parámetros específicos del proveedor. + +Por ejemplo, con los modelos de razonamiento de OpenAI, puedes controlar el esfuerzo de razonamiento: + +```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" + } + } +} +``` + +Estas opciones adicionales son específicas del modelo y del proveedor. Consulte la documentación de su proveedor para conocer los parámetros disponibles. + +:::tip +Ejecute `opencode models` para ver una lista de los modelos disponibles. +::: + +--- + +## Crear agentes + +Puede crear nuevos agentes usando el siguiente comando: + +```bash +opencode agent create +``` + +Este comando interactivo: + +1. Preguntar dónde guardar al agente; global o específico del proyecto. +2. Descripción de lo que debe hacer el agente. +3. Genere un indicador y un identificador del sistema adecuados. +4. Le permite seleccionar a qué herramientas puede acceder el agente. +5. Finalmente, cree un archivo Markdown con la configuración del agente. + +--- + +## Casos de uso + +A continuación se muestran algunos casos de uso comunes para diferentes agentes. + +- **Agente Build**: trabajo de desarrollo completo con todas las herramientas habilitadas +- **Agente Plan**: Análisis y planificación sin realizar cambios +- **Agente Review**: revisión de código con acceso de solo lectura más herramientas de documentación +- **Agente Debug**: centrado en la investigación con bash y herramientas de lectura habilitadas +- **Agente Docs**: escritura de documentación con operaciones de archivos pero sin comandos del sistema. + +--- + +## Ejemplos + +A continuación se muestran algunos agentes de ejemplo que pueden resultarle útiles. + +:::tip +¿Tiene un agente que le gustaría compartir? [Enviar un PR](https://github.com/anomalyco/opencode). +::: + +--- + +### Agente de documentación + +```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 +``` + +--- + +### Auditor de seguridad + +```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/es/cli.mdx b/packages/web/src/content/docs/es/cli.mdx new file mode 100644 index 00000000000..705da0de4b0 --- /dev/null +++ b/packages/web/src/content/docs/es/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: Opciones y comandos de la CLI de OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +La CLI de OpenCode de forma predeterminada inicia el [TUI](/docs/tui) cuando se ejecuta sin ningún argumento. + +```bash +opencode +``` + +Pero también acepta comandos como se documenta en esta página. Esto le permite interactuar con OpenCode mediante programación. + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +Inicie la interfaz de usuario del terminal OpenCode. + +```bash +opencode [project] +``` + +#### Opciones + +| Opción | Corta | Descripción | +| ------------ | ----- | --------------------------------------------------------------------- | +| `--continue` | `-c` | Continuar la última sesión | +| `--session` | `-s` | ID de sesión para continuar | +| `--fork` | | Bifurcar la sesión al continuar (usar con `--continue` o `--session`) | +| `--prompt` | | Aviso de uso | +| `--model` | `-m` | Modelo a utilizar en forma de proveedor/modelo | +| `--agent` | | Agente a utilizar | +| `--port` | | Puerto para escuchar | +| `--hostname` | | Nombre de host para escuchar | + +--- + +## Comandos + +La CLI de OpenCode también tiene los siguientes comandos. + +--- + +### agent + +Administrar agentes para OpenCode. + +```bash +opencode agent [command] +``` + +--- + +### attach + +Conecte una terminal a un servidor backend OpenCode que ya se esté ejecutando y iniciado mediante los comandos `serve` o `web`. + +```bash +opencode attach [url] +``` + +Esto permite usar TUI con un backend remoto OpenCode. Por ejemplo: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### Opciones + +| Opción | Corta | Descripción | +| ----------- | ----- | ----------------------------------------- | +| `--dir` | | Directorio de trabajo para iniciar TUI en | +| `--session` | `-s` | ID de sesión para continuar | + +--- + +#### create + +Cree un nuevo agente con configuración personalizada. + +```bash +opencode agent create +``` + +Este comando lo guiará en la creación de un nuevo agente con un mensaje del sistema personalizado y una configuración de herramientas. + +--- + +#### list + +Enumere todos los agentes disponibles. + +```bash +opencode agent list +``` + +--- + +### auth + +Comando para administrar credenciales e iniciar sesión para proveedores. + +```bash +opencode auth [command] +``` + +--- + +#### login + +OpenCode funciona con la lista de proveedores en [Models.dev](https://models.dev), por lo que puede usar `opencode auth login` para configurar las claves API para cualquier proveedor que desee utilizar. Esto se almacena en `~/.local/share/opencode/auth.json`. + +```bash +opencode auth login +``` + +Cuando se inicia OpenCode, carga los proveedores desde el archivo de credenciales. Y si hay claves definidas en sus entornos o un archivo `.env` en su proyecto. + +--- + +#### list + +Enumera todos los proveedores autenticados tal como están almacenados en el archivo de credenciales. + +```bash +opencode auth list +``` + +O la versión corta. + +```bash +opencode auth ls +``` + +--- + +#### logout + +Cierra tu sesión de un proveedor eliminándolo del archivo de credenciales. + +```bash +opencode auth logout +``` + +--- + +### github + +Administre el agente GitHub para la automatización del repositorio. + +```bash +opencode github [command] +``` + +--- + +#### install + +Instale el agente GitHub en su repositorio. + +```bash +opencode github install +``` + +Esto configura el flujo de trabajo de acciones GitHub necesario y lo guía a través del proceso de configuración. [Más información](/docs/github). + +--- + +#### run + +Ejecute el agente GitHub. Esto se usa normalmente en acciones GitHub. + +```bash +opencode github run +``` + +##### Opciones + +| Opción | Descripción | +| --------- | ---------------------------------------------- | +| `--event` | GitHub evento simulado para ejecutar el agente | +| `--token` | GitHub token de acceso personal | + +--- + +### mcp + +Administrar servidores de protocolo de contexto modelo. + +```bash +opencode mcp [command] +``` + +--- + +#### add + +Agregue un servidor MCP a su configuración. + +```bash +opencode mcp add +``` + +Este comando lo guiará para agregar un servidor MCP local o remoto. + +--- + +#### list + +Enumere todos los servidores MCP configurados y su estado de conexión. + +```bash +opencode mcp list +``` + +O utilice la versión corta. + +```bash +opencode mcp ls +``` + +--- + +#### auth + +Autentíquese con un servidor MCP habilitado para OAuth. + +```bash +opencode mcp auth [name] +``` + +Si no proporciona un nombre de servidor, se le pedirá que seleccione entre los servidores compatibles con OAuth disponibles. + +También puede enumerar los servidores compatibles con OAuth y su estado de autenticación. + +```bash +opencode mcp auth list +``` + +O utilice la versión corta. + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +Elimine las credenciales OAuth para un servidor MCP. + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +Depurar problemas de conexión OAuth para un servidor MCP. + +```bash +opencode mcp debug +``` + +--- + +### models + +Enumere todos los modelos disponibles de los proveedores configurados. + +```bash +opencode models [provider] +``` + +Este comando muestra todos los modelos disponibles en sus proveedores configurados en el formato `provider/model`. + +Esto es útil para determinar el nombre exacto del modelo que se usará en [su configuración](/docs/config/). + +Opcionalmente, puede pasar un ID de proveedor para filtrar modelos por ese proveedor. + +```bash +opencode models anthropic +``` + +#### Opciones + +| Opción | Descripción | +| ----------- | --------------------------------------------------------------------------- | +| `--refresh` | Actualizar la caché de modelos desde models.dev | +| `--verbose` | Utilice una salida del modelo más detallada (incluye metadatos como costos) | + +Utilice el indicador `--refresh` para actualizar la lista de modelos almacenados en caché. Esto es útil cuando se han agregado nuevos modelos a un proveedor y desea verlos en OpenCode. + +```bash +opencode models --refresh +``` + +--- + +### run + +Ejecute opencode en modo no interactivo pasando un mensaje directamente. + +```bash +opencode run [message..] +``` + +Esto es útil para secuencias de comandos, automatización o cuando desea una respuesta rápida sin iniciar el TUI completo. Por ejemplo. + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +También puede conectarse a una instancia `opencode serve` en ejecución para evitar tiempos de arranque en frío del servidor MCP en cada ejecución: + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### Opciones + +| Opción | Corta | Descripción | +| ------------ | ----- | ----------------------------------------------------------------------------------- | +| `--command` | | El comando a ejecutar, use mensaje para args | +| `--continue` | `-c` | Continuar la última sesión | +| `--session` | `-s` | ID de sesión para continuar | +| `--fork` | | Bifurcar la sesión al continuar (usar con `--continue` o `--session`) | +| `--share` | | Comparte la sesión | +| `--model` | `-m` | Modelo a utilizar en forma de proveedor/modelo | +| `--agent` | | Agente a utilizar | +| `--file` | `-f` | Archivo(s) para adjuntar al mensaje | +| `--format` | | Formato: predeterminado (formateado) o json (eventos JSON sin formato) | +| `--title` | | Título de la sesión (utiliza un mensaje truncado si no se proporciona ningún valor) | +| `--attach` | | Adjuntar a un servidor opencode en ejecución (por ejemplo, http://localhost:4096) | +| `--port` | | Puerto para el servidor local (el puerto predeterminado es aleatorio) | + +--- + +### serve + +Inicie un servidor OpenCode sin cabeza para acceso API. Consulte los [documentos del servidor](/docs/server) para conocer la interfaz HTTP completa. + +```bash +opencode serve +``` + +Esto inicia un servidor HTTP que proporciona acceso API a la funcionalidad opencode sin la interfaz TUI. Configure `OPENCODE_SERVER_PASSWORD` para habilitar la autenticación básica HTTP (el nombre de usuario predeterminado es `opencode`). + +#### Opciones + +| Opción | Descripción | +| ------------ | ---------------------------------------------------- | +| `--port` | Puerto para escuchar | +| `--hostname` | Nombre de host para escuchar | +| `--mdns` | Habilitar el descubrimiento de mDNS | +| `--cors` | Orígenes de navegador adicionales para permitir CORS | + +--- + +### session + +Administrar OpenCode sesiones. + +```bash +opencode session [command] +``` + +--- + +#### list + +Enumere todas las sesiones OpenCode. + +```bash +opencode session list +``` + +##### Opciones + +| Opción | Corta | Descripción | +| ------------- | ----- | --------------------------------------- | +| `--max-count` | `-n` | Limitar a N sesiones más recientes | +| `--format` | | Formato de salida: tabla o json (tabla) | + +--- + +### stats + +Muestre el uso de tokens y las estadísticas de costos para sus sesiones OpenCode. + +```bash +opencode stats +``` + +#### Opciones + +| Opción | Descripción | +| ----------- | ------------------------------------------------------------------------------------------------------------------------ | +| `--days` | Mostrar estadísticas de los últimos N días (todo el tiempo) | +| `--tools` | Número de herramientas para mostrar (todas) | +| `--models` | Mostrar el desglose del uso del modelo (oculto de forma predeterminada). Pase un número para mostrar la parte superior N | +| `--project` | Filtrar por proyecto (todos los proyectos, cadena vacía: proyecto actual) | + +--- + +### export + +Exportar datos de la sesión como JSON. + +```bash +opencode export [sessionID] +``` + +Si no proporciona una ID de sesión, se le pedirá que seleccione entre las sesiones disponibles. + +--- + +### import + +Importe datos de sesión desde un archivo JSON o una URL compartida OpenCode. + +```bash +opencode import +``` + +Puede importar desde un archivo local o una URL compartida OpenCode. + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +Inicie un servidor OpenCode sin cabeza con una interfaz web. + +```bash +opencode web +``` + +Esto inicia un servidor HTTP y abre un navegador web para acceder a OpenCode a través de una interfaz web. Configure `OPENCODE_SERVER_PASSWORD` para habilitar la autenticación básica HTTP (el nombre de usuario predeterminado es `opencode`). + +#### Opciones + +| Opción | Descripción | +| ------------ | ---------------------------------------------------- | +| `--port` | Puerto para escuchar | +| `--hostname` | Nombre de host para escuchar | +| `--mdns` | Habilitar el descubrimiento de mDNS | +| `--cors` | Orígenes de navegador adicionales para permitir CORS | + +--- + +### acp + +Inicie un servidor ACP (Agent Client Protocol). + +```bash +opencode acp +``` + +Este comando inicia un servidor ACP que se comunica a través de stdin/stdout usando nd-JSON. + +#### Opciones + +| Opción | Descripción | +| ------------ | ---------------------------- | +| `--cwd` | Directorio de trabajo | +| `--port` | Puerto para escuchar | +| `--hostname` | Nombre de host para escuchar | + +--- + +### uninstall + +Desinstale OpenCode y elimine todos los archivos relacionados. + +```bash +opencode uninstall +``` + +#### Opciones + +| Opción | Corta | Descripción | +| --------------- | ----- | ----------------------------------------- | +| `--keep-config` | `-c` | Mantener archivos de configuración | +| `--keep-data` | `-d` | Conservar datos de sesión e instantáneas | +| `--dry-run` | | Mostrar lo que se eliminaría sin eliminar | +| `--force` | `-f` | Saltar mensajes de confirmación | + +--- + +### upgrade + +Actualiza opencode a la última versión o a una versión específica. + +```bash +opencode upgrade [target] +``` + +Para actualizar a la última versión. + +```bash +opencode upgrade +``` + +Para actualizar a una versión específica. + +```bash +opencode upgrade v0.1.48 +``` + +#### Opciones + +| Opción | Corta | Descripción | +| ---------- | ----- | ------------------------------------------------------------------- | +| `--method` | `-m` | El método de instalación que se utilizó; curl, npm, pnpm, bun, brew | + +--- + +## Opciones globales + +La CLI de OpenCode toma las siguientes banderas globales. + +| Opción | Corta | Descripción | +| -------------- | ----- | -------------------------------------------- | +| `--help` | `-h` | Mostrar ayuda | +| `--version` | `-v` | Número de versión de impresión | +| `--print-logs` | | Imprimir registros en stderr | +| `--log-level` | | Nivel de registro (DEBUG, INFO, WARN, ERROR) | + +--- + +## Variables de entorno + +OpenCode se puede configurar mediante variables de entorno. + +| Variable | Type | Description | +| ------------------------------------- | -------- | ------------------------------------------------------------------------------- | +| `OPENCODE_AUTO_SHARE` | booleano | Compartir sesiones automáticamente | +| `OPENCODE_GIT_BASH_PATH` | cadena | Ruta al ejecutable de Git Bash en Windows | +| `OPENCODE_CONFIG` | cadena | Ruta al archivo de configuración | +| `OPENCODE_CONFIG_DIR` | cadena | Ruta al directorio de configuración | +| `OPENCODE_CONFIG_CONTENT` | cadena | Contenido de configuración json en línea | +| `OPENCODE_DISABLE_AUTOUPDATE` | booleano | Deshabilitar las comprobaciones automáticas de actualizaciones | +| `OPENCODE_DISABLE_PRUNE` | booleano | Deshabilitar la poda de datos antiguos | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | booleano | Deshabilitar las actualizaciones automáticas de títulos de terminal | +| `OPENCODE_PERMISSION` | cadena | Configuración de permisos json incorporados | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | booleano | Deshabilitar complementos predeterminados | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | booleano | Deshabilitar las descargas automáticas del servidor LSP | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | booleano | Habilitar modelos experimentales | +| `OPENCODE_DISABLE_AUTOCOMPACT` | booleano | Deshabilitar la compactación automática de contexto | +| `OPENCODE_DISABLE_CLAUDE_CODE` | booleano | Deshabilitar la lectura desde `.claude` (mensaje + habilidades) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | booleano | Desactivar lectura `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | booleano | Deshabilitar la carga `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | booleano | Deshabilitar la recuperación de modelos desde fuentes remotas | +| `OPENCODE_FAKE_VCS` | cadena | Proveedor de VCS falso para fines de prueba | +| `OPENCODE_DISABLE_FILETIME_CHECK` | booleano | Deshabilite la verificación del tiempo del archivo para optimizarlo | +| `OPENCODE_CLIENT` | cadena | Identificador de cliente (por defecto `cli`) | +| `OPENCODE_ENABLE_EXA` | booleano | Habilitar las herramientas de búsqueda web de Exa | +| `OPENCODE_SERVER_PASSWORD` | cadena | Habilite la autenticación básica para `serve`/`web` | +| `OPENCODE_SERVER_USERNAME` | cadena | Anular el nombre de usuario de autenticación básica (predeterminado `opencode`) | +| `OPENCODE_MODELS_URL` | cadena | URL personalizada para buscar la configuración de modelos | + +--- + +### Experimental + +Estas variables de entorno habilitan funciones experimentales que pueden cambiar o eliminarse. + +| Variable | Type | Description | +| ----------------------------------------------- | -------- | ---------------------------------------------------------- | +| `OPENCODE_EXPERIMENTAL` | booleano | Habilitar todas las funciones experimentales | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | booleano | Habilitar descubrimiento de íconos | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | booleano | Deshabilitar copia al seleccionar en TUI | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | número | Tiempo de espera predeterminado para comandos bash en ms | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | número | Tokens de salida máximos para respuestas LLM | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | booleano | Habilite el observador de archivos para todo el directorio | +| `OPENCODE_EXPERIMENTAL_OXFMT` | booleano | Habilitar el formateador oxfmt | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | booleano | Habilitar herramienta experimental LSP | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | booleano | Deshabilitar el observador de archivos | +| `OPENCODE_EXPERIMENTAL_EXA` | booleano | Habilitar funciones experimentales de Exa | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | booleano | Habilitar la verificación de tipo experimental LSP | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | booleano | Habilitar funciones de Markdown experimentales | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | booleano | Habilitar modo de plan | diff --git a/packages/web/src/content/docs/es/commands.mdx b/packages/web/src/content/docs/es/commands.mdx new file mode 100644 index 00000000000..68b9da1cfa4 --- /dev/null +++ b/packages/web/src/content/docs/es/commands.mdx @@ -0,0 +1,323 @@ +--- +title: Comandos +description: Cree comandos personalizados para tareas repetitivas. +--- + +Los comandos personalizados le permiten especificar un mensaje que desea ejecutar cuando ese comando se ejecuta en TUI. + +```bash frame="none" +/my-command +``` + +Los comandos personalizados se suman a los comandos integrados como `/init`, `/undo`, `/redo`, `/share`, `/help`. [Más información](/docs/tui#commands). + +--- + +## Crear archivos de comando + +Cree archivos de Markdown en el directorio `commands/` para definir comandos personalizados. + +Crear `.opencode/commands/test.md`: + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +El frontmatter define las propiedades del comando. El contenido se convierte en la plantilla. + +Utilice el comando escribiendo `/` seguido del nombre del comando. + +```bash frame="none" +"/test" +``` + +--- + +## Configuración + +Puede agregar comandos personalizados a través de la configuración OpenCode o creando archivos de Markdown en el directorio `commands/`. + +--- + +### JSON + +Utilice la opción `command` en su OpenCode [config](/docs/config): + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Ahora puedes ejecutar este comando en TUI: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +También puede definir comandos utilizando archivos de Markdown. Colócalos en: + +- Global: `~/.config/opencode/commands/` +- Por proyecto: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +El nombre del archivo de Markdown se convierte en el nombre del comando. Por ejemplo, `test.md` permite +que lo ejecutes: + +```bash frame="none" +/test +``` + +--- + +## Configuración de indicaciones + +Las indicaciones para los comandos personalizados admiten varios marcadores de posición y sintaxis especiales. + +--- + +### Argumentos + +Pase argumentos a comandos usando el marcador de posición `$ARGUMENTS`. + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +Ejecute el comando con argumentos: + +```bash frame="none" +/component Button +``` + +Y `$ARGUMENTS` será reemplazado por `Button`. + +También puede acceder a argumentos individuales utilizando parámetros posicionales: + +- `$1` - Primer argumento +- `$2` - Segundo argumento +- `$3` - Tercer argumento +- Etcétera... + +Por ejemplo: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +Ejecute el comando: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +Esto reemplaza: + +- `$1` con `config.json` +- `$2` con `src` +- `$3` con `{ "key": "value" }` + +--- + +### Salida del shell + +Utilice _!`command`_ para inyectar la salida de [comando bash](/docs/tui#bash-commands) en su mensaje. + +Por ejemplo, para crear un comando personalizado que analice la cobertura de la prueba: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +O para revisar cambios recientes: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +Los comandos se ejecutan en el directorio raíz de su proyecto y su salida pasa a formar parte del mensaje. + +--- + +### Referencias de archivos + +Incluya archivos en su comando usando `@` seguido del nombre del archivo. + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +El contenido del archivo se incluye automáticamente en el mensaje. + +--- + +## Opciones + +Veamos las opciones de configuración en detalle. + +--- + +### Plantilla + +La opción `template` define el mensaje que se enviará al LLM cuando se ejecute el comando. + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +Esta es una opción de configuración **obligatoria**. + +--- + +### Descripción + +Utilice la opción `description` para proporcionar una breve descripción de lo que hace el comando. + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +Esto se muestra como descripción en TUI cuando escribe el comando. + +--- + +### Agente + +Utilice la configuración `agent` para especificar opcionalmente qué [agente](/docs/agents) debe ejecutar este comando. +Si se trata de un [subagente](/docs/agents/#subagents), el comando activará una invocación de subagente de forma predeterminada. +Para desactivar este comportamiento, establezca `subtask` en `false`. + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +Esta es una opción de configuración **opcional**. Si no se especifica, el valor predeterminado es su agente actual. + +--- + +### Subtarea + +Utilice el booleano `subtask` para forzar que el comando active una invocación de [subagente](/docs/agents/#subagents). +Esto es útil si desea que el comando no contamine su contexto principal y **obligue** al agente a actuar como subagente. +incluso si `mode` está configurado en `primary` en la configuración de [agente](/docs/agents). + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +Esta es una opción de configuración **opcional**. + +--- + +### Modelo + +Utilice la configuración `model` para anular el modelo predeterminado para este comando. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Esta es una opción de configuración **opcional**. + +--- + +## Integrados + +opencode incluye varios comandos integrados como `/init`, `/undo`, `/redo`, `/share`, `/help`; [más información](/docs/tui#commands). + +:::note +Los comandos personalizados pueden anular los comandos integrados. +::: + +Si define un comando personalizado con el mismo nombre, anulará el comando integrado. diff --git a/packages/web/src/content/docs/es/config.mdx b/packages/web/src/content/docs/es/config.mdx new file mode 100644 index 00000000000..c6142e69901 --- /dev/null +++ b/packages/web/src/content/docs/es/config.mdx @@ -0,0 +1,685 @@ +--- +title: Configuración +description: Usando la configuración OpenCode JSON. +--- + +Puede configurar OpenCode usando un archivo de configuración JSON. + +--- + +## Formato + +OpenCode admite los formatos **JSON** y **JSONC** (JSON con comentarios). + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + // Theme configuration + "theme": "opencode", + "model": "anthropic/claude-sonnet-4-5", + "autoupdate": true, +} +``` + +--- + +## Ubicaciones + +Puedes colocar tu configuración en un par de ubicaciones diferentes y tienen un +diferente orden de precedencia. + +:::note +Los archivos de configuración se **fusionan**, no se reemplazan. +::: + +Los archivos de configuración se fusionan, no se reemplazan. Se combinan las configuraciones de las siguientes ubicaciones de configuración. Las configuraciones posteriores anulan las anteriores solo para claves en conflicto. Se conservan las configuraciones no conflictivas de todas las configuraciones. + +Por ejemplo, si su configuración global establece `theme: "opencode"` y `autoupdate: true`, y la configuración de su proyecto establece `model: "anthropic/claude-sonnet-4-5"`, la configuración final incluirá las tres configuraciones. + +--- + +### Orden de precedencia + +Las fuentes de configuración se cargan en este orden (las fuentes posteriores anulan las anteriores): + +1. **Configuración remota** (de `.well-known/opencode`): valores predeterminados de la organización +2. **Configuración global** (`~/.config/opencode/opencode.json`) - preferencias del usuario +3. **Configuración personalizada** (`OPENCODE_CONFIG` env var): anulaciones personalizadas +4. **Configuración del proyecto** (`opencode.json` en el proyecto): configuración específica del proyecto +5. Directorios **`.opencode`** - agentes, comandos, complementos +6. **Configuración en línea** (`OPENCODE_CONFIG_CONTENT` env var): anulaciones del tiempo de ejecución + +Esto significa que las configuraciones del proyecto pueden anular los valores predeterminados globales y las configuraciones globales pueden anular los valores predeterminados de la organización remota. + +:::note +Los directorios `.opencode` y `~/.config/opencode` usan **nombres en plural** para los subdirectorios: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/` y `themes/`. También se admiten nombres singulares (por ejemplo, `agent/`) para compatibilidad con versiones anteriores. +::: + +--- + +### Remoto + +Las organizaciones pueden proporcionar una configuración predeterminada a través del punto final `.well-known/opencode`. Esto se obtiene automáticamente cuando se autentica con un proveedor que lo admita. + +La configuración remota se carga primero y sirve como capa base. Todas las demás fuentes de configuración (global, proyecto) pueden anular estos valores predeterminados. + +Por ejemplo, si su organización proporciona servidores MCP que están deshabilitados de forma predeterminada: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +Puede habilitar servidores específicos en su configuración local: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### Global + +Coloque su configuración global OpenCode en `~/.config/opencode/opencode.json`. Utilice la configuración global para las preferencias de todo el usuario, como temas, proveedores o combinaciones de teclas. + +La configuración global anula los valores predeterminados de la organización remota. + +--- + +### Por proyecto + +Agregue `opencode.json` en la raíz de su proyecto. La configuración del proyecto tiene la mayor prioridad entre los archivos de configuración estándar: anula las configuraciones globales y remotas. + +:::tip +Coloque la configuración específica del proyecto en la raíz de su proyecto. +::: + +Cuando se inicia OpenCode, busca un archivo de configuración en el directorio actual o recorre hasta el directorio Git más cercano. + +Esto también es seguro para registrarlo en Git y utiliza el mismo esquema que el global. + +--- + +### Ruta personalizada + +Especifique una ruta de archivo de configuración personalizada utilizando la variable de entorno `OPENCODE_CONFIG`. + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +La configuración personalizada se carga entre las configuraciones globales y del proyecto en orden de prioridad. + +--- + +### Directorio personalizado + +Especifique un directorio de configuración personalizado usando `OPENCODE_CONFIG_DIR` +variable de entorno. En este directorio se buscarán agentes, comandos, +modos y complementos como el directorio estándar `.opencode`, y debería +Sigue la misma estructura. + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +El directorio personalizado se carga después de los directorios global config y `.opencode`, por lo que **puede anular** su configuración. + +--- + +## Esquema + +El archivo de configuración tiene un esquema definido en [**`opencode.ai/config.json`**](https://opencode.ai/config.json). + +Su editor debería poder validar y autocompletar según el esquema. + +--- + +### TUI + +Puede configurar ajustes específicos de TUI a través de la opción `tui`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +Opciones disponibles: + +- `scroll_acceleration.enabled` - Habilita la aceleración de desplazamiento estilo macOS. **Tiene prioridad sobre `scroll_speed`.** +- `scroll_speed` - Multiplicador de velocidad de desplazamiento personalizado (predeterminado: `3`, mínimo: `1`). Se ignora si `scroll_acceleration.enabled` es `true`. +- `diff_style` - Controla la representación de diferencias. `"auto"` se adapta al ancho del terminal, `"stacked"` siempre muestra una sola columna. + +[Obtenga más información sobre el uso de TUI aquí](/docs/tui). + +--- + +### Servidor + +Puede configurar los ajustes del servidor para los comandos `opencode serve` y `opencode web` a través de la opción `server`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +Opciones disponibles: + +- `port` - Puerto para escuchar. +- `hostname`: nombre de host para escuchar. Cuando `mdns` está habilitado y no se establece ningún nombre de host, el valor predeterminado es `0.0.0.0`. +- `mdns`: habilita el descubrimiento de servicios mDNS. Esto permite que otros dispositivos en la red descubran su servidor OpenCode. +- `mdnsDomain` - Nombre de dominio personalizado para el servicio mDNS. El valor predeterminado es `opencode.local`. Útil para ejecutar múltiples instancias en la misma red. +- `cors`: orígenes adicionales para permitir CORS cuando se utiliza el servidor HTTP desde un cliente basado en navegador. Los valores deben ser orígenes completos (esquema + host + puerto opcional), por ejemplo, `https://app.example.com`. + +[Obtenga más información sobre el servidor aquí](/docs/server). + +--- + +### Herramientas + +Puede administrar las herramientas que un LLM puede usar a través de la opción `tools`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[Obtenga más información sobre las herramientas aquí](/docs/tools). + +--- + +### Modelos + +Puede configurar los proveedores y modelos que desea utilizar en su configuración OpenCode a través de las opciones `provider`, `model` y `small_model`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +La opción `small_model` configura un modelo separado para tareas livianas como la generación de títulos. De forma predeterminada, OpenCode intenta utilizar un modelo más económico si su proveedor tiene uno disponible; de ​​lo contrario, recurre a su modelo principal. + +Las opciones de proveedores pueden incluir `timeout` y `setCacheKey`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout`: tiempo de espera de solicitud en milisegundos (predeterminado: 300000). Establezca en `false` para desactivar. +- `setCacheKey`: asegúrese de que siempre haya una clave de caché configurada para el proveedor designado. + +También puede configurar [modelos locales](/docs/models#local). [Más información](/docs/models). + +--- + +#### Opciones específicas del proveedor + +Algunos proveedores admiten opciones de configuración adicionales más allá de las configuraciones genéricas `timeout` y `apiKey`. + +##### Amazon Bedrock + +Amazon Bedrock admite la configuración específica de AWS: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` - AWS región para Bedrock (el valor predeterminado es `AWS_REGION` env var o `us-east-1`) +- `profile` - AWS perfil con nombre de `~/.aws/credentials` (el valor predeterminado es `AWS_PROFILE` var env) +- `endpoint`: URL de punto de enlace personalizada para puntos de enlace de VPC. Este es un alias para la opción genérica `baseURL` que utiliza terminología específica de AWS. Si se especifican ambos, `endpoint` tiene prioridad. + +:::note +Los tokens de portador (`AWS_BEARER_TOKEN_BEDROCK` o `/connect`) tienen prioridad sobre la autenticación basada en perfil. Consulte [precedencia de autenticación](/docs/providers#authentication-precedence) para obtener más detalles. +::: + +[Obtenga más información sobre la configuración de Amazon Bedrock](/docs/providers#amazon-bedrock). + +--- + +### Temas + +Puede configurar el tema que desea usar en su configuración OpenCode a través de la opción `theme`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[Más información aquí](/docs/themes). + +--- + +### Agentes + +Puedes configurar agentes especializados para tareas específicas a través de la opción `agent`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +También puede definir agentes utilizando archivos de Markdown en `~/.config/opencode/agents/` o `.opencode/agents/`. [Más información aquí](/docs/agents). + +--- + +### Agente predeterminado + +Puede configurar el agente predeterminado usando la opción `default_agent`. Esto determina qué agente se utiliza cuando no se especifica ninguno explícitamente. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +El agente predeterminado debe ser un agente principal (no un subagente). Puede ser un agente integrado como `"build"` o `"plan"`, o un [agente personalizado](/docs/agents) que haya definido. Si el agente especificado no existe o es un subagente, OpenCode recurrirá a `"build"` con una advertencia. + +Esta configuración se aplica en todas las interfaces: TUI, CLI (`opencode run`), aplicación de escritorio y GitHub Acción. + +--- + +### Compartir + +Puede configurar la función [compartir](/docs/share) a través de la opción `share`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +Esto requiere: + +- `"manual"` - Permitir compartir manualmente mediante comandos (predeterminado) +- `"auto"` - Comparte automáticamente nuevas conversaciones +- `"disabled"` - Deshabilitar el uso compartido por completo + +De forma predeterminada, el uso compartido está configurado en modo manual, donde debe compartir conversaciones explícitamente usando el comando `/share`. + +--- + +### Comandos + +Puede configurar comandos personalizados para tareas repetitivas a través de la opción `command`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +También puede definir comandos utilizando archivos de Markdown en `~/.config/opencode/commands/` o `.opencode/commands/`. [Más información aquí](/docs/commands). + +--- + +### Atajos de teclado + +Puede personalizar sus combinaciones de teclas a través de la opción `keybinds`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[Más información aquí](/docs/keybinds). + +--- + +### Actualización automática + +OpenCode descargará automáticamente cualquier actualización nueva cuando se inicie. Puede desactivar esto con la opción `autoupdate`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +Si no desea actualizaciones pero desea recibir una notificación cuando haya una nueva versión disponible, configure `autoupdate` en `"notify"`. +Tenga en cuenta que esto sólo funciona si no se instaló mediante un administrador de paquetes como Homebrew. + +--- + +### Formateadores + +Puede configurar formateadores de código a través de la opción `formatter`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[Obtenga más información sobre los formateadores aquí](/docs/formatters). + +--- + +### Permisos + +De forma predeterminada, opencode **permite todas las operaciones** sin requerir aprobación explícita. Puede cambiar esto usando la opción `permission`. + +Por ejemplo, para garantizar que las herramientas `edit` y `bash` requieran la aprobación del usuario: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[Obtenga más información sobre los permisos aquí](/docs/permissions). + +--- + +### Compactación + +Puede controlar el comportamiento de compactación del contexto a través de la opción `compaction`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto`: compacta automáticamente la sesión cuando el contexto está lleno (predeterminado: `true`). +- `prune`: elimina las salidas de herramientas antiguas para guardar tokens (predeterminado: `true`). + +--- + +### Observador + +Puede configurar patrones de ignorancia del observador de archivos a través de la opción `watcher`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +Los patrones siguen la sintaxis global. Utilice esto para excluir directorios ruidosos de la visualización de archivos. + +--- + +### Servidores MCP + +Puede configurar los servidores MCP que desee utilizar a través de la opción `mcp`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[Más información aquí](/docs/mcp-servers). + +--- + +### Complementos + +Los [complementos](/docs/plugins) amplían OpenCode con herramientas, enlaces e integraciones personalizados. + +Coloque los archivos de complemento en `.opencode/plugins/` o `~/.config/opencode/plugins/`. También puedes cargar complementos desde npm a través de la opción `plugin`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[Más información aquí](/docs/plugins). + +--- + +### Instrucciones + +Puedes configurar las instrucciones para el modelo que estás usando a través de la opción `instructions`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Esto requiere una variedad de rutas y patrones globales para archivos de instrucciones. [Más información +sobre las reglas aquí](/docs/rules). + +--- + +### Proveedores deshabilitados + +Puede deshabilitar proveedores que se cargan automáticamente a través de la opción `disabled_providers`. Esto es útil cuando desea evitar que se carguen ciertos proveedores incluso si sus credenciales están disponibles. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +El `disabled_providers` tiene prioridad sobre `enabled_providers`. +::: + +La opción `disabled_providers` acepta una variedad de ID de proveedores. Cuando un proveedor está deshabilitado: + +- No se cargará incluso si se establecen variables de entorno. +- No se cargará incluso si las teclas API están configuradas mediante el comando `/connect`. +- Los modelos del proveedor no aparecerán en la lista de selección de modelos. + +--- + +### Proveedores habilitados + +Puede especificar una lista de proveedores permitidos a través de la opción `enabled_providers`. Cuando se establece, solo se habilitarán los proveedores especificados y se ignorarán todos los demás. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +Esto es útil cuando desea restringir OpenCode para que utilice únicamente proveedores específicos en lugar de deshabilitarlos uno por uno. + +:::note +El `disabled_providers` tiene prioridad sobre `enabled_providers`. +::: + +Si un proveedor aparece tanto en `enabled_providers` como en `disabled_providers`, el `disabled_providers` tiene prioridad para la compatibilidad con versiones anteriores. + +--- + +### Experimental + +La clave `experimental` contiene opciones que se encuentran en desarrollo activo. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +Las opciones experimentales no son estables. Pueden cambiar o eliminarse sin previo aviso. +::: + +--- + +## Variables + +Puede utilizar la sustitución de variables en sus archivos de configuración para hacer referencia a variables de entorno y contenidos de archivos. + +--- + +### Variables de entorno + +Utilice `{env:VARIABLE_NAME}` para sustituir variables de entorno: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +Si la variable de entorno no está configurada, se reemplazará con una cadena vacía. + +--- + +### Archivos + +Utilice `{file:path/to/file}` para sustituir el contenido de un archivo: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +Las rutas de los archivos pueden ser: + +- Relativo al directorio del archivo de configuración +- O rutas absolutas que comienzan con `/` o `~` + +Estos son útiles para: + +- Mantener datos confidenciales como claves API en archivos separados. +- Incluye archivos de instrucciones grandes sin saturar tu configuración. +- Compartir fragmentos de configuración comunes en múltiples archivos de configuración. diff --git a/packages/web/src/content/docs/es/custom-tools.mdx b/packages/web/src/content/docs/es/custom-tools.mdx new file mode 100644 index 00000000000..76188e184e3 --- /dev/null +++ b/packages/web/src/content/docs/es/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: Herramientas personalizadas +description: Cree herramientas que LLM pueda llamar en opencode. +--- + +Las herramientas personalizadas son funciones que usted crea y que el LLM puede llamar durante las conversaciones. Trabajan junto con las [herramientas integradas](/docs/tools) de opencode como `read`, `write` y `bash`. + +--- + +## Crear una herramienta + +Las herramientas se definen como archivos **TypeScript** o **JavaScript**. Sin embargo, la definición de la herramienta puede invocar secuencias de comandos escritas en **cualquier idioma**: TypeScript o JavaScript solo se utilizan para la definición de la herramienta en sí. + +--- + +### Ubicación + +Se pueden definir: + +- Localmente colocándolos en el directorio `.opencode/tools/` de tu proyecto. +- O de forma global, colocándolos en `~/.config/opencode/tools/`. + +--- + +### Estructura + +La forma más sencilla de crear herramientas es utilizar el asistente `tool()` que proporciona seguridad de tipos y validación. + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +El **nombre de archivo** se convierte en el **nombre de la herramienta**. Lo anterior crea una herramienta `database`. + +--- + +#### Múltiples herramientas por archivo + +También puede exportar varias herramientas desde un solo archivo. Cada exportación se convierte en **una herramienta independiente** con el nombre **`_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +Esto crea dos herramientas: `math_add` y `math_multiply`. + +--- + +### Argumentos + +Puedes usar `tool.schema`, que es simplemente [Zod](https://zod.dev), para definir tipos de argumentos. + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +También puedes importar [Zod](https://zod.dev) directamente y devolver un objeto simple: + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### Contexto + +Las herramientas reciben contexto sobre la sesión actual: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +Utilice `context.directory` para el directorio de trabajo de la sesión. +Utilice `context.worktree` para la raíz del árbol de trabajo de git. + +--- + +## Ejemplos + +### Escribir una herramienta en Python + +Puede escribir sus herramientas en cualquier idioma que desee. Aquí hay un ejemplo que suma dos números usando Python. + +Primero, cree la herramienta como un script de Python: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +Luego cree la definición de herramienta que la invoca: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +Aquí estamos usando la utilidad [`Bun.$`](https://bun.com/docs/runtime/shell) para ejecutar el script Python. diff --git a/packages/web/src/content/docs/es/ecosystem.mdx b/packages/web/src/content/docs/es/ecosystem.mdx new file mode 100644 index 00000000000..b1f4bdc9a40 --- /dev/null +++ b/packages/web/src/content/docs/es/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: Ecosistema +description: Proyectos e integraciones construidas con OpenCode. +--- + +Una colección de proyectos comunitarios construidos en OpenCode. + +:::note +¿Quieres agregar tu proyecto relacionado con OpenCode a esta lista? Envíe un PR. +::: + +También puedes consultar [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) y [opencode.cafe](https://opencode.cafe), una comunidad que agrega el ecosistema y la comunidad. + +--- + +## Complementos + +| Nombre | Descripción | +| --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | Ejecute automáticamente sesiones OpenCode en entornos sandbox aislados de Daytona con git sync y vistas previas en vivo | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | Inyecte automáticamente encabezados de sesión de Helicone para agrupación de solicitudes | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | Inyecte automáticamente tipos TypeScript/Svelte en lecturas de archivos con herramientas de búsqueda | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | Utilice su suscripción ChatGPT Plus/Pro en lugar de créditos API | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | Utilice su plan Gemini existente en lugar de la facturación API | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | Utilice los modelos gratuitos de Antigravity en lugar de la facturación API | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Aislamiento de contenedores de desarrollo de múltiples ramas con clones superficiales y puertos asignados automáticamente | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Complemento Google Antigravity OAuth, compatible con la Búsqueda de Google y manejo más sólido de API | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Optimice el uso de tokens eliminando los resultados de herramientas obsoletas | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Agregue soporte de búsqueda web nativa para proveedores compatibles con el estilo basado en Google | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Permite a los agentes de IA ejecutar procesos en segundo plano en un PTY y enviarles información interactiva. | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Instrucciones para comandos de shell no interactivos: evita bloqueos de operaciones dependientes de TTY | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Seguimiento del uso de OpenCode con Wakatime | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Limpiar tablas de Markdown producidas por LLMs | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | Edición de código 10 veces más rápida con Morph Fast Apply API y marcadores de edición diferidos | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Agentes en segundo plano, herramientas LSP/AST/MCP prediseñadas, agentes seleccionados, compatible con Claude Code | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | Notificaciones de escritorio y alertas sonoras para sesiones OpenCode | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Notificaciones de escritorio y alertas sonoras para eventos de permiso, finalización y error | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | Nomenclatura automática de sesiones Zellij impulsada por IA basada en el contexto OpenCode | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Permitir que los agentes OpenCode carguen mensajes de forma diferida a pedido con descubrimiento e inyección de habilidades | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Memoria persistente entre sesiones utilizando Supermemoria | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Revisión interactiva del plan con anotaciones visuales y uso compartido privado/sin conexión | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Amplíe opencode /commands a un potente sistema de orquestación con control de flujo granular | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | Programe trabajos recurrentes usando launchd (Mac) o systemd (Linux) con sintaxis cron | +| [micode](https://github.com/vtemian/micode) | Lluvia de ideas estructurada → Planificar → Implementar flujo de trabajo con continuidad de sesión | +| [octto](https://github.com/vtemian/octto) | Interfaz de usuario interactiva del navegador para lluvia de ideas de IA con formularios de preguntas múltiples | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | Agentes en segundo plano estilo Claude Code con delegación asíncrona y persistencia de contexto | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | Notificaciones nativas del sistema operativo para OpenCode: sepa cuándo se completan las tareas | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | Arnés de orquestación multiagente incluido: 16 componentes, una instalación | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | Árboles de trabajo de Git de fricción cero para OpenCode | + +--- + +## Proyectos + +| Nombre | Descripción | +| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | +| [kimaki](https://github.com/remorses/kimaki) | Bot de Discord para controlar sesiones OpenCode, basado en el SDK | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Complemento Neovim para avisos compatibles con el editor, creado en API | +| [portal](https://github.com/hosenur/portal) | Interfaz de usuario web móvil para OpenCode a través de Tailscale/VPN | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | Plantilla para crear complementos OpenCode | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Interfaz de Neovim para opencode: un agente de codificación de IA basado en terminal | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Proveedor Vercel AI SDK para usar OpenCode a través de @opencode-ai/sdk | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | Aplicación web/de escritorio y extensión VS Code para OpenCode | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Complemento de Obsidian que incorpora OpenCode en la interfaz de usuario de Obsidian | +| [OpenWork](https://github.com/different-ai/openwork) | Una alternativa de código abierto a Claude Cowork, impulsada por OpenCode | +| [ocx](https://github.com/kdcokenny/ocx) | Administrador de extensiones OpenCode con perfiles portátiles y aislados. | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | Aplicación de escritorio, web, móvil y de cliente remoto para OpenCode | + +--- + +## Agentes + +| Nombre | Descripción | +| ----------------------------------------------------------------- | -------------------------------------------------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | Agentes y comandos modulares de IA para un desarrollo estructurado | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | Configuraciones, avisos, agentes y complementos para flujos de trabajo mejorados | diff --git a/packages/web/src/content/docs/es/enterprise.mdx b/packages/web/src/content/docs/es/enterprise.mdx new file mode 100644 index 00000000000..787ff095a17 --- /dev/null +++ b/packages/web/src/content/docs/es/enterprise.mdx @@ -0,0 +1,170 @@ +--- +title: Empresa +description: Usar OpenCode de forma segura en su organización. +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +OpenCode Enterprise es para organizaciones que desean garantizar que su código y sus datos nunca abandonen su infraestructura. Puede hacerlo mediante el uso de una configuración centralizada que se integra con su SSO y su puerta de enlace AI interna. + +:::note +OpenCode no almacena ningún código ni datos de contexto. +::: + +Para comenzar con OpenCode Enterprise: + +1. Haz una prueba interna con tu equipo. +2. **Contáctenos** para analizar los precios y las opciones de implementación. + +--- + +## Prueba + +OpenCode es de código abierto y no almacena ningún código ni datos de contexto, por lo que sus desarrolladores pueden simplemente [comenzar](/docs/) y realizar una prueba. + +--- + +### Manejo de datos + +**OpenCode no almacena su código ni datos de contexto.** Todo el procesamiento se realiza localmente o mediante llamadas directas API a su proveedor de IA. + +Esto significa que, siempre que uses un proveedor de confianza o un +AI gateway interno, puedes usar OpenCode de forma segura. + +La única advertencia aquí es la característica opcional `/share`. + +--- + +#### Compartir conversaciones + +Si un usuario habilita la función `/share`, la conversación y los datos asociados con ella se envían al servicio que utilizamos para alojar estas páginas compartidas en opencode.ai. + +Actualmente, los datos se entregan a través de la red perimetral de nuestra CDN y se almacenan en caché en el perímetro cerca de sus usuarios. + +Le recomendamos que desactive esto para su prueba. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[Más información sobre cómo compartir](/docs/share). + +--- + +### Propiedad del código + +**Eres propietario de todo el código producido por OpenCode.** No existen restricciones de licencia ni reclamaciones de propiedad. + +--- + +## Precios + +Usamos un modelo por puesto para OpenCode Enterprise. Si tiene su propia puerta de enlace LLM, no cobramos por los tokens utilizados. Para obtener más detalles sobre precios y opciones de implementación, **contáctenos**. + +--- + +## Implementación + +Una vez que haya completado su prueba y esté listo para usar OpenCode en +su organización, puede **contáctenos** para discutir +opciones de fijación de precios y de implementación. + +--- + +### Configuración central + +Podemos configurar OpenCode para usar una única configuración central para toda su organización. + +Esta configuración centralizada puede integrarse con su proveedor de SSO y garantiza que todos los usuarios accedan únicamente a su puerta de enlace de IA interna. + +--- + +### Integración SSO + +A través de la configuración central, OpenCode puede integrarse con el proveedor de SSO de su organización para la autenticación. + +Esto permite a OpenCode obtener credenciales para su puerta de enlace interna de IA a través de su sistema de gestión de identidad existente. + +--- + +### Puerta de enlace interna de IA + +Con la configuración central, OpenCode también se puede configurar para usar solo su puerta de enlace AI interna. + +También puede desactivar todos los demás proveedores de IA, asegurándose de que todas las solicitudes pasen por la infraestructura aprobada de su organización. + +--- + +### Autohospedaje + +Si bien recomendamos desactivar las páginas para compartir para garantizar que sus datos nunca abandonen +su organización, también podemos ayudarle a autohospedarlos en su infraestructura. + +Esto se encuentra actualmente en nuestra hoja de ruta. Si está interesado, **háganoslo saber**. + +--- + +## Preguntas frecuentes + +

+¿Qué es OpenCode Enterprise? + +OpenCode Enterprise es para organizaciones que desean garantizar que su código y sus datos nunca abandonen su infraestructura. Puede hacerlo mediante el uso de una configuración centralizada que se integra con su SSO y su puerta de enlace AI interna. + +
+ +
+¿Cómo empiezo con OpenCode Enterprise? + +Simplemente comience con una prueba interna con su equipo. OpenCode de forma predeterminada no almacena su código ni datos de contexto, lo que facilita el inicio. + +Luego **contáctenos** para analizar los precios y las opciones de implementación. + +
+ +
+¿Cómo funcionan los precios empresariales? + +Ofrecemos precios empresariales por asiento. Si tiene su propia puerta de enlace LLM, no cobramos por los tokens utilizados. Para obtener más detalles, **contáctenos** para obtener una cotización personalizada basada en las necesidades de su organización. + +
+ +
+¿Están mis datos seguros con OpenCode Enterprise? + +Sí. OpenCode no almacena su código ni datos de contexto. Todo el procesamiento se realiza localmente o mediante llamadas directas API a su proveedor de IA. Con la configuración central y la integración de SSO, sus datos permanecen seguros dentro de la infraestructura de su organización. + +
+ +
+¿Podemos utilizar nuestro propio registro privado de NPM? + +OpenCode admite registros privados npm a través del soporte de archivos `.npmrc` nativo de Bun. Si su organización utiliza un registro privado, como JFrog Artifactory, Nexus o similar, asegúrese de que los desarrolladores estén autenticados antes de ejecutar OpenCode. + +Para configurar la autenticación con su registro privado: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +Esto crea `~/.npmrc` con detalles de autenticación. OpenCode automáticamente +recoge esto. + +:::caution +Debe iniciar sesión en el registro privado antes de ejecutar OpenCode. +::: + +Alternativamente, puede configurar manualmente un archivo `.npmrc`: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +Los desarrolladores deben iniciar sesión en el registro privado antes de ejecutar OpenCode para garantizar que los paquetes se puedan instalar desde su registro empresarial. + +
diff --git a/packages/web/src/content/docs/es/formatters.mdx b/packages/web/src/content/docs/es/formatters.mdx new file mode 100644 index 00000000000..f09ef925270 --- /dev/null +++ b/packages/web/src/content/docs/es/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: Formateadores +description: OpenCode utiliza formateadores específicos del idioma. +--- + +OpenCode formatea automáticamente los archivos después de escribirlos o editarlos utilizando formateadores específicos del idioma. Esto garantiza que el código generado siga los estilos de código de su proyecto. + +--- + +## Integrados + +OpenCode viene con varios formateadores integrados para lenguajes y marcos populares. A continuación se muestra una lista de los formateadores, las extensiones de archivo compatibles y los comandos u opciones de configuración que necesita. + +| Formateador | Extensiones | Requisitos | +| -------------------- | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | +| gofmt | .go | Comando `gofmt` disponible | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | Comando `mix` disponible | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml y [más](https://prettier.io/docs/en/index.html) | dependencia `prettier` en `package.json` | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml y [más](https://biomejs.dev/) | `biome.json(c)` archivo de configuración | +| zig | .zig, .zon | Comando `zig` disponible | +| clang-format | .c, .cpp, .h, .hpp, .ino y [más](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` archivo de configuración | +| ktlint | .kt, .kts | Comando `ktlint` disponible | +| ruff | .py, .pyi | Comando `ruff` disponible con configuración | +| rustfmt | .rs | Comando `rustfmt` disponible | +| cargo fmt | .rs | Comando `cargo fmt` disponible | +| uv | .py, .pyi | Comando `uv` disponible | +| rubocop | .rb, .rake, .gemspec, .ru | Comando `rubocop` disponible | +| standardrb | .rb, .rake, .gemspec, .ru | Comando `standardrb` disponible | +| htmlbeautifier | .erb, .html.erb | Comando `htmlbeautifier` disponible | +| air | .R | Comando `air` disponible | +| dart | .dart | Comando `dart` disponible | +| ocamlformat | .ml, .mli | Comando `ocamlformat` disponible y archivo de configuración `.ocamlformat` | +| terraform | .tf, .tfvars | Comando `terraform` disponible | +| gleam | .gleam | Comando `gleam` disponible | +| nixfmt | .nix | Comando `nixfmt` disponible | +| shfmt | .sh, .bash | Comando `shfmt` disponible | +| pint | .php | dependencia `laravel/pint` en `composer.json` | +| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | Dependencia de `oxfmt` en `package.json` y un [indicador de variable de entorno experimental](/docs/cli/#experimental) | +| ormolu | .hs | Comando `ormolu` disponible | + +Entonces, si su proyecto tiene `prettier` en su `package.json`, OpenCode lo usará automáticamente. + +--- + +## Cómo funciona + +Cuando OpenCode escribe o edita un archivo: + +1. Comprueba la extensión del archivo con todos los formateadores habilitados. +2. Ejecuta el comando de formateo apropiado en el archivo. +3. Aplica los cambios de formato automáticamente. + +Este proceso ocurre en segundo plano, lo que garantiza que los estilos de su código se mantengan sin ningún paso manual. + +--- + +## Configuración + +Puede personalizar los formateadores a través de la sección `formatter` en su configuración OpenCode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +Cada configuración del formateador admite lo siguiente: + +| Propiedad | Tipo | Descripción | +| ------------- | -------- | --------------------------------------------------------------- | +| `disabled` | booleano | Establezca esto en `true` para deshabilitar el formateador | +| `command` | cadena[] | El comando a ejecutar para formatear | +| `environment` | objeto | Variables de entorno para configurar al ejecutar el formateador | +| `extensions` | cadena[] | Extensiones de archivo que este formateador debería manejar | + +Veamos algunos ejemplos. + +--- + +### Deshabilitar formateadores + +Para deshabilitar **todos** los formateadores globalmente, configure `formatter` en `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +Para deshabilitar un formateador **específico**, establezca `disabled` en `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### Formateadores personalizados + +Puede anular los formateadores integrados o agregar otros nuevos especificando el comando, las variables de entorno y las extensiones de archivo: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +El marcador de posición **`$FILE`** en el comando se reemplazará con la ruta al archivo que se está formateando. diff --git a/packages/web/src/content/docs/es/github.mdx b/packages/web/src/content/docs/es/github.mdx new file mode 100644 index 00000000000..57375a8d7c5 --- /dev/null +++ b/packages/web/src/content/docs/es/github.mdx @@ -0,0 +1,321 @@ +--- +title: GitHub +description: Utilice OpenCode en problemas y solicitudes de extracción de GitHub. +--- + +OpenCode se integra con su flujo de trabajo GitHub. Mencione `/opencode` o `/oc` en su comentario y OpenCode ejecutará tareas dentro de su corredor de acciones GitHub. + +--- + +## Características + +- **Clasificación de problemas**: Pídele a OpenCode que investigue un problema y te lo explique. +- **Reparar e implementar**: pídale a OpenCode que solucione un problema o implemente una función. Y funcionará en una nueva sucursal y enviará un PR con todos los cambios. +- **Seguro**: OpenCode se ejecuta dentro de los corredores de tu GitHub. + +--- + +## Instalación + +Ejecute el siguiente comando en un proyecto que se encuentra en un repositorio GitHub: + +```bash +opencode github install +``` + +Esto lo guiará a través de la instalación de la aplicación GitHub, la creación del flujo de trabajo y la configuración de secretos. + +--- + +### Configuración manual + +O puede configurarlo manualmente. + +1. **Instale la aplicación GitHub** + + Dirígete a [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). Asegúrese de que esté instalado en el repositorio de destino. + +2. **Agregar el flujo de trabajo** + + Agregue el siguiente archivo de flujo de trabajo a `.github/workflows/opencode.yml` en su repositorio. Asegúrese de configurar las claves `model` apropiadas y API requeridas en `env`. + + ```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx + ``` + +3. **Guarda las claves API en secretos** + + En la **configuración** de tu organización o proyecto, expande **Secretos y variables** a la izquierda y selecciona **Acciones**. Y agregue las claves API requeridas. + +--- + +## Configuración + +- `model`: El modelo a usar con OpenCode. Toma el formato de `provider/model`. Esto es **obligatorio**. +- `agent`: El agente a utilizar. Debe ser un agente primario. Vuelve a `default_agent` desde la configuración o `"build"` si no se encuentra. +- `share`: si se comparte la sesión OpenCode. El valor predeterminado es **verdadero** para repositorios públicos. +- `prompt`: mensaje personalizado opcional para anular el comportamiento predeterminado. Utilice esto para personalizar cómo OpenCode procesa las solicitudes. +- `token`: token de acceso GitHub opcional para realizar operaciones como crear comentarios, confirmar cambios y abrir solicitudes de extracción. De forma predeterminada, OpenCode usa el token de acceso a la instalación de la aplicación OpenCode GitHub, por lo que las confirmaciones, los comentarios y las solicitudes de extracción aparecen como provenientes de la aplicación. + + Alternativamente, puede usar el GitHub Action Runner [`GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) incorporado sin instalar la aplicación OpenCode GitHub. Solo asegúrese de otorgar los permisos necesarios en su flujo de trabajo: + + ```yaml + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + ``` + + También puede utilizar [tokens de acceso personal](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) si lo prefiere. + +--- + +## Eventos admitidos + +OpenCode puede desencadenarse por los siguientes eventos GitHub: + +| Tipo de evento | Activado por | Detalles | +| ----------------------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | +| `issue_comment` | Comentar sobre un tema o PR | Mencione `/opencode` o `/oc` en su comentario. OpenCode lee el contexto y puede crear ramas, abrir relaciones públicas o responder. | +| `pull_request_review_comment` | Comente líneas de código específicas en un PR | Mencione `/opencode` o `/oc` mientras revisa el código. OpenCode recibe la ruta del archivo, los números de línea y el contexto de diferencias. | +| `issues` | Número abierto o editado | Activa automáticamente OpenCode cuando se crean o modifican problemas. Requiere entrada `prompt`. | +| `pull_request` | PR abierto o actualizado | Activa automáticamente OpenCode cuando los PR se abren, sincronizan o vuelven a abrir. Útil para revisiones automatizadas. | +| `schedule` | Programación basada en cron | Ejecute OpenCode según una programación. Requiere entrada `prompt`. La salida va a registros y relaciones públicas (no hay temas que comentar). | +| `workflow_dispatch` | Activador manual desde GitHub UI | Active OpenCode a pedido a través de la pestaña Acciones. Requiere entrada `prompt`. La salida va a registros y relaciones públicas. | + +### Ejemplo de programación + +Ejecute OpenCode según una programación para realizar tareas automatizadas: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +Para eventos programados, la entrada `prompt` es **obligatoria** ya que no hay comentarios del que extraer instrucciones. Los flujos de trabajo programados se ejecutan sin un contexto de usuario para verificar los permisos, por lo que el flujo de trabajo debe otorgar `contents: write` y `pull-requests: write` si espera que OpenCode cree ramas o PR. + +--- + +### Ejemplo de solicitud de extracción + +Revisar automáticamente los PR cuando se abren o actualizan: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Para los eventos `pull_request`, si no se proporciona `prompt`, OpenCode revisa de forma predeterminada la solicitud de extracción. + +--- + +### Ejemplo de clasificación de problemas + +Clasifique automáticamente nuevos problemas. Este ejemplo filtra cuentas con más de 30 días para reducir el spam: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +Para eventos `issues`, la entrada `prompt` es **obligatoria** ya que no hay ningún comentario del que extraer instrucciones. + +--- + +## Indicaciones personalizadas + +Anule el mensaje predeterminado para personalizar el comportamiento de OpenCode para su flujo de trabajo. + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Esto es útil para hacer cumplir criterios de revisión específicos, estándares de codificación o áreas de enfoque relevantes para su proyecto. + +--- + +## Ejemplos + +A continuación se muestran algunos ejemplos de cómo puede utilizar OpenCode en GitHub. + +- **Explica un problema** + + Agregue este comentario en una edición GitHub. + + ``` + /opencode explain this issue + ``` + + OpenCode leerá el hilo completo, incluidos todos los comentarios, y responderá con una explicación clara. + +- **Solucionar un problema** + + En un problema GitHub, diga: + + ``` + /opencode fix this + ``` + + Y OpenCode creará una nueva rama, implementará los cambios y abrirá un PR con los cambios. + +- **Revisar relaciones públicas y realizar cambios** + + Deja el siguiente comentario en un GitHub PR. + + ``` + Delete the attachment from S3 when the note is removed /oc + ``` + + OpenCode implementará el cambio solicitado y lo comprometerá con el mismo PR. + +- **Revisar líneas de código específicas** + + Deje un comentario directamente en las líneas de código en la pestaña "Archivos" del PR. OpenCode detecta automáticamente el archivo, los números de línea y el contexto de diferencias para proporcionar respuestas precisas. + + ``` + [Comment on specific lines in Files tab] + /oc add error handling here + ``` + + Al comentar líneas específicas, OpenCode recibe: + - El archivo exacto que se está revisando. + - Las líneas de código específicas. + - El contexto diferencial circundante. + - Información del número de línea + + Esto permite solicitudes más específicas sin necesidad de especificar rutas de archivo o números de línea manualmente. diff --git a/packages/web/src/content/docs/es/gitlab.mdx b/packages/web/src/content/docs/es/gitlab.mdx new file mode 100644 index 00000000000..a8e4baa9091 --- /dev/null +++ b/packages/web/src/content/docs/es/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: Utilice OpenCode en problemas GitLab y solicitudes de fusión. +--- + +OpenCode se integra con su flujo de trabajo GitLab a través de su canal de CI/CD GitLab o con GitLab Duo. + +En ambos casos, OpenCode se ejecutará en tus corredores GitLab. + +--- + +## GitLab CI + +OpenCode funciona en una tubería GitLab normal. Puede integrarlo en una canalización como un [componente de CI](https://docs.gitlab.com/ee/ci/components/) + +Aquí estamos utilizando un componente CI/CD creado por la comunidad para OpenCode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### Características + +- **Usar configuración personalizada por trabajo**: configure OpenCode con un directorio de configuración personalizado, por ejemplo `./config/#custom-directory` para habilitar o deshabilitar la funcionalidad por invocación de OpenCode. +- **Configuración mínima**: el componente CI configura OpenCode en segundo plano, solo necesita crear la configuración OpenCode y el mensaje inicial. +- **Flexible**: el componente CI admite varias entradas para personalizar su comportamiento + +--- + +### Configuración + +1. Guarde su OpenCode autenticación JSON como variables de entorno de CI de tipo de archivo en **Configuración** > **CI/CD** > **Variables**. Asegúrate de marcarlos como "Enmascarados y ocultos". +2. Agregue lo siguiente a su archivo `.gitlab-ci.yml`. + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +Para obtener más entradas y casos de uso, [consulte los documentos](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) de este componente. + +--- + +## GitLab Duo + +OpenCode se integra con su flujo de trabajo GitLab. +Mencione `@opencode` en un comentario y OpenCode ejecutará tareas dentro de su canal de CI GitLab. + +--- + +### Características + +- **Clasificación de problemas**: Pídele a OpenCode que investigue un problema y te lo explique. +- **Reparar e implementar**: pídale a OpenCode que solucione un problema o implemente una función. + Creará una nueva rama y generará una solicitud de fusión con los cambios. +- **Seguro**: OpenCode se ejecuta en tus corredores GitLab. + +--- + +### Configuración + +OpenCode se ejecuta en su canalización de CI/CD GitLab. Esto es lo que necesitará para configurarlo: + +:::tip +Consulte los [**GitLab documentos**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) para obtener instrucciones actualizadas. +::: + +1. Configure su entorno GitLab +2. Configurar CI/CD +3. Obtenga una clave API de proveedor de modelo de IA +4. Crea una cuenta de servicio +5. Configurar variables CI/CD +6. Cree un archivo de configuración de flujo, aquí hay un ejemplo: + +
+ + Configuración de flujo + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +Puede consultar los [GitLab CLI documentos de los agentes](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) para obtener instrucciones detalladas. + +--- + +### Ejemplos + +A continuación se muestran algunos ejemplos de cómo puede utilizar OpenCode en GitLab. + +:::tip +Puede configurarlo para utilizar una frase de activación diferente a `@opencode`. +::: + +- **Explica un problema** + + Agregue este comentario en una edición GitLab. + + ``` + @opencode explain this issue + ``` + + OpenCode leerá el problema y responderá con una explicación clara. + +- **Solucionar un problema** + + En un problema GitLab, diga: + + ``` + @opencode fix this + ``` + + OpenCode creará una nueva rama, implementará los cambios y abrirá una solicitud de fusión con los cambios. + +- **Revisar solicitudes de fusión** + + Deje el siguiente comentario sobre una solicitud de fusión GitLab. + + ``` + @opencode review this merge request + ``` + + OpenCode revisará la solicitud de fusión y brindará comentarios. diff --git a/packages/web/src/content/docs/es/ide.mdx b/packages/web/src/content/docs/es/ide.mdx new file mode 100644 index 00000000000..ba40f77ef08 --- /dev/null +++ b/packages/web/src/content/docs/es/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: La extensión OpenCode para VS Code, Cursor y otros IDE +--- + +OpenCode se integra con VS Code, Cursor o cualquier IDE que admita un terminal. Simplemente ejecute `opencode` en la terminal para comenzar. + +--- + +## Uso + +- **Inicio rápido**: use `Cmd+Esc` (Mac) o `Ctrl+Esc` (Windows/Linux) para abrir OpenCode en una vista de terminal dividida, o enfoque una sesión de terminal existente si ya se está ejecutando una. +- **Nueva sesión**: use `Cmd+Shift+Esc` (Mac) o `Ctrl+Shift+Esc` (Windows/Linux) para iniciar una nueva sesión de terminal OpenCode, incluso si ya hay una abierta. También puede hacer clic en el botón OpenCode en la interfaz de usuario. +- **Conciencia del contexto**: comparte automáticamente tu selección o pestaña actual con OpenCode. +- **Atajos de referencia de archivos**: utilice `Cmd+Option+K` (Mac) o `Alt+Ctrl+K` (Linux/Windows) para insertar referencias de archivos. Por ejemplo, `@File#L37-42`. + +--- + +## Instalación + +Para instalar OpenCode en VS Code y bifurcaciones populares como Cursor, Windsurf, VSCodium: + +1. Abra VS Code +2. Abra el terminal integrado +3. Ejecute `opencode`: la extensión se instala automáticamente + +Si, por otro lado, desea utilizar su propio IDE cuando ejecuta `/editor` o `/export` desde TUI, deberá configurar `export EDITOR="code --wait"`. [Más información](/docs/tui/#editor-setup). + +--- + +### Instalación manual + +Busque **OpenCode** en Extension Marketplace y haga clic en **Instalar**. + +--- + +### Solución de problemas + +Si la extensión no se instala automáticamente: + +- Asegúrese de estar ejecutando `opencode` en el terminal integrado. +- Confirme que el CLI para su IDE esté instalado: + - Para VS Code: comando `code` + - Para cursor: comando `cursor` + - Para Windsurf: comando `windsurf` + - Para VSCodium: comando `codium` + - Si no, ejecute `Cmd+Shift+P` (Mac) o `Ctrl+Shift+P` (Windows/Linux) y busque "Shell Command: Install 'code' command in PATH" (o el equivalente para su IDE) +- Asegúrese de que VS Code tenga permiso para instalar extensiones. diff --git a/packages/web/src/content/docs/es/index.mdx b/packages/web/src/content/docs/es/index.mdx new file mode 100644 index 00000000000..fa8c40c7ff7 --- /dev/null +++ b/packages/web/src/content/docs/es/index.mdx @@ -0,0 +1,358 @@ +--- +title: Introducción +description: Comience con OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**OpenCode**](/) es un agente de codificación de IA de código abierto. Está disponible como interfaz basada en terminal, aplicación de escritorio o extensión IDE. + +![OpenCode TUI con el tema opencode](../../../assets/lander/screenshot.png) + +Empecemos. + +--- + +#### Requisitos previos + +Para usar OpenCode en su terminal, necesitará: + +1. Un emulador de terminal moderno como: + - [WezTerm](https://wezterm.org), multiplataforma + - [Alacritty](https://alacritty.org), multiplataforma + - [Ghostty](https://ghostty.org), Linux y macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux y macOS + +2. Claves API para los LLM proveedores que desea utilizar. + +--- + +## Instalar + +La forma más sencilla de instalar OpenCode es mediante el script de instalación. + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +También puedes instalarlo con los siguientes comandos: + +- **Usando Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **Usando Homebrew en macOS y Linux** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > Recomendamos utilizar el tap OpenCode para las versiones más actualizadas. La fórmula oficial `brew install opencode` la mantiene el equipo Homebrew y se actualiza con menos frecuencia. + +- **Usando Paru en Arch Linux** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[Recomendado: Usar WSL] +Para obtener la mejor experiencia en Windows, recomendamos utilizar [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Proporciona un mejor rendimiento y compatibilidad total con las funciones de OpenCode. +::: + +- **Usando Chocolatey** + + ```bash + choco install opencode + ``` + +- **Usando Scoop** + + ```bash + scoop install opencode + ``` + +- **Usando NPM** + + ```bash + npm install -g opencode-ai + ``` + +- **Usando Mise** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **Usando Docker** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +Actualmente se encuentra en progreso el soporte para instalar OpenCode en Windows usando Bun. + +También puede obtener el binario de [Versiones](https://github.com/anomalyco/opencode/releases). + +--- + +## Configuración + +Con OpenCode puedes usar cualquier proveedor LLM configurando sus claves API. + +Si es nuevo en el uso de proveedores LLM, le recomendamos usar [OpenCode Zen](/docs/zen). +Es una lista seleccionada de modelos que han sido probados y verificados por el equipo de OpenCode. + +1. Ejecute el comando `/connect` en TUI, seleccione opencode y diríjase a [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. Inicie sesión, agregue sus datos de facturación y copie su clave API. + +3. Pega tu clave API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +Alternativamente, puede seleccionar uno de los otros proveedores. [Más información](/docs/providers#directory). + +--- + +## Inicializar + +Ahora que ha configurado un proveedor, puede navegar a un proyecto que +quieres trabajar. + +```bash +cd /path/to/project +``` + +Y ejecute OpenCode. + +```bash +opencode +``` + +A continuación, inicialice OpenCode para el proyecto ejecutando el siguiente comando. + +```bash frame="none" +/init +``` + +Esto hará que OpenCode analice su proyecto y cree un archivo `AGENTS.md` en +la raíz del proyecto. + +:::tip +Debes enviar el archivo `AGENTS.md` de tu proyecto a Git. +::: + +Esto ayuda a OpenCode a comprender la estructura del proyecto y los patrones de codificación. +usado. + +--- + +## Usar + +Ahora está listo para usar OpenCode para trabajar en su proyecto. No dudes en preguntarle +¡cualquier cosa! + +Si es nuevo en el uso de un agente de codificación de IA, aquí hay algunos ejemplos que podrían +ayuda. + +--- + +### Hacer preguntas + +Puede pedirle a OpenCode que le explique el código base. + +:::tip +Utilice la tecla `@` para realizar una búsqueda aproximada de archivos en el proyecto. +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +Esto es útil si hay una parte del código base en la que no trabajaste. + +--- + +### Agregar funciones + +Puede pedirle a OpenCode que agregue nuevas funciones a su proyecto. Aunque primero recomendamos pedirle que cree un plan. + +1. **Crea un plan** + + OpenCode tiene un _Modo Plan_ que desactiva su capacidad para realizar cambios y + en su lugar, sugiera _cómo_ implementará la función. + + Cambie a él usando la tecla **Tab**. Verás un indicador para esto en la esquina inferior derecha. + + ```bash frame="none" title="Switch to Plan mode" + + ``` + + Ahora describamos lo que queremos que haga. + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + Quiere darle a OpenCode suficientes detalles para entender lo que quiere. ayuda + hablar con él como si estuviera hablando con un desarrollador junior de su equipo. + + :::tip + Dale a OpenCode mucho contexto y ejemplos para ayudarlo a comprender lo que + desear. + ::: + +2. **Repetir el plan** + + Una vez que le proporcione un plan, puede enviarle comentarios o agregar más detalles. + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + + :::tip + Arrastre y suelte imágenes en la terminal para agregarlas al mensaje. + ::: + + OpenCode puede escanear cualquier imagen que le proporcione y agregarla al mensaje. Puede + Haga esto arrastrando y soltando una imagen en la terminal. + +3. **Crea la función** + + Una vez que se sienta cómodo con el plan, vuelva al _Modo Build_ + presionando la tecla **Tab** nuevamente. + + ```bash frame="none" + + ``` + + Y pidiéndole que haga los cambios. + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### Realizar cambios + +Para cambios más sencillos, puede pedirle a OpenCode que lo construya directamente. +sin tener que revisar el plan primero. + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +Desea asegurarse de proporcionar una buena cantidad de detalles para que OpenCode tome la decisión correcta. +cambios. + +--- + +### Deshacer cambios + +Digamos que le pides a OpenCode que haga algunos cambios. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Pero te das cuenta de que no es lo que querías. Puedes **deshacer** los cambios +usando el comando `/undo`. + +```bash frame="none" +/undo +``` + +OpenCode ahora revertirá los cambios que realizó y mostrará su mensaje original +de nuevo. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Desde aquí puedes modificar el mensaje y pedirle a OpenCode que vuelva a intentarlo. + +:::tip +Puede ejecutar `/undo` varias veces para deshacer varios cambios. +::: + +O **puedes rehacer** los cambios usando el comando `/redo`. + +```bash frame="none" +/redo +``` + +--- + +## Compartir + +Las conversaciones que tengas con OpenCode pueden ser [compartidas con tu +equipo](/docs/share). + +```bash frame="none" +/share +``` + +Esto creará un enlace a la conversación actual y lo copiará en su portapapeles. + +:::note +Las conversaciones no se comparten de forma predeterminada. +::: + +Aquí hay una [conversación de ejemplo](https://opencode.ai/s/4XP1fce5) con OpenCode. + +--- + +## Personalizar + +¡Y eso es todo! Ahora eres un profesional en el uso de OpenCode. + +Para personalizarlo, recomendamos [elegir un tema](/docs/themes), [personalizar las combinaciones de teclas](/docs/keybinds), [configurar formateadores de código](/docs/formatters), [crear comandos personalizados](/docs/commands) o jugar con la [configuración OpenCode](/docs/config). diff --git a/packages/web/src/content/docs/es/keybinds.mdx b/packages/web/src/content/docs/es/keybinds.mdx new file mode 100644 index 00000000000..7ce014f0a22 --- /dev/null +++ b/packages/web/src/content/docs/es/keybinds.mdx @@ -0,0 +1,192 @@ +--- +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. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## Tecla líder + +OpenCode usa una tecla `leader` para la mayoría de las combinaciones de teclas. Esto evita conflictos en tu terminal. + +De forma predeterminada, `ctrl+x` es la tecla principal y la mayoría de las acciones requieren que primero presione la tecla principal y luego el acceso directo. Por ejemplo, para iniciar una nueva sesión, primero presione `ctrl+x` y luego presione `n`. + +No es necesario utilizar una tecla líder para las combinaciones de teclas, pero le recomendamos que lo haga. + +--- + +## Desactivar combinación de teclas + +Puede deshabilitar una combinación de teclas agregando la clave a su configuración con un valor de "ninguno". + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## Atajos de mensajes de escritorio + +La entrada de solicitud de la aplicación de escritorio OpenCode admite atajos comunes de estilo Readline/Emacs para editar texto. Estos están integrados y actualmente no se pueden configurar a través de `opencode.json`. + +| Atajo | Acción | +| -------- | -------------------------------------------------------------- | +| `ctrl+a` | Mover al inicio de la línea actual | +| `ctrl+e` | Mover al final de la línea actual | +| `ctrl+b` | Mover el cursor hacia atrás un carácter | +| `ctrl+f` | Mover el cursor hacia adelante un carácter | +| `alt+b` | Mover el cursor hacia atrás una palabra | +| `alt+f` | Mover el cursor hacia adelante una palabra | +| `ctrl+d` | Eliminar carácter debajo del cursor | +| `ctrl+k` | Borrar hasta el final de la línea | +| `ctrl+u` | Borrar al inicio de la línea | +| `ctrl+w` | Borrar palabra anterior | +| `alt+d` | Borrar la siguiente palabra | +| `ctrl+t` | Transponer caracteres | +| `ctrl+g` | Cancelar ventanas emergentes/abortar la respuesta en ejecución | + +--- + +## Mayús+Entrar + +Algunos terminales no envían teclas modificadoras con Enter de forma predeterminada. Es posible que necesite configurar su terminal para enviar `Shift+Enter` como secuencia de escape. + +### Windows Terminal + +Abra su `settings.json` en: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +Agregue esto a la matriz `actions` de nivel raíz: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Agregue esto a la matriz `keybindings` de nivel raíz: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Guarde el archivo y reinicie Windows Terminal o abra una nueva pestaña. diff --git a/packages/web/src/content/docs/es/lsp.mdx b/packages/web/src/content/docs/es/lsp.mdx new file mode 100644 index 00000000000..fc741ca898f --- /dev/null +++ b/packages/web/src/content/docs/es/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: Servidores LSP +description: OpenCode se integra con sus servidores LSP. +--- + +OpenCode se integra con su protocolo de servidor de idiomas (LSP) para ayudar a LLM a interactuar con su código base. Utiliza diagnósticos para proporcionar retroalimentación al LLM. + +--- + +## Incorporados + +OpenCode viene con varios servidores LSP integrados para idiomas populares: + +| Servidor LSP | Extensiones | Requisitos | +| ------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| astro | .astro | Autoinstalaciones para proyectos Astro | +| bash | .sh, .bash, .zsh, .ksh | Autoinstala el servidor en lenguaje bash | +| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | Instalaciones automáticas para proyectos C/C++ | +| csharp | .cs | `.NET SDK` instalado | +| clojure-lsp | .clj, .cljs, .cljc, .edn | Comando `clojure-lsp` disponible | +| dart | .dart | Comando `dart` disponible | +| deno | .ts, .tsx, .js, .jsx, .mjs | Comando `deno` disponible (detecta automáticamente deno.json/deno.jsonc) | +| elixir-ls | .ex, .exs | Comando `elixir` disponible | +| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | `eslint` dependencia en proyecto | +| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` instalado | +| gleam | .gleam | Comando `gleam` disponible | +| gopls | .go | Comando `go` disponible | +| hls | .hs, .lhs | Comando `haskell-language-server-wrapper` disponible | +| jdtls | .java | `Java SDK (version 21+)` instalado | +| kotlin-ls | .kt, .kts | Autoinstalaciones para proyectos Kotlin | +| lua-ls | .lua | Autoinstalaciones para proyectos Lua | +| nixd | .nix | Comando `nixd` disponible | +| ocaml-lsp | .ml, .mli | Comando `ocamllsp` disponible | +| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | `oxlint` dependencia en proyecto | +| php intelephense | .php | Autoinstalaciones para proyectos PHP | +| prisma | .prisma | Comando `prisma` disponible | +| pyright | .py, .pyi | Dependencia `pyright` instalada | +| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | Comandos `ruby` y `gem` disponibles | +| rust | .rs | Comando `rust-analyzer` disponible | +| sourcekit-lsp | .swift, .objc, .objcpp | `swift` instalado (`xcode` en macOS) | +| svelte | .svelte | Autoinstalaciones para proyectos Svelte | +| terraform | .tf, .tfvars | Instalaciones automáticas desde versiones GitHub | +| tinymist | .typ, .typc | Instalaciones automáticas desde versiones GitHub | +| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` dependencia en proyecto | +| vue | .vue | Autoinstalaciones para proyectos Vue | +| yaml-ls | .yaml, .yml | Autoinstala Red Hat yaml-language-server | +| zls | .zig, .zon | Comando `zig` disponible | + +Los servidores LSP se habilitan automáticamente cuando se detecta una de las extensiones de archivo anteriores y se cumplen los requisitos. + +:::note +Puede deshabilitar las descargas automáticas del servidor LSP configurando la variable de entorno `OPENCODE_DISABLE_LSP_DOWNLOAD` en `true`. +::: + +--- + +## Cómo funciona + +Cuando opencode abre un archivo: + +1. Comprueba la extensión del archivo con todos los servidores LSP habilitados. +2. Inicia el servidor LSP apropiado si aún no se está ejecutando. + +--- + +## Configuración + +Puede personalizar los servidores LSP a través de la sección `lsp` en su configuración opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +Cada servidor LSP admite lo siguiente: + +| Propiedad | Tipo | Descripción | +| ---------------- | -------- | ------------------------------------------------------------ | +| `disabled` | booleano | Establezca esto en `true` para deshabilitar el servidor LSP | +| `command` | cadena[] | El comando para iniciar el servidor LSP | +| `extensions` | cadena[] | Extensiones de archivo que este servidor LSP debería manejar | +| `env` | objeto | Variables de entorno para configurar al iniciar el servidor | +| `initialization` | objeto | Opciones de inicialización para enviar al servidor LSP | + +Veamos algunos ejemplos. + +--- + +### Variables de entorno + +Utilice la propiedad `env` para establecer variables de entorno al iniciar el servidor LSP: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### Opciones de inicialización + +Utilice la propiedad `initialization` para pasar opciones de inicialización al servidor LSP. Estas son configuraciones específicas del servidor enviadas durante la solicitud LSP `initialize`: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +Las opciones de inicialización varían según el servidor LSP. Consulte la documentación de su servidor LSP para conocer las opciones disponibles. +::: + +--- + +### Deshabilitar servidores LSP + +Para deshabilitar **todos** los servidores LSP globalmente, configure `lsp` en `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +Para deshabilitar un servidor LSP **específico**, configure `disabled` en `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### Servidores LSP personalizados + +Puede agregar servidores LSP personalizados especificando el comando y las extensiones de archivo: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## Información adicional + +### PHP Intelephense + +PHP Intelephense ofrece funciones premium a través de una clave de licencia. Puede proporcionar una clave de licencia colocando (únicamente) la clave en un archivo de texto en: + +- En macOS/Linux: `$HOME/intelephense/license.txt` +- En Windows: `%USERPROFILE%/intelephense/license.txt` + +El archivo debe contener sólo la clave de licencia sin contenido adicional. diff --git a/packages/web/src/content/docs/es/mcp-servers.mdx b/packages/web/src/content/docs/es/mcp-servers.mdx new file mode 100644 index 00000000000..3b1cabac391 --- /dev/null +++ b/packages/web/src/content/docs/es/mcp-servers.mdx @@ -0,0 +1,511 @@ +--- +title: MCP servidores +description: Agregue herramientas MCP locales y remotas. +--- + +Puede agregar herramientas externas a OpenCode utilizando el _Model Context Protocol_ o MCP. OpenCode admite servidores locales y remotos. + +Una vez agregadas, las herramientas MCP están disponibles automáticamente para LLM junto con las herramientas integradas. + +--- + +#### Advertencias + +Cuando utiliza un servidor MCP, se suma al contexto. Esto puede acumularse rápidamente si tiene muchas herramientas. Por lo que recomendamos tener cuidado con qué servidores MCP utiliza. + +:::tip +Los servidores MCP se agregan a su contexto, por lo que debe tener cuidado con cuáles habilita. +::: + +Ciertos servidores MCP, como el servidor GitHub MCP, tienden a agregar muchos tokens y pueden exceder fácilmente el límite de contexto. + +--- + +## Habilitar + +Puede definir servidores MCP en su [OpenCode Config](https://opencode.ai/docs/config/) en `mcp`. Agregue cada MCP con un nombre único. Puede referirse a ese MCP por su nombre cuando solicite el LLM. + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +También puede desactivar un servidor configurando `enabled` en `false`. Esto es útil si desea desactivar temporalmente un servidor sin eliminarlo de su configuración. + +--- + +### Anulación de los valores predeterminados remotos + +Las organizaciones pueden proporcionar servidores MCP predeterminados a través de su punto final `.well-known/opencode`. Estos servidores pueden estar deshabilitados de forma predeterminada, lo que permite a los usuarios optar por los que necesitan. + +Para habilitar un servidor específico desde la configuración remota de su organización, agréguelo a su configuración local con `enabled: true`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +Los valores de configuración local anulan los valores predeterminados remotos. Consulte [precedencia de configuración](/docs/config#precedence-order) para obtener más detalles. + +--- + +## Locales + +Agregue servidores MCP locales usando `type` a `"local"` dentro del objeto 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", + }, + }, + }, +} +``` + +El comando es cómo se inicia el servidor MCP local. También puede pasar una lista de variables de entorno. + +Por ejemplo, así es como puede agregar el servidor de prueba [`@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"], + }, + }, +} +``` + +Y para usarlo puedo agregar `use the mcp_everything tool` a mis indicaciones. + +```txt "mcp_everything" +use the mcp_everything tool to add the number 3 and 4 +``` + +--- + +#### Opciones + +Aquí están todas las opciones para configurar un servidor MCP local. + +| Opción | Tipo | Requerido | Descripción | +| ------------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------ | +| `type` | Cadena | Y | El tipo de conexión del servidor MCP debe ser `"local"`. | +| `command` | Matriz | Y | Comando y argumentos para ejecutar el servidor MCP. | +| `environment` | Objeto | | Variables de entorno para configurar al ejecutar el servidor. | +| `enabled` | booleano | | Habilite o deshabilite el servidor MCP al inicio. | +| `timeout` | Número | | Tiempo de espera en ms para recuperar herramientas del servidor MCP. El valor predeterminado es 5000 (5 segundos). | + +--- + +## Remoto + +Agregue servidores MCP remotos configurando `type` en `"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" + } + } + } +} +``` + +`url` es la URL del servidor MCP remoto y con la opción `headers` puede pasar una lista de encabezados. + +--- + +#### Opciones + +| Opción | Tipo | Requerido | Descripción | +| --------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------ | +| `type` | Cadena | Y | El tipo de conexión del servidor MCP debe ser `"remote"`. | +| `url` | Cadena | Y | URL del servidor MCP remoto. | +| `enabled` | booleano | | Habilite o deshabilite el servidor MCP al inicio. | +| `headers` | Objeto | | Encabezados para enviar con la solicitud. | +| `oauth` | Objeto | | OAuth configuración de autenticación. Consulte la sección [OAuth](#oauth) a continuación. | +| `timeout` | Número | | Tiempo de espera en ms para recuperar herramientas del servidor MCP. El valor predeterminado es 5000 (5 segundos). | + +--- + +## OAuth + +OpenCode maneja automáticamente la autenticación OAuth para servidores MCP remotos. Cuando un servidor requiere autenticación, OpenCode: + +1. Detectar la respuesta 401 e iniciar el flujo OAuth +2. Utilice **Registro dinámico de cliente (RFC 7591)** si el servidor lo admite. +3. Almacene tokens de forma segura para futuras solicitudes + +--- + +### Automático + +Para la mayoría de los servidores MCP habilitados para OAuth, no se necesita ninguna configuración especial. Simplemente configure el servidor remoto: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "my-oauth-server": { + "type": "remote", + "url": "https://mcp.example.com/mcp" + } + } +} +``` + +Si el servidor requiere autenticación, OpenCode le pedirá que se autentique cuando intente usarlo por primera vez. De lo contrario, puede [activar manualmente el flujo](#authenticating) con `opencode mcp auth `. + +--- + +### Preinscrito + +Si tiene credenciales de cliente del proveedor del servidor MCP, puede configurarlas: + +```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" + } + } + } +} +``` + +--- + +### Autenticación + +Puede activar manualmente la autenticación o administrar las credenciales. + +Autenticar con un servidor MCP específico: + +```bash +opencode mcp auth my-oauth-server +``` + +Enumere todos los servidores MCP y su estado de autenticación: + +```bash +opencode mcp list +``` + +Eliminar las credenciales almacenadas: + +```bash +opencode mcp logout my-oauth-server +``` + +El comando `mcp auth` abrirá su navegador para obtener autorización. Después de su autorización, OpenCode almacenará los tokens de forma segura en `~/.local/share/opencode/mcp-auth.json`. + +--- + +#### Deshabilitando OAuth + +Si desea deshabilitar el OAuth automático para un servidor (por ejemplo, para servidores que usan claves API), configure `oauth` en `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}" + } + } + } +} +``` + +--- + +#### Opciones de OAuth + +| Opción | Tipo | Descripción | +| -------------- | --------------- | -------------------------------------------------------------------------------------------- | +| `oauth` | Objeto \| falso | OAuth objeto de configuración, o `false` para deshabilitar la detección automática de OAuth. | +| `clientId` | Cadena | OAuth ID de cliente. Si no se proporciona, se intentará el registro dinámico del cliente. | +| `clientSecret` | Cadena | OAuth secreto del cliente, si lo requiere el servidor de autorización. | +| `scope` | Cadena | OAuth alcances para solicitar durante la autorización. | + +#### Depuración + +Si un servidor MCP remoto no puede autenticarse, puede diagnosticar problemas con: + +```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 +``` + +El comando `mcp debug` muestra el estado de autenticación actual, prueba la conectividad HTTP e intenta el flujo de descubrimiento OAuth. + +--- + +## Administrar + +Sus MCP están disponibles como herramientas en OpenCode, junto con herramientas integradas. Para que puedas administrarlos a través de la configuración OpenCode como cualquier otra herramienta. + +--- + +### Global + +Esto significa que puede habilitarlos o deshabilitarlos globalmente. + +```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 + } +} +``` + +También podemos usar un patrón global para deshabilitar todos los MCP coincidentes. + +```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 + } +} +``` + +Aquí estamos usando el patrón global `my-mcp*` para deshabilitar todos los MCP. + +--- + +### Por agente + +Si tiene una gran cantidad de servidores MCP, es posible que desee habilitarlos solo por agente y deshabilitarlos globalmente. Para hacer esto: + +1. Desactívelo como herramienta a nivel global. +2. En su [configuración del agente](/docs/agents#tools), habilite el servidor MCP como herramienta. + +```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 + } + } + } +} +``` + +--- + +#### Patrones globales + +El patrón global utiliza patrones globales simples de expresiones regulares: + +- `*` coincide con cero o más de cualquier carácter (por ejemplo, `"my-mcp*"` coincide con `my-mcp_search`, `my-mcp_list`, etc.) +- `?` coincide exactamente con un carácter +- Todos los demás caracteres coinciden literalmente + +:::note +Las herramientas del servidor MCP están registradas con el nombre del servidor como prefijo, por lo que para deshabilitar todas las herramientas para un servidor simplemente use: + +``` +"mymcpservername_*": false +``` + +::: + +--- + +## Ejemplos + +A continuación se muestran ejemplos de algunos servidores MCP comunes. Puede enviar un PR si desea documentar otros servidores. + +--- + +### sentry + +Agregue el [servidor Sentry MCP](https://mcp.sentry.dev) para interactuar con sus proyectos y problemas Sentry. + +```json title="opencode.json" {4-8} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "sentry": { + "type": "remote", + "url": "https://mcp.sentry.dev/mcp", + "oauth": {} + } + } +} +``` + +Después de agregar la configuración, autentíquese con Sentry: + +```bash +opencode mcp auth sentry +``` + +Esto abrirá una ventana del navegador para completar el flujo OAuth y conectar OpenCode a su cuenta Sentry. + +Una vez autenticado, puede utilizar las herramientas Sentry en sus indicaciones para consultar problemas, proyectos y datos de errores. + +```txt "use sentry" +Show me the latest unresolved issues in my project. use sentry +``` + +--- + +### Context7 + +Agregue el [servidor Context7 MCP](https://github.com/upstash/context7) para buscar en los documentos. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "context7": { + "type": "remote", + "url": "https://mcp.context7.com/mcp" + } + } +} +``` + +Si se ha registrado para obtener una cuenta gratuita, puede usar su clave API y obtener límites de tarifas más altos. + +```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}" + } + } + } +} +``` + +Aquí asumimos que tiene configurada la variable de entorno `CONTEXT7_API_KEY`. + +Agregue `use context7` a sus indicaciones para usar el servidor Context7 MCP. + +```txt "use context7" +Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 +``` + +Alternativamente, puede agregar algo como esto a su [AGENTS.md](/docs/rules/). + +```md title="AGENTS.md" +When you need to search docs, use `context7` tools. +``` + +--- + +### Grep by Vercel + +Agregue el servidor [Grep by Vercel](https://grep.app) MCP para buscar fragmentos de código en GitHub. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "gh_grep": { + "type": "remote", + "url": "https://mcp.grep.app" + } + } +} +``` + +Dado que llamamos a nuestro servidor MCP `gh_grep`, puede agregar `use the gh_grep tool` a sus indicaciones para que el agente lo use. + +```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 +``` + +Alternativamente, puede agregar algo como esto a su [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/es/models.mdx b/packages/web/src/content/docs/es/models.mdx new file mode 100644 index 00000000000..a722fa0a875 --- /dev/null +++ b/packages/web/src/content/docs/es/models.mdx @@ -0,0 +1,223 @@ +--- +title: Modelos +description: Configuración de un proveedor y modelo LLM. +--- + +OpenCode usa el [AI SDK](https://ai-sdk.dev/) y [Models.dev](https://models.dev) para admitir **75+ proveedores LLM** y admite la ejecución de modelos locales. + +--- + +## Proveedores + +Los proveedores más populares están precargados de forma predeterminada. Si agregó las credenciales de un proveedor mediante el comando `/connect`, estarán disponibles cuando inicie OpenCode. + +Obtenga más información sobre [proveedores](/docs/providers). + +--- + +## Seleccionar un modelo + +Una vez que hayas configurado tu proveedor podrás seleccionar el modelo que desees escribiendo: + +```bash frame="none" +/models +``` + +--- + +## Modelos recomendados + +Hay muchos modelos disponibles y cada semana salen nuevos modelos. + +:::tip +Considere utilizar uno de los modelos que recomendamos. +::: + +Sin embargo, sólo unos pocos de ellos son buenos tanto para generar código como para llamar a herramientas. + +Aqui tienes varios modelos que funcionan bien con OpenCode, sin orden particular. (Esta no es una lista exhaustiva ni necesariamente actualizada): + +- GPT 5.2 +- GPT 5.1 Codex +- Claude Opus 4.5 +- Claude Sonnet 4.5 +- Minimax M2.1 +- Gemini 3 Pro + +--- + +## Establecer un valor predeterminado + +Para configurar uno de estos como modelo predeterminado, puedes definir la clave `model` en tu +configuracion de OpenCode. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +Aquí el ID completo es `provider_id/model_id`. Por ejemplo, si usa [OpenCode Zen](/docs/zen), usaría `opencode/gpt-5.1-codex` para GPT 5.1 Codex. + +Si ha configurado un [proveedor personalizado](/docs/providers#custom), `provider_id` es la clave de la parte `provider` de su configuración y `model_id` es la clave de `provider.models`. + +--- + +## Configurar modelos + +Puede configurar globalmente las opciones de un modelo a través de la configuración. + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +Aquí estamos configurando ajustes globales para dos modelos integrados: `gpt-5` cuando se accede a través del proveedor `openai` y `claude-sonnet-4-20250514` cuando se accede a través del proveedor `anthropic`. +Los nombres de modelo y proveedor integrados se pueden encontrar en [Models.dev](https://models.dev). + +También puede configurar estas opciones para cualquier agente que esté utilizando. La configuración del agente anula cualquier opción global aquí. [Más información](/docs/agents/#additional). + +También puede definir variantes personalizadas que amplíen las integradas. Las variantes le permiten configurar diferentes ajustes para el mismo modelo sin crear entradas duplicadas: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## Variantes + +Muchos modelos admiten múltiples variantes con diferentes configuraciones. OpenCode se envía con variantes predeterminadas integradas para proveedores populares. + +### Variantes integradas + +OpenCode se envía con variantes predeterminadas para muchos proveedores: + +**Anthropic**: + +- `high` - Presupuesto de pensamiento alto (predeterminado) +- `max` - Presupuesto de pensamiento máximo + +**OpenAI**: + +Varía según el modelo, pero aproximadamente: + +- `none` - Sin razonamiento +- `minimal` - Mínimo esfuerzo de razonamiento +- `low` - Bajo esfuerzo de razonamiento +- `medium` - Esfuerzo de razonamiento medio +- `high` - Alto esfuerzo de razonamiento +- `xhigh` - Esfuerzo de razonamiento extra alto + +**Google**: + +- `low` - Menor esfuerzo/presupuesto simbólico +- `high` - Mayor esfuerzo/presupuesto simbólico + +:::tip +Esta lista no es exhaustiva. Muchos otros proveedores también tienen valores predeterminados integrados. +::: + +### Variantes personalizadas + +Puede anular las variantes existentes o agregar las suyas propias: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### Alternar variantes + +Utilice la combinación de teclas `variant_cycle` para cambiar rápidamente entre variantes. [Más información](/docs/keybinds). + +--- + +## Carga de modelos + +Cuando se inicia OpenCode, busca modelos en el siguiente orden de prioridad: + +1. El indicador de línea de comando `--model` o `-m`. El formato es el mismo que en el archivo de configuración: `provider_id/model_id`. + +2. La lista de modelos en la configuración OpenCode. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + + El formato aquí es `provider/model`. + +3. El último modelo utilizado. + +4. El primer modelo que utiliza una prioridad interna. diff --git a/packages/web/src/content/docs/es/modes.mdx b/packages/web/src/content/docs/es/modes.mdx new file mode 100644 index 00000000000..c57e8e6a956 --- /dev/null +++ b/packages/web/src/content/docs/es/modes.mdx @@ -0,0 +1,331 @@ +--- +title: Modos +description: Diferentes modos para diferentes casos de uso. +--- + +:::caution +Los modos ahora se configuran a través de la opción `agent` en la configuración opencode. El +La opción `mode` ahora está en desuso. [Más información](/docs/agents). +::: + +Los modos en opencode le permiten personalizar el comportamiento, las herramientas y las indicaciones para diferentes casos de uso. + +Viene con dos modos integrados: **construir** y **planificar**. Puedes personalizar +estos o configure el suyo propio a través de la configuración opencode. + +Puede cambiar entre modos durante una sesión o configurarlos en su archivo de configuración. + +--- + +## Integrados + +opencode viene con dos modos integrados. + +--- + +### Modo Build + +Build es el modo **predeterminado** con todas las herramientas habilitadas. Este es el modo estándar para el trabajo de desarrollo en el que necesita acceso completo a las operaciones de archivos y a los comandos del sistema. + +--- + +### Modo Plan + +Un modo restringido diseñado para la planificación y el análisis. En el modo de plan, las siguientes herramientas están deshabilitadas de forma predeterminada: + +- `write` - No se pueden crear archivos nuevos +- `edit` - No se pueden modificar archivos existentes, excepto los archivos ubicados en `.opencode/plans/*.md` para detallar el plan en sí. +- `patch` - No se pueden aplicar parches +- `bash` - No se pueden ejecutar comandos de shell + +Este modo es útil cuando desea que la IA analice código, sugiera cambios o cree planes sin realizar modificaciones reales en su base de código. + +--- + +## Cambiar de modo + +Puede cambiar entre modos durante una sesión usando la tecla _Tab_. O su combinación de teclas `switch_mode` configurada. + +Consulte también: [Formateadores](/docs/formatters) para obtener información sobre la configuración de formato de código. + +--- + +## Configuración + +Puede personalizar los modos integrados o crear los suyos propios mediante la configuración. Los modos se pueden configurar de dos maneras: + +### Configuración JSON + +Configure los modos en su archivo de configuración `opencode.json`: + +```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 + } + } + } +} +``` + +### Configuración de Markdown + +También puede definir modos utilizando archivos de Markdown. Colócalos en: + +- Global: `~/.config/opencode/modes/` +- Proyecto: `.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. +``` + +El nombre del archivo de Markdown se convierte en el nombre del modo (por ejemplo, `review.md` crea un modo `review`). + +Veamos estas opciones de configuración en detalle. + +--- + +### Modelo + +Utilice la configuración `model` para anular el modelo predeterminado para este modo. Útil para utilizar diferentes modelos optimizados para diferentes tareas. Por ejemplo, un modelo más rápido de planificación, un modelo más capaz de implementación. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### Temperatura + +Controle la aleatoriedad y la creatividad de las respuestas de la IA con la configuración `temperature`. Los valores más bajos hacen que las respuestas sean más centradas y deterministas, mientras que los valores más altos aumentan la creatividad y la variabilidad. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Los valores de temperatura suelen oscilar entre 0,0 y 1,0: + +- **0.0-0.2**: Respuestas muy enfocadas y deterministas, ideales para análisis y planificación de código. +- **0,3-0,5**: respuestas equilibradas con algo de creatividad, buenas para tareas de desarrollo general. +- **0.6-1.0**: respuestas más creativas y variadas, útiles para la lluvia de ideas y la exploración. + +```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}" + } + } +} +``` + +Si no se especifica ninguna temperatura, opencode utiliza valores predeterminados específicos del modelo (normalmente 0 para la mayoría de los modelos, 0,55 para los modelos Qwen). + +--- + +### Indicación + +Especifique un archivo de aviso del sistema personalizado para este modo con la configuración `prompt`. El archivo de aviso debe contener instrucciones específicas para el propósito del modo. + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Esta ruta es relativa a donde se encuentra el archivo de configuración. Entonces esto funciona para +tanto la configuración global opencode como la configuración específica del proyecto. + +--- + +### Herramientas + +Controle qué herramientas están disponibles en este modo con la configuración `tools`. Puede habilitar o deshabilitar herramientas específicas configurándolas en `true` o `false`. + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +Si no se especifica ninguna herramienta, todas las herramientas están habilitadas de forma predeterminada. + +--- + +#### Herramientas disponibles + +Aquí están todas las herramientas que se pueden controlar a través del modo de configuración. + +| Herramienta | Descripción | +| ----------- | --------------------------------------- | +| `bash` | Ejecutar comandos de shell | +| `edit` | Modificar archivos existentes | +| `write` | Crear nuevos archivos | +| `read` | Leer el contenido del archivo | +| `grep` | Buscar contenido del archivo | +| `glob` | Buscar archivos por patrón | +| `list` | Listar el contenido del directorio | +| `patch` | Aplicar parches a archivos | +| `todowrite` | Administrar listas de tareas pendientes | +| `todoread` | Leer listas de tareas pendientes | +| `webfetch` | Obtener contenido web | + +--- + +## Modos personalizados + +Puede crear sus propios modos personalizados agregándolos a la configuración. A continuación se muestran ejemplos que utilizan ambos enfoques: + +### Usando la configuración JSON + +```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 + } + } + } +} +``` + +### Usando archivos de Markdown + +Cree archivos de modo en `.opencode/modes/` para modos específicos del proyecto o `~/.config/opencode/modes/` para modos globales: + +```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 +``` + +--- + +### Casos de uso + +A continuación se muestran algunos casos de uso comunes para diferentes modos. + +- **Modo Build**: trabajo de desarrollo completo con todas las herramientas habilitadas +- **Modo Plan**: Análisis y planificación sin realizar cambios +- **Modo Review**: revisión de código con acceso de solo lectura más herramientas de documentación +- **Modo Debug**: centrado en la investigación con bash y herramientas de lectura habilitadas +- **Modo Docs**: escritura de documentacion con operaciones de archivos pero sin comandos del sistema + +También puede encontrar que diferentes modelos son buenos para diferentes casos de uso. diff --git a/packages/web/src/content/docs/es/network.mdx b/packages/web/src/content/docs/es/network.mdx new file mode 100644 index 00000000000..f5b6e1130ba --- /dev/null +++ b/packages/web/src/content/docs/es/network.mdx @@ -0,0 +1,57 @@ +--- +title: Red +description: Configure proxies y certificados personalizados. +--- + +OpenCode admite variables de entorno de proxy estándar y certificados personalizados para entornos de red empresarial. + +--- + +## Proxy + +OpenCode respeta las variables de entorno de proxy estándar. + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +El TUI se comunica con un servidor HTTP local. Debe omitir el proxy para esta conexión para evitar bucles de enrutamiento. +::: + +Puede configurar el puerto y el nombre de host del servidor usando [CLI flags](/docs/cli#run). + +--- + +### Autenticación + +Si su proxy requiere autenticación básica, incluya las credenciales en la URL. + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +Evite codificar contraseñas. Utilice variables de entorno o almacenamiento seguro de credenciales. +::: + +Para servidores proxy que requieren autenticación avanzada como NTLM o Kerberos, considere usar una puerta de enlace LLM que admita su método de autenticación. + +--- + +## Certificados personalizados + +Si su empresa utiliza CA personalizadas para conexiones HTTPS, configure OpenCode para confiar en ellas. + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +Esto funciona tanto para conexiones proxy como para acceso directo a API. diff --git a/packages/web/src/content/docs/es/permissions.mdx b/packages/web/src/content/docs/es/permissions.mdx new file mode 100644 index 00000000000..3ebe67fd2c1 --- /dev/null +++ b/packages/web/src/content/docs/es/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: Permisos +description: Controle qué acciones requieren aprobación para ejecutarse. +--- + +OpenCode usa la configuración `permission` para decidir si una acción determinada debe ejecutarse automáticamente, avisarle o bloquearse. + +A partir de `v1.1.1`, la configuración booleana heredada `tools` está obsoleta y se ha fusionado en `permission`. La antigua configuración `tools` todavía se admite por compatibilidad con versiones anteriores. + +--- + +## Acciones + +Cada regla de permiso se resuelve en una de: + +- `"allow"` — ejecutar sin aprobación +- `"ask"` — solicitar aprobación +- `"deny"` — bloquea la acción + +--- + +## Configuración + +Puede establecer permisos globalmente (con `*`) y anular herramientas específicas. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +También puedes configurar todos los permisos a la vez: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## Reglas granulares (sintaxis de objeto) + +Para la mayoría de los permisos, puede utilizar un objeto para aplicar diferentes acciones según la entrada de la herramienta. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +Las reglas se evalúan según la coincidencia de patrones, y la **última regla coincidente gana**. Un patrón común es poner primero la regla general `"*"` y después reglas más específicas. + +### Comodines + +Los patrones de permisos utilizan una simple coincidencia de comodines: + +- `*` coincide con cero o más de cualquier carácter +- `?` coincide exactamente con un carácter +- Todos los demás caracteres coinciden literalmente + +### Expansión del directorio de inicio + +Puede usar `~` o `$HOME` al comienzo de un patrón para hacer referencia a su directorio de inicio. Esto es particularmente útil para las reglas [`external_directory`](#external-directories). + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### Directorios externos + +Utilice `external_directory` para permitir llamadas a herramientas que toquen rutas fuera del directorio de trabajo donde se inició OpenCode. Esto se aplica a cualquier herramienta que tome una ruta como entrada (por ejemplo, `read`, `edit`, `list`, `glob`, `grep` y muchos comandos `bash`). + +La expansión del hogar (como `~/...`) solo afecta la forma en que se escribe un patrón. No hace que una ruta externa forme parte del espacio de trabajo actual, por lo que las rutas fuera del directorio de trabajo aún deben permitirse a través de `external_directory`. + +Por ejemplo, esto permite el acceso a todo lo que se encuentra en `~/projects/personal/`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +Cualquier directorio permitido aquí hereda los mismos valores predeterminados que el espacio de trabajo actual. Dado que [`read` tiene por defecto `allow`](#defaults), también se permiten lecturas para entradas bajo `external_directory` a menos que se anulen. Agregue reglas explícitas cuando una herramienta deba restringirse en estas rutas, como bloquear ediciones mientras se mantienen las lecturas: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +Mantenga la lista centrada en rutas confiables y aplique reglas adicionales de permitir o denegar según sea necesario para otras herramientas (por ejemplo, `bash`). + +--- + +## Permisos disponibles + +Los permisos OpenCode están codificados por el nombre de la herramienta, además de un par de medidas de seguridad: + +- `read` — leer un archivo (coincide con la ruta del archivo) +- `edit` — todas las modificaciones de archivos (cubre `edit`, `write`, `patch`, `multiedit`) +- `glob` — globalización de archivos (coincide con el patrón global) +- `grep` — búsqueda de contenido (coincide con el patrón de expresiones regulares) +- `list` — enumerar archivos en un directorio (coincide con la ruta del directorio) +- `bash`: ejecuta comandos de shell (coincide con comandos analizados como `git status --porcelain`) +- `task` — lanzamiento de subagentes (coincide con el tipo de subagente) +- `skill` — cargar una habilidad (coincide con el nombre de la habilidad) +- `lsp`: ejecución de consultas LSP (actualmente no granulares) +- `todoread`, `todowrite` — leer/actualizar la lista de tareas pendientes +- `webfetch` — obteniendo una URL (coincide con la URL) +- `websearch`, `codesearch` — búsqueda web/código (coincide con la consulta) +- `external_directory`: se activa cuando una herramienta toca rutas fuera del directorio de trabajo del proyecto. +- `doom_loop`: se activa cuando la misma llamada de herramienta se repite 3 veces con entrada idéntica + +--- + +## Valores predeterminados + +Si no especifica nada, OpenCode comienza desde valores predeterminados permisivos: + +- La mayoría de los permisos están predeterminados en `"allow"`. +- `doom_loop` y `external_directory` por defecto son `"ask"`. +- `read` es `"allow"`, pero los archivos `.env` están denegados de forma predeterminada: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## ¿Qué significa "preguntar"? + +Cuando OpenCode solicita aprobación, la interfaz de usuario ofrece tres resultados: + +- `once` — aprobar solo esta solicitud +- `always`: aprueba solicitudes futuras que coincidan con los patrones sugeridos (para el resto de la sesión actual OpenCode) +- `reject` — rechazar la solicitud + +La herramienta proporciona el conjunto de patrones que `always` aprobaría (por ejemplo, las aprobaciones de bash generalmente incluyen en la lista blanca un prefijo de comando seguro como `git status*`). + +--- + +## Agentes + +Puede anular los permisos por agente. Los permisos del agente se combinan con la configuración global y las reglas del agente tienen prioridad. [Más información](/docs/agents#permissions) sobre los permisos de los agentes. + +:::note +Consulte la sección [Reglas granulares (sintaxis de objeto)](#granular-rules-object-syntax) anterior para obtener ejemplos de coincidencia de patrones más detallados. +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +También puede configurar los permisos del agente en Markdown: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +Utilice la coincidencia de patrones para comandos con argumentos. `"grep *"` permite `grep pattern file.txt`, mientras que `"grep"` solo lo bloquearía. Los comandos como `git status` funcionan para el comportamiento predeterminado pero requieren permiso explícito (como `"git status *"`) cuando se pasan argumentos. +::: diff --git a/packages/web/src/content/docs/es/plugins.mdx b/packages/web/src/content/docs/es/plugins.mdx new file mode 100644 index 00000000000..904821bdb83 --- /dev/null +++ b/packages/web/src/content/docs/es/plugins.mdx @@ -0,0 +1,385 @@ +--- +title: Complementos +description: Escriba sus propios complementos para extender OpenCode. +--- + +Los complementos le permiten extender OpenCode al conectarse a varios eventos y personalizar el comportamiento. Puede crear complementos para agregar nuevas funciones, integrarlos con servicios externos o modificar el comportamiento predeterminado de OpenCode. + +Para ver ejemplos, consulte los [complementos](/docs/ecosystem#plugins) creados por la comunidad. + +--- + +## Usar un complemento + +Hay dos formas de cargar complementos. + +--- + +### Desde archivos locales + +Coloque los archivos JavaScript o TypeScript en el directorio del complemento. + +- `.opencode/plugins/` - Complementos a nivel de proyecto +- `~/.config/opencode/plugins/` - Complementos globales + +Los archivos en estos directorios se cargan automáticamente al inicio. + +--- + +### Desde npm + +Especifique paquetes npm en su archivo de configuración. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +Se admiten paquetes npm regulares y de alcance. + +Explore los complementos disponibles en el [ecosistema](/docs/ecosystem#plugins). + +--- + +### Cómo se instalan los complementos + +Los **complementos npm** se instalan automáticamente usando Bun al inicio. Los paquetes y sus dependencias se almacenan en caché en `~/.cache/opencode/node_modules/`. + +**Los complementos locales** se cargan directamente desde el directorio de complementos. Para usar paquetes externos, debe crear un `package.json` dentro de su directorio de configuración (consulte [Dependencias](#dependencies)), o publicar el complemento en npm y [agregarlo a su configuración](/docs/config#plugins). + +--- + +### Orden de carga + +Los complementos se cargan desde todas las fuentes y todos los enlaces se ejecutan en secuencia. El orden de carga es: + +1. Configuración global (`~/.config/opencode/opencode.json`) +2. Configuración del proyecto (`opencode.json`) +3. Directorio global de complementos (`~/.config/opencode/plugins/`) +4. Directorio de complementos del proyecto (`.opencode/plugins/`) + +Los paquetes npm duplicados con el mismo nombre y versión se cargan una vez. Sin embargo, un complemento local y un complemento npm con nombres similares se cargan por separado. + +--- + +## Crear un complemento + +Un complemento es un módulo **JavaScript/TypeScript** que exporta uno o más complementos. +funciones. Cada función recibe un objeto de contexto y devuelve un objeto de enlace. + +--- + +### Dependencias + +Los complementos locales y las herramientas personalizadas pueden utilizar paquetes npm externos. Agregue un `package.json` a su directorio de configuración con las dependencias que necesita. + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +OpenCode ejecuta `bun install` al inicio para instalarlos. Luego, sus complementos y herramientas pueden importarlos. + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### Estructura básica + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +La función del complemento recibe: + +- `project`: La información actual del proyecto. +- `directory`: El directorio de trabajo actual. +- `worktree`: La ruta del árbol de trabajo de git. +- `client`: Un cliente SDK opencode para interactuar con la IA. +- `$`: [shell API](https://bun.com/docs/runtime/shell) de Bun para ejecutar comandos. + +--- + +### Soporte TypeScript + +Para los complementos TypeScript, puede importar tipos desde el paquete de complementos: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### Eventos + +Los complementos pueden suscribirse a eventos como se ve a continuación en la sección Ejemplos. Aquí hay una lista de los diferentes eventos disponibles. + +#### Eventos de comando + +- `command.executed` + +#### Eventos de archivo + +- `file.edited` +- `file.watcher.updated` + +#### Eventos de instalación + +- `installation.updated` + +#### Eventos LSP + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### Eventos de mensajes + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### Eventos de permiso + +- `permission.asked` +- `permission.replied` + +#### Eventos del servidor + +- `server.connected` + +#### Eventos de sesión + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### Eventos de Todo + +- `todo.updated` + +#### Eventos de Shell + +- `shell.env` + +#### Eventos de herramientas + +- `tool.execute.after` +- `tool.execute.before` + +#### Eventos TUI + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## Ejemplos + +A continuación se muestran algunos ejemplos de complementos que puede utilizar para ampliar opencode. + +--- + +### Enviar notificaciones + +Enviar notificaciones cuando ocurran ciertos eventos: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +Estamos usando `osascript` para ejecutar AppleScript en macOS. Aquí lo estamos usando para enviar notificaciones. + +:::note +Si está utilizando la aplicación de escritorio OpenCode, puede enviar notificaciones del sistema automáticamente cuando una respuesta esté lista o cuando se produzca un error en una sesión. +::: + +--- + +### Protección .env + +Evite que opencode lea archivos `.env`: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### Inyectar variables de entorno + +Inyecte variables de entorno en toda la ejecución del shell (herramientas de inteligencia artificial y terminales de usuario): + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### Herramientas personalizadas + +Los complementos también pueden agregar herramientas personalizadas a opencode: + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +El ayudante `tool` crea una herramienta personalizada a la que opencode puede llamar. Toma una función de esquema Zod y devuelve una definición de herramienta con: + +- `description`: Qué hace la herramienta +- `args`: Esquema Zod para los argumentos de la herramienta. +- `execute`: Función que se ejecuta cuando se llama a la herramienta + +Sus herramientas personalizadas estarán disponibles para opencode junto con las herramientas integradas. + +--- + +### Registro + +Utilice `client.app.log()` en lugar de `console.log` para el registro estructurado: + +```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" }, + }, + }) +} +``` + +Niveles: `debug`, `info`, `warn`, `error`. Consulte la [documentación del SDK](https://opencode.ai/docs/sdk) para obtener más detalles. + +--- + +### Hooks de compactación + +Personalice el contexto incluido cuando se compacta una sesión: + +```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 +`) + }, + } +} +``` + +El hook `experimental.session.compacting` se activa antes de que LLM genere un resumen de continuación. Úselo para inyectar contexto específico del dominio que el mensaje de compactación predeterminado omitiría. + +También puede reemplazar completamente el mensaje de compactación configurando `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. +` + }, + } +} +``` + +Cuando se configura `output.prompt`, reemplaza completamente el mensaje de compactación predeterminado. En este caso, se ignora la matriz `output.context`. diff --git a/packages/web/src/content/docs/es/providers.mdx b/packages/web/src/content/docs/es/providers.mdx new file mode 100644 index 00000000000..8d86612538b --- /dev/null +++ b/packages/web/src/content/docs/es/providers.mdx @@ -0,0 +1,1892 @@ +--- +title: Proveedores +description: Usando cualquier proveedor LLM en OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console + +OpenCode usa el [AI SDK](https://ai-sdk.dev/) y [Models.dev](https://models.dev) para admitir **75+ proveedores LLM** y admite la ejecución de modelos locales. + +Para agregar un proveedor necesita: + +1. Agregue las claves API para el proveedor usando el comando `/connect`. +2. Configure el proveedor en su configuración OpenCode. + +--- + +### Credenciales + +Cuando agrega las claves API de un proveedor con el comando `/connect`, se almacenan +en `~/.local/share/opencode/auth.json`. + +--- + +### Configuración + +Puedes personalizar los proveedores a través de la sección `provider` en tu OpenCode +configuración. + +--- + +#### URL base + +Puede personalizar la URL base para cualquier proveedor configurando la opción `baseURL`. Esto resulta útil cuando se utilizan servicios proxy o puntos finales personalizados. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen es una lista de modelos proporcionados por el equipo OpenCode que han sido +probado y verificado para funcionar bien con OpenCode. [Más información](/docs/zen). + +:::tip +Si eres nuevo, te recomendamos comenzar con OpenCode Zen. +::: + +1. Ejecute el comando `/connect` en TUI, seleccione opencode y diríjase a [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. Inicie sesión, agregue sus datos de facturación y copie su clave API. + +3. Pega tu 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 +lista, no dude en abrir un PR. + +:::note +¿No ves un proveedor aquí? Envíe un PR. +::: + +--- + +### 302.AI + +1. Dirígete a la [consola 302.AI](https://302.ai/), crea una cuenta y genera una clave API. + +2. Ejecute el comando `/connect` y busque **302.AI**. + + ```txt + /connect + ``` + +3. Ingrese su clave 302.AI API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo. + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +Para usar Amazon Bedrock con OpenCode: + +1. Dirígete al **Catálogo de modelos** en la consola Amazon Bedrock y solicita + Accede a los modelos que desees. + + :::consejo + Necesita tener acceso al modelo que desea en Amazon Bedrock. + ::: + +2. **Configure la autenticación** utilizando uno de los siguientes métodos: + + #### Variables de entorno (Inicio rápido) + + Establezca una de estas variables de entorno mientras ejecuta opencode: + + ```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode + ``` + + O agrégalos a tu perfil de bash: + + ```bash title="~/.bash_profile" + export AWS_PROFILE=my-dev-profile + export AWS_REGION=us-east-1 + ``` + + #### Archivo de configuración (recomendado) + + Para una configuración persistente o específica del proyecto, utilice `opencode.json`: + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile" + } + } + } + } + ``` + + **Opciones disponibles:** + - `region` - AWS región (p. ej., `us-east-1`, `eu-west-1`) + - `profile` - AWS perfil con nombre de `~/.aws/credentials` + - `endpoint`: URL de punto de enlace personalizada para puntos de enlace de la VPC (alias para la opción genérica `baseURL`) + + :::consejo + Las opciones del archivo de configuración tienen prioridad sobre las variables de entorno. + ::: + + #### Avanzado: puntos finales de la VPC + + Si utiliza puntos de enlace de VPC para Bedrock: + + ```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" + } + } + } + } + ``` + + :::nota + La opción `endpoint` es un alias para la opción genérica `baseURL`, que utiliza terminología específica de AWS. Si se especifican `endpoint` y `baseURL`, `endpoint` tiene prioridad. + ::: + + #### Métodos de autenticación + - **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: Crear un usuario de IAM y generar claves de acceso en la Consola AWS + - **`AWS_PROFILE`**: Utilice perfiles con nombre de `~/.aws/credentials`. Primero configure con `aws configure --profile my-profile` o `aws sso login` + - **`AWS_BEARER_TOKEN_BEDROCK`**: Genera claves API a largo plazo desde la consola Amazon Bedrock + - **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: Para EKS IRSA (Roles IAM para Cuentas de Servicio) u otros entornos de Kubernetes con federación OIDC. Kubernetes inyecta automáticamente estas variables de entorno cuando se utilizan anotaciones de cuentas de servicio. + + #### Prioridad de autenticación + + Amazon Bedrock utiliza la siguiente prioridad de autenticación: + 1. **Bearer token** - variable de entorno `AWS_BEARER_TOKEN_BEDROCK` o token del comando `/connect` + 2. **AWS Cadena de credenciales**: perfil, claves de acceso, credenciales compartidas, roles de IAM, tokens de identidad web (EKS IRSA), metadatos de instancia + + :::nota + Cuando se define un bearer token (a traves de `/connect` o `AWS_BEARER_TOKEN_BEDROCK`), tiene prioridad sobre todos los metodos de credenciales de AWS, incluidos los perfiles configurados. + ::: + +3. Ejecute el comando `/models` para seleccionar el modelo que desee. + + ```txt + /models + ``` + +:::note +Para perfiles de inferencia personalizados, utilice el modelo y el nombre del proveedor en la clave y establezca la propiedad `id` en arn. Esto garantiza un almacenamiento en caché correcto: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. Una vez que se haya registrado, ejecute el comando `/connect` y seleccione Anthropic. + + ```txt + /connect + ``` + +2. Aquí puedes seleccionar la opción **Claude Pro/Max** y se abrirá tu navegador. + y pedirle que se autentique. + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. Ahora todos los modelos Anthropic deberían estar disponibles cuando use el comando `/models`. + + ```txt + /models + ``` + +:::info +El uso de su suscripción Claude Pro/Max en OpenCode no está oficialmente respaldado por [Anthropic](https://anthropic.com). +::: + +##### Usando las teclas API + +También puede seleccionar **Crear una clave API** si no tiene una suscripción Pro/Max. También abrirá su navegador y le pedirá que inicie sesión en Anthropic y le dará un código que puede pegar en su terminal. + +O si ya tienes una clave API, puedes seleccionar **Ingresar manualmente la clave API** y pegarla en tu terminal. + +--- + +### Azure OpenAI + +:::note +Si encuentra errores del tipo "Lo siento, pero no puedo ayudar con esa solicitud", intente cambiar el filtro de contenido de **DefaultV2** a **Default** en su recurso de Azure. +::: + +1. Diríjase al [portal de Azure](https://portal.azure.com/) y cree un recurso **Azure OpenAI**. Necesitarás: + - **Nombre del recurso**: esto pasa a formar parte de su punto final API (`https://RESOURCE_NAME.openai.azure.com/`) + - **Clave API**: `KEY 1` o `KEY 2` de su recurso + +2. Vaya a [Azure AI Foundry](https://ai.azure.com/) e implemente un modelo. + + :::nota + El nombre de la implementación debe coincidir con el nombre del modelo para que opencode funcione correctamente. + ::: + +3. Ejecute el comando `/connect` y busque **Azure**. + + ```txt + /connect + ``` + +4. Ingrese su clave API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Configure el nombre de su recurso como una variable de entorno: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + O agrégalo a tu perfil de bash: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. Ejecute el comando `/models` para seleccionar su modelo implementado. + + ```txt + /models + ``` + +--- + +### Servicios cognitivos de Azure + +1. Diríjase al [portal de Azure](https://portal.azure.com/) y cree un recurso **Azure OpenAI**. Necesitarás: + - **Nombre del recurso**: esto pasa a formar parte de su punto final API (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) + - **Clave API**: `KEY 1` o `KEY 2` de su recurso + +2. Vaya a [Azure AI Foundry](https://ai.azure.com/) e implemente un modelo. + + :::nota + El nombre de la implementación debe coincidir con el nombre del modelo para que opencode funcione correctamente. + ::: + +3. Ejecute el comando `/connect` y busque **Azure Cognitive Services**. + + ```txt + /connect + ``` + +4. Ingrese su clave API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Configure el nombre de su recurso como una variable de entorno: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + O agrégalo a tu perfil de bash: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. Ejecute el comando `/models` para seleccionar su modelo implementado. + + ```txt + /models + ``` + +--- + +### Baseten + +1. Dirígete a [Baseten](https://app.baseten.co/), crea una cuenta y genera una clave API. + +2. Ejecute el comando `/connect` y busque **Baseten**. + + ```txt + /connect + ``` + +3. Ingrese su clave Baseten API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo. + + ```txt + /models + ``` + +--- + +### Cerebras + +1. Dirígete a la [consola Cerebras](https://inference.cerebras.ai/), crea una cuenta y genera una clave API. + +2. Ejecute el comando `/connect` y busque **Cerebras**. + + ```txt + /connect + ``` + +3. Ingrese su clave Cerebras API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo como _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +Cloudflare AI Gateway le permite acceder a modelos de OpenAI, Anthropic, Workers AI y más a través de un punto final unificado. Con [Facturación unificada](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) no necesita claves API independientes para cada proveedor. + +1. Dirígete al [panel de Cloudflare](https://dash.cloudflare.com/), navega hasta **AI** > **AI Gateway** y crea una nueva puerta de enlace. + +2. Configure su ID de cuenta y su ID de puerta de enlace como variables de entorno. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. Ejecute el comando `/connect` y busque **Cloudflare AI Gateway**. + + ```txt + /connect + ``` + +4. Ingrese su token API de Cloudflare. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + O configúrelo como una variable de entorno. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. Ejecute el comando `/models` para seleccionar un modelo. + + ```txt + /models + ``` + + También puede agregar modelos a través de su configuración opencode. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +### Córtecs + +1. Dirígete a la [consola de Cortecs](https://cortecs.ai/), crea una cuenta y genera una clave API. + +2. Ejecute el comando `/connect` y busque **Cortecs**. + + ```txt + /connect + ``` + +3. Ingrese su clave Cortecs API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo como _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. Dirígete a la [consola de DeepSeek](https://platform.deepseek.com/), crea una cuenta y haz clic en **Crear nueva clave API**. + +2. Ejecute el comando `/connect` y busque **DeepSeek**. + + ```txt + /connect + ``` + +3. Ingrese su clave DeepSeek API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo de DeepSeek como _DeepSeek Reasoner_. + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. Dirígete al [panel de Deep Infra](https://deepinfra.com/dash), crea una cuenta y genera una clave API. + +2. Ejecute el comando `/connect` y busque **Deep Infra**. + + ```txt + /connect + ``` + +3. Ingrese su clave Deep Infra API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo. + + ```txt + /models + ``` + +--- + +### Firmware + +1. Dirígete al [Panel de firmware](https://app.firmware.ai/signup), crea una cuenta y genera una clave API. + +2. Ejecute el comando `/connect` y busque **Firmware**. + + ```txt + /connect + ``` + +3. Ingrese su clave de firmware API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo. + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. Dirígete a la [Consola de Fireworks AI](https://app.fireworks.ai/), crea una cuenta y haz clic en **Crear clave API**. + +2. Ejecute el comando `/connect` y busque **Fireworks AI**. + + ```txt + /connect + ``` + +3. Ingrese su clave API de AI de Fireworks. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo como _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo proporciona chat agente basado en IA con capacidades de llamada de herramientas nativas a través del proxy Anthropic de GitLab. + +1. Ejecute el comando `/connect` y seleccione GitLab. + + ```txt + /connect + ``` + +2. Elija su método de autenticación: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + │ + └ + ``` + + #### Usando OAuth (recomendado) + + Seleccione **OAuth** y su navegador se abrirá para autorización. + + #### Uso del token de acceso personal + 1. Vaya a [GitLab Configuración de usuario > Tokens de acceso](https://gitlab.com/-/user_settings/personal_access_tokens) + 2. Haga clic en **Agregar nuevo token** + 3. Nombre: `OpenCode`, Alcances: `api` + 4. Copie el token (comienza con `glpat-`) + 5. Introdúcelo en la terminal. + +3. Ejecute el comando `/models` para ver los modelos disponibles. + + ```txt + /models + ``` + + Hay tres modelos basados ​​en Claude disponibles: + - **duo-chat-haiku-4-5** (predeterminado) - Respuestas rápidas para tareas rápidas + - **duo-chat-sonnet-4-5** - Rendimiento equilibrado para la mayoría de los flujos de trabajo + - **duo-chat-opus-4-5** - Más capaz para análisis complejos + +:::note +También puede especificar la variable de entorno 'GITLAB_TOKEN' si no desea +para almacenar el token en el almacenamiento de autenticación opencode. +::: + +##### Autohospedado GitLab + +:::note[nota de cumplimiento] +OpenCode utiliza un modelo pequeño para algunas tareas de IA, como generar el título de la sesión. +Está configurado para usar gpt-5-nano de forma predeterminada, alojado por Zen. Para bloquear OpenCode +Para usar solo su propia instancia alojada en GitLab, agregue lo siguiente a su +Archivo `opencode.json`. También se recomienda desactivar el uso compartido de sesiones. + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +Para instancias GitLab autohospedadas: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +Si su instancia ejecuta una puerta de enlace AI personalizada: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +O agregue a su perfil de bash: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +Su administrador GitLab debe habilitar lo siguiente: + +1. [Plataforma de agente Duo](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) para el usuario, grupo o instancia +2. Indicadores de funciones (a través de la consola Rails): + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: + +##### OAuth para instancias autohospedadas + +Para que Oauth funcione para su instancia autohospedada, debe crear +una nueva aplicación (Configuración → Aplicaciones) con el +URL de devolución de llamada `http://127.0.0.1:8080/callback` y siguientes ámbitos: + +- api (Acceda al API en su nombre) +- read_user (Lee tu información personal) +- read_repository (Permite acceso de solo lectura al repositorio) + +Luego exponga el ID de la aplicación como variable de entorno: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +Más documentación en la página de inicio de [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth). + +##### Configuración + +Personalizar a través de `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### Herramientas de API de GitLab (opcionales, pero muy recomendables) + +Para acceder a herramientas GitLab (solicitudes de fusión, problemas, canalizaciones, CI/CD, etc.): + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +Este complemento proporciona capacidades integrales de administración del repositorio GitLab que incluyen revisiones de MR, seguimiento de problemas, monitoreo de canalizaciones y más. + +--- + +### GitHub Copilot + +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. + + ```txt + /connect + ``` + +2. Navegue hasta [github.com/login/device](https://github.com/login/device) e ingrese el código. + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + │ + └ Waiting for authorization... + ``` + +3. Ahora ejecute el comando `/models` para seleccionar el modelo que desea. + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +Para utilizar Google Vertex AI con OpenCode: + +1. Dirígete a **Model Garden** en Google Cloud Console y verifica el + Modelos disponibles en su región. + + :::note + Debes tener un proyecto de Google Cloud con Vertex AI API habilitado. + ::: + +2. Establezca las variables de entorno requeridas: + - `GOOGLE_CLOUD_PROJECT`: tu ID de proyecto de Google Cloud + - `VERTEX_LOCATION` (opcional): la región para Vertex AI (por defecto es `global`) + - Autenticación (elija una): + - `GOOGLE_APPLICATION_CREDENTIALS`: ruta al archivo clave JSON de su cuenta de servicio + - Autenticar usando gcloud CLI: `gcloud auth application-default login` + + Configúrelos mientras ejecuta opencode. + + ```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode + ``` + + O agréguelos a su perfil de bash. + + ```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 +La región `global` mejora la disponibilidad y reduce los errores sin costo adicional. Utilice puntos finales regionales (por ejemplo, `us-central1`) para los requisitos de residencia de datos. [Más información](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. Ejecute el comando `/models` para seleccionar el modelo que desee. + + ```txt + /models + ``` + +--- + +### Groq + +1. Dirígete a la [consola Groq](https://console.groq.com/), haz clic en **Crear clave API** y copia la clave. + +2. Ejecute el comando `/connect` y busque Groq. + + ```txt + /connect + ``` + +3. Ingrese la clave API para el proveedor. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar el que desee. + + ```txt + /models + ``` + +--- + +### Hugging Face + +[Hugging Face Inference Providers](https://huggingface.co/docs/inference-providers) proporciona acceso a modelos abiertos compatibles con más de 17 proveedores. + +1. Ve a [Hugging Face settings](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained) para crear un token con permisos para llamar a inference providers. + +2. Ejecute el comando `/connect` y busque **Hugging Face**. + + ```txt + /connect + ``` + +3. Ingresa tu token de Hugging Face. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo como _Kimi-K2-Instruct_ o _GLM-4.6_. + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) es una plataforma de observabilidad LLM que proporciona registro, monitoreo y análisis para sus aplicaciones de IA. Helicone AI Gateway enruta sus solicitudes al proveedor apropiado automáticamente según el modelo. + +1. Dirígete a [Helicone](https://helicone.ai), crea una cuenta y genera una clave API desde tu panel. + +2. Ejecute el comando `/connect` y busque **Helicone**. + + ```txt + /connect + ``` + +3. Ingrese su clave Helicone API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo. + + ```txt + /models + ``` + +Para obtener más proveedores y funciones avanzadas como almacenamiento en caché y limitación de velocidad, consulte la [documentación de Helicone](https://docs.helicone.ai). + +#### Configuraciones opcionales + +En caso de que vea una característica o modelo de Helicone que no esté configurado automáticamente a través de opencode, siempre podrá configurarlo usted mismo. + +Aquí está el [Directorio de modelos de Helicone](https://helicone.ai/models), lo necesitará para obtener las ID de los modelos que desea agregar. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### Encabezados personalizados + +Helicone admite encabezados personalizados para funciones como almacenamiento en caché, seguimiento de usuarios y gestión de sesiones. Agréguelos a la configuración de su proveedor usando `options.headers`: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### Seguimiento de sesión + +La función [Sesiones](https://docs.helicone.ai/features/sessions) de Helicone le permite agrupar solicitudes LLM relacionadas. Utilice el complemento [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) para registrar automáticamente cada conversación OpenCode como una sesión en Helicone. + +```bash +npm install -g opencode-helicone-session +``` + +Agréguelo a su configuración. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +El complemento inyecta encabezados `Helicone-Session-Id` y `Helicone-Session-Name` en sus solicitudes. En la página Sesiones de Helicone, verá cada conversación OpenCode enumerada como una sesión separada. + +##### Cabeceras comunes de Helicone + +| Encabezado | Descripción | +| -------------------------- | --------------------------------------------------------------------------------- | +| `Helicone-Cache-Enabled` | Habilitar el almacenamiento en caché de respuestas (`true`/`false`) | +| `Helicone-User-Id` | Seguimiento de métricas por usuario | +| `Helicone-Property-[Name]` | Agregar propiedades personalizadas (por ejemplo, `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | Solicitudes asociadas con versiones rápidas | + +Consulte el [Directorio de encabezados de Helicone](https://docs.helicone.ai/helicone-headers/header-directory) para conocer todos los encabezados disponibles. + +--- + +### llama.cpp + +Puede configurar opencode para usar modelos locales a través de la utilidad llama-server de [llama.cpp](https://github.com/ggml-org/llama.cpp) + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +En este ejemplo: + +- `llama.cpp` es el ID del proveedor personalizado. Puede ser cualquier cadena que desees. +- `npm` especifica el paquete que se utilizará para este proveedor. Aquí, `@ai-sdk/openai-compatible` se utiliza para cualquier OpenAI compatible con API. +- `name` es el nombre para mostrar del proveedor en la interfaz de usuario. +- `options.baseURL` es el punto final del servidor local. +- `models` es un mapa de ID de modelo para sus configuraciones. El nombre del modelo se mostrará en la lista de selección de modelos. + +--- + +### IO.NET + +IO.NET ofrece 17 modelos optimizados para varios casos de uso: + +1. Dirígete a la [consola IO.NET](https://ai.io.net/), crea una cuenta y genera una clave API. + +2. Ejecute el comando `/connect` y busque **IO.NET**. + + ```txt + /connect + ``` + +3. Ingrese su clave IO.NET API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo. + + ```txt + /models + ``` + +--- + +### LM Studio + +Puede configurar opencode para usar modelos locales a través de LM Studio. + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +En este ejemplo: + +- `lmstudio` es el ID del proveedor personalizado. Puede ser cualquier cadena que desees. +- `npm` especifica el paquete que se utilizará para este proveedor. Aquí, `@ai-sdk/openai-compatible` se utiliza para cualquier OpenAI compatible con API. +- `name` es el nombre para mostrar del proveedor en la interfaz de usuario. +- `options.baseURL` es el punto final del servidor local. +- `models` es un mapa de ID de modelo para sus configuraciones. El nombre del modelo se mostrará en la lista de selección de modelos. + +--- + +### Moonshot AI + +Para usar Kimi K2 de Moonshot AI: + +1. Dirígete a la [consola Moonshot AI](https://platform.moonshot.ai/console), crea una cuenta y haz clic en **Crear clave API**. + +2. Ejecute el comando `/connect` y busque **Moonshot AI**. + + ```txt + /connect + ``` + +3. Ingrese su clave Moonshot API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar _Kimi K2_. + + ```txt + /models + ``` + +--- + +### MiniMax + +1. Dirígete a la [Consola MiniMax API](https://platform.minimax.io/login), crea una cuenta y genera una clave API. + +2. Ejecute el comando `/connect` y busque **MiniMax**. + + ```txt + /connect + ``` + +3. Ingrese su clave MiniMax API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo como _M2.1_. + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. Dirígete a la [consola de Nebius Token Factory](https://tokenfactory.nebius.com/), crea una cuenta y haz clic en **Agregar clave**. + +2. Ejecute el comando `/connect` y busque **Nebius Token Factory**. + + ```txt + /connect + ``` + +3. Ingrese su clave API de Nebius Token Factory. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo como _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Ollama + +Puedes configurar opencode para usar modelos locales a través de Ollama. + +:::tip +Ollama puede configurarse automáticamente para OpenCode. Consulte los [documentos de integración de Ollama](https://docs.ollama.com/integrations/opencode) para obtener más detalles. +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +En este ejemplo: + +- `ollama` es el ID del proveedor personalizado. Puede ser cualquier cadena que desees. +- `npm` especifica el paquete que se utilizará para este proveedor. Aquí, `@ai-sdk/openai-compatible` se utiliza para cualquier OpenAI compatible con API. +- `name` es el nombre para mostrar del proveedor en la interfaz de usuario. +- `options.baseURL` es el punto final del servidor local. +- `models` es un mapa de ID de modelo para sus configuraciones. El nombre del modelo se mostrará en la lista de selección de modelos. + +:::tip +Si las llamadas a herramientas no funcionan, intente aumentar `num_ctx` en Ollama. Comience alrededor de 16k - 32k. +::: + +--- + +### Ollama Cloud + +Para usar Ollama Cloud con OpenCode: + +1. Dirígete a [https://ollama.com/](https://ollama.com/) e inicia sesión o crea una cuenta. + +2. Vaya a **Configuración** > **Claves** y haga clic en **Agregar clave API** para generar una nueva clave API. + +3. Copie la clave API para usarla en OpenCode. + +4. Ejecute el comando `/connect` y busque **Ollama Cloud**. + + ```txt + /connect + ``` + +5. Ingrese su clave Ollama Cloud API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **Importante**: Antes de usar modelos en la nube en OpenCode, debe obtener la información del modelo localmente: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. Ejecute el comando `/models` para seleccionar su modelo de Ollama Cloud. + + ```txt + /models + ``` + +--- + +### OpenAI + +Recomendamos registrarse en [ChatGPT Plus o Pro](https://chatgpt.com/pricing). + +1. Una vez que se haya registrado, ejecute el comando `/connect` y seleccione OpenAI. + + ```txt + /connect + ``` + +2. Aquí puedes seleccionar la opción **ChatGPT Plus/Pro** y se abrirá tu navegador. + y pedirle que se autentique. + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + │ + └ + ``` + +3. Ahora todos los modelos OpenAI deberían estar disponibles cuando use el comando `/models`. + + ```txt + /models + ``` + +##### Usando las teclas API + +Si ya tiene una clave API, puede seleccionar **Ingresar manualmente la clave API** y pegarla en su terminal. + +--- + +### OpenCode Zen + +OpenCode Zen es una lista de modelos probados y verificados proporcionada por el equipo OpenCode. [Más información](/docs/zen). + +1. Inicie sesión en **OpenCode Zen** y haga clic en **Crear API clave**. + +2. Ejecute el comando `/connect` y busque **OpenCode Zen**. + + ```txt + /connect + ``` + +3. Ingrese su clave OpenCode API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo como _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### OpenRouter + +1. Dirígete al [panel de OpenRouter](https://openrouter.ai/settings/keys), haz clic en **Crear clave API** y copia la clave. + +2. Ejecute el comando `/connect` y busque OpenRouter. + + ```txt + /connect + ``` + +3. Ingrese la clave API para el proveedor. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Muchos modelos de OpenRouter están precargados de forma predeterminada, ejecute el comando `/models` para seleccionar el que desee. + + ```txt + /models + ``` + + También puede agregar modelos adicionales a través de su configuración opencode. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +5. También puedes personalizarlos a través de tu configuración opencode. A continuación se muestra un ejemplo de cómo especificar un proveedor. + + ```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 brinda acceso a más de 40 modelos de OpenAI, Anthropic, Google, Amazon, Meta, Mistral y AI21 a través de una plataforma unificada. + +1. Vaya a su [SAP BTP Cockpit](https://account.hana.ondemand.com/), navegue hasta su instancia de servicio SAP AI Core y cree una clave de servicio. + + :::consejo + La clave de servicio es un objeto JSON que contiene `clientid`, `clientsecret`, `url` y `serviceurls.AI_API_URL`. Puede encontrar su instancia de AI Core en **Servicios** > **Instancias y suscripciones** en BTP Cockpit. + ::: + +2. Ejecute el comando `/connect` y busque **SAP AI Core**. + + ```txt + /connect + ``` + +3. Ingrese su clave de servicio JSON. + + ```txt + ┌ Service key + │ + │ + └ enter + ``` + + O configure la variable de entorno `AICORE_SERVICE_KEY`: + + ```bash + AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode + ``` + + O agrégalo a tu perfil de bash: + + ```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' + ``` + +4. Opcionalmente, configure el ID de implementación y el grupo de recursos: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + Estas configuraciones son opcionales y deben configurarse de acuerdo con su configuración de SAP AI Core. + ::: + +5. Ejecute el comando `/models` para seleccionar entre más de 40 modelos disponibles. + + ```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**. + +2. Ejecute el comando `/connect` y busque **OVHcloud AI Endpoints**. + + ```txt + /connect + ``` + +3. Introduzca la clave API de sus OVHcloud AI Endpoints. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo como _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Scaleway + +Para utilizar [API generativas de Scaleway](https://www.scaleway.com/en/docs/generative-apis/) con OpenCode: + +1. Dirígete a la [Configuración de IAM de la consola Scaleway](https://console.scaleway.com/iam/api-keys) para generar una nueva clave API. + +2. Ejecute el comando `/connect` y busque **Scaleway**. + + ```txt + /connect + ``` + +3. Ingrese su clave Scaleway API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo como _devstral-2-123b-instruct-2512_ o _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Together AI + +1. Dirígete a la [consola de Together AI](https://api.together.ai), crea una cuenta y haz clic en **Agregar clave**. + +2. Ejecute el comando `/connect` y busque **Together AI**. + + ```txt + /connect + ``` + +3. Ingrese su clave Together AI API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo como _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Venice AI + +1. Dirígete a la [consola de Venice AI](https://venice.ai), crea una cuenta y genera una clave API. + +2. Ejecute el comando `/connect` y busque **Venice AI**. + + ```txt + /connect + ``` + +3. Ingrese su clave Venice AI API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo como _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + +### Vercel AI Gateway + +Vercel AI Gateway le permite acceder a modelos de OpenAI, Anthropic, Google, xAI y más a través de un punto final unificado. Los modelos se ofrecen a precio de lista sin margen de beneficio. + +1. Dirígete al [panel de Vercel](https://vercel.com/), navega hasta la pestaña **AI Gateway** y haz clic en **API claves** para crear una nueva clave API. + +2. Ejecute el comando `/connect` y busque **Vercel AI Gateway**. + + ```txt + /connect + ``` + +3. Ingrese su clave Vercel AI Gateway API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo. + + ```txt + /models + ``` + +También puede personalizar modelos a través de su configuración opencode. A continuación se muestra un ejemplo de cómo especificar el orden de enrutamiento del proveedor. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "vercel": { + "models": { + "anthropic/claude-sonnet-4": { + "options": { + "order": ["anthropic", "vertex"] + } + } + } + } + } +} +``` + +Algunas opciones de enrutamiento útiles: + +| Opción | Descripción | +| ------------------- | ----------------------------------------------------------------------- | +| `order` | Secuencia de proveedores para probar | +| `only` | Restringir a proveedores específicos | +| `zeroDataRetention` | Utilice únicamente proveedores con políticas de retención de datos cero | + +--- + +### xAI + +1. Dirígete a la [consola xAI](https://console.x.ai/), crea una cuenta y genera una clave API. + +2. Ejecute el comando `/connect` y busque **xAI**. + + ```txt + /connect + ``` + +3. Ingrese su clave xAI API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo como _Grok Beta_. + + ```txt + /models + ``` + +--- + +### Z.AI + +1. Dirígete a la [consola Z.AI API](https://z.ai/manage-apikey/apikey-list), crea una cuenta y haz clic en **Crear una nueva clave API**. + +2. Ejecute el comando `/connect` y busque **Z.AI**. + + ```txt + /connect + ``` + + Si está suscrito al **Plan de codificación GLM**, seleccione **Plan de codificación Z.AI**. + +3. Ingrese su clave Z.AI API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar un modelo como _GLM-4.7_. + + ```txt + /models + ``` + +--- + +### ZenMux + +1. Dirígete al [panel de ZenMux](https://zenmux.ai/settings/keys), haz clic en **Crear clave API** y copia la clave. + +2. Ejecute el comando `/connect` y busque ZenMux. + + ```txt + /connect + ``` + +3. Ingrese la clave API para el proveedor. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Muchos modelos de ZenMux están precargados de forma predeterminada, ejecute el comando `/models` para seleccionar el que desee. + + ```txt + /models + ``` + + También puede agregar modelos adicionales a través de su configuración opencode. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "zenmux": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +--- + +## Proveedor personalizado + +Para agregar cualquier proveedor **compatible con OpenAI** que no aparezca en el comando `/connect`: + +:::tip +Puede utilizar cualquier proveedor compatible con OpenAI con opencode. La mayoría de los proveedores de IA modernos ofrecen API compatibles con OpenAI. +::: + +1. Ejecute el comando `/connect` y desplácese hacia abajo hasta **Otro**. + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. Ingrese una identificación única para el proveedor. + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::note + Elija una identificación memorable, la usará en su archivo de configuración. + ::: + +3. Ingrese su clave API para el proveedor. + + ```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. Cree o actualice su archivo `opencode.json` en el directorio de su proyecto: + + ```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" + } + } + } + } + } + ``` + + Aquí están las opciones de configuración: + - **npm**: paquete AI SDK para usar, `@ai-sdk/openai-compatible` para proveedores compatibles con OpenAI + - **nombre**: nombre para mostrar en la interfaz de usuario. + - **modelos**: Modelos disponibles. + - **options.baseURL**: API URL del punto final. + - **options.apiKey**: Opcionalmente, configure la clave API, si no usa autenticación. + - **options.headers**: Opcionalmente, configure encabezados personalizados. + + Más información sobre las opciones avanzadas en el siguiente ejemplo. + +5. Ejecute el comando `/models` y su proveedor y modelos personalizados aparecerán en la lista de selección. + +--- + +##### Ejemplo + +A continuación se muestra un ejemplo de configuración de las opciones `apiKey`, `headers` y modelo `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 + } + } + } + } + } +} +``` + +Detalles de configuración: + +- **apiKey**: se configura usando la sintaxis de la variable `env`, [más información](/docs/config#env-vars). +- **encabezados**: encabezados personalizados enviados con cada solicitud. +- **limit.context**: tokens de entrada máximos que acepta el modelo. +- **limit.output**: tokens máximos que el modelo puede generar. + +Los campos `limit` le permiten a OpenCode comprender cuánto contexto le queda. Los proveedores estándar los extraen de models.dev automáticamente. + +--- + +## Solución de problemas + +Si tiene problemas para configurar un proveedor, verifique lo siguiente: + +1. **Verifique la configuración de autenticación**: Ejecute `opencode auth list` para ver si las credenciales + para el proveedor se agregan a su configuración. + + Esto no se aplica a proveedores como Amazon Bedrock, que dependen de variables de entorno para su autenticación. + +2. Para proveedores personalizados, verifique la configuración opencode y: + - Asegúrese de que el ID del proveedor utilizado en el comando `/connect` coincida con el ID en su configuración opencode. + - Se utiliza el paquete npm correcto para el proveedor. Por ejemplo, utilice `@ai-sdk/cerebras` para Cerebras. Y para todos los demás proveedores compatibles con OpenAI, utilice `@ai-sdk/openai-compatible`. + - Verifique que se utilice el punto final API correcto en el campo `options.baseURL`. diff --git a/packages/web/src/content/docs/es/rules.mdx b/packages/web/src/content/docs/es/rules.mdx new file mode 100644 index 00000000000..6f429a80375 --- /dev/null +++ b/packages/web/src/content/docs/es/rules.mdx @@ -0,0 +1,180 @@ +--- +title: Reglas +description: Establezca instrucciones personalizadas para opencode. +--- + +Puede proporcionar instrucciones personalizadas a opencode creando un archivo `AGENTS.md`. Esto es similar a las reglas del Cursor. Contiene instrucciones que se incluirán en el contexto de LLM para personalizar su comportamiento para su proyecto específico. + +--- + +## Inicializar + +Para crear un nuevo archivo `AGENTS.md`, puede ejecutar el comando `/init` en opencode. + +:::tip +Debes enviar el archivo `AGENTS.md` de tu proyecto a Git. +::: + +Esto escaneará su proyecto y todo su contenido para comprender de qué se trata y generar un archivo `AGENTS.md` con él. Esto ayuda a opencode a navegar mejor por el proyecto. + +Si tiene un archivo `AGENTS.md` existente, intentará agregarlo. + +--- + +## Ejemplo + +También puedes crear este archivo manualmente. A continuación se muestra un ejemplo de algunas cosas que puede colocar en un archivo `AGENTS.md`. + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +Estamos agregando instrucciones específicas del proyecto aquí y esto se compartirá con todo su equipo. + +--- + +## Tipos + +opencode también admite la lectura del archivo `AGENTS.md` desde múltiples ubicaciones. Y esto tiene diferentes propósitos. + +### Proyecto + +Coloque un `AGENTS.md` en la raíz de su proyecto para reglas específicas del proyecto. Estos solo se aplican cuando trabaja en este directorio o sus subdirectorios. + +### Global + +También puedes tener reglas globales en un archivo `~/.config/opencode/AGENTS.md`. Esto se aplica en todas las sesiones opencode. + +Dado que esto no está comprometido con Git ni se comparte con su equipo, recomendamos usarlo para especificar las reglas personales que debe seguir LLM. + +### Compatibilidad con Claude Code + +Para los usuarios que migran desde Claude Code, OpenCode admite las convenciones de archivos de Claude Code como alternativas: + +- **Reglas del proyecto**: `CLAUDE.md` en el directorio de tu proyecto (se usa si no existe `AGENTS.md`) +- **Reglas globales**: `~/.claude/CLAUDE.md` (se usa si no existe `~/.config/opencode/AGENTS.md`) +- **Habilidades**: `~/.claude/skills/`; consulte [Habilidades del agente](/docs/skills/) para obtener más detalles. + +Para deshabilitar la compatibilidad de Claude Code, configure una de estas variables de entorno: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## Prioridad + +Cuando se inicia opencode, busca archivos de reglas en este orden: + +1. **Archivos locales** atravesando desde el directorio actual (`AGENTS.md`, `CLAUDE.md`) +2. **Archivo global** en `~/.config/opencode/AGENTS.md` +3. **Archivo de Claude Code** en `~/.claude/CLAUDE.md` (a menos que esté deshabilitado) + +El primer archivo coincidente gana en cada categoría. Por ejemplo, si tiene `AGENTS.md` y `CLAUDE.md`, solo se usa `AGENTS.md`. De manera similar, `~/.config/opencode/AGENTS.md` tiene prioridad sobre `~/.claude/CLAUDE.md`. + +--- + +## Instrucciones personalizadas + +Puede especificar archivos de instrucciones personalizados en su `opencode.json` o el `~/.config/opencode/opencode.json` global. Esto le permite a usted y a su equipo reutilizar las reglas existentes en lugar de tener que duplicarlas en AGENTS.md. + +Ejemplo: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +También puede utilizar URL remotas para cargar instrucciones desde la web. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +Las instrucciones remotas se recuperan con un tiempo de espera de 5 segundos. + +Todos los archivos de instrucciones se combinan con sus archivos `AGENTS.md`. + +--- + +## Hacer referencia a archivos externos + +Si bien opencode no analiza automáticamente las referencias de archivos en `AGENTS.md`, puedes lograr una funcionalidad similar de dos maneras: + +### Usar opencode.json + +El enfoque recomendado es utilizar el campo `instructions` en `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### Instrucciones manuales en AGENTS.md + +Puede enseñarle a opencode a leer archivos externos proporcionando instrucciones explícitas en su `AGENTS.md`. He aquí un ejemplo práctico: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +Este enfoque le permite: + +- Crear archivos de reglas modulares y reutilizables +- Compartir reglas entre proyectos a través de enlaces simbólicos o submódulos de git +- Mantenga AGENTS.md conciso mientras hace referencia a pautas detalladas +- Asegúrese de que opencode cargue archivos solo cuando sea necesario para la tarea específica + +:::tip +Para monorepos o proyectos con estándares compartidos, usar `opencode.json` con patrones globales (como `packages/*/AGENTS.md`) es más fácil de mantener que las instrucciones manuales. +::: diff --git a/packages/web/src/content/docs/es/sdk.mdx b/packages/web/src/content/docs/es/sdk.mdx new file mode 100644 index 00000000000..d1282b95e9a --- /dev/null +++ b/packages/web/src/content/docs/es/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: Cliente JS con seguridad de tipos para el servidor opencode. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +El SDK opencode JS/TS proporciona un cliente con seguridad de tipos para interactuar con el servidor. +Úselo para crear integraciones y controlar opencode mediante programación. + +[Más información](/docs/server) sobre cómo funciona el servidor. Para ver ejemplos, consulte los [proyectos](/docs/ecosystem#projects) creados por la comunidad. + +--- + +## Instalar + +Instale el SDK desde npm: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## Crear cliente + +Cree una instancia de opencode: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +Esto inicia tanto un servidor como un cliente. + +#### Opciones + +| Opción | Tipo | Descripción | Predeterminado | +| ---------- | ------------- | ----------------------------------------------- | -------------- | +| `hostname` | `string` | Nombre de host del servidor | `127.0.0.1` | +| `port` | `number` | Puerto del servidor | `4096` | +| `signal` | `AbortSignal` | Señal de aborto para cancelación | `undefined` | +| `timeout` | `number` | Tiempo de espera en ms para inicio del servidor | `5000` | +| `config` | `Config` | Objeto de configuración | `{}` | + +--- + +## Configuración + +Puede pasar un objeto de configuración para personalizar el comportamiento. La instancia aún recoge su `opencode.json`, pero puede anular o agregar configuración en línea: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## Solo cliente + +Si ya tiene una instancia en ejecución de opencode, puede crear una instancia de cliente para conectarse a ella: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### Opciones + +| Opción | Tipo | Descripción | Predeterminado | +| --------------- | ---------- | -------------------------------------------- | ----------------------- | +| `baseUrl` | `string` | URL del servidor | `http://localhost:4096` | +| `fetch` | `function` | Implementación de recuperación personalizada | `globalThis.fetch` | +| `parseAs` | `string` | Método de análisis de respuesta | `auto` | +| `responseStyle` | `string` | Estilo de devolución: `data` o `fields` | `fields` | +| `throwOnError` | `boolean` | Lanzar errores en lugar de devolver | `false` | + +--- + +## Tipos + +El SDK incluye definiciones TypeScript para todos los tipos API. Importarlos directamente: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +Todos los tipos se generan a partir de la especificación OpenAPI del servidor y están disponibles en el archivo de tipos. + +--- + +## Errores + +El SDK puede generar errores que puedes detectar y manejar: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## API + +El SDK expone todas las API del servidor a través de un cliente con seguridad de tipos. + +--- + +### Global + +| Método | Descripción | Respuesta | +| ----------------- | --------------------------------------------- | ------------------------------------ | +| `global.health()` | Verificar el estado y la versión del servidor | `{ healthy: true, version: string }` | + +--- + +#### Ejemplos + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### Aplicación + +| Método | Descripción | Respuesta | +| -------------- | ------------------------------------ | ------------------------------------------- | +| `app.log()` | Escribe una entrada de registro | `boolean` | +| `app.agents()` | Listar todos los agentes disponibles | Agent[] | + +--- + +#### Ejemplos + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### Proyecto + +| Método | Descripción | Respuesta | +| ------------------- | -------------------------- | --------------------------------------------- | +| `project.list()` | Listar todos los proyectos | Project[] | +| `project.current()` | Obtener proyecto actual | Project | + +--- + +#### Ejemplos + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### Ruta + +| Método | Descripción | Respuesta | +| ------------ | ------------------- | ---------------------------------------- | +| `path.get()` | Obtener ruta actual | Path | + +--- + +#### Ejemplos + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### Configuración + +| Método | Descripción | Respuesta | +| -------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | Obtener información de configuración | Config | +| `config.providers()` | Lista de proveedores y modelos predeterminados | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### Ejemplos + +```javascript +const config = await client.config.get() + +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` | + +--- + +#### Ejemplos + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### Archivos + +| Método | Descripción | Respuesta | +| ------------------------- | -------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| `find.text({ query })` | Buscar texto en archivos | Matriz de objetos coincidentes con `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `find.files({ query })` | Buscar archivos y directorios por nombre | `string[]` (rutas) | +| `find.symbols({ query })` | Buscar símbolos del espacio de trabajo | Symbol[] | +| `file.read({ query })` | Leer un archivo | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | Obtener el estado de los archivos rastreados | File[] | + +`find.files` admite algunos campos de consulta opcionales: + +- `type`: `"file"` o `"directory"` +- `directory`: anula la raíz del proyecto para la búsqueda. +- `limit`: resultados máximos (1–200) + +--- + +#### Ejemplos + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| Método | Descripción | Respuesta | +| ------------------------------ | ---------------------------------- | --------- | +| `tui.appendPrompt({ body })` | Agregar texto al mensaje | `boolean` | +| `tui.openHelp()` | Abra el cuadro de diálogo de ayuda | `boolean` | +| `tui.openSessions()` | Abrir el selector de sesiones | `boolean` | +| `tui.openThemes()` | Abra el selector de temas | `boolean` | +| `tui.openModels()` | Abrir el selector de modelo | `boolean` | +| `tui.submitPrompt()` | Enviar el mensaje actual | `boolean` | +| `tui.clearPrompt()` | Borrar el mensaje | `boolean` | +| `tui.executeCommand({ body })` | Ejecutar un comando | `boolean` | +| `tui.showToast({ body })` | Mostrar notificación del brindis | `boolean` | + +--- + +#### Ejemplos + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### Autenticación + +| Método | Descripción | Respuesta | +| ------------------- | ---------------------------------------- | --------- | +| `auth.set({ ... })` | Establecer credenciales de autenticación | `boolean` | + +--- + +#### Ejemplos + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### Eventos + +| Método | Descripción | Respuesta | +| ------------------- | ----------------------------------------------- | ----------------------------------------------- | +| `event.subscribe()` | Transmisión de eventos enviados por el servidor | Transmisión de eventos enviados por el servidor | + +--- + +#### Ejemplos + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/es/server.mdx b/packages/web/src/content/docs/es/server.mdx new file mode 100644 index 00000000000..c3ce97421e3 --- /dev/null +++ b/packages/web/src/content/docs/es/server.mdx @@ -0,0 +1,287 @@ +--- +title: Servidor +description: Interactuar con el servidor opencode a través de HTTP. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +El comando `opencode serve` ejecuta un servidor HTTP sin cabeza que expone un punto final OpenAPI que un cliente opencode puede usar. + +--- + +### Uso + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### Opciones + +| Bandera | Descripción | Predeterminado | +| --------------- | ----------------------------------------------------- | ---------------- | +| `--port` | Puerto para escuchar | `4096` | +| `--hostname` | Nombre de host para escuchar | `127.0.0.1` | +| `--mdns` | Habilitar el descubrimiento de mDNS | `false` | +| `--mdns-domain` | Nombre de dominio personalizado para el servicio mDNS | `opencode.local` | +| `--cors` | Orígenes de navegador adicionales para permitir | `[]` | + +`--cors` se puede pasar varias veces: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### Autenticación + +Configure `OPENCODE_SERVER_PASSWORD` para proteger el servidor con autenticación básica HTTP. El nombre de usuario predeterminado es `opencode`, o configure `OPENCODE_SERVER_USERNAME` para anularlo. Esto se aplica tanto a `opencode serve` como a `opencode web`. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### Cómo funciona + +Cuando ejecuta `opencode`, inicia un TUI y un servidor. Donde el TUI es el +Cliente que habla con el servidor. El servidor expone una especificación OpenAPI 3.1 +punto final. Este punto final también se utiliza para generar un [SDK](/docs/sdk). + +:::tip +Utilice el servidor opencode para interactuar con opencode mediante programación. +::: + +Esta arquitectura permite que opencode admita múltiples clientes y le permite interactuar con opencode mediante programación. + +Puede ejecutar `opencode serve` para iniciar un servidor independiente. Si tienes el +opencode TUI ejecutándose, `opencode serve` iniciará un nuevo servidor. + +--- + +#### Conectarse a un servidor existente + +Cuando inicia el TUI, asigna aleatoriamente un puerto y un nombre de host. En su lugar, puede pasar `--hostname` y `--port` [banderas](/docs/cli). Luego use esto para conectarse a su servidor. + +El punto final [`/tui`](#tui) se puede utilizar para conducir el TUI a través del servidor. Por ejemplo, puede completar previamente o ejecutar un mensaje. Esta configuración es utilizada por los complementos OpenCode [IDE](/docs/ide). + +--- + +## Especificaciones + +El servidor publica una especificación OpenAPI 3.1 que se puede ver en: + +``` +http://:/doc +``` + +Por ejemplo, `http://localhost:4096/doc`. Utilice la especificación para generar clientes o inspeccionar tipos de solicitudes y respuestas. O verlo en un explorador Swagger. + +--- + +## API + +El servidor opencode expone las siguientes API. + +--- + +### Global + +| Método | Ruta | Descripción | Respuesta | +| ------ | ---------------- | ------------------------------------------- | ------------------------------------ | +| `GET` | `/global/health` | Obtener el estado y la versión del servidor | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | Obtenga eventos globales (transmisión SSE) | Flujo de eventos | + +--- + +### Proyecto + +| Método | Ruta | Descripción | Respuesta | +| ------ | ------------------ | -------------------------- | --------------------------------------------- | +| `GET` | `/project` | Listar todos los proyectos | Project[] | +| `GET` | `/project/current` | Obtener el proyecto actual | Project | + +--- + +### Ruta y VCS + +| Método | Ruta | Descripción | Respuesta | +| ------ | ------- | -------------------------------------------------- | ------------------------------------------- | +| `GET` | `/path` | Obtener la ruta actual | Path | +| `GET` | `/vcs` | Obtenga información de VCS para el proyecto actual | VcsInfo | + +--- + +### Instancia + +| Método | Ruta | Descripción | Respuesta | +| ------ | ------------------- | ---------------------------- | --------- | +| `POST` | `/instance/dispose` | Eliminar la instancia actual | `boolean` | + +--- + +### Configuración + +| Método | Ruta | Descripción | Respuesta | +| ------- | ------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------- | +| `GET` | `/config` | Obtener información de configuración | Config | +| `PATCH` | `/config` | Actualizar configuración | Config | +| `GET` | `/config/providers` | Lista de proveedores y modelos predeterminados | `{ providers: `Proveedor[]`, default: { [key: string]: string } }` | + +--- + +### Proveedor + +| Método | Ruta | Descripción | Respuesta | +| ------ | -------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------ | +| `GET` | `/provider` | Listar todos los proveedores | `{ all: `Proveedor[]`, default: {...}, connected: string[] }` | +| `GET` | `/provider/auth` | Obtener métodos de autenticación de proveedores | `{ [providerID: string]: `ProviderAuthMethod[]` }` | +| `POST` | `/provider/{id}/oauth/authorize` | Autorizar a un proveedor usando OAuth | ProviderAuthAuthorization | +| `POST` | `/provider/{id}/oauth/callback` | Manejar la devolución de llamada OAuth para un proveedor | `boolean` | + +--- + +### Sesiones + +| Método | Ruta | Descripción | Notas | +| -------- | ---------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------- | +| `GET` | `/session` | Listar todas las sesiones | Devuelve Session[] | +| `POST` | `/session` | Crear una nueva sesión | cuerpo: `{ parentID?, title? }`, devuelve Session | +| `GET` | `/session/status` | Obtener el estado de la sesión para todas las sesiones | Devuelve `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | Obtener detalles de la sesión | Devuelve Session | +| `DELETE` | `/session/:id` | Eliminar una sesión y todos sus datos | Devuelve `boolean` | +| `PATCH` | `/session/:id` | Actualizar propiedades de sesión | cuerpo: `{ title? }`, devuelve Session | +| `GET` | `/session/:id/children` | Obtener las sesiones secundarias de una sesión | Devuelve Session[] | +| `GET` | `/session/:id/todo` | Obtener la lista de tareas pendientes para una sesión | Devuelve Todo[] | +| `POST` | `/session/:id/init` | Analizar aplicación y crear `AGENTS.md` | cuerpo: `{ messageID, providerID, modelID }`, devuelve `boolean` | +| `POST` | `/session/:id/fork` | Bifurca una sesión existente en un mensaje | cuerpo: `{ messageID? }`, devuelve Session | +| `POST` | `/session/:id/abort` | Cancelar una sesión en ejecución | Devuelve `boolean` | +| `POST` | `/session/:id/share` | Compartir una sesión | Devuelve Session | +| `DELETE` | `/session/:id/share` | Dejar de compartir una sesión | Devuelve Session | +| `GET` | `/session/:id/diff` | Obtenga la diferencia para esta sesión | consulta: `messageID?`, devuelve FileDiff[] | +| `POST` | `/session/:id/summarize` | Resumir la sesión | cuerpo: `{ providerID, modelID }`, devuelve `boolean` | +| `POST` | `/session/:id/revert` | Revertir un mensaje | cuerpo: `{ messageID, partID? }`, devuelve `boolean` | +| `POST` | `/session/:id/unrevert` | Restaurar todos los mensajes revertidos | Devuelve `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | Responder a una solicitud de permiso | cuerpo: `{ response, remember? }`, devuelve `boolean` | + +--- + +### Mensajes + +| Método | Ruta | Descripción | Notas | +| ------ | --------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `GET` | `/session/:id/message` | Listar mensajes en una sesión | consulta: `limit?`, devuelve `{ info: `Mensaje`, parts: `Parte[]`}[]` | +| `POST` | `/session/:id/message` | Envía un mensaje y espera respuesta | cuerpo: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, devuelve `{ info: `Mensaje`, parts: `Parte[]`}` | +| `GET` | `/session/:id/message/:messageID` | Obtener detalles del mensaje | Devuelve `{ info: `Mensaje`, parts: `Parte[]`}` | +| `POST` | `/session/:id/prompt_async` | Enviar un mensaje de forma asincrónica (sin espera) | cuerpo: igual que `/session/:id/message`, devuelve `204 No Content` | +| `POST` | `/session/:id/command` | Ejecutar un comando de barra diagonal | cuerpo: `{ messageID?, agent?, model?, command, arguments }`, devuelve `{ info: `Mensaje`, parts: `Parte[]`}` | +| `POST` | `/session/:id/shell` | Ejecute un comando de shell | cuerpo: `{ agent, model?, command }`, devuelve `{ info: `Mensaje`, parts: `Parte[]`}` | + +--- + +### Comandos + +| Método | Ruta | Descripción | Respuesta | +| ------ | ---------- | ------------------------- | --------------------------------------------- | +| `GET` | `/command` | Listar todos los comandos | Command[] | + +--- + +### Archivos + +| Método | Ruta | Descripción | Respuesta | +| ------ | ------------------------ | -------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| `GET` | `/find?pattern=` | Buscar texto en archivos | Matriz de objetos coincidentes con `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `GET` | `/find/file?query=` | Buscar archivos y directorios por nombre | `string[]` (caminos) | +| `GET` | `/find/symbol?query=` | Buscar símbolos del espacio de trabajo | Symbol[] | +| `GET` | `/file?path=` | Listar archivos y directorios | FileNode[] | +| `GET` | `/file/content?path=

` | Leer un archivo | FileContent | +| `GET` | `/file/status` | Obtener el estado de los archivos rastreados | File[] | + +#### Parámetros de consulta de /find/file + +- `query` (obligatorio) — cadena de búsqueda (coincidencia aproximada) +- `type` (opcional): limita los resultados a `"file"` o `"directory"` +- `directory` (opcional): anula la raíz del proyecto para la búsqueda. +- `limit` (opcional) — resultados máximos (1–200) +- `dirs` (opcional): indicador heredado (`"false"` devuelve solo archivos) + +--- + +### Herramientas (experimentales) + +| Método | Ruta | Descripción | Respuesta | +| ------ | ------------------------------------------- | ---------------------------------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | Listar todos los ID de herramientas | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | Listar herramientas con esquemas JSON para un modelo | ToolList | + +--- + +### LSP, formateadores y MCP + +| Método | Ruta | Descripción | Respuesta | +| ------ | ------------ | ------------------------------------- | --------------------------------------------------------- | +| `GET` | `/lsp` | Obtener el estado del servidor LSP | LSPStatus[] | +| `GET` | `/formatter` | Obtener estado del formateador | FormatterStatus[] | +| `GET` | `/mcp` | Obtener el estado del servidor MCP | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | Agregue el servidor MCP dinámicamente | cuerpo: `{ name, config }`, devuelve MCP objeto de estado | + +--- + +### Agentes + +| Método | Ruta | Descripción | Respuesta | +| ------ | -------- | ------------------------------------ | ------------------------------------------- | +| `GET` | `/agent` | Listar todos los agentes disponibles | Agent[] | + +--- + +### Registro + +| Método | Ruta | Descripción | Respuesta | +| ------ | ------ | --------------------------------------------------------------------------- | --------- | +| `POST` | `/log` | Escribir entrada de registro. Cuerpo: `{ service, level, message, extra? }` | `boolean` | + +--- + +### TUI + +| Método | Ruta | Descripción | Respuesta | +| ------ | ----------------------- | ------------------------------------------------- | ------------------------------ | +| `POST` | `/tui/append-prompt` | Agregar texto al mensaje | `boolean` | +| `POST` | `/tui/open-help` | Abra el cuadro de diálogo de ayuda | `boolean` | +| `POST` | `/tui/open-sessions` | Abrir el selector de sesiones | `boolean` | +| `POST` | `/tui/open-themes` | Abra el selector de temas | `boolean` | +| `POST` | `/tui/open-models` | Abrir el selector de modelo | `boolean` | +| `POST` | `/tui/submit-prompt` | Enviar el mensaje actual | `boolean` | +| `POST` | `/tui/clear-prompt` | Borrar el mensaje | `boolean` | +| `POST` | `/tui/execute-command` | Ejecutar un comando (`{ command }`) | `boolean` | +| `POST` | `/tui/show-toast` | Mostrar brindis (`{ title?, message, variant }`) | `boolean` | +| `GET` | `/tui/control/next` | Espere la próxima solicitud de control | Objeto de solicitud de control | +| `POST` | `/tui/control/response` | Responder a una solicitud de control (`{ body }`) | `boolean` | + +--- + +### Autenticación + +| Método | Ruta | Descripción | Respuesta | +| ------ | ----------- | ----------------------------------------------------------------------------------------------- | --------- | +| `PUT` | `/auth/:id` | Establecer credenciales de autenticación. El cuerpo debe coincidir con el esquema del proveedor | `boolean` | + +--- + +### Eventos + +| Método | Ruta | Descripción | Respuesta | +| ------ | -------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | +| `GET` | `/event` | Transmisión de eventos enviados por el servidor. El primer evento es `server.connected`, luego eventos de bus | Transmisión de eventos enviados por el servidor | + +--- + +### Documentación + +| Método | Ruta | Descripción | Respuesta | +| ------ | ------ | -------------------------- | -------------------------------------- | +| `GET` | `/doc` | Especificación OpenAPI 3.1 | Página HTML con especificación OpenAPI | diff --git a/packages/web/src/content/docs/es/share.mdx b/packages/web/src/content/docs/es/share.mdx new file mode 100644 index 00000000000..e1c62a031c0 --- /dev/null +++ b/packages/web/src/content/docs/es/share.mdx @@ -0,0 +1,128 @@ +--- +title: Compartir +description: Comparte tus conversaciones OpenCode. +--- + +La función para compartir de OpenCode te permite crear enlaces públicos a tus conversaciones de OpenCode, para que puedas colaborar con compañeros de equipo u obtener ayuda de otros. + +:::note +Las conversaciones compartidas son de acceso público para cualquier persona que tenga el enlace. +::: + +--- + +## Cómo funciona + +Cuando compartes una conversación, OpenCode: + +1. Crea una URL pública única para su sesión. +2. Sincroniza tu historial de conversaciones con nuestros servidores +3. Hace que la conversación sea accesible a través del enlace para compartir: `opncd.ai/s/` + +--- + +## Uso compartido + +OpenCode admite tres modos de compartir que controlan cómo se comparten las conversaciones: + +--- + +### Manual (predeterminado) + +De forma predeterminada, OpenCode usa el modo de compartir manual. Las sesiones no se comparten automáticamente, pero puedes compartirlas manualmente usando el comando `/share`: + +``` +/share +``` + +Esto generará una URL única que se copiará en su portapapeles. + +Para configurar explícitamente el modo manual en su [archivo de configuración](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### Compartir automáticamente + +Puede habilitar el uso compartido automático para todas las conversaciones nuevas configurando la opción `share` en `"auto"` en su [archivo de configuración](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +Con el uso compartido automático habilitado, cada nueva conversación se compartirá automáticamente y se generará un enlace. + +--- + +### Desactivado + +Puede desactivar el uso compartido por completo configurando la opción `share` en `"disabled"` en su [archivo de configuración](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +Para aplicar esto en todo su equipo para un proyecto determinado, agréguelo al `opencode.json` en su proyecto y regístrelo en Git. + +--- + +## Dejar de compartir + +Para dejar de compartir una conversación y eliminarla del acceso público: + +``` +/unshare +``` + +Esto eliminará el enlace para compartir y eliminará los datos relacionados con la conversación. + +--- + +## Privacidad + +Hay algunas cosas a tener en cuenta al compartir una conversación. + +--- + +### Retención de datos + +Las conversaciones compartidas permanecen accesibles hasta que las dejes de compartir explícitamente. Este +incluye: + +- Historial de conversaciones completo +- Todos los mensajes y respuestas. +- Metadatos de la sesión + +--- + +### Recomendaciones + +- Comparta únicamente conversaciones que no contengan información confidencial. +- Revisar el contenido de la conversación antes de compartir. +- Dejar de compartir conversaciones cuando se complete la colaboración. +- Evite compartir conversaciones con código propietario o datos confidenciales. +- Para proyectos confidenciales, deshabilite el uso compartido por completo. + +--- + +## Para empresas + +Para implementaciones empresariales, la función de compartir puede ser: + +- **Desactivado** completamente por motivos de seguridad. +- **Restringido** solo a usuarios autenticados a través de SSO +- **Autohospedado** en tu propia infraestructura + +[Obtenga más información](/docs/enterprise) sobre el uso de opencode en su organización. diff --git a/packages/web/src/content/docs/es/skills.mdx b/packages/web/src/content/docs/es/skills.mdx new file mode 100644 index 00000000000..46f7bc24f5c --- /dev/null +++ b/packages/web/src/content/docs/es/skills.mdx @@ -0,0 +1,222 @@ +--- +title: "Habilidades del agente" +description: "Defina el comportamiento reutilizable mediante definiciones de SKILL.md" +--- + +Las habilidades del agente permiten a OpenCode descubrir instrucciones reutilizables de su repositorio o directorio de inicio. +Las habilidades se cargan bajo demanda a través de la herramienta nativa `skill`: los agentes ven las habilidades disponibles y pueden cargar el contenido completo cuando sea necesario. + +--- + +## Colocar archivos + +Cree una carpeta por nombre de habilidad y coloque un `SKILL.md` dentro de ella. +OpenCode busca estas ubicaciones: + +- Configuración del proyecto: `.opencode/skills//SKILL.md` +- Configuración global: `~/.config/opencode/skills//SKILL.md` +- Compatible con Proyecto Claude: `.claude/skills//SKILL.md` +- Compatible con Claude global: `~/.claude/skills//SKILL.md` +- Compatible con agente de proyecto: `.agents/skills//SKILL.md` +- Compatible con agentes globales: `~/.agents/skills//SKILL.md` + +--- + +## Entender el descubrimiento + +Para las rutas locales del proyecto, OpenCode sube desde su directorio de trabajo actual hasta llegar al árbol de trabajo de git. +Carga cualquier `skills/*/SKILL.md` coincidente en `.opencode/` y cualquier `.claude/skills/*/SKILL.md` o `.agents/skills/*/SKILL.md` coincidente a lo largo del camino. + +Las definiciones globales también se cargan desde `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md` y `~/.agents/skills/*/SKILL.md`. + +--- + +## Escribir la introducción + +Cada `SKILL.md` debe comenzar con el frontmatter de YAML. +Sólo se reconocen estos campos: + +- `name` (obligatorio) +- `description` (obligatorio) +- `license` (opcional) +- `compatibility` (opcional) +- `metadata` (opcional, mapa de cadena a cadena) + +Los campos desconocidos se ignoran. + +--- + +## Validar nombres + +`name` debe: + +- Tener entre 1 y 64 caracteres. +- Ser alfanuméricos en minúsculas con separadores de guión simple +- No comienza ni termina con `-` +- No contener `--` consecutivos +- Coincide con el nombre del directorio que contiene `SKILL.md` + +expresión regular equivalente: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## Seguir las reglas de longitud + +`description` debe tener entre 1 y 1024 caracteres. +Manténgalo lo suficientemente específico para que el agente elija correctamente. + +--- + +## Usar un ejemplo + +Crea `.opencode/skills/git-release/SKILL.md` así: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## Reconocer la descripción de la herramienta + +OpenCode enumera las habilidades disponibles en la descripción de la herramienta `skill`. +Cada entrada incluye el nombre y la descripción de la habilidad: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +El agente carga una habilidad llamando a la herramienta: + +``` +skill({ name: "git-release" }) +``` + +--- + +## Configurar permisos + +Controle a qué agentes de habilidades pueden acceder utilizando permisos basados ​​en patrones en `opencode.json`: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| Permiso | Comportamiento | +| ------- | ------------------------------------------------- | +| `allow` | La habilidad se carga inmediatamente | +| `deny` | Habilidad oculta al agente, acceso rechazado | +| `ask` | Se solicita al usuario aprobación antes de cargar | + +Los patrones admiten comodines: `internal-*` coincide con `internal-docs`, `internal-tools`, etc. + +--- + +## Anulación por agente + +Otorgue a agentes específicos permisos diferentes a los predeterminados globales. + +**Para agentes personalizados** (en el frente del agente): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**Para agentes integrados** (en `opencode.json`): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## Deshabilitar la herramienta de habilidades + +Deshabilite completamente las habilidades para los agentes que no deberían usarlas: + +**Para agentes personalizados**: + +```yaml +--- +tools: + skill: false +--- +``` + +**Para agentes integrados**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +Cuando está deshabilitada, la sección `` se omite por completo. + +--- + +## Solucionar problemas de carga + +Si una habilidad no aparece: + +1. Verifique que `SKILL.md` esté escrito en mayúsculas. +2. Verifique que el frontmatter incluya `name` y `description` +3. Asegúrese de que los nombres de las habilidades sean únicos en todas las ubicaciones +4. Verifique los permisos: las habilidades con `deny` están ocultas para los agentes diff --git a/packages/web/src/content/docs/es/themes.mdx b/packages/web/src/content/docs/es/themes.mdx new file mode 100644 index 00000000000..d7c7426267c --- /dev/null +++ b/packages/web/src/content/docs/es/themes.mdx @@ -0,0 +1,369 @@ +--- +title: Temas +description: Seleccione un tema integrado o defina el suyo propio. +--- + +Con OpenCode puede seleccionar uno de varios temas integrados, usar un tema que se adapte al tema de su terminal o definir su propio tema personalizado. + +De forma predeterminada, OpenCode usa nuestro propio tema `opencode`. + +--- + +## Requisitos del terminal + +Para que los temas se muestren correctamente con su paleta de colores completa, su terminal debe admitir **truecolor** (color de 24 bits). La mayoría de los terminales modernos admiten esto de forma predeterminada, pero es posible que debas habilitarlo: + +- **Verificar soporte**: Ejecute `echo $COLORTERM` - debería generar `truecolor` o `24bit` +- **Habilitar color verdadero**: establezca la variable de entorno `COLORTERM=truecolor` en su perfil de shell +- **Compatibilidad de terminal**: asegúrese de que su emulador de terminal admita colores de 24 bits (la mayoría de los terminales modernos como iTerm2, Alacritty, Kitty, Windows Terminal y las versiones recientes de GNOME Terminal lo hacen) + +Sin soporte de color verdadero, los temas pueden aparecer con una precisión de color reducida o retroceder a la aproximación de 256 colores más cercana. + +--- + +## Temas integrados + +OpenCode viene con varios temas integrados. + +| Nombre | Descripción | +| ---------------------- | ----------------------------------------------------------------------------- | +| `system` | Se adapta al color de fondo de tu terminal | +| `tokyonight` | Basado en el tema [Tokyonight](https://github.com/folke/tokyonight.nvim) | +| `everforest` | Basado en el tema [Everforest](https://github.com/sainnhe/everforest) | +| `ayu` | Basado en el tema oscuro de [Ayu](https://github.com/ayu-theme) | +| `catppuccin` | Basado en el tema [Catppuccin](https://github.com/catppuccin) | +| `catppuccin-macchiato` | Basado en el tema [Catppuccin](https://github.com/catppuccin) | +| `gruvbox` | Basado en el tema [Gruvbox](https://github.com/morhetz/gruvbox) | +| `kanagawa` | Basado en el tema [Kanagawa](https://github.com/rebelot/kanagawa.nvim) | +| `nord` | Basado en el tema [Nord](https://github.com/nordtheme/nord) | +| `matrix` | Verde estilo hacker sobre el tema negro | +| `one-dark` | Basado en el tema oscuro [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) | + +Y más, constantemente agregamos nuevos temas. + +--- + +## Tema del sistema + +El tema `system` está diseñado para adaptarse automáticamente a la combinación de colores de su terminal. A diferencia de los temas tradicionales que utilizan colores fijos, el tema _system_: + +- **Genera escala de grises**: Crea una escala de grises personalizada basada en el color de fondo de tu terminal, asegurando un contraste óptimo. +- **Utiliza colores ANSI**: aprovecha los colores ANSI estándar (0-15) para resaltar la sintaxis y los elementos de la interfaz de usuario, que respetan la paleta de colores de su terminal. +- **Conserva los valores predeterminados del terminal**: utiliza `none` para el texto y los colores de fondo para mantener la apariencia nativa de su terminal. + +El tema del sistema es para usuarios que: + +- Quiere que OpenCode coincida con la apariencia de su terminal +- Utilice esquemas de color de terminal personalizados +- Prefiere una apariencia consistente en todas las aplicaciones de terminal + +--- + +## 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). + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## Temas personalizados + +OpenCode admite un sistema de temas flexible basado en JSON que permite a los usuarios crear y personalizar temas fácilmente. + +--- + +### Jerarquía + +Los temas se cargan desde varios directorios en el siguiente orden, donde los directorios posteriores anulan los anteriores: + +1. **Temas integrados**: están integrados en el binario +2. **Directorio de configuración de usuario**: definido en `~/.config/opencode/themes/*.json` o `$XDG_CONFIG_HOME/opencode/themes/*.json` +3. **Directorio raíz del proyecto**: definido en `/.opencode/themes/*.json` +4. **Directorio de trabajo actual** - Definido en `./.opencode/themes/*.json` + +Si varios directorios contienen un tema con el mismo nombre, se utilizará el tema del directorio con mayor prioridad. + +--- + +### Crear un tema + +Para crear un tema personalizado, cree un archivo JSON en uno de los directorios de temas. + +Para temas para todo el usuario: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +Y para temas específicos del proyecto. + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### Formato JSON + +Los temas utilizan un formato JSON flexible compatible con: + +- **Colores hexadecimales**: `"#ffffff"` +- **Colores ANSI**: `3` (0-255) +- **Referencias de color**: `"primary"` o definiciones personalizadas +- **Variantes oscuras/claras**: `{"dark": "#000", "light": "#fff"}` +- **Sin color**: `"none"` - Utiliza el color predeterminado del terminal o transparente + +--- + +### Definiciones de colores + +La sección `defs` es opcional y le permite definir colores reutilizables a los que se puede hacer referencia en el tema. + +--- + +### Valores predeterminados del terminal + +El valor especial `"none"` se puede utilizar para que cualquier color herede el color predeterminado del terminal. Esto es particularmente útil para crear temas que combinen perfectamente con la combinación de colores de su terminal: + +- `"text": "none"` - Utiliza el color de primer plano predeterminado del terminal +- `"background": "none"` - Utiliza el color de fondo predeterminado del terminal + +--- + +### Ejemplo + +A continuación se muestra un ejemplo de un tema personalizado: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/es/tools.mdx b/packages/web/src/content/docs/es/tools.mdx new file mode 100644 index 00000000000..69f1340466a --- /dev/null +++ b/packages/web/src/content/docs/es/tools.mdx @@ -0,0 +1,379 @@ +--- +title: Herramientas +description: Administre las herramientas que puede usar un LLM. +--- + +Las herramientas permiten que LLM realice acciones en su código base. OpenCode viene con un conjunto de herramientas integradas, pero puede ampliarlo con [herramientas personalizadas](/docs/custom-tools) o [servidores MCP](/docs/mcp-servers). + +De forma predeterminada, todas las herramientas están **habilitadas** y no necesitan permiso para ejecutarse. Puede controlar el comportamiento de la herramienta a través de [permisos](/docs/permissions). + +--- + +## Configuración + +Utilice el campo `permission` para controlar el comportamiento de la herramienta. Puede permitir, denegar o exigir aprobación para cada herramienta. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +También puedes utilizar comodines para controlar varias herramientas a la vez. Por ejemplo, para solicitar aprobación para todas las herramientas de un servidor MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[Más información](/docs/permissions) sobre la configuración de permisos. + +--- + +## Integradas + +Aquí están todas las herramientas integradas disponibles en OpenCode. + +--- + +### bash + +Ejecute comandos de shell en el entorno de su proyecto. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +Esta herramienta permite que LLM ejecute comandos de terminal como `npm install`, `git status` o cualquier otro comando de shell. + +--- + +### edit + +Modifique archivos existentes utilizando reemplazos de cadenas exactas. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Esta herramienta realiza ediciones precisas de archivos reemplazando coincidencias de texto exactas. Es la forma principal en que LLM modifica el código. + +--- + +### write + +Cree nuevos archivos o sobrescriba los existentes. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Utilice esto para permitir que LLM cree nuevos archivos. Sobrescribirá los archivos existentes si ya existen. + +:::note +La herramienta `write` está controlada por el permiso `edit`, que cubre todas las modificaciones de archivos (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### read + +Lea el contenido del archivo desde su base de código. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +Esta herramienta lee archivos y devuelve su contenido. Admite la lectura de rangos de líneas específicos para archivos grandes. + +--- + +### grep + +Busque contenidos de archivos utilizando expresiones regulares. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +Búsqueda rápida de contenido en su base de código. Admite sintaxis de expresiones regulares completa y filtrado de patrones de archivos. + +--- + +### glob + +Encuentre archivos por coincidencia de patrones. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +Busque archivos usando patrones globales como `**/*.js` o `src/**/*.ts`. Devuelve rutas de archivos coincidentes ordenadas por hora de modificación. + +--- + +### list + +Enumere archivos y directorios en una ruta determinada. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +Esta herramienta enumera el contenido del directorio. Acepta patrones globales para filtrar resultados. + +--- + +### lsp (experimental) + +Interactúe con sus servidores LSP configurados para obtener funciones de inteligencia de código como definiciones, referencias, información de desplazamiento y jerarquía de llamadas. + +:::note +Esta herramienta solo está disponible cuando `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (o `OPENCODE_EXPERIMENTAL=true`). +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +Las operaciones admitidas incluyen `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls` y `outgoingCalls`. + +Para configurar qué servidores LSP están disponibles para su proyecto, consulte [Servidores LSP](/docs/lsp). + +--- + +### patch + +Aplicar parches a los archivos. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Esta herramienta aplica archivos de parche a su código base. Útil para aplicar diferencias y parches de diversas fuentes. + +:::note +La herramienta `patch` está controlada por el permiso `edit`, que cubre todas las modificaciones de archivos (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### skill + +Cargue una [habilidad](/docs/skills) (un archivo `SKILL.md`) y devuelva su contenido en la conversación. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +Administre listas de tareas pendientes durante las sesiones de codificación. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +Crea y actualiza listas de tareas para realizar un seguimiento del progreso durante operaciones complejas. El LLM usa esto para organizar tareas de varios pasos. + +:::note +Esta herramienta está deshabilitada para los subagentes de forma predeterminada, pero puede habilitarla manualmente. [Más información](/docs/agents/#permissions) +::: + +--- + +### todoread + +Leer listas de tareas pendientes existentes. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +Lee el estado actual de la lista de tareas pendientes. Utilizado por LLM para rastrear qué tareas están pendientes o completadas. + +:::note +Esta herramienta está deshabilitada para los subagentes de forma predeterminada, pero puede habilitarla manualmente. [Más información](/docs/agents/#permissions) +::: + +--- + +### webfetch + +Obtener contenido web. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +Permite que LLM busque y lea páginas web. Útil para buscar documentación o investigar recursos en línea. + +--- + +### websearch + +Busque información en la web. + +:::note +Esta herramienta solo está disponible cuando se utiliza el proveedor OpenCode o cuando la variable de entorno `OPENCODE_ENABLE_EXA` está configurada en cualquier valor verdadero (por ejemplo, `true` o `1`). + +Para habilitar al iniciar OpenCode: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +Realiza búsquedas web utilizando Exa AI para encontrar información relevante en línea. Útil para investigar temas, encontrar eventos actuales o recopilar información más allá del límite de datos de entrenamiento. + +No se requiere ninguna clave API: la herramienta se conecta directamente al servicio MCP alojado de Exa AI sin autenticación. + +:::tip +Utilice `websearch` cuando necesite encontrar información (descubrimiento) y `webfetch` cuando necesite recuperar contenido de una URL específica (recuperación). +::: + +--- + +### question + +Haga preguntas al usuario durante la ejecución. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +Esta herramienta permite que LLM haga preguntas al usuario durante una tarea. Es útil para: + +- Recopilar preferencias o requisitos del usuario. +- Aclarar instrucciones ambiguas +- Tomar decisiones sobre las opciones de implementación. +- Ofrecer opciones sobre qué dirección tomar. + +Cada pregunta incluye un encabezado, el texto de la pregunta y una lista de opciones. Los usuarios pueden seleccionar entre las opciones proporcionadas o escribir una respuesta personalizada. Cuando hay varias preguntas, los usuarios pueden navegar entre ellas antes de enviar todas las respuestas. + +--- + +## Herramientas personalizadas + +Las herramientas personalizadas le permiten definir sus propias funciones a las que LLM puede llamar. Estos están definidos en su archivo de configuración y pueden ejecutar código arbitrario. + +[Más información](/docs/custom-tools) sobre la creación de herramientas personalizadas. + +--- + +## Servidores MCP + +Los servidores MCP (Model Context Protocol) le permiten integrar herramientas y servicios externos. Esto incluye acceso a bases de datos, integraciones API y servicios de terceros. + +[Más información](/docs/mcp-servers) sobre la configuración de servidores MCP. + +--- + +## Internos + +Internamente, herramientas como `grep`, `glob` y `list` usan [ripgrep](https://github.com/BurntSushi/ripgrep) bajo el capó. De forma predeterminada, ripgrep respeta los patrones `.gitignore`, lo que significa que los archivos y directorios enumerados en su `.gitignore` se excluirán de las búsquedas y listados. + +--- + +### Ignorar patrones + +Para incluir archivos que normalmente se ignorarían, cree un archivo `.ignore` en la raíz de su proyecto. Este archivo puede permitir explícitamente ciertas rutas. + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +Por ejemplo, este archivo `.ignore` permite que ripgrep busque dentro de los directorios `node_modules/`, `dist/` y `build/` incluso si figuran en `.gitignore`. diff --git a/packages/web/src/content/docs/es/troubleshooting.mdx b/packages/web/src/content/docs/es/troubleshooting.mdx new file mode 100644 index 00000000000..19f41bd6877 --- /dev/null +++ b/packages/web/src/content/docs/es/troubleshooting.mdx @@ -0,0 +1,300 @@ +--- +title: Solución de problemas +description: Problemas comunes y cómo resolverlos. +--- + +Para depurar problemas con OpenCode, comience verificando los registros y los datos locales que almacena en el disco. + +--- + +## Registros + +Los archivos de registro se escriben en: + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: Presione `WIN+R` y pegue `%USERPROFILE%\.local\share\opencode\log` + +Los archivos de registro reciben nombres con marcas de tiempo (por ejemplo, `2025-01-09T123456.log`) y se conservan los 10 archivos de registro más recientes. + +Puede configurar el nivel de registro con la opción de línea de comandos `--log-level` para obtener información de depuración más detallada. Por ejemplo, `opencode --log-level DEBUG`. + +--- + +## Almacenamiento + +opencode almacena datos de sesión y otros datos de aplicaciones en el disco en: + +- **macOS/Linux**: `~/.local/share/opencode/` +- **Windows**: Presione `WIN+R` y pegue `%USERPROFILE%\.local\share\opencode` + +Este directorio contiene: + +- `auth.json` - Datos de autenticación como API claves, OAuth tokens +- `log/` - Registros de aplicaciones +- `project/` - Datos específicos del proyecto, como datos de sesión y mensajes. + - Si el proyecto está dentro de un repositorio de Git, se almacena en `.//storage/` + - Si no es un repositorio de Git, se almacena en `./global/storage/` + +--- + +## Aplicación de escritorio + +OpenCode Desktop ejecuta un servidor OpenCode local (el sidecar `opencode-cli`) en segundo plano. La mayoría de los problemas se deben a un complemento que no funciona correctamente, una memoria caché dañada o una mala configuración del servidor. + +### Comprobaciones rápidas + +- Salga por completo y reinicie la aplicación. +- Si la aplicación muestra una pantalla de error, haga clic en **Reiniciar** y copie los detalles del error. +- Solo macOS: menú `OpenCode` -> **Recargar vista web** (ayuda si la interfaz de usuario está en blanco/congelada). + +--- + +### Deshabilitar complementos + +Si la aplicación de escritorio falla al iniciarse, se bloquea o se comporta de manera extraña, comience por deshabilitar los complementos. + +#### Verifique la configuración global + +Abra su archivo de configuración global y busque una clave `plugin`. + +- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (o `~/.config/opencode/opencode.json`) +- **macOS/Linux** (instalaciones anteriores): `~/.local/share/opencode/opencode.jsonc` +- **Windows**: Presione `WIN+R` y pegue `%USERPROFILE%\.config\opencode\opencode.jsonc` + +Si tiene complementos configurados, desactívelos temporalmente eliminando la clave o configurándola en una matriz vacía: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### Verificar directorios de complementos + +OpenCode también puede cargar complementos locales desde el disco. Quítelos temporalmente del camino (o cambie el nombre de la carpeta) y reinicie la aplicación de escritorio: + +- **Complementos globales** + - **macOS/Linux**: `~/.config/opencode/plugins/` + - **Windows**: Presione `WIN+R` y pegue `%USERPROFILE%\.config\opencode\plugins` +- **Complementos de proyecto** (solo si usas la configuración por proyecto) + - `/.opencode/plugins/` + +Si la aplicación comienza a funcionar nuevamente, vuelva a habilitar los complementos uno a la vez para encontrar cuál está causando el problema. + +--- + +### Borrar el caché + +Si deshabilitar los complementos no ayuda (o la instalación de un complemento está bloqueada), borre el caché para que OpenCode pueda reconstruirlo. + +1. Salga de OpenCode Desktop por completo. +2. Elimine el directorio de caché: + +- **macOS**: Buscador -> `Cmd+Shift+G` -> pegar `~/.cache/opencode` +- **Linux**: eliminar `~/.cache/opencode` (o ejecutar `rm -rf ~/.cache/opencode`) +- **Windows**: Presione `WIN+R` y pegue `%USERPROFILE%\.cache\opencode` + +3. Reinicie el escritorio OpenCode. + +--- + +### Solucionar problemas de conexión del servidor + +OpenCode Desktop puede iniciar su propio servidor local (predeterminado) o conectarse a la URL de un servidor que haya configurado. + +Si ve un cuadro de diálogo **"Error de conexión"** (o la aplicación nunca pasa de la pantalla de inicio), busque una URL de servidor personalizada. + +#### Borrar la URL del servidor predeterminado del escritorio + +Desde la pantalla de inicio, haga clic en el nombre del servidor (con el punto de estado) para abrir el selector de servidor. En la sección **Servidor predeterminado**, haga clic en **Borrar**. + +#### Elimina `server.port` / `server.hostname` de tu configuración + +Si su `opencode.json(c)` contiene una sección `server`, elimínela temporalmente y reinicie la aplicación de escritorio. + +#### Verificar variables de entorno + +Si tiene `OPENCODE_PORT` configurado en su entorno, la aplicación de escritorio intentará usar ese puerto para el servidor local. + +- Desarme `OPENCODE_PORT` (o elija un puerto libre) y reinicie. + +--- + +### Linux: Problemas con Wayland/X11 + +En Linux, algunas configuraciones de Wayland pueden causar ventanas en blanco o errores de compositor. + +- Si estás en Wayland y la aplicación está en blanco o falla, intenta iniciarla con `OC_ALLOW_WAYLAND=1`. +- Si eso empeora las cosas, elimínelo e intente iniciarlo en una sesión X11. + +--- + +### Windows: tiempo de ejecución de WebView2 + +En Windows, el escritorio OpenCode requiere Microsoft Edge **WebView2 Runtime**. Si la aplicación se abre en una ventana en blanco o no se inicia, instale/actualice WebView2 e inténtelo nuevamente. + +--- + +### Windows: Problemas generales de rendimiento + +Si tiene un rendimiento lento, problemas de acceso a archivos o problemas de terminal en Windows, intente usar [WSL (Windows Subsistema para Linux)](/docs/windows-wsl). WSL proporciona un entorno Linux que funciona de manera más fluida con las funciones de OpenCode. + +--- + +### Notificaciones que no se muestran + +OpenCode Desktop solo muestra notificaciones del sistema cuando: + +- las notificaciones están habilitadas para OpenCode en la configuración de su sistema operativo, y +- la ventana de la aplicación no está enfocada. + +--- + +### Restablecer el almacenamiento de la aplicación de escritorio (último recurso) + +Si la aplicación no se inicia y no puede borrar la configuración desde la interfaz de usuario, restablezca el estado guardado de la aplicación de escritorio. + +1. Salga del escritorio OpenCode. +2. Busque y elimine estos archivos (se encuentran en el directorio de datos de la aplicación de escritorio OpenCode): + +- `opencode.settings.dat` (URL del servidor predeterminado de escritorio) +- `opencode.global.dat` y `opencode.workspace.*.dat` (estado de la interfaz de usuario como servidores/proyectos recientes) + +Para encontrar el directorio rápidamente: + +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (luego busque los nombres de archivo arriba) +- **Linux**: busque en `~/.local/share` los nombres de archivo anteriores +- **Windows**: Presione `WIN+R` -> `%APPDATA%` (luego busque los nombres de archivo arriba) + +--- + +## Obtener ayuda + +Si tiene problemas con OpenCode: + +1. **Informar problemas el GitHub** + + La mejor manera de informar errores o solicitar funciones es a través de nuestro repositorio GitHub: + + [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + + Antes de crear un nuevo problema, busque los problemas existentes para ver si su problema ya ha sido informado. + +2. **Únete a nuestro Discord** + + Para obtener ayuda en tiempo real y debates comunitarios, únase a nuestro servidor de Discord: + + [**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## Problemas comunes + +A continuación se detallan algunos problemas comunes y cómo resolverlos. + +--- + +### OpenCode no se inicia + +1. Verifique los registros en busca de mensajes de error. +2. Intente ejecutar con `--print-logs` para ver el resultado en la terminal. +3. Asegúrese de tener la última versión con `opencode upgrade` + +--- + +### Problemas de autenticación + +1. Intente volver a autenticarse con el comando `/connect` en TUI +2. Verifique que sus claves API sean válidas +3. Asegúrese de que su red permita conexiones al API del proveedor. + +--- + +### Modelo no disponible + +1. Comprueba que te has autenticado con el proveedor. +2. Verifique que el nombre del modelo en su configuración sea correcto +3. Algunos modelos pueden requerir acceso o suscripciones específicas + +Si encuentra `ProviderModelNotFoundError`, lo más probable es que esté equivocado. +haciendo referencia a un modelo en alguna parte. +Se debe hacer referencia a los modelos así: `/` + +Ejemplos: + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +Para saber a qué modelos tiene acceso, ejecute `opencode models` + +--- + +### Error de inicio del proveedor + +Si encuentra un ProviderInitError, es probable que tenga una configuración no válida o dañada. + +Para resolver esto: + +1. Primero, verifique que su proveedor esté configurado correctamente siguiendo la [guía de proveedores](/docs/providers) +2. Si el problema persiste, intente borrar la configuración almacenada: + + ```bash + rm -rf ~/.local/share/opencode + ``` + + En Windows, presione `WIN+R` y elimine: `%USERPROFILE%\.local\share\opencode` + +3. Vuelva a autenticarse con su proveedor utilizando el comando `/connect` en TUI. + +--- + +### AI_APICallError y problemas con el paquete del proveedor + +Si encuentra errores de llamada API, esto puede deberse a paquetes de proveedores obsoletos. opencode instala dinámicamente paquetes de proveedores (OpenAI, Anthropic, Google, etc.) según sea necesario y los almacena en caché localmente. + +Para resolver problemas con el paquete del proveedor: + +1. Borre la caché del paquete del proveedor: + + ```bash + rm -rf ~/.cache/opencode + ``` + + En Windows, presione `WIN+R` y elimine: `%USERPROFILE%\.cache\opencode` + +2. Reinicie opencode para reinstalar los paquetes del proveedor más recientes. + +Esto obligará a opencode a descargar las versiones más recientes de los paquetes del proveedor, lo que a menudo resuelve problemas de compatibilidad con los parámetros del modelo y los cambios de API. + +--- + +### Copiar/pegar no funciona en Linux + +Los usuarios de Linux deben tener instalada una de las siguientes utilidades del portapapeles para que funcione la función copiar/pegar: + +**Para sistemas X11:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**Para sistemas Wayland:** + +```bash +apt install -y wl-clipboard +``` + +**Para entornos sin cabeza:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +opencode detectará si estás usando Wayland y prefieres `wl-clipboard`; de lo contrario, intentará encontrar herramientas del portapapeles en el orden de: `xclip` y `xsel`. diff --git a/packages/web/src/content/docs/es/tui.mdx b/packages/web/src/content/docs/es/tui.mdx new file mode 100644 index 00000000000..ba7430f5020 --- /dev/null +++ b/packages/web/src/content/docs/es/tui.mdx @@ -0,0 +1,390 @@ +--- +title: TUI +description: Usando la interfaz de usuario del terminal OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode proporciona una interfaz de terminal interactiva o TUI para trabajar en sus proyectos con un LLM. + +Al ejecutar OpenCode se inicia TUI para el directorio actual. + +```bash +opencode +``` + +O puede iniciarlo para un directorio de trabajo específico. + +```bash +opencode /path/to/project +``` + +Una vez que esté en TUI, puede indicarlo con un mensaje. + +```text +Give me a quick summary of the codebase. +``` + +--- + +## Referencias de archivos + +Puede hacer referencia a archivos en sus mensajes usando `@`. Esto realiza una búsqueda difusa de archivos en el directorio de trabajo actual. + +:::tip +También puede utilizar `@` para hacer referencia a archivos en sus mensajes. +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +El contenido del archivo se agrega a la conversación automáticamente. + +--- + +## Comandos bash + +Inicie un mensaje con `!` para ejecutar un comando de shell. + +```bash frame="none" +!ls -la +``` + +El resultado del comando se agrega a la conversación como resultado de la herramienta. + +--- + +## Comandos + +Cuando utilice OpenCode TUI, puede escribir `/` seguido de un nombre de comando para ejecutar acciones rápidamente. Por ejemplo: + +```bash frame="none" +/help +``` + +La mayoría de los comandos también tienen una combinación de teclas que utiliza `ctrl+x` como tecla principal, donde `ctrl+x` es la tecla principal predeterminada. [Más información](/docs/keybinds). + +Aquí están todos los comandos de barra diagonal disponibles: + +--- + +### connect + +Agregue un proveedor a OpenCode. Le permite seleccionar entre proveedores disponibles y agregar sus claves API. + +```bash frame="none" +/connect +``` + +--- + +### compact + +Compacta la sesión actual. _Alias_: `/summarize` + +```bash frame="none" +/compact +``` + +**Combinación de teclas:** `ctrl+x c` + +--- + +### details + +Alternar detalles de ejecución de la herramienta. + +```bash frame="none" +/details +``` + +**Combinación de teclas:** `ctrl+x d` + +--- + +### editor + +Abra un editor externo para redactar mensajes. Utiliza el editor configurado en su variable de entorno `EDITOR`. [Más información](#editor-setup). + +```bash frame="none" +/editor +``` + +**Combinación de teclas:** `ctrl+x e` + +--- + +### exit + +Salga de OpenCode. _Alias_: `/quit`, `/q` + +```bash frame="none" +/exit +``` + +**Combinación de teclas:** `ctrl+x q` + +--- + +### export + +Exporte la conversación actual a Markdown y ábrala en su editor predeterminado. Utiliza el editor configurado en su variable de entorno `EDITOR`. [Más información](#editor-setup). + +```bash frame="none" +/export +``` + +**Combinación de teclas:** `ctrl+x x` + +--- + +### help + +Muestra el cuadro de diálogo de ayuda. + +```bash frame="none" +/help +``` + +**Combinación de teclas:** `ctrl+x h` + +--- + +### init + +Cree o actualice el archivo `AGENTS.md`. [Más información](/docs/rules). + +```bash frame="none" +/init +``` + +**Combinación de teclas:** `ctrl+x i` + +--- + +### models + +Listar modelos disponibles. + +```bash frame="none" +/models +``` + +**Combinación de teclas:** `ctrl+x m` + +--- + +### new + +Iniciar una nueva sesión. _Alias_: `/clear` + +```bash frame="none" +/new +``` + +**Combinación de teclas:** `ctrl+x n` + +--- + +### redo + +Rehacer un mensaje previamente deshecho. Solo disponible después de usar `/undo`. + +:::tip +También se restaurarán todos los cambios en el archivo. +::: + +Internamente, esto utiliza Git para gestionar los cambios de archivos. Entonces tu proyecto **necesita +ser un repositorio Git**. + +```bash frame="none" +/redo +``` + +**Combinación de teclas:** `ctrl+x r` + +--- + +### sessions + +Enumere y cambie entre sesiones. _Alias_: `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +**Combinación de teclas:** `ctrl+x l` + +--- + +### share + +Compartir la sesión actual. [Más información](/docs/share). + +```bash frame="none" +/share +``` + +**Combinación de teclas:** `ctrl+x s` + +--- + +### theme + +Listar temas disponibles. + +```bash frame="none" +/theme +``` + +**Combinación de teclas:** `ctrl+x t` + +--- + +### thinking + +Alterna la visibilidad de los bloques de pensamiento/razonamiento en la conversación. Cuando está habilitado, puede ver el proceso de razonamiento del modelo para los modelos que admiten el pensamiento extendido. + +:::note +Este comando solo controla si se **muestran** los bloques de pensamiento; no habilita ni deshabilita las capacidades de razonamiento del modelo. Para alternar las capacidades de razonamiento reales, use `ctrl+t` para recorrer las variantes del modelo. +::: + +```bash frame="none" +/thinking +``` + +--- + +### undo + +Deshacer el último mensaje de la conversación. Elimina el mensaje de usuario más reciente, todas las respuestas posteriores y cualquier cambio de archivo. + +:::tip +Cualquier cambio de archivo realizado también se revertirá. +::: + +Internamente, esto utiliza Git para gestionar los cambios de archivos. Entonces tu proyecto **necesita +ser un repositorio Git**. + +```bash frame="none" +/undo +``` + +**Combinación de teclas:** `ctrl+x u` + +--- + +### unshare + +Dejar de compartir la sesión actual. [Más información](/docs/share#un-sharing). + +```bash frame="none" +/unshare +``` + +--- + +## Configuración del editor + +Tanto el comando `/editor` como el `/export` usan el editor especificado en su variable de entorno `EDITOR`. + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + + Para hacerlo permanente, agréguelo a su perfil de shell; + `~/.bashrc`, `~/.zshrc`, etc. + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + + Para hacerlo permanente, use **Propiedades del sistema** > **Entorno + Variables**. + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + + Para hacerlo permanente, agréguelo a su perfil de PowerShell. + + + + +Las opciones de editor populares incluyen: + +- `code` - Código de Visual Studio +- `cursor` - Cursor +- `windsurf` - Windsurf +- `nvim` - Editor Neovim +- `vim` - Editor Vim +- `nano` - Nanoeditor +- `notepad` - Windows Bloc de notas +- `subl` - Texto sublime + +:::note +Algunos editores como VS Code deben iniciarse con el indicador `--wait`. +::: + +Algunos editores necesitan argumentos de línea de comandos para ejecutarse en modo de bloqueo. El indicador `--wait` hace que el proceso del editor se bloquee hasta que se cierre. + +--- + +## Configurar + +Puede personalizar el comportamiento de TUI a través de su archivo de configuración OpenCode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### 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`.** + +--- + +## Personalización + +Puede personalizar varios aspectos de la vista TUI usando la paleta de comandos (`ctrl+x h` o `/help`). Estas configuraciones persisten después de los reinicios. + +--- + +#### Visualización del nombre de usuario + +Alterna si tu nombre de usuario aparece en los mensajes de chat. Accede a este a través de: + +- Paleta de comandos: busque "nombre de usuario" u "ocultar nombre de usuario" +- La configuración persiste automáticamente y se recordará en TUI sesiones diff --git a/packages/web/src/content/docs/es/web.mdx b/packages/web/src/content/docs/es/web.mdx new file mode 100644 index 00000000000..b5a2ad8fae2 --- /dev/null +++ b/packages/web/src/content/docs/es/web.mdx @@ -0,0 +1,142 @@ +--- +title: Web +description: Usando OpenCode en su navegador. +--- + +OpenCode puede ejecutarse como una aplicación web en su navegador, brindando la misma poderosa experiencia de codificación de IA sin necesidad de una terminal. + +![OpenCode Web - Nueva sesión](../../../assets/web/web-homepage-new-session.png) + +## Empezar + +Inicie la interfaz web ejecutando: + +```bash +opencode web +``` + +Esto inicia un servidor local en `127.0.0.1` con un puerto disponible aleatorio y abre automáticamente OpenCode en su navegador predeterminado. + +:::caution +Si no se establece `OPENCODE_SERVER_PASSWORD`, el servidor no será seguro. Esto está bien para uso local, pero debe configurarse para acceso a la red. +::: + +:::tip[Windows Usuarios] +Para obtener la mejor experiencia, ejecute `opencode web` desde [WSL](/docs/windows-wsl) en lugar de PowerShell. Esto garantiza el acceso adecuado al sistema de archivos y la integración del terminal. +::: + +--- + +## Configuración + +Puede configurar el servidor web usando indicadores de línea de comando o en su [archivo de configuración](/docs/config). + +### Puerto + +De forma predeterminada, OpenCode elige un puerto disponible. Puede especificar un puerto: + +```bash +opencode web --port 4096 +``` + +### Nombre de host + +De forma predeterminada, el servidor se vincula a `127.0.0.1` (solo localhost). Para hacer que OpenCode sea accesible en su red: + +```bash +opencode web --hostname 0.0.0.0 +``` + +Al usar `0.0.0.0`, OpenCode mostrará direcciones locales y de red: + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### Descubrimiento de mDNS + +Habilite mDNS para que su servidor sea reconocible en la red local: + +```bash +opencode web --mdns +``` + +Esto establece automáticamente el nombre de host en `0.0.0.0` y anuncia el servidor como `opencode.local`. + +Puede personalizar el nombre de dominio mDNS para ejecutar varias instancias en la misma red: + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +Para permitir dominios adicionales para CORS (útil para interfaces personalizadas): + +```bash +opencode web --cors https://example.com +``` + +### Autenticación + +Para proteger el acceso, establezca una contraseña utilizando la variable de entorno `OPENCODE_SERVER_PASSWORD`: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +El nombre de usuario predeterminado es `opencode` pero se puede cambiar con `OPENCODE_SERVER_USERNAME`. + +--- + +## Usar la interfaz web + +Una vez iniciada, la interfaz web proporciona acceso a sus sesiones OpenCode. + +### Sesiones + +Vea y administre sus sesiones desde la página de inicio. Puedes ver sesiones activas e iniciar otras nuevas. + +![OpenCode Web - Sesión activa](../../../assets/web/web-homepage-active-session.png) + +### Estado del servidor + +Haga clic en "Ver servidores" para ver los servidores conectados y su estado. + +![OpenCode Web - Ver Servidores](../../../assets/web/web-homepage-see-servers.png) + +--- + +## Adjuntar una terminal + +Puede conectar un terminal TUI a un servidor web en ejecución: + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +Esto le permite utilizar la interfaz web y el terminal simultáneamente, compartiendo las mismas sesiones y estados. + +--- + +## Archivo de configuración + +También puede configurar los ajustes del servidor en su archivo de configuración `opencode.json`: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +Los indicadores de la línea de comando tienen prioridad sobre la configuración del archivo de configuración. diff --git a/packages/web/src/content/docs/es/windows-wsl.mdx b/packages/web/src/content/docs/es/windows-wsl.mdx new file mode 100644 index 00000000000..eea984348c2 --- /dev/null +++ b/packages/web/src/content/docs/es/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: Ejecuta OpenCode en Windows con WSL para una mejor experiencia. +--- + +import { Steps } from "@astrojs/starlight/components" + +Aunque OpenCode puede ejecutarse directamente en Windows, recomendamos usar [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) para obtener la mejor experiencia. WSL ofrece un entorno Linux que funciona perfectamente con las funciones de OpenCode. + +:::tip[¿Por qué WSL?] +WSL ofrece mejor rendimiento del sistema de archivos, soporte completo de terminal y compatibilidad con las herramientas de desarrollo de las que depende OpenCode. +::: + +--- + +## Configuración + + + +1. **Instala WSL** + + Si aún no lo hiciste, [instala WSL](https://learn.microsoft.com/en-us/windows/wsl/install) usando la guía oficial de Microsoft. + +2. **Instala OpenCode en WSL** + + Cuando WSL esté listo, abre tu terminal de WSL e instala OpenCode con uno de los [métodos de instalación](/docs/). + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **Usa OpenCode desde WSL** + + Ve al directorio de tu proyecto (accede a los archivos de Windows desde `/mnt/c/`, `/mnt/d/`, etc.) y ejecuta OpenCode. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## Aplicación de escritorio + servidor WSL + +Si prefieres usar la app de escritorio de OpenCode pero quieres ejecutar el servidor en WSL: + +1. **Inicia el servidor en WSL** con `--hostname 0.0.0.0` para permitir conexiones externas: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **Conecta la app de escritorio** a `http://localhost:4096` + +:::note +Si `localhost` no funciona en tu configuración, conéctate usando la dirección IP de WSL (desde WSL: `hostname -I`) y usa `http://:4096`. +::: + +:::caution +Cuando uses `--hostname 0.0.0.0`, define `OPENCODE_SERVER_PASSWORD` para proteger el servidor. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## Cliente web + WSL + +Para obtener la mejor experiencia web en Windows: + +1. **Ejecuta `opencode web` en la terminal de WSL** en lugar de PowerShell: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Accede desde tu navegador de Windows** en `http://localhost:` (OpenCode muestra la URL) + +Ejecutar `opencode web` desde WSL garantiza acceso correcto al sistema de archivos e integración con la terminal, manteniéndolo accesible desde tu navegador de Windows. + +--- + +## Acceso a archivos de Windows + +WSL puede acceder a todos tus archivos de Windows mediante el directorio `/mnt/`: + +- Unidad `C:` → `/mnt/c/` +- Unidad `D:` → `/mnt/d/` +- Y así sucesivamente... + +Ejemplo: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +Para una experiencia más fluida, considera clonar o copiar tu repo al sistema de archivos de WSL (por ejemplo en `~/code/`) y ejecutar OpenCode ahí. +::: + +--- + +## Consejos + +- Ejecuta OpenCode en WSL para proyectos guardados en unidades de Windows: el acceso a archivos es transparente +- Usa la [extensión WSL de VS Code](https://code.visualstudio.com/docs/remote/wsl) junto con OpenCode para un flujo de desarrollo integrado +- Tu configuración y tus sesiones de OpenCode se guardan dentro del entorno WSL en `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/es/zen.mdx b/packages/web/src/content/docs/es/zen.mdx new file mode 100644 index 00000000000..10847b452e4 --- /dev/null +++ b/packages/web/src/content/docs/es/zen.mdx @@ -0,0 +1,252 @@ +--- +title: Zen +description: Lista seleccionada de modelos proporcionada por OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen es una lista de modelos probados y verificados proporcionada por el equipo OpenCode. + +:::note +OpenCode Zen se encuentra actualmente en versión beta. +::: + +Zen funciona como cualquier otro proveedor en OpenCode. Inicias sesion en OpenCode Zen y obtienes +tu API key. Es **completamente opcional** y no necesitas usarlo para usar OpenCode. + +--- + +## Contexto + +Hay una gran cantidad de modelos, pero solo unos pocos funcionan bien como agentes de coding. +Ademas, la mayoria de proveedores se configura de forma diferente, asi que el rendimiento y la calidad varian mucho. + +:::tip +Probamos un grupo selecto de modelos y proveedores que funcionan bien con OpenCode. +::: + +Si usas un modelo a traves de algo como OpenRouter, nunca puedes estar +seguro de que recibes la mejor version del modelo que quieres. + +Para solucionar este problema, hicimos un par de cosas: + +1. Probamos un grupo selecto de modelos y hablamos con sus equipos sobre cómo + mejor ejecutarlos. +2. Luego trabajamos con algunos proveedores para asegurarnos de que estuvieran siendo atendidos. + correctamente. +3. Finalmente, comparamos la combinación modelo/proveedor y llegamos + con una lista que nos sentimos bien recomendando. + +OpenCode Zen es una puerta de enlace de IA que le brinda acceso a estos modelos. + +--- + +## Cómo funciona + +OpenCode Zen funciona como cualquier otro proveedor en OpenCode. + +1. Inicias sesión en **OpenCode Zen**, agregas tu facturación + detalles y copie su clave API. +2. Ejecuta el comando `/connect` en TUI, selecciona OpenCode Zen y pega tu clave API. +3. Ejecute `/models` en TUI para ver la lista de modelos que recomendamos. + +Se le cobra por solicitud y puede agregar créditos a su cuenta. + +--- + +## Puntos finales + +También puede acceder a nuestros modelos a través de los siguientes puntos finales API. + +| Modelo | Model ID | Endpoint | AI SDK package | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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` | + +El [model ID](/docs/config/#models) en tu configuracion de OpenCode +usa el formato `opencode/`. Por ejemplo, para GPT 5.2 Codex, debes +usar `opencode/gpt-5.2-codex` en tu configuracion. + +--- + +### Modelos + +Puede obtener la lista completa de modelos disponibles y sus metadatos en: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## Precios + +Apoyamos un modelo de pago por uso. A continuación se muestran los precios **por 1 millón de tokens**. + +| Modelo | Entrada | Salida | Lectura en caché | Escritura en caché | +| ------------------------------------ | ------- | ------ | ---------------- | ------------------ | +| Big Pickle | Gratis | Gratis | Gratis | - | +| MiniMax M2.1 Free | Gratis | Gratis | Gratis | - | +| MiniMax M2.1 | $0,30 | $1,20 | $0,10 | - | +| GLM 4.7 Free | Gratis | Gratis | Gratis | - | +| 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 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 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.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 | Gratis | Gratis | Gratis | - | + +Es posible que notes _Claude Haiku 3.5_ en tu historial de uso. Este es un [modelo de bajo costo](/docs/config/#models) que se utiliza para generar los títulos de tus sesiones. + +:::note +Las tarifas de las tarjetas de crédito se trasladan al costo (4,4% + 0,30 dólares por transacción); No cobramos nada más allá de eso. +::: + +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. +- 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. + +--- + +### Recarga automática + +Si su saldo es inferior a $5, Zen recargará automáticamente $20. + +Puedes cambiar el monto de la recarga automática. También puedes desactivar la recarga automática por completo. + +--- + +### Límites mensuales + +También puede establecer un límite de uso mensual para todo el espacio de trabajo y para cada +miembro de tu equipo. + +Por ejemplo, digamos que establece un límite de uso mensual de $20, Zen no usará +más de $20 en un mes. Pero si tienes habilitada la recarga automática, Zen podría terminar +cobrarle más de $20 si su saldo es inferior a $5. + +--- + +## Privacidad + +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. +- 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). + +--- + +## Para equipos + +Zen también funciona muy bien para equipos. Puedes invitar a compañeros de equipo, asignar roles, seleccionar +los modelos que utiliza su equipo y más. + +:::note +Actualmente, los espacios de trabajo son gratuitos para los equipos como parte de la versión beta. +::: + +Actualmente, administrar su espacio de trabajo es gratuito para equipos como parte de la versión beta. estaremos +compartiremos más detalles sobre los precios pronto. + +--- + +### Roles + +Puedes invitar a compañeros de equipo a tu espacio de trabajo y asignar roles: + +- **Administrador**: administra modelos, miembros, claves API y facturación +- **Miembro**: administra solo sus propias claves API + +Los administradores también pueden establecer límites de gastos mensuales para cada miembro para mantener los costos bajo control. + +--- + +### Acceso al modelo + +Los administradores pueden habilitar o deshabilitar modelos específicos para el espacio de trabajo. Las solicitudes realizadas a un modelo deshabilitado devolverán un error. + +Esto es útil para los casos en los que desea desactivar el uso de un modelo que +recopila datos. + +--- + +### Trae tu propia clave API + +Puedes usar tus propias API keys de OpenAI o Anthropic mientras accedes a otros modelos en Zen. + +Cuando utiliza sus propias claves, los tokens los factura directamente el proveedor, no Zen. + +Por ejemplo, es posible que su organización ya tenga una clave para OpenAI o Anthropic. +y quieres usar ese en lugar del que proporciona Zen. + +--- + +## Objetivos + +Creamos OpenCode Zen para: + +1. **Evaluar** los mejores modelos/proveedores de agentes de codificación. +2. Tener acceso a las opciones de **más alta calidad** y no degradar el rendimiento ni recurrir a proveedores más baratos. +3. Transmitir cualquier **bajada de precio** vendiendo al costo; por lo que el único margen de beneficio es para cubrir nuestras tarifas de procesamiento. +4. **No tener ningún bloqueo** al permitirle usarlo con cualquier otro agente de codificación. Y siempre le permitirá utilizar cualquier otro proveedor con OpenCode también. diff --git a/packages/web/src/content/docs/fr/acp.mdx b/packages/web/src/content/docs/fr/acp.mdx new file mode 100644 index 00000000000..81254d47927 --- /dev/null +++ b/packages/web/src/content/docs/fr/acp.mdx @@ -0,0 +1,156 @@ +--- +title: Support ACP +description: Utilisez OpenCode dans n’importe quel éditeur compatible ACP. +--- + +OpenCode prend en charge le [Agent Client Protocol](https://agentclientprotocol.com) (ACP), vous permettant de l'utiliser directement dans les éditeurs et IDE compatibles. + +:::tip +Pour obtenir une liste des éditeurs et des outils prenant en charge ACP, consultez le [ACP progress report](https://zed.dev/blog/acp-progress-report#available-now). +::: + +ACP est un protocole ouvert qui standardise la communication entre les éditeurs de code et les agents de codage AI. + +--- + +## Configuration + +Pour utiliser OpenCode via ACP, configurez votre éditeur pour exécuter la commande `opencode acp`. + +La commande démarre OpenCode en tant que sous-processus compatible ACP qui communique avec votre éditeur via JSON-RPC sur stdio. + +Vous trouverez ci-dessous des exemples d'éditeurs populaires prenant en charge ACP. + +--- + +### Zed + +Ajoutez à votre configuration [Zed](https://zed.dev) (`~/.config/zed/settings.json`) : + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +Pour l'ouvrir, utilisez l'action `agent: new thread` dans la **Palette de commandes**. + +Vous pouvez également associer un raccourci clavier en modifiant votre `keymap.json` : + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### IDE JetBrains + +Ajoutez `acp.json` à votre [IDE JetBrains](https://www.jetbrains.com/) conformément à la [documentation](https://www.jetbrains.com/help/ai-assistant/acp.html) : + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +Pour l'ouvrir, utilisez le nouvel agent « OpenCode » dans le sélecteur d'agent AI Chat. + +--- + +### Avante.nvim + +Ajoutez à votre configuration [Avante.nvim](https://github.com/yetone/avante.nvim) : + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +Si vous devez transmettre des variables d'environnement : + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +Pour utiliser OpenCode comme agent ACP dans [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim), ajoutez ce qui suit à votre configuration Neovim : + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +Cette configuration configure CodeCompanion pour utiliser OpenCode comme agent ACP pour le chat. + +Si vous devez transmettre des variables d'environnement (comme `OPENCODE_API_KEY`), reportez-vous à [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) dans la documentation CodeCompanion.nvim pour plus de détails. + +## Prise en charge + +OpenCode fonctionne de la même manière via ACP que dans le terminal. Toutes les fonctionnalités sont prises en charge : + +:::note +Certaines commandes slash intégrées telles que `/undo` et `/redo` ne sont actuellement pas prises en charge. +::: + +- Outils intégrés (opérations sur les fichiers, commandes de terminal, etc.) +- Outils personnalisés et commandes slash +- Serveurs MCP configurés dans votre configuration OpenCode +- Règles spécifiques au projet à partir de `AGENTS.md` +- Formateurs et linters personnalisés +- Système d'agents et d'autorisations diff --git a/packages/web/src/content/docs/fr/agents.mdx b/packages/web/src/content/docs/fr/agents.mdx new file mode 100644 index 00000000000..b18d3353943 --- /dev/null +++ b/packages/web/src/content/docs/fr/agents.mdx @@ -0,0 +1,747 @@ +--- +title: Agents +description: Configurez et utilisez des agents spécialisés. +--- + +Les agents sont des assistants IA spécialisés qui peuvent être configurés pour des tâches et des flux de travail spécifiques. Ils vous permettent de créer des outils ciblés avec des prompts, des modèles et un accès aux outils personnalisés. + +:::tip +Utilisez l'agent de plan pour analyser le code et examiner les suggestions sans apporter de modifications au code. +::: + +Vous pouvez basculer entre les agents au cours d'une session ou les appeler avec la mention `@`. + +--- + +## Types + +Il existe deux types d'agents dans OpenCode ; agents primaires et sous-agents. + +--- + +### Agents primaires + +Les agents primaires sont les principaux assistants avec lesquels vous interagissez directement. Vous pouvez les parcourir à l'aide de la touche **Tab** ou de votre combinaison de touches `switch_agent` configurée. Ces agents gèrent votre conversation principale. L'accès aux outils est configuré via les autorisations : par exemple, Build a tous les outils activés tandis que Plan est restreint. + +:::tip +Vous pouvez utiliser la touche **Tab** pour basculer entre les agents primaires au cours d'une session. +::: + +OpenCode est livré avec deux agents primaires intégrés, **Build** et **Plan**. +Nous les verrons ci-dessous. + +--- + +### Sous-agents + +Les sous-agents sont des assistants spécialisés que les agents primaires peuvent appeler pour des tâches spécifiques. Vous pouvez également les invoquer manuellement en **@ les mentionnant** dans vos messages. + +OpenCode est livré avec deux sous-agents intégrés, **General** et **Explore**. Nous verrons cela ci-dessous. + +--- + +## Agents intégrés + +OpenCode est livré avec deux agents primaires intégrés et deux sous-agents intégrés. + +--- + +### Agent Build + +_Mode_ : `primary` + +Build est l'agent primaire **par défaut** avec tous les outils activés. Il s'agit de l'agent standard pour les travaux de développement où vous avez besoin d'un accès complet aux opérations sur les fichiers et aux commandes système. + +--- + +### Agent Plan + +_Mode_ : `primary` + +Un agent restreint conçu pour la planification et l'analyse. Nous utilisons un système d'autorisation pour vous donner plus de contrôle et empêcher toute modification involontaire. +Par défaut, tous les éléments suivants sont définis sur `ask` : + +- `file edits` : toutes les écritures, correctifs et modifications +- `bash` : toutes les commandes bash + +Cet agent est utile lorsque vous souhaitez que le LLM analyse le code, suggère des modifications ou crée des plans sans apporter de modifications réelles à votre base de code. + +--- + +### Agent General + +_Mode_ : `subagent` + +Un agent polyvalent pour traiter des questions complexes et exécuter des tâches en plusieurs étapes. Dispose d'un accès complet aux outils (sauf todo), il peut donc apporter des modifications aux fichiers en cas de besoin. Utilisez-le pour exécuter plusieurs unités de travail en parallèle. + +--- + +### Agent Explore + +_Mode_ : `subagent` + +Un agent rapide en lecture seule pour explorer les bases de code. Impossible de modifier les fichiers. Utilisez-le lorsque vous avez besoin de rechercher rapidement des fichiers par modèles, de rechercher du code par mots-clés ou de répondre à des questions sur la base de code. + +--- + +### Agent Compaction + +_Mode_ : `primary` + +Agent système caché qui compacte un contexte long en un résumé plus petit. Il s'exécute automatiquement en cas de besoin et n'est pas sélectionnable dans l'interface utilisateur. + +--- + +### Agent Title + +_Mode_ : `primary` + +Agent système caché qui génère des titres de session courts. Il s'exécute automatiquement et n'est pas sélectionnable dans l'interface utilisateur. + +--- + +### Agent Summary + +_Mode_ : `primary` + +Agent système caché qui crée des résumés de session. Il s'exécute automatiquement et n'est pas sélectionnable dans l'interface utilisateur. + +--- + +## Utilisation + +1. Pour les agents primaires, utilisez la touche **Tab** pour les parcourir au cours d'une session. Vous pouvez également utiliser votre raccourci clavier `switch_agent` configuré. + +2. Les sous-agents peuvent être invoqués : + - **Automatiquement** par les agents primaires pour des tâches spécialisées en fonction de leurs descriptions. + - Manuellement en **@ mentionnant** un sous-agent dans votre message. Par exemple : + + ```txt frame="none" + @general help me search for this function + ``` + +3. **Navigation entre les sessions** : lorsque les sous-agents créent leurs propres sessions enfants, vous pouvez naviguer entre la session parent et toutes les sessions enfants en utilisant : + - **\+Right** (ou votre combinaison de touches `session_child_cycle` configurée) pour avancer via parent → enfant1 → enfant2 → ... → parent + - **\+Left** (ou votre combinaison de touches `session_child_cycle_reverse` configurée) pour revenir en arrière dans parent ← enfant1 ← enfant2 ← ... ← parent + +Cela vous permet de basculer en toute transparence entre la conversation principale et le travail spécialisé des sous-agents. + +--- + +## Configuration + +Vous pouvez personnaliser les agents intégrés ou créer les vôtres via la configuration. Les agents peuvent être configurés de deux manières : + +--- + +### JSON + +Configurez les agents dans votre fichier de configuration `opencode.json` : + +```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 + +Vous pouvez également définir des agents à l'aide de fichiers markdown. Placez-les dans : + +- Global : `~/.config/opencode/agents/` +- Par projet : `.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. +``` + +Le nom du fichier Markdown devient le nom de l'agent. Par exemple, `review.md` crée un agent `review`. + +--- + +## Options + +Examinons ces options de configuration en détail. + +--- + +### Description + +Utilisez l'option `description` pour fournir une brève description de ce que fait l'agent et quand l'utiliser. + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +Il s'agit d'une option de configuration **obligatoire**. + +--- + +### Température + +Contrôlez le caractère aléatoire et la créativité des réponses du LLM avec la configuration `temperature`. + +Des valeurs faibles rendent les réponses plus ciblées et déterministes, tandis que des valeurs plus élevées augmentent la créativité et la variabilité. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Les valeurs de température varient généralement de 0,0 à 1,0 : + +- **0,0-0,2** : réponses très ciblées et déterministes, idéales pour l'analyse et la planification du code +- **0,3-0,5** : réponses équilibrées avec une certaine créativité, idéales pour les tâches de développement générales +- **0,6-1,0** : réponses plus créatives et variées, utiles pour le brainstorming et l'exploration + +```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}" + } + } +} +``` + +Si aucune température n'est spécifiée, OpenCode utilise les valeurs par défaut spécifiques au modèle ; généralement 0 pour la plupart des modèles, 0,55 pour les modèles Qwen. + +--- + +### Étapes maximum + +Contrôlez le nombre maximum d'itérations que l'agent peut effectuer avant d'être obligé de répondre avec du texte uniquement. Cela permet aux utilisateurs qui souhaitent contrôler les coûts de fixer une limite aux actions agents. + +Si cela n'est pas défini, l'agent continuera à itérer jusqu'à ce que le modèle choisisse de s'arrêter ou que l'utilisateur interrompe la session. + +```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 + } + } +} +``` + +Lorsque la limite est atteinte, l'agent reçoit un prompt système spécial lui demandant de répondre avec un résumé de son travail et des tâches restantes recommandées. + +:::caution +L’ancien champ `maxSteps` est obsolète. Utilisez plutôt `steps`. +::: + +--- + +### Désactiver + +Définissez sur `true` pour désactiver l'agent. + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### Invite + +Spécifiez un fichier de prompt système personnalisé pour cet agent avec la configuration `prompt`. Le fichier de prompt doit contenir des instructions spécifiques à l'objectif de l'agent. + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Ce chemin est relatif à l'emplacement du fichier de configuration. Cela fonctionne donc à la fois pour la configuration globale OpenCode et pour la configuration spécifique au projet. + +--- + +### Modèle + +Utilisez la configuration `model` pour remplacer le modèle de cet agent. Utile pour utiliser différents modèles optimisés pour différentes tâches. Par exemple, un modèle de planification plus rapide, un modèle de mise en œuvre plus performant. + +:::tip +Si vous ne spécifiez pas de modèle, les agents primaires utilisent le [modèle globalement configuré](/docs/config#models) tandis que les sous-agents utiliseront le modèle de l'agent primaire qui a appelé le sous-agent. +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +L'ID de modèle dans votre configuration OpenCode utilise le format `provider/model-id`. Par exemple, si vous utilisez [OpenCode Zen](/docs/zen), vous utiliserez `opencode/gpt-5.1-codex` pour GPT 5.1 Codex. + +--- + +### Outils + +Contrôlez quels outils sont disponibles dans cet agent avec la configuration `tools`. Vous pouvez activer ou désactiver des outils spécifiques en les définissant sur `true` ou `false`. + +```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 +La configuration spécifique à l'agent remplace la configuration globale. +::: + +Vous pouvez également utiliser des caractères génériques pour contrôler plusieurs outils à la fois. Par exemple, pour désactiver tous les outils d'un serveur MCP : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[En savoir plus sur les outils](/docs/tools). + +--- + +### Autorisations + +Vous pouvez configurer des autorisations pour gérer les actions qu'un agent peut effectuer. Actuellement, les autorisations pour les outils `edit`, `bash` et `webfetch` peuvent être configurées pour : + +- `"ask"` — Demander l'approbation avant d'exécuter l'outil +- `"allow"` — Autoriser toutes les opérations sans approbation +- `"deny"` – Désactiver l'outil + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +Vous pouvez remplacer ces autorisations par agent. + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +Vous pouvez également définir des autorisations dans les agents Markdown. + +```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. +``` + +Vous pouvez définir des autorisations pour des commandes bash spécifiques. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +Cela peut prendre un pattern glob. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +Et vous pouvez également utiliser le caractère générique `*` pour gérer les autorisations pour toutes les commandes. +Puisque la dernière règle correspondante est prioritaire, placez le caractère générique `*` en premier et les règles spécifiques après. + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[En savoir plus sur les autorisations](/docs/permissions). + +--- + +### Mode + +Contrôlez le mode de l'agent avec la configuration `mode`. L'option `mode` est utilisée pour déterminer comment l'agent peut être utilisé. + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +L'option `mode` peut être définie sur `primary`, `subagent` ou `all`. Si aucun `mode` n’est spécifié, la valeur par défaut est `all`. + +--- + +### Masqué + +Masquez un sous-agent du menu de saisie semi-automatique `@` avec `hidden: true`. Utile pour les sous-agents internes qui ne doivent être invoqués que par programme par d'autres agents via l'outil Tâche. + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +Cela affecte uniquement la visibilité de l'utilisateur dans le menu de saisie semi-automatique. Les agents masqués peuvent toujours être invoqués par le modèle via l'outil Tâche si les autorisations le permettent. + +:::note +S'applique uniquement aux agents `mode: subagent`. +::: + +--- + +### Autorisations de tâches + +Contrôlez quels sous-agents un agent peut appeler via l'outil Tâche avec `permission.task`. Utilise des patterns glob pour une correspondance flexible. + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +Lorsqu'il est défini sur `deny`, le sous-agent est entièrement supprimé de la description de l'outil Tâche, de sorte que le modèle ne tentera pas de l'invoquer. + +:::tip +Les règles sont évaluées dans l'ordre et la **dernière règle correspondante l'emporte**. Dans l'exemple ci-dessus, `orchestrator-planner` correspond à la fois à `*` (refuser) et à `orchestrator-*` (autoriser), mais comme `orchestrator-*` vient après `*`, le résultat est `allow`. +::: + +:::tip +Les utilisateurs peuvent toujours appeler n'importe quel sous-agent directement via le menu de saisie semi-automatique `@`, même si les autorisations de tâche de l'agent le refuseraient. +::: + +--- + +### Couleur + +Personnalisez l'apparence visuelle de l'agent dans l'interface utilisateur avec l'option `color`. Cela affecte la façon dont l'agent apparaît dans l'interface. + +Utilisez une couleur hexadécimale valide (par exemple, `#FF5733`) ou une couleur de thème : `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +Contrôlez la diversité des réponses avec l’option `top_p`. Alternative à la température pour contrôler le caractère aléatoire. + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +Les valeurs vont de 0,0 à 1,0. Les valeurs inférieures sont plus ciblées, les valeurs élevées plus diversifiées. + +--- + +### Options supplémentaires + +Toutes les autres options que vous spécifiez dans la configuration de votre agent seront **transmises directement** au fournisseur en tant qu'options de modèle. Cela vous permet d'utiliser des fonctionnalités et des paramètres spécifiques au fournisseur. + +Par exemple, avec les modèles de raisonnement d'OpenAI, vous pouvez contrôler l'effort de raisonnement : + +```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" + } + } +} +``` + +Ces options supplémentaires sont spécifiques au modèle et au fournisseur. Consultez la documentation de votre fournisseur pour connaître les paramètres disponibles. + +:::tip +Exécutez `opencode models` pour voir une liste des modèles disponibles. +::: + +--- + +## Création d'agents + +Vous pouvez créer de nouveaux agents à l'aide de la commande suivante : + +```bash +opencode agent create +``` + +Cette commande interactive va : + +1. Demander où enregistrer l'agent ; global ou spécifique à un projet. +2. Demander une description de ce que l'agent doit faire. +3. Générer un prompt système et un identifiant appropriés. +4. Vous permettre de sélectionner les outils auxquels l'agent peut accéder. +5. Enfin, créer un fichier markdown avec la configuration de l'agent. + +--- + +## Cas d'utilisation + +Voici quelques cas d’utilisation courants pour différents agents. + +- **Agent de build** : travail de développement complet avec tous les outils activés +- **Agent de plan** : analyse et planification sans apporter de modifications +- **Agent de révision** : révision de code avec accès en lecture seule et outils de documentation +- **Agent de débogage** : axé sur l'investigation avec les outils bash et read activés +- **Agent Docs** : écriture de documentation avec des opérations sur les fichiers mais pas de commandes système + +--- + +## Exemples + +Voici quelques exemples d’agents qui pourraient vous être utiles. + +:::tip +Avez-vous un agent que vous aimeriez partager ? [Soumettez un PR](https://github.com/anomalyco/opencode). +::: + +--- + +### Agent de documentation + +```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 +``` + +--- + +### Auditeur de sécurité + +```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/fr/cli.mdx b/packages/web/src/content/docs/fr/cli.mdx new file mode 100644 index 00000000000..8773d941f37 --- /dev/null +++ b/packages/web/src/content/docs/fr/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: Options et commandes de la CLI OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +La CLI OpenCode démarre par défaut le [TUI](/docs/tui) lorsqu'il est exécuté sans aucun argument. + +```bash +opencode +``` + +Mais elle accepte également les commandes documentées sur cette page. Cela vous permet d'interagir avec OpenCode par programme. + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +Démarrez l’interface utilisateur du terminal OpenCode. + +```bash +opencode [project] +``` + +#### Options + +| Option | Court | Description | +| ------------ | ----- | ----------------------------------------------------------------------------- | +| `--continue` | `-c` | Continuer la dernière session | +| `--session` | `-s` | ID de session pour continuer | +| `--fork` | | Forker la session en continuant (à utiliser avec `--continue` ou `--session`) | +| `--prompt` | | Prompt à utiliser | +| `--model` | `-m` | Modèle à utiliser sous forme de fournisseur/modèle | +| `--agent` | | Agent à utiliser | +| `--port` | | Port d'écoute | +| `--hostname` | | Nom d'hôte d'écoute | + +--- + +## Commandes + +La CLI OpenCode dispose également des commandes suivantes. + +--- + +### agent + +Gérer les agents pour OpenCode. + +```bash +opencode agent [command] +``` + +--- + +### attach + +Attachez un terminal à un serveur backend OpenCode déjà en cours d'exécution démarré via les commandes `serve` ou `web`. + +```bash +opencode attach [url] +``` + +Cela permet d'utiliser le TUI avec un backend OpenCode distant. Par exemple : + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### Options + +| Option | Court | Description | +| ----------- | ----- | ---------------------------------------------- | +| `--dir` | | Répertoire de travail dans lequel démarrer TUI | +| `--session` | `-s` | ID de session pour continuer | + +--- + +#### create + +Créez un nouvel agent avec une configuration personnalisée. + +```bash +opencode agent create +``` + +Cette commande vous guidera dans la création d'un nouvel agent avec un prompt système personnalisé et une configuration d'outils. + +--- + +#### list + +Liste tous les agents disponibles. + +```bash +opencode agent list +``` + +--- + +### auth + +Commande pour gérer les informations d’identification et la connexion des fournisseurs. + +```bash +opencode auth [command] +``` + +--- + +#### login + +OpenCode est alimenté par la liste des fournisseurs sur [Models.dev](https://models.dev), vous pouvez donc utiliser `opencode auth login` pour configurer les clés API pour tout fournisseur que vous souhaitez utiliser. Ceci est stocké dans `~/.local/share/opencode/auth.json`. + +```bash +opencode auth login +``` + +Lorsque OpenCode démarre, il charge les fournisseurs à partir du fichier d'informations d'identification, ainsi que les clés définies dans vos environnements ou un fichier `.env` dans votre projet. + +--- + +#### list + +Liste tous les fournisseurs authentifiés tels qu'ils sont stockés dans le fichier d'informations d'identification. + +```bash +opencode auth list +``` + +Ou la version courte. + +```bash +opencode auth ls +``` + +--- + +#### logout + +Vous déconnecte d'un fournisseur en l'effaçant du fichier d'informations d'identification. + +```bash +opencode auth logout +``` + +--- + +### github + +Gérez l'agent GitHub pour l'automatisation du dépôt. + +```bash +opencode github [command] +``` + +--- + +#### install + +Installez l'agent GitHub dans votre dépôt. + +```bash +opencode github install +``` + +Cela configure le flux de travail GitHub Actions nécessaire et vous guide tout au long du processus de configuration. [En savoir plus](/docs/github). + +--- + +#### run + +Exécutez l'agent GitHub. Ceci est généralement utilisé dans les GitHub Actions. + +```bash +opencode github run +``` + +##### Options + +| Option | Description | +| --------- | ---------------------------------------------------- | +| `--event` | Événement simulé GitHub pour lequel exécuter l'agent | +| `--token` | Jeton d'accès personnel GitHub | + +--- + +### MCP + +Gérer les serveurs Model Context Protocol. + +```bash +opencode mcp [command] +``` + +--- + +#### add + +Ajoutez un serveur MCP à votre configuration. + +```bash +opencode mcp add +``` + +Cette commande vous guidera dans l’ajout d’un serveur MCP local ou distant. + +--- + +#### list + +Liste tous les serveurs MCP configurés et leur état de connexion. + +```bash +opencode mcp list +``` + +Ou utilisez la version courte. + +```bash +opencode mcp ls +``` + +--- + +#### auth + +Authentifiez-vous auprès d'un serveur MCP compatible OAuth. + +```bash +opencode mcp auth [name] +``` + +Si vous ne fournissez pas de nom de serveur, vous serez invité à sélectionner parmi les serveurs compatibles OAuth disponibles. + +Vous pouvez également répertorier les serveurs compatibles OAuth et leur statut d'authentification. + +```bash +opencode mcp auth list +``` + +Ou utilisez la version courte. + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +Supprimez les informations d'identification OAuth pour un serveur MCP. + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +Déboguer les problèmes de connexion OAuth pour un serveur MCP. + +```bash +opencode mcp debug +``` + +--- + +### models + +Liste tous les modèles disponibles auprès des fournisseurs configurés. + +```bash +opencode models [provider] +``` + +Cette commande affiche tous les modèles disponibles parmi vos fournisseurs configurés au format `provider/model`. + +Ceci est utile pour déterminer le nom exact du modèle à utiliser dans [votre config](/docs/config/). + +Vous pouvez éventuellement transmettre un ID de fournisseur pour filtrer les modèles en fonction de ce fournisseur. + +```bash +opencode models anthropic +``` + +#### Options + +| Option | Description | +| ----------- | ------------------------------------------------------------------------------------------ | +| `--refresh` | Actualisez le cache des modèles à partir de models.dev | +| `--verbose` | Utiliser une sortie de modèle plus détaillée (inclut des métadonnées telles que les coûts) | + +Utilisez l'option `--refresh` pour mettre à jour la liste des modèles mis en cache. Ceci est utile lorsque de nouveaux modèles ont été ajoutés à un fournisseur et que vous souhaitez les voir dans OpenCode. + +```bash +opencode models --refresh +``` + +--- + +### run + +Exécutez opencode en mode non interactif en transmettant directement un prompt. + +```bash +opencode run [message..] +``` + +Ceci est utile pour les scripts, l'automatisation ou lorsque vous souhaitez une réponse rapide sans lancer le TUI complet. Par exemple : + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +Vous pouvez également vous connecter à une instance `opencode serve` en cours d'exécution pour éviter les temps de démarrage à froid du serveur MCP à chaque exécution : + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### Options + +| Option | Court | Description | +| ------------ | ----- | ---------------------------------------------------------------------------------------------- | +| `--command` | | La commande à exécuter, utilisez le message pour les arguments | +| `--continue` | `-c` | Continuer la dernière session | +| `--session` | `-s` | ID de session pour continuer | +| `--fork` | | Forker la session en continuant (à utiliser avec `--continue` ou `--session`) | +| `--share` | | Partager la session | +| `--model` | `-m` | Modèle à utiliser sous forme de fournisseur/modèle | +| `--agent` | | Agent à utiliser | +| `--file` | `-f` | Fichier(s) à joindre au message | +| `--format` | | Format : par défaut (formaté) ou json (événements JSON bruts) | +| `--title` | | Titre de la session (utilise un prompt tronqué si aucune valeur n'est fournie) | +| `--attach` | | Connectez-vous à un serveur opencode en cours d'exécution (par exemple, http://localhost:4096) | +| `--port` | | Port du serveur local (port aléatoire par défaut) | + +--- + +### serve + +Démarrez un serveur OpenCode sans interface graphique pour un accès API. Consultez le [serveur docs](/docs/server) pour l'interface complète HTTP. + +```bash +opencode serve +``` + +Cela démarre un serveur HTTP qui fournit un accès API aux fonctionnalités d'OpenCode sans l'interface TUI. Définissez `OPENCODE_SERVER_PASSWORD` pour activer l'authentification de base HTTP (le nom d'utilisateur par défaut est `opencode`). + +#### Options + +| Option | Description | +| ------------ | ---------------------------------------------------------- | +| `--port` | Port d'écoute | +| `--hostname` | Nom d'hôte d'écoute | +| `--mdns` | Activer la découverte mDNS | +| `--cors` | Origines de navigateur supplémentaires pour autoriser CORS | + +--- + +### session + +Gérer les sessions OpenCode. + +```bash +opencode session [command] +``` + +--- + +#### list + +Liste toutes les sessions OpenCode. + +```bash +opencode session list +``` + +##### Options + +| Option | Court | Description | +| ------------- | ----- | -------------------------------------------- | +| `--max-count` | `-n` | Limiter aux N sessions les plus récentes | +| `--format` | | Format de sortie : tableau ou json (tableau) | + +--- + +### stats + +Affichez les statistiques d'utilisation et de coût des jetons pour vos sessions OpenCode. + +```bash +opencode stats +``` + +#### Options + +| Option | Description | +| ----------- | --------------------------------------------------------------------------------------------------------------------- | +| `--days` | Afficher les statistiques des N derniers jours (depuis le début) | +| `--tools` | Nombre d'outils à afficher (tous) | +| `--models` | Afficher la répartition de l'utilisation du modèle (masqué par défaut). Passez un numéro pour afficher les N premiers | +| `--project` | Filtrer par projet (tous les projets, chaîne vide : projet actuel) | + +--- + +### export + +Exportez les données de session au format JSON. + +```bash +opencode export [sessionID] +``` + +Si vous ne fournissez pas d'ID de session, vous serez invité à sélectionner parmi les sessions disponibles. + +--- + +### import + +Importez les données de session à partir d'un fichier JSON ou d'une URL de partage OpenCode. + +```bash +opencode import +``` + +Vous pouvez importer à partir d'un fichier local ou d'une URL de partage OpenCode. + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +Démarrez un serveur OpenCode sans interface graphique avec une interface Web. + +```bash +opencode web +``` + +Cela démarre un serveur HTTP et ouvre un navigateur Web pour accéder à OpenCode via une interface Web. Définissez `OPENCODE_SERVER_PASSWORD` pour activer l'authentification de base HTTP (le nom d'utilisateur par défaut est `opencode`). + +#### Options + +| Option | Description | +| ------------ | ---------------------------------------------------------- | +| `--port` | Port d'écoute | +| `--hostname` | Nom d'hôte d'écoute | +| `--mdns` | Activer la découverte mDNS | +| `--cors` | Origines de navigateur supplémentaires pour autoriser CORS | + +--- + +### acp + +Démarrez un serveur ACP (Agent Client Protocol). + +```bash +opencode acp +``` + +Cette commande démarre un serveur ACP qui communique via stdin/stdout en utilisant nd-JSON. + +#### Options + +| Option | Description | +| ------------ | --------------------- | +| `--cwd` | Répertoire de travail | +| `--port` | Port d'écoute | +| `--hostname` | Nom d'hôte d'écoute | + +--- + +### uninstall + +Désinstallez OpenCode et supprimez tous les fichiers associés. + +```bash +opencode uninstall +``` + +#### Options + +| Option | Court | Description | +| --------------- | ----- | --------------------------------------------------- | +| `--keep-config` | `-c` | Conserver les fichiers de configuration | +| `--keep-data` | `-d` | Conserver les données de session et les instantanés | +| `--dry-run` | | Afficher ce qui serait supprimé sans supprimer | +| `--force` | `-f` | Ignorer les invites de confirmation | + +--- + +### upgrade + +Met à jour opencode vers la dernière version ou une version spécifique. + +```bash +opencode upgrade [target] +``` + +Pour mettre à niveau vers la dernière version. + +```bash +opencode upgrade +``` + +Pour passer à une version spécifique. + +```bash +opencode upgrade v0.1.48 +``` + +#### Options + +| Option | Court | Description | +| ---------- | ----- | --------------------------------------------------------------- | +| `--method` | `-m` | La méthode d'installation utilisée ; curl, npm, pnpm, bun, brew | + +--- + +## Options globales + +La CLI opencode prend les flags globaux suivants. + +| Option | Court | Description | +| -------------- | ----- | ---------------------------------------- | +| `--help` | `-h` | Afficher l'aide | +| `--version` | `-v` | Afficher le numéro de version | +| `--print-logs` | | Afficher les logs sur stderr | +| `--log-level` | | Niveau de log (DEBUG, INFO, WARN, ERROR) | + +--- + +## Variables d'environnement + +OpenCode peut être configuré à l'aide de variables d'environnement. + +| Variables | Type | Description | +| ------------------------------------- | ------- | --------------------------------------------------------------------------------- | +| `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_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 | +| `OPENCODE_DISABLE_PRUNE` | booléen | Désactiver le nettoyage des anciennes données | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | booléen | Désactiver les mises à jour automatiques des titres du terminal | +| `OPENCODE_PERMISSION` | chaîne | Configuration des autorisations JSON intégrées | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | booléen | Désactiver les plugins par défaut | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | booléen | Désactiver les téléchargements automatiques du serveur LSP | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | booléen | Activer les modèles expérimentaux | +| `OPENCODE_DISABLE_AUTOCOMPACT` | booléen | Désactiver le compactage automatique du contexte | +| `OPENCODE_DISABLE_CLAUDE_CODE` | booléen | Désactiver la lecture de `.claude` (prompt + compétences) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | booléen | Désactiver la lecture `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | booléen | Désactiver le chargement de `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | booléen | Désactiver la récupération de modèles à partir de sources distantes | +| `OPENCODE_FAKE_VCS` | chaîne | Faux fournisseur VCS à des fins de test | +| `OPENCODE_DISABLE_FILETIME_CHECK` | booléen | Désactiver la vérification de l'heure des fichiers pour l'optimisation | +| `OPENCODE_CLIENT` | chaîne | Identifiant du client (par défaut `cli`) | +| `OPENCODE_ENABLE_EXA` | booléen | Activer les outils de recherche Web Exa | +| `OPENCODE_SERVER_PASSWORD` | chaîne | Activer l'authentification de base pour `serve`/`web` | +| `OPENCODE_SERVER_USERNAME` | chaîne | Remplacer le nom d'utilisateur d'authentification de base (par défaut `opencode`) | +| `OPENCODE_MODELS_URL` | chaîne | URL personnalisé pour récupérer la configuration des modèles | + +--- + +### Expérimental + +Ces variables d'environnement activent des fonctionnalités expérimentales qui peuvent être modifiées ou supprimées. + +| Variables | Type | Description | +| ----------------------------------------------- | ------- | --------------------------------------------------------------- | +| `OPENCODE_EXPERIMENTAL` | booléen | Activer toutes les fonctionnalités expérimentales | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | booléen | Activer la découverte d'icônes | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | booléen | Désactiver la copie lors de la sélection dans TUI | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | numéro | Délai d'expiration par défaut pour les commandes bash en ms | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | numéro | Nombre maximum de jetons de sortie pour les réponses LLM | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | booléen | Activer l'observateur de fichiers pour l'ensemble du répertoire | +| `OPENCODE_EXPERIMENTAL_OXFMT` | booléen | Activer le formateur oxfmt | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | booléen | Activer l'outil expérimental LSP | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | booléen | Désactiver l'observateur de fichiers | +| `OPENCODE_EXPERIMENTAL_EXA` | booléen | Activer les fonctionnalités Exa expérimentales | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | booléen | Activer la vérification expérimentale de type LSP | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | booléen | Activer les fonctionnalités Markdown expérimentales | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | booléen | Activer le mode plan | diff --git a/packages/web/src/content/docs/fr/commands.mdx b/packages/web/src/content/docs/fr/commands.mdx new file mode 100644 index 00000000000..71e03342e1d --- /dev/null +++ b/packages/web/src/content/docs/fr/commands.mdx @@ -0,0 +1,322 @@ +--- +title: Commandes +description: Créez des commandes personnalisées pour les tâches répétitives. +--- + +Les commandes personnalisées vous permettent de spécifier un prompt que vous souhaitez exécuter lorsque cette commande est exécutée dans le TUI. + +```bash frame="none" +/my-command +``` + +Les commandes personnalisées s'ajoutent aux commandes intégrées telles que `/init`, `/undo`, `/redo`, `/share`, `/help`. [En savoir plus](/docs/tui#commands). + +--- + +## Créer des fichiers de commandes + +Créez des fichiers markdown dans le répertoire `commands/` pour définir des commandes personnalisées. + +Créez `.opencode/commands/test.md` : + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Le frontmatter définit les propriétés de la commande. Le contenu devient le modèle (template). + +Utilisez la commande en tapant `/` suivi du nom de la commande. + +```bash frame="none" +"/test" +``` + +--- + +## Configuration + +Vous pouvez ajouter des commandes personnalisées via la configuration OpenCode ou en créant des fichiers markdown dans le répertoire `commands/`. + +--- + +### JSON + +Utilisez l'option `command` dans votre OpenCode [config](/docs/config) : + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Vous pouvez maintenant exécuter cette commande dans le TUI : + +```bash frame="none" +/test +``` + +--- + +### Markdown + +Vous pouvez également définir des commandes à l'aide de fichiers markdown. Placez-les dans : + +- Global : `~/.config/opencode/commands/` +- Par projet : `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Le nom du fichier markdown devient le nom de la commande. Par exemple, `test.md` permet d'exécuter : + +```bash frame="none" +/test +``` + +--- + +## Configuration rapide + +Les prompts pour les commandes personnalisées prennent en charge plusieurs espaces réservés et syntaxes spéciaux. + +--- + +### Arguments + +Transmettez les arguments aux commandes à l’aide de l’espace réservé `$ARGUMENTS`. + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +Exécutez la commande avec des arguments : + +```bash frame="none" +/component Button +``` + +Et `$ARGUMENTS` sera remplacé par `Button`. + +Vous pouvez également accéder à des arguments individuels à l'aide de paramètres de position : + +- `$1` - Premier argument +- `$2` - Deuxième argument +- `$3` - Troisième argument +- Et ainsi de suite... + +Par exemple: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +Exécutez la commande : + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +Celui-ci remplace : + +- `$1` avec `config.json` +- `$2` avec `src` +- `$3` avec `{ "key": "value" }` + +--- + +### Sortie du shell + +Utilisez _!`command`_ pour injecter la sortie [bash command](/docs/tui#bash-commands) dans votre prompt. + +Par exemple, pour créer une commande personnalisée qui analyse la couverture des tests : + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +Ou pour consulter les modifications récentes : + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +Les commandes s'exécutent dans le répertoire racine de votre projet et leur sortie fait partie du prompt. + +--- + +### Références de fichiers + +Incluez les fichiers dans votre commande en utilisant `@` suivi du nom du fichier. + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +Le contenu du fichier est automatiquement inclus dans le prompt. + +--- + +## Options + +Examinons les options de configuration en détail. + +--- + +### Template + +L'option `template` définit le prompt qui sera envoyé au LLM lors de l'exécution de la commande. + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +Il s'agit d'une option de configuration **obligatoire**. + +--- + +### Description + +Utilisez l'option `description` pour fournir une brève description de ce que fait la commande. + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +Ceci est affiché comme description dans le TUI lorsque vous tapez la commande. + +--- + +### Agent + +Utilisez la configuration `agent` pour spécifier éventuellement quel [agent](/docs/agents) doit exécuter cette commande. +S'il s'agit d'un [subagent](/docs/agents/#subagents), la commande déclenchera un appel de sous-agent par défaut. +Pour désactiver ce comportement, définissez `subtask` sur `false`. + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +Il s'agit d'une option de configuration **facultative**. S’il n’est pas spécifié, la valeur par défaut est votre agent actuel. + +--- + +### Sous-tâche + +Utilisez le booléen `subtask` pour forcer la commande à déclencher une invocation de [subagent](/docs/agents/#subagents). +Ceci est utile si vous souhaitez que la commande ne pollue pas votre contexte principal et **force** l'agent à agir en tant que sous-agent, +même si `mode` est défini sur `primary` dans la configuration [agent](/docs/agents). + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +Il s'agit d'une option de configuration **facultative**. + +--- + +### Modèle + +Utilisez la configuration `model` pour remplacer le modèle par défaut pour cette commande. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Il s'agit d'une option de configuration **facultative**. + +--- + +## Commandes intégrées + +opencode comprend plusieurs commandes intégrées comme `/init`, `/undo`, `/redo`, `/share`, `/help` ; [en savoir plus](/docs/tui#commands). + +:::note +Les commandes personnalisées peuvent remplacer les commandes intégrées. +::: + +Si vous définissez une commande personnalisée portant le même nom, elle remplacera la commande intégrée. diff --git a/packages/web/src/content/docs/fr/config.mdx b/packages/web/src/content/docs/fr/config.mdx new file mode 100644 index 00000000000..8c0d15e183a --- /dev/null +++ b/packages/web/src/content/docs/fr/config.mdx @@ -0,0 +1,681 @@ +--- +title: Configuration +description: Utilisation de la configuration JSON OpenCode. +--- + +Vous pouvez configurer OpenCode à l'aide d'un fichier de configuration JSON. + +--- + +## Format + +OpenCode prend en charge les formats **JSON** et **JSONC** (JSON avec commentaires). + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + // Theme configuration + "theme": "opencode", + "model": "anthropic/claude-sonnet-4-5", + "autoupdate": true, +} +``` + +--- + +## Emplacements + +Vous pouvez placer votre configuration à plusieurs emplacements différents et ils ont un +ordre de priorité différent. + +:::note +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. + +--- + +### Ordre de priorité + +Les sources de configuration sont chargées dans cet ordre (les sources ultérieures remplacent les précédentes) : + +1. **Configuration distante** (à partir de `.well-known/opencode`) - paramètres par défaut de l'organisation +2. **Configuration globale** (`~/.config/opencode/opencode.json`) - préférences utilisateur +3. **Configuration personnalisée** (`OPENCODE_CONFIG` env var) - remplacements personnalisés +4. **Configuration du projet** (`opencode.json` dans le projet) - paramètres spécifiques au projet +5. **Répertoires `.opencode`** - agents, commandes, plugins +6. **Configuration en ligne** (`OPENCODE_CONFIG_CONTENT` env var) - remplacements d'exécution + +Cela signifie que les configurations de projet peuvent remplacer les valeurs par défaut globales, et que les configurations globales peuvent remplacer les valeurs par défaut de l'organisation distante. + +:::note +Les répertoires `.opencode` et `~/.config/opencode` utilisent des **noms au pluriel** pour les sous-répertoires : `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/` et `themes/`. Les noms singuliers (par exemple, `agent/`) sont également pris en charge pour une compatibilité ascendante. +::: + +--- + +### Configuration distante + +Les organisations peuvent fournir une configuration par défaut via le point de terminaison `.well-known/opencode`. Ceci est récupéré automatiquement lorsque vous vous authentifiez auprès d’un fournisseur qui le prend en charge. + +La configuration distante est chargée en premier, servant de couche de base. Toutes les autres sources de configuration (globales, projet) peuvent remplacer ces valeurs par défaut. + +Par exemple, si votre organisation fournit des serveurs MCP qui sont désactivés par défaut : + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +Vous pouvez activer des serveurs spécifiques dans votre configuration locale : + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### 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. + +La configuration globale remplace les paramètres par défaut de l'organisation distante. + +--- + +### Par projet + +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. + +:::tip +Placez la configuration spécifique au projet à la racine de votre projet. +::: + +Lorsque OpenCode démarre, il recherche un fichier de configuration dans le répertoire actuel ou remonte jusqu'au répertoire Git le plus proche. + +Il peut également être archivé en toute sécurité dans Git et utilise le même schéma que le schéma global. + +--- + +### Chemin personnalisé + +Spécifiez un chemin de fichier de configuration personnalisé à l'aide de la variable d'environnement `OPENCODE_CONFIG`. + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +La configuration personnalisée est chargée entre les configurations globales et celles du projet dans l'ordre de priorité. + +--- + +### Répertoire personnalisé + +Spécifiez un répertoire de configuration personnalisé à l'aide de `OPENCODE_CONFIG_DIR` variable d'environnement. Ce répertoire sera recherché pour les agents, les commandes, modes et plugins tout comme le répertoire standard `.opencode`, et devrait suivre la même structure. + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +Le répertoire personnalisé est chargé après les répertoires de configuration globale et `.opencode`, il **peut donc remplacer** leurs paramètres. + +--- + +## Schéma + +Le fichier de configuration a un schéma défini dans [**`opencode.ai/config.json`**](https://opencode.ai/config.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`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +Options disponibles : + +- `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. + +[En savoir plus sur l'utilisation du TUI ici](/docs/tui). + +--- + +### Serveur + +Vous pouvez configurer les paramètres du serveur pour les commandes `opencode serve` et `opencode web` via l'option `server`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +Options disponibles : + +- `port` - Port d'écoute. +- `hostname` - Nom d'hôte d'écoute. Lorsque `mdns` est activé et qu'aucun nom d'hôte n'est défini, la valeur par défaut est `0.0.0.0`. +- `mdns` - Activer la découverte du service mDNS. Cela permet à d'autres appareils du réseau de découvrir votre serveur OpenCode. +- `mdnsDomain` - Nom de domaine personnalisé pour le service mDNS. La valeur par défaut est `opencode.local`. Utile pour exécuter plusieurs instances sur le même réseau. +- `cors` - Origines supplémentaires pour autoriser CORS lors de l'utilisation du serveur HTTP à partir d'un client basé sur un navigateur. Les valeurs doivent être des origines complètes (schéma + hôte + port facultatif), par exemple `https://app.example.com`. + +[En savoir plus sur le serveur ici](/docs/server). + +--- + +### Outils + +Vous pouvez gérer les outils qu'un LLM peut utiliser via l'option `tools`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[En savoir plus sur les outils ici](/docs/tools). + +--- + +### Modèles + +Vous pouvez configurer les fournisseurs et les modèles que vous souhaitez utiliser dans votre configuration OpenCode via les options `provider`, `model` et `small_model`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +L'option `small_model` configure un modèle distinct pour les tâches légères comme la génération de titres. Par défaut, OpenCode essaie d'utiliser un modèle moins cher s'il est disponible auprès de votre fournisseur, sinon il revient à votre modèle principal. + +Les options du fournisseur peuvent inclure `timeout` et `setCacheKey` : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` - Délai d'expiration de la demande en millisecondes (par défaut : 300 000). Réglez sur `false` pour désactiver. +- `setCacheKey` - Assurez-vous qu'une clé de cache est toujours définie pour le fournisseur désigné. + +Vous pouvez également configurer [modèles locaux](/docs/models#local). [En savoir plus](/docs/models). + +--- + +#### Options spécifiques au fournisseur + +Certains fournisseurs prennent en charge des options de configuration supplémentaires au-delà des paramètres génériques `timeout` et `apiKey`. + +##### Amazon Bedrock + +Amazon Bedrock prend en charge la configuration spécifique à AWS : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` - Région AWS pour Bedrock (par défaut : `AWS_REGION` env var ou `us-east-1`) +- `profile` - Profil nommé AWS de `~/.aws/credentials` (par défaut : `AWS_PROFILE` env var) +- `endpoint` - Point de terminaison personnalisé URL pour les points de terminaison d'un VPC. Il s'agit d'un alias pour l'option générique `baseURL` utilisant la terminologie spécifique à AWS. Si les deux sont spécifiés, `endpoint` est prioritaire. + +:::note +Les jetons du porteur (`AWS_BEARER_TOKEN_BEDROCK` ou `/connect`) ont priorité sur l'authentification basée sur le profil. Voir [précédence d'authentification](/docs/providers#authentication-precedence) pour plus de détails. +::: + +[En savoir plus sur la configuration d'Amazon Bedrock](/docs/providers#amazon-bedrock). + +--- + +### Thèmes + +Vous pouvez configurer le thème que vous souhaitez utiliser dans votre configuration OpenCode via l'option `theme`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[En savoir plus ici](/docs/themes). + +--- + +### Agents + +Vous pouvez configurer des agents spécialisés pour des tâches spécifiques via l'option `agent`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +Vous pouvez également définir des agents à l'aide de fichiers markdown dans `~/.config/opencode/agents/` ou `.opencode/agents/`. [En savoir plus ici](/docs/agents). + +--- + +### Agent par défaut + +Vous pouvez définir l'agent par défaut à l'aide de l'option `default_agent`. Ceci détermine quel agent est utilisé lorsqu'aucun n'est explicitement spécifié. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +L'agent par défaut doit être un agent principal (et non un sous-agent). Il peut s'agir d'un agent intégré tel que `"build"` ou `"plan"`, ou d'un [agent personnalisé](/docs/agents) que vous avez défini. Si l'agent spécifié n'existe pas ou est un sous-agent, OpenCode reviendra à `"build"` avec un avertissement. + +Ce paramètre s'applique à toutes les interfaces : TUI, CLI (`opencode run`), application de bureau et GitHub Action. + +--- + +### Partage + +Vous pouvez configurer la fonctionnalité [share](/docs/share) via l'option `share`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +Elle accepte : + +- `"manual"` – Autoriser le partage manuel via des commandes (par défaut) +- `"auto"` – Partager automatiquement de nouvelles conversations +- `"disabled"` – Désactiver complètement le partage + +Par défaut, le partage est défini en mode manuel où vous devez partager explicitement les conversations à l'aide de la commande `/share`. + +--- + +### Commandes + +Vous pouvez configurer des commandes personnalisées pour les tâches répétitives via l'option `command`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +Vous pouvez également définir des commandes à l'aide de fichiers markdown dans `~/.config/opencode/commands/` ou `.opencode/commands/`. [En savoir plus ici](/docs/commands). + +--- + +### Raccourcis clavier + +Vous pouvez personnaliser vos raccourcis clavier via l'option `keybinds`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[En savoir plus ici](/docs/keybinds). + +--- + +### Mise à jour automatique + +OpenCode téléchargera automatiquement toutes les nouvelles mises à jour au démarrage. Vous pouvez désactiver cela avec l'option `autoupdate`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +Si vous ne souhaitez pas de mises à jour mais souhaitez être averti lorsqu'une nouvelle version est disponible, définissez `autoupdate` sur `"notify"`. +Notez que cela ne fonctionne que s'il n'a pas été installé à l'aide d'un gestionnaire de packages tel que Homebrew. + +--- + +### Formateurs + +Vous pouvez configurer les formateurs de code via l'option `formatter`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[En savoir plus sur les formateurs ici](/docs/formatters). + +--- + +### Autorisations + +Par défaut, opencode **autorise toutes les opérations** sans nécessiter d'approbation explicite. Vous pouvez modifier cela en utilisant l'option `permission`. + +Par exemple, pour garantir que les outils `edit` et `bash` nécessitent l'approbation de l'utilisateur : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[En savoir plus sur les autorisations ici](/docs/permissions). + +--- + +### Compactage + +Vous pouvez contrôler le comportement de compactage du contexte via l'option `compaction`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `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`). + +--- + +### Observateur + +Vous pouvez configurer les modèles d'ignorance de l'observateur de fichiers via l'option `watcher`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +Les modèles suivent la syntaxe glob. Utilisez ceci pour exclure les répertoires bruyants de la surveillance des fichiers. + +--- + +### Serveurs MCP + +Vous pouvez configurer les serveurs MCP que vous souhaitez utiliser via l'option `mcp`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[En savoir plus ici](/docs/mcp-servers). + +--- + +### Extensions + +[Plugins](/docs/plugins) étendent OpenCode avec des outils, des hooks et des intégrations personnalisés. + +Placez les fichiers du plugin dans `.opencode/plugins/` ou `~/.config/opencode/plugins/`. Vous pouvez également charger des plugins depuis npm via l'option `plugin`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[En savoir plus ici](/docs/plugins). + +--- + +### Instructions + +Vous pouvez configurer les instructions pour le modèle que vous utilisez via l'option `instructions`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Cela prend un tableau de chemins et de modèles globaux vers les fichiers d'instructions. [En savoir plus sur les règles ici](/docs/rules). + +--- + +### Fournisseurs désactivés + +Vous pouvez désactiver les fournisseurs chargés automatiquement via l'option `disabled_providers`. Ceci est utile lorsque vous souhaitez empêcher le chargement de certains fournisseurs même si leurs informations d'identification sont disponibles. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +Le `disabled_providers` est prioritaire sur `enabled_providers`. +::: + +L'option `disabled_providers` accepte un tableau d'ID de fournisseur. Lorsqu'un fournisseur est désactivé : + +- Il ne sera pas chargé même si des variables d'environnement sont définies. +- Il ne sera pas chargé même si les clés API sont configurées via la commande `/connect`. +- Les modèles du fournisseur n'apparaîtront pas dans la liste de sélection des modèles. + +--- + +### Fournisseurs activés + +Vous pouvez spécifier une liste autorisée de fournisseurs via l'option `enabled_providers`. Une fois défini, seuls les fournisseurs spécifiés seront activés et tous les autres seront ignorés. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +Ceci est utile lorsque vous souhaitez restreindre OpenCode à l'utilisation de fournisseurs spécifiques plutôt que de les désactiver un par un. + +:::note +Le `disabled_providers` est prioritaire sur `enabled_providers`. +::: + +Si un fournisseur apparaît à la fois dans `enabled_providers` et `disabled_providers`, le `disabled_providers` est prioritaire pour la compatibilité ascendante. + +--- + +### Expérimental + +La clé `experimental` contient des options en cours de développement actif. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +Les options expérimentales ne sont pas stables. Elles peuvent changer ou être supprimées sans préavis. +::: + +--- + +## Variables + +Vous pouvez utiliser la substitution de variables dans vos fichiers de configuration pour référencer les variables d'environnement et le contenu des fichiers. + +--- + +### Variables d'environnement + +Utilisez `{env:VARIABLE_NAME}` pour remplacer les variables d'environnement : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +Si la variable d'environnement n'est pas définie, elle sera remplacée par une chaîne vide. + +--- + +### Fichiers + +Utilisez `{file:path/to/file}` pour remplacer le contenu d'un fichier : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +Les chemins de fichiers peuvent être : + +- Relatifs au répertoire du fichier de configuration +- Ou des chemins absolus commençant par `/` ou `~` + +Elles sont utiles pour : + +- Conserver les données sensibles telles que les clés API dans des fichiers séparés. +- Inclure de gros fichiers d'instructions sans encombrer votre configuration. +- Partager des extraits de configuration communs sur plusieurs fichiers de configuration. diff --git a/packages/web/src/content/docs/fr/custom-tools.mdx b/packages/web/src/content/docs/fr/custom-tools.mdx new file mode 100644 index 00000000000..2753f0e322b --- /dev/null +++ b/packages/web/src/content/docs/fr/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: Outils personnalisés +description: Créez des outils que le LLM peut appeler dans opencode. +--- + +Les outils personnalisés sont des fonctions que vous créez et que le LLM peut appeler pendant les conversations. Ils fonctionnent avec les [outils intégrés](/docs/tools) de opencode comme `read`, `write` et `bash`. + +--- + +## Création d'un outil + +Les outils sont définis sous forme de fichiers **TypeScript** ou **JavaScript**. Cependant, la définition de l'outil peut appeler des scripts écrits dans **n'importe quel langage** : TypeScript ou JavaScript n'est utilisé que pour la définition de l'outil elle-même. + +--- + +### Emplacement + +Ils peuvent être définis : + +- Localement en les plaçant dans le répertoire `.opencode/tools/` de votre projet. +- Ou globalement, en les plaçant dans `~/.config/opencode/tools/`. + +--- + +### Structure + +Le moyen le plus simple de créer des outils est d'utiliser l'assistant `tool()` qui fournit la sécurité et la validation de type. + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +Le **nom de fichier** devient le **nom de l'outil**. Ce qui précède crée un outil `database`. + +--- + +#### Plusieurs outils par fichier + +Vous pouvez également exporter plusieurs outils à partir d'un seul fichier. Chaque exportation devient **un outil distinct** portant le nom **`_`** : + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +Cela crée deux outils : `math_add` et `math_multiply`. + +--- + +### Arguments + +Vous pouvez utiliser `tool.schema`, qui est simplement [Zod](https://zod.dev), pour définir les types d'arguments. + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +Vous pouvez également importer [Zod](https://zod.dev) directement et renvoyer un objet simple : + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### Contexte + +Les outils reçoivent le contexte de la session en cours : + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +Utilisez `context.directory` pour le répertoire de travail de la session. +Utilisez `context.worktree` pour la racine du worktree git. + +--- + +## Exemples + +### Écrire un outil en Python + +Vous pouvez écrire vos outils dans le langage de votre choix. Voici un exemple qui ajoute deux nombres à l'aide de Python. + +Tout d'abord, créez l'outil en tant que script Python : + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +Créez ensuite la définition d'outil qui l'invoque : + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +Ici, nous utilisons l'utilitaire [`Bun.$`](https://bun.com/docs/runtime/shell) pour exécuter le script Python. diff --git a/packages/web/src/content/docs/fr/ecosystem.mdx b/packages/web/src/content/docs/fr/ecosystem.mdx new file mode 100644 index 00000000000..dd74e1f7bf5 --- /dev/null +++ b/packages/web/src/content/docs/fr/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: Écosystème +description: Projets et intégrations construits avec OpenCode. +--- + +Une collection de projets communautaires construits sur OpenCode. + +:::note +Vous souhaitez ajouter votre projet lié à OpenCode à cette liste ? Soumettez un PR. +::: + +Vous pouvez également consulter [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) et [opencode.cafe](https://opencode.cafe), une communauté qui regroupe l'écosystème OpenCode. + +--- + +## Extensions + +| Nom | Description | +| --------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | Exécute automatiquement des sessions OpenCode dans des environnements sandbox Daytona isolés avec synchronisation git et prévisualisations en direct | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | Injecte automatiquement les en-têtes de session Helicone pour le regroupement des requêtes | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | Injecte automatiquement les types TypeScript/Svelte dans les lectures de fichiers avec des outils de recherche | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | Utilise votre abonnement ChatGPT Plus/Pro au lieu de crédits API | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | Utilise votre forfait Gemini existant au lieu de la facturation API | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | Utilise les modèles gratuits d'Antigravity au lieu de la facturation API | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Isolation de conteneur de développement multibranche avec clones superficiels et ports attribués automatiquement | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Plugin Google Antigravity OAuth, avec support de la recherche Google et gestion API plus robuste | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Optimise l'utilisation des jetons en éliminant les sorties d'outils obsolètes | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Ajoute le support natif de la recherche Web pour les fournisseurs pris en charge avec le style ancré par Google | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Permet aux agents IA d'exécuter des processus en arrière-plan dans un PTY et de leur envoyer des entrées interactives. | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Instructions pour les commandes shell non interactives - empêche les blocages des opérations dépendantes du TTY | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Suit l'utilisation de OpenCode avec Wakatime | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Nettoie les tableaux Markdown produits par les LLM | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | Édition de code 10 fois plus rapide avec Morph Fast Apply API et les marqueurs d'édition différée | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Agents d'arrière-plan, outils LSP/AST/MCP prédéfinis, agents sélectionnés, compatibles Claude Code | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | Notifications de bureau et alertes sonores pour les sessions OpenCode | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Notifications sur le bureau et alertes sonores pour les événements d'autorisation, d'achèvement et d'erreur | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | Dénomination automatique de session Zellij basée sur l'IA et le contexte OpenCode | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Autorise les agents OpenCode à charger paresseusement les prompts à la demande grâce à la découverte et à l'injection de compétences | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Mémoire persistante entre les sessions utilisant Supermemory | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Révision interactive du plan avec annotation visuelle et partage privé/hors ligne | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Étend les commandes /commands d'opencode dans un système d'orchestration puissant avec contrôle de flux granulaire | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | Planifie des tâches récurrentes à l'aide de launchd (Mac) ou systemd (Linux) avec la syntaxe cron | +| [micode](https://github.com/vtemian/micode) | Workflow structuré Brainstorming → Planifier → Mettre en œuvre avec continuité de session | +| [octto](https://github.com/vtemian/octto) | Interface utilisateur de navigateur interactive pour le brainstorming IA avec des formulaires multi-questions | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | Agents d'arrière-plan de style Claude Code avec délégation asynchrone et persistance du contexte | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | Notifications natives du système d'exploitation pour OpenCode – savoir quand les tâches sont terminées | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | Harness d'orchestration multi-agent prêt à l'emploi - 16 composants, une installation | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | Arbres de travail Git sans friction pour OpenCode | + +--- + +## Projets + +| Nom | Description | +| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | +| [kimaki](https://github.com/remorses/kimaki) | Bot Discord pour contrôler les sessions OpenCode, construit sur le SDK | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Plugin Neovim pour les prompts compatibles avec l'éditeur, construit sur l'API | +| [portal](https://github.com/hosenur/portal) | Interface utilisateur Web axée sur le mobile pour OpenCode sur Tailscale/VPN | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | Modèle pour créer des plugins OpenCode | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Frontend Neovim pour opencode - un agent de codage d'IA basé sur un terminal | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Fournisseur Vercel AI SDK pour l'utilisation de OpenCode via @opencode-ai/sdk | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | Application Web/De bureau et extension VS Code pour OpenCode | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Plugin Obsidian qui intègre OpenCode dans l'interface utilisateur d'Obsidian | +| [OpenWork](https://github.com/different-ai/openwork) | Une alternative open source à Claude Cowork, propulsée par OpenCode | +| [ocx](https://github.com/kdcokenny/ocx) | Gestionnaire d'extensions OpenCode avec profils portables et isolés. | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | Application client de bureau, Web, mobile et distante pour OpenCode | + +--- + +## Agents + +| Nom | Description | +| ----------------------------------------------------------------- | ----------------------------------------------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | Agents et commandes d'IA modulaires pour un développement structuré | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | Configurations, prompts, agents et plugins pour des flux de travail améliorés | diff --git a/packages/web/src/content/docs/fr/enterprise.mdx b/packages/web/src/content/docs/fr/enterprise.mdx new file mode 100644 index 00000000000..659fc3e7cc8 --- /dev/null +++ b/packages/web/src/content/docs/fr/enterprise.mdx @@ -0,0 +1,165 @@ +--- +title: Entreprise +description: Utiliser OpenCode en toute sécurité dans votre organisation. +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +OpenCode Enterprise est destiné aux organisations qui souhaitent s'assurer que leur code et leurs données ne quittent jamais leur infrastructure. Cela est possible grâce à une configuration centralisée qui s'intègre à votre SSO et à votre passerelle IA interne. + +:::note +OpenCode ne stocke aucune de vos données de code ou de contexte. +::: + +Pour démarrer avec OpenCode Enterprise : + +1. Faites un essai en interne avec votre équipe. +2. **Contactez-nous** pour discuter des options de tarification et de mise en œuvre. + +--- + +## Essai + +OpenCode est open source et ne stocke aucune de vos données de code ou de contexte, vos développeurs peuvent donc simplement [commencer ](/docs/) et effectuer un essai. + +--- + +### Traitement des données + +**OpenCode ne stocke pas votre code ni vos données contextuelles.** Tous les traitements s'effectuent localement ou via des appels API directs à votre fournisseur d'IA. + +Cela signifie que tant que vous faites appel à un fournisseur de confiance ou à une passerelle IA, vous pouvez utiliser OpenCode en toute sécurité. + +La seule mise en garde ici concerne la fonctionnalité facultative `/share`. + +--- + +#### Partager des conversations + +Si un utilisateur active la fonctionnalité `/share`, la conversation et les données qui y sont associées sont envoyées au service que nous utilisons pour héberger ces pages de partage sur opencode.ai. + +Les données sont actuellement servies via le réseau périphérique de notre CDN et sont mises en cache en périphérie, à proximité de vos utilisateurs. + +Nous vous recommandons de désactiver cette option pour votre essai. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[En savoir plus sur le partage](/docs/share). + +--- + +### Propriété du code + +**Vous possédez tout le code produit par OpenCode.** Il n'y a aucune restriction de licence ni revendication de propriété. + +--- + +## Tarifs + +Nous utilisons un modèle par siège pour OpenCode Enterprise. Si vous disposez de votre propre passerelle LLM, nous ne facturons pas les jetons utilisés. Pour plus de détails sur les options de tarification et de mise en œuvre, **contactez-nous**. + +--- + +## Déploiement + +Une fois que vous avez terminé votre essai et que vous êtes prêt à utiliser OpenCode à votre organisation, vous pouvez **nous contacter** pour discuter des options de tarification et de mise en œuvre. + +--- + +### Configuration centrale + +Nous pouvons configurer OpenCode pour utiliser une seule configuration centrale pour l'ensemble de votre organisation. + +Cette configuration centralisée peut s'intégrer à votre fournisseur SSO et garantit que tous les utilisateurs accèdent uniquement à votre passerelle IA interne. + +--- + +### Intégration SSO + +Grâce à la configuration centrale, OpenCode peut s'intégrer au fournisseur SSO de votre organisation pour l'authentification. + +Cela permet à OpenCode d'obtenir les informations d'identification de votre passerelle IA interne via votre système de gestion des identités existant. + +--- + +### Passerelle IA interne + +Avec la configuration centrale, OpenCode peut également être configuré pour utiliser uniquement votre passerelle IA interne. + +Vous pouvez également désactiver tous les autres fournisseurs d'IA, en vous assurant que toutes les demandes transitent par l'infrastructure approuvée de votre organisation. + +--- + +### Auto-hébergement + +Bien que nous vous recommandons de désactiver les pages de partage pour garantir que vos données ne quittent jamais votre organisation, nous pouvons également vous aider à les auto-héberger sur votre infrastructure. + +Ceci est actuellement sur notre feuille de route. Si vous êtes intéressé, **faites-le-nous savoir**. + +--- + +## FAQ + +

+Qu’est-ce que OpenCode Entreprise ? + +OpenCode Enterprise est destiné aux organisations qui souhaitent s'assurer que leur code et leurs données ne quittent jamais leur infrastructure. Il peut le faire en utilisant une configuration centralisée qui s'intègre à votre SSO et à votre passerelle IA interne. + +
+ +
+Comment démarrer avec OpenCode Enterprise ? + +Commencez simplement par un essai interne avec votre équipe. OpenCode par défaut ne stocke pas votre code ni vos données contextuelles, ce qui facilite le démarrage. + +Ensuite, **contactez-nous** pour discuter des options de tarification et de mise en œuvre. + +
+ +
+Comment fonctionne la tarification d'entreprise ? + +Nous proposons des tarifs d'entreprise par siège. Si vous disposez de votre propre passerelle LLM, nous ne facturons pas les jetons utilisés. Pour plus de détails, **contactez-nous** pour un devis personnalisé basé sur les besoins de votre organisation. + +
+ +
+Mes données sont-elles sécurisées avec OpenCode Enterprise ? + +Oui. OpenCode ne stocke pas votre code ni vos données contextuelles. Tout le traitement s'effectue localement ou via des appels API directs à votre fournisseur d'IA. Grâce à la configuration centrale et à l'intégration SSO, vos données restent sécurisées au sein de l'infrastructure de votre organisation. + +
+ +
+Pouvons-nous utiliser notre propre registre privé NPM ? + +OpenCode prend en charge les registres npm privés via la prise en charge native des fichiers `.npmrc` de Bun. Si votre organisation utilise un registre privé, tel que JFrog Artifactory, Nexus ou similaire, assurez-vous que les développeurs sont authentifiés avant d'exécuter OpenCode. + +Pour configurer l'authentification avec votre registre privé : + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +Cela crée `~/.npmrc` avec les détails d'authentification. OpenCode le détectera automatiquement. + +:::caution +Vous devez être connecté au registre privé avant d'exécuter OpenCode. +::: + +Alternativement, vous pouvez configurer manuellement un fichier `.npmrc` : + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +Les développeurs doivent être connectés au registre privé avant d'exécuter OpenCode pour garantir que les packages peuvent être installés à partir du registre de votre entreprise. + +
diff --git a/packages/web/src/content/docs/fr/formatters.mdx b/packages/web/src/content/docs/fr/formatters.mdx new file mode 100644 index 00000000000..ef59b810819 --- /dev/null +++ b/packages/web/src/content/docs/fr/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: Formateurs +description: OpenCode utilise des formateurs spécifiques au langage. +--- + +OpenCode formate automatiquement les fichiers après leur écriture ou leur modification à l'aide de formateurs spécifiques au langage. Cela garantit que le code généré suit les styles de code de votre projet. + +--- + +## Formateurs intégrés + +OpenCode est livré avec plusieurs formateurs intégrés pour les langages et frameworks populaires. Vous trouverez ci-dessous une liste des formateurs, des extensions de fichiers prises en charge et des commandes ou options de configuration dont il a besoin. + +| Formateur | Extensions | Prérequis | +| -------------------- | ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | +| gofmt | .go | Commande `gofmt` disponible | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | Commande `mix` disponible | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml et [plus](https://prettier.io/docs/en/index.html) | Dépendance `prettier` dans `package.json` | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml et [plus](https://biomejs.dev/) | Fichier de configuration `biome.json(c)` | +| zig | .zig, .zon | Commande `zig` disponible | +| clang-format | .c, .cpp, .h, .hpp, .ino et [plus](https://clang.llvm.org/docs/ClangFormat.html) | Fichier de configuration `.clang-format` | +| ktlint | .kt, .kts | Commande `ktlint` disponible | +| ruff | .py, .pyi | Commande `ruff` disponible avec config | +| rustfmt | .rs | Commande `rustfmt` disponible | +| cargofmt | .rs | Commande `cargo fmt` disponible | +| uv | .py, .pyi | Commande `uv` disponible | +| rubocop | .rb, .rake, .gemspec, .ru | Commande `rubocop` disponible | +| standardrb | .rb, .rake, .gemspec, .ru | Commande `standardrb` disponible | +| htmlbeautifier | .erb, .html.erb | Commande `htmlbeautifier` disponible | +| air | .R | Commande `air` disponible | +| dart | .dart | Commande `dart` disponible | +| ocamlformat | .ml, .mli | Commande `ocamlformat` disponible et fichier de configuration `.ocamlformat` | +| terraform | .tf, .tfvars | Commande `terraform` disponible | +| gleam | .gleam | Commande `gleam` disponible | +| nixfmt | .nix | Commande `nixfmt` disponible | +| shfmt | .sh, .bash | Commande `shfmt` disponible | +| pint | .php | Dépendance `laravel/pint` dans `composer.json` | +| oxfmt (expérimental) | .js, .jsx, .ts, .tsx | Dépendance `oxfmt` dans `package.json` et un [flag de variable d'environnement expérimental](/docs/cli/#experimental) | +| ormolu | .hs | Commande `ormolu` disponible | + +Ainsi, si votre projet a `prettier` dans votre `package.json`, OpenCode l'utilisera automatiquement. + +--- + +## Comment ça marche + +Lorsque OpenCode écrit ou modifie un fichier, il : + +1. Vérifie l'extension du fichier par rapport à tous les formateurs activés. +2. Exécute la commande de formatage appropriée sur le fichier. +3. Applique automatiquement les modifications de formatage. + +Ce processus se déroule en arrière-plan, garantissant que vos styles de code sont conservés sans aucune étape manuelle. + +--- + +## Configuration + +Vous pouvez personnaliser les formateurs via la section `formatter` de votre configuration OpenCode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +Chaque configuration du formateur prend en charge les éléments suivants : + +| Propriété | Type | Description | +| ------------- | -------- | -------------------------------------------------------------------- | +| `disabled` | booléen | Définissez ceci sur `true` pour désactiver le formateur | +| `command` | chaîne[] | La commande à exécuter pour le formatage | +| `environment` | objet | Variables d'environnement à définir lors de l'exécution du formateur | +| `extensions` | chaîne[] | Extensions de fichiers que ce formateur doit gérer | + +Regardons quelques exemples. + +--- + +### Désactivation des formateurs + +Pour désactiver **tous** les formateurs globalement, définissez `formatter` sur `false` : + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +Pour désactiver un formateur **spécifique**, définissez `disabled` sur `true` : + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### Formateurs personnalisés + +Vous pouvez remplacer les formateurs intégrés ou en ajouter de nouveaux en spécifiant la commande, les variables d'environnement et les extensions de fichier : + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +L'espace réservé **`$FILE`** dans la commande sera remplacé par le chemin d'accès au fichier en cours de formatage. diff --git a/packages/web/src/content/docs/fr/github.mdx b/packages/web/src/content/docs/fr/github.mdx new file mode 100644 index 00000000000..968ae4d458e --- /dev/null +++ b/packages/web/src/content/docs/fr/github.mdx @@ -0,0 +1,322 @@ +--- +title: GitHub +description: Utilisez OpenCode dans les issues et les pull-requests GitHub. +--- + +OpenCode s'intègre à votre flux de travail GitHub. Mentionnez `/opencode` ou `/oc` dans votre commentaire, et OpenCode exécutera des tâches dans votre runner GitHub Actions. + +--- + +## Fonctionnalités + +- **Triage des issues** : demandez à OpenCode d'examiner une issue et de vous l'expliquer. +- **Correction et implémentation** : demandez à OpenCode de résoudre un problème ou d'implémenter une fonctionnalité. Il travaillera dans une nouvelle branche et soumettra une PR avec tous les changements. +- **Sécurisé** : OpenCode s'exécute à l'intérieur de vos runners GitHub. + +--- + +## Installation + +Exécutez la commande suivante dans un projet qui se trouve dans un dépôt GitHub : + +```bash +opencode github install +``` + +Cela vous guidera dans l'installation de l'application GitHub, la création du workflow et la configuration des secrets. + +--- + +### Configuration manuelle + +Ou vous pouvez le configurer manuellement. + +1. **Installez l'application GitHub** + +Rendez-vous sur [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). Assurez-vous qu'il est installé sur le dépôt cible. + +2. **Ajouter le workflow** + +Ajoutez le fichier de workflow suivant à `.github/workflows/opencode.yml` dans votre dépôt. Assurez-vous de définir les clés `model` appropriées et les clés API requises dans `env`. + +```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx +``` + +3. **Stockez les clés API dans les secrets** + +Dans les **paramètres** de votre organisation ou de votre projet, développez **Secrets et variables** sur la gauche et sélectionnez **Actions**. Puis ajoutez les clés API requises. + +--- + +## Configuration + +- `model` : Le modèle à utiliser avec OpenCode. Prend le format `provider/model`. Ceci est **obligatoire**. +- `agent` : l'agent à utiliser. Doit être un agent primaire. Revient à `default_agent` à partir de la configuration ou à `"build"` s'il n'est pas trouvé. +- `share` : s'il faut partager la session OpenCode. La valeur par défaut est **true** pour les référentiels publics. +- `prompt` : prompt personnalisé facultatif pour remplacer le comportement par défaut. Utilisez-le pour personnaliser la façon dont OpenCode traite les demandes. +- `token` : jeton d'accès GitHub facultatif pour effectuer des opérations telles que la création de commentaires, le commit de modifications et l'ouverture de pull requests. Par défaut, OpenCode utilise le jeton d'accès à l'installation de l'application OpenCode GitHub, de sorte que les commits, les commentaires et les pull requests apparaissent comme provenant de l'application. + +Vous pouvez également utiliser le `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) intégré du runner GitHub Actions sans installer l'application OpenCode GitHub. Assurez-vous simplement d'accorder les autorisations requises dans votre workflow : + +```yaml +permissions: + id-token: write + contents: write + pull-requests: write + issues: write +``` + +Vous pouvez également utiliser un [jeton d'accès personnel](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) si vous préférez. + +--- + +## Événements supportés + +OpenCode peut être déclenché par les événements GitHub suivants : + +| Type d'événement | Déclenché par | Détails | +| ----------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `issue_comment` | Commentaire sur une issue ou une PR | Mentionnez `/opencode` ou `/oc` dans votre commentaire. OpenCode lit le contexte et peut créer des branches, ouvrir des PR ou répondre. | +| `pull_request_review_comment` | Commentaire sur des lignes de code spécifiques dans une PR | Mentionnez `/opencode` ou `/oc` lors de la révision du code. OpenCode reçoit le chemin du fichier, les numéros de ligne et le contexte de comparaison. | +| `issues` | Issue ouverte ou modifiée | Déclenchez automatiquement OpenCode lorsque des issues sont créées ou modifiées. Nécessite une entrée `prompt`. | +| `pull_request` | PR ouverte ou mise à jour | Déclenchez automatiquement OpenCode lorsque les PR sont ouvertes, synchronisées ou rouvertes. Utile pour les revues automatisées. | +| `schedule` | Planification basée sur Cron | Exécutez OpenCode selon un planning. Nécessite une entrée `prompt`. La sortie va aux journaux et aux PR (pas de commentaire sur les issues). | +| `workflow_dispatch` | Déclenchement manuel depuis l'interface utilisateur GitHub | Déclenchez OpenCode à la demande via l'onglet Actions. Nécessite une entrée `prompt`. La sortie va aux journaux et aux PR. | + +### Exemple de planification + +Exécutez OpenCode selon un planning pour effectuer des tâches automatisées : + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +Pour les événements planifiés, l'entrée `prompt` est **obligatoire** car il n'y a aucun commentaire pour extraire les instructions. Les workflows planifiés s'exécutent sans contexte utilisateur pour vérifier les autorisations. Le workflow doit donc accorder `contents: write` et `pull-requests: write` si vous vous attendez à ce que OpenCode crée des branches ou des PR. + +--- + +### Exemple de Pull Request + +Examinez automatiquement les PR lorsqu'ils sont ouverts ou mis à jour : + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Pour les événements `pull_request`, si aucun `prompt` n'est fourni, OpenCode examine par défaut la pull request. + +--- + +### Exemple de Triage d'Issue + +Triez automatiquement les nouvelles issues. Cet exemple filtre les comptes datant de plus de 30 jours pour réduire le spam : + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +Pour les événements `issues`, l'entrée `prompt` est **obligatoire** car il n'y a aucun commentaire à partir duquel extraire les instructions. + +--- + +## Invites personnalisées + +Remplacez l'invite par défaut pour personnaliser le comportement de OpenCode pour votre workflow. + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Ceci est utile pour appliquer des critères d’évaluation spécifiques, des normes de codage ou des domaines d’intervention pertinents pour votre projet. + +--- + +## Exemples + +Voici quelques exemples de la façon dont vous pouvez utiliser OpenCode dans GitHub. + +- **Expliquer une issue** + +Ajoutez ce commentaire dans une issue GitHub. + +``` + /opencode explain this issue +``` + +OpenCode lira l'intégralité du fil de discussion, y compris tous les commentaires, et répondra avec une explication claire. + +- **Résoudre une issue** + +Dans une issue GitHub, dites : + +``` + /opencode fix this +``` + +Et OpenCode créera une nouvelle branche, mettra en œuvre les modifications et ouvrira une PR avec les modifications. + +- **Examinez les PR et apportez des modifications** + +Laissez le commentaire suivant sur une PR GitHub. + +``` + Delete the attachment from S3 when the note is removed /oc +``` + +OpenCode mettra en œuvre la modification demandée et la validera dans la même PR. + +- **Revue de lignes de code spécifiques** + +Laissez un commentaire directement sur les lignes de code dans l'onglet "Fichiers" de la PR. OpenCode détecte automatiquement le fichier, les numéros de ligne et le contexte de comparaison pour fournir des réponses précises. + +``` + [Comment on specific lines in Files tab] + /oc add error handling here +``` + +Lorsqu'il commente des lignes spécifiques, OpenCode reçoit : + +- Le fichier exact en cours d'examen +- Les lignes de code spécifiques +- Le contexte différentiel environnant +- Informations sur le numéro de ligne + +Cela permet des requêtes plus ciblées sans avoir besoin de spécifier manuellement les chemins de fichiers ou les numéros de ligne. diff --git a/packages/web/src/content/docs/fr/gitlab.mdx b/packages/web/src/content/docs/fr/gitlab.mdx new file mode 100644 index 00000000000..db4b1c1a4f5 --- /dev/null +++ b/packages/web/src/content/docs/fr/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: Utilisez OpenCode dans les issues GitLab et les merge requests. +--- + +OpenCode s'intègre à votre flux de travail GitLab via votre pipeline CI/CD GitLab ou avec GitLab Duo. + +Dans les deux cas, OpenCode fonctionnera sur vos runners GitLab. + +--- + +## GitLab CI + +OpenCode fonctionne dans un pipeline GitLab régulier. Vous pouvez l'intégrer dans un pipeline en tant que [composant CI](https://docs.gitlab.com/ee/ci/components/) + +Ici, nous utilisons un composant CI/CD créé par la communauté pour OpenCode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### Fonctionnalités + +- **Utiliser une configuration personnalisée par tâche** : configurez OpenCode avec un répertoire de configuration personnalisé, par exemple `./config/#custom-directory` pour activer ou désactiver la fonctionnalité pour chaque appel d'OpenCode. +- **Configuration minimale** : le composant CI configure OpenCode en arrière-plan, il vous suffit de créer la configuration OpenCode et le prompt initial. +- **Flexible** : le composant CI prend en charge plusieurs entrées pour personnaliser son comportement + +--- + +### Installation + +1. Stockez votre authentification OpenCode JSON en tant que variables d'environnement CI de type fichier sous **Paramètres** > **CI/CD** > **Variables**. Assurez-vous de les marquer comme « Masquées et protégées ». +2. Ajoutez ce qui suit à votre fichier `.gitlab-ci.yml`. + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +Pour plus d'entrées et de cas d'utilisation [consultez la doc](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) pour ce composant. + +--- + +## GitLab Duo + +OpenCode s'intègre à votre flux de travail GitLab. +Mentionnez `@opencode` dans un commentaire et OpenCode exécutera les tâches au sein de votre pipeline CI GitLab. + +--- + +### Fonctionnalités + +- **Triage d'issues** : demandez à OpenCode d'examiner une issue et de vous l'expliquer. +- **Correction et implémentation** : demandez à OpenCode de résoudre une issue ou d'implémenter une fonctionnalité. + Cela créera une nouvelle branche et déclenchera une merge request avec les modifications. +- **Sécurisé** : OpenCode fonctionne sur vos runners GitLab. + +--- + +### Installation + +OpenCode s'exécute dans votre pipeline CI/CD GitLab. Voici ce dont vous aurez besoin pour le configurer : + +:::tip +Consultez la [**documentation GitLab**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) pour obtenir des instructions à jour. +::: + +1. Configurez votre environnement GitLab +2. Configurer CI/CD +3. Obtenez la clé API d'un fournisseur de modèles d'IA +4. Créer un compte de service +5. Configurer les variables CI/CD +6. Créez un fichier de configuration de flux, voici un exemple : + +
+ + Configuration du flux + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +Vous pouvez vous référer aux [GitLab CLI agents docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) pour des instructions détaillées. + +--- + +### Exemples + +Voici quelques exemples de la façon dont vous pouvez utiliser OpenCode dans GitLab. + +:::tip +Vous pouvez configurer pour utiliser une phrase de déclenchement différente de `@opencode`. +::: + +- **Expliquer une issue** + +Ajoutez ce commentaire dans une issue GitLab. + +``` + @opencode explain this issue +``` + +OpenCode lira l'issue et répondra avec une explication claire. + +- **Résoudre une issue** + +Dans une issue GitLab, dites : + +``` + @opencode fix this +``` + +OpenCode créera une nouvelle branche, mettra en œuvre les modifications et ouvrira une merge request avec les modifications. + +- **Revue de merge request** + +Laissez le commentaire suivant sur une merge request GitLab. + +``` + @opencode review this merge request +``` + +OpenCode examinera la merge request et fournira des commentaires. diff --git a/packages/web/src/content/docs/fr/ide.mdx b/packages/web/src/content/docs/fr/ide.mdx new file mode 100644 index 00000000000..fc0c526191c --- /dev/null +++ b/packages/web/src/content/docs/fr/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: L'extension OpenCode pour VS Code, Cursor et autres IDE +--- + +OpenCode s'intègre à VS Code, Cursor ou tout IDE prenant en charge un terminal. Exécutez simplement `opencode` dans le terminal pour commencer. + +--- + +## Utilisation + +- **Lancement rapide** : utilisez `Cmd+Esc` (Mac) ou `Ctrl+Esc` (Windows/Linux) pour ouvrir OpenCode dans une vue de terminal divisée, ou focus sur une session de terminal existante si elle est déjà en cours d'exécution. +- **Nouvelle session** : utilisez `Cmd+Shift+Esc` (Mac) ou `Ctrl+Shift+Esc` (Windows/Linux) pour démarrer une nouvelle session de terminal OpenCode, même si elle est déjà ouverte. Vous pouvez également cliquer sur le bouton OpenCode dans l'interface utilisateur. +- **Contexte** : partagez automatiquement votre sélection ou onglet actuel avec OpenCode. +- **Raccourcis de référence de fichier** : utilisez `Cmd+Option+K` (Mac) ou `Alt+Ctrl+K` (Linux/Windows) pour insérer des références de fichier. Par exemple, `@File#L37-42`. + +--- + +## Installation + +Pour installer OpenCode sur VS Code et les forks populaires comme Cursor, Windsurf, VSCodium : + +1. Ouvrir VS Code +2. Ouvrez le terminal intégré +3. Exécutez `opencode` - l'extension s'installe automatiquement + +Si, d'un autre côté, vous souhaitez utiliser votre propre IDE lorsque vous exécutez `/editor` ou `/export` à partir du TUI, vous devrez définir `export EDITOR="code --wait"`. [En savoir plus](/docs/tui/#editor-setup). + +--- + +### Installation manuelle + +Recherchez **OpenCode** dans Extension Marketplace et cliquez sur **Installer**. + +--- + +### Dépannage + +Si l'extension ne parvient pas à s'installer automatiquement : + +- Assurez-vous que vous exécutez `opencode` dans le terminal intégré. +- Confirmez que la CLI de votre IDE est installée : + - Pour VS Code : commande `code` + - Pour Cursor : commande `cursor` + - Pour Windsurf : commande `windsurf` + - Pour VSCodium : commande `codium` + - Sinon, exécutez `Cmd+Shift+P` (Mac) ou `Ctrl+Shift+P` (Windows/Linux) et recherchez « Shell Command: Install 'code' command in PATH » (ou l'équivalent pour votre IDE) +- Assurez-vous que VS Code est autorisé à installer des extensions diff --git a/packages/web/src/content/docs/fr/index.mdx b/packages/web/src/content/docs/fr/index.mdx new file mode 100644 index 00000000000..06d650de7e4 --- /dev/null +++ b/packages/web/src/content/docs/fr/index.mdx @@ -0,0 +1,343 @@ +--- +title: Introduction +description: Commencez avec OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**OpenCode**](/) est un agent de codage d'IA open source. Il est disponible sous forme d'interface basée sur un terminal, d'application de bureau ou d'extension IDE. + +![OpenCode TUI avec le thème opencode](../../../assets/lander/screenshot.png) + +Commençons. + +--- + +#### Prérequis + +Pour utiliser OpenCode dans votre terminal, vous aurez besoin de : + +1. Un émulateur de terminal moderne comme : + - [WezTerm](https://wezterm.org), multiplateforme + - [Alacritty](https://alacritty.org), multiplateforme + - [Ghostty](https://ghostty.org), Linux et macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux et macOS + +2. Clés API pour les fournisseurs de LLM que vous souhaitez utiliser. + +--- + +## Installation + +Le moyen le plus simple d'installer OpenCode est d'utiliser le script d'installation. + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +Vous pouvez également l'installer avec les commandes suivantes : + +- **Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **Via Homebrew sur macOS et Linux** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > Nous vous recommandons d'utiliser le tap OpenCode pour les versions les plus récentes. La formule officielle `brew install opencode` est maintenue par l'équipe Homebrew et est mise à jour moins fréquemment. + +- **Via Paru sur Arch Linux** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[Recommandé : utilisez WSL] +Pour une expérience optimale sur Windows, nous vous recommandons d'utiliser le [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Il offre de meilleures performances et une compatibilité totale avec les fonctionnalités de OpenCode. +::: + +- **Via Chocolatey** + + ```bash + choco install opencode + ``` + +- **Via Scoop** + + ```bash + scoop install opencode + ``` + +- **Via NPM** + + ```bash + npm install -g opencode-ai + ``` + +- **Via Mise** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **Via Docker** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +Le support de l'installation de OpenCode sur Windows à l'aide de Bun est actuellement en cours de développement. + +Vous pouvez également récupérer le binaire dans les [Releases](https://github.com/anomalyco/opencode/releases). + +--- + +## Configuration + +Avec OpenCode, vous pouvez utiliser n'importe quel fournisseur de LLM en configurant ses clés API. + +Si vous débutez avec les fournisseurs de LLM, nous vous recommandons d'utiliser [OpenCode Zen](/docs/zen). +C'est une liste curée de modèles qui ont été testés et vérifiés par l'équipe OpenCode. + +1. Exécutez la commande `/connect` dans le TUI, sélectionnez opencode et allez sur [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. Connectez-vous, ajoutez vos informations de facturation et copiez votre clé API. + +3. Collez votre clé API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +Vous pouvez également sélectionner l'un des autres fournisseurs. [En savoir plus](/docs/providers#directory). + +--- + +## Initialisation + +Maintenant que vous avez configuré un fournisseur, vous pouvez accéder à un projet sur lequel vous voulez travailler. + +```bash +cd /path/to/project +``` + +Et exécutez OpenCode. + +```bash +opencode +``` + +Ensuite, initialisez OpenCode pour le projet en exécutant la commande suivante. + +```bash frame="none" +/init +``` + +Cela permettra à OpenCode d'analyser votre projet et de créer un fichier `AGENTS.md` à la racine du projet. + +:::tip +Vous devez valider le fichier `AGENTS.md` de votre projet dans Git. +::: + +Cela aide OpenCode à comprendre la structure du projet et les modèles de codage utilisés. + +--- + +## Utilisation + +Vous êtes maintenant prêt à utiliser OpenCode pour travailler sur votre projet. N'hésitez pas à lui demander n'importe quoi ! + +Si vous débutez dans l'utilisation d'un agent de codage IA, voici quelques exemples qui pourraient aider. + +--- + +### Poser des questions + +Vous pouvez demander à OpenCode de vous expliquer la base de code. + +:::tip +Utilisez la touche `@` pour effectuer une recherche floue de fichiers dans le projet. +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +Ceci est utile s'il y a une partie de la base de code sur laquelle vous n'avez pas travaillé. + +--- + +### Ajouter des fonctionnalités + +Vous pouvez demander à OpenCode d'ajouter de nouvelles fonctionnalités à votre projet. Cependant, nous recommandons d’abord de lui demander de créer un plan. + +1. **Créer un plan** + +OpenCode dispose d'un _Mode Plan_ qui désactive sa capacité à apporter des modifications et suggère plutôt _comment_ il implémentera la fonctionnalité. + +Accédez-y à l'aide de la touche **Tab**. Vous verrez un indicateur à cet effet dans le coin inférieur droit. + +```bash frame="none" title="Switch to Plan mode" + +``` + +Décrivons maintenant ce que nous voulons qu'il fasse. + +```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. +``` + +Vous souhaitez donner à OpenCode suffisamment de détails pour comprendre ce que vous voulez. Ça aide pour lui parler comme si vous parliez à un développeur junior de votre équipe. + +:::tip +Donnez à OpenCode beaucoup de contexte et d'exemples pour l'aider à comprendre ce que vous voulez. +::: + +2. **Itérer sur le plan** + +Une fois qu'il vous donne un plan, vous pouvez lui faire part de vos commentaires ou ajouter plus de détails. + +```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. +``` + +:::tip +Glissez-déposez des images dans le terminal pour les ajouter à l'invite. +::: + +OpenCode peut scanner toutes les images que vous lui donnez et les ajouter à l'invite. Vous pouvez le faire en glissant et en déposant une image dans le terminal. + +3. **Créez la fonctionnalité** + +Une fois que vous vous sentez à l'aise avec le plan, revenez au _Mode Build_ en appuyant à nouveau sur la touche **Tab**. + +```bash frame="none" + +``` + +Et demandez-lui d'apporter les modifications. + +```bash frame="none" + Sounds good! Go ahead and make the changes. +``` + +--- + +### Apporter des modifications + +Pour des modifications plus simples, vous pouvez demander à OpenCode de construire directement sans avoir à revoir le plan au préalable. + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +Vous devez fournir suffisamment de détails pour qu'OpenCode effectue les bonnes modifications. + +--- + +### Annuler les modifications + +Disons que vous demandez à OpenCode d'apporter quelques modifications. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Mais vous réalisez que ce n’est pas ce que vous vouliez. Vous **pouvez annuler** les modifications à l'aide de la commande `/undo`. + +```bash frame="none" +/undo +``` + +OpenCode annulera désormais les modifications que vous avez apportées et affichera votre message d'origine encore. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +À partir de là, vous pouvez modifier l'invite et demander à OpenCode de réessayer. + +:::tip +Vous pouvez exécuter `/undo` plusieurs fois pour annuler plusieurs modifications. +::: + +Ou vous **pouvez refaire** les modifications à l'aide de la commande `/redo`. + +```bash frame="none" +/redo +``` + +--- + +## Partager + +Les conversations que vous avez avec OpenCode peuvent être [partagées avec votre équipe](/docs/share). + +```bash frame="none" +/share +``` + +Cela créera un lien vers la conversation en cours et le copiera dans votre presse-papiers. + +:::note +Les conversations ne sont pas partagées par défaut. +::: + +Voici un [exemple de conversation](https://opencode.ai/s/4XP1fce5) avec OpenCode. + +--- + +## Personnaliser + +Et c'est tout ! Vous êtes désormais un pro de l'utilisation de OpenCode. + +Pour vous l'approprier, nous vous recommandons de [choisir un thème](/docs/themes), [de personnaliser les raccourcis clavier](/docs/keybinds), de [configurer les formateurs de code](/docs/formatters), de [créer des commandes personnalisées](/docs/commands) ou de jouer avec la [OpenCode Config](/docs/config). diff --git a/packages/web/src/content/docs/fr/keybinds.mdx b/packages/web/src/content/docs/fr/keybinds.mdx new file mode 100644 index 00000000000..4ec98adfa2b --- /dev/null +++ b/packages/web/src/content/docs/fr/keybinds.mdx @@ -0,0 +1,192 @@ +--- +title: Raccourcis clavier +description: Personnalisez vos raccourcis clavier. +--- + +OpenCode a une liste de raccourcis clavier que vous pouvez personnaliser via la configuration OpenCode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## Touche Leader + +OpenCode utilise une touche `leader` pour la plupart des raccourcis clavier. Cela évite les conflits dans votre terminal. + +Par défaut, `ctrl+x` est la touche leader et la plupart des actions nécessitent que vous appuyiez d'abord sur la touche leader, puis sur le raccourci. Par exemple, pour démarrer une nouvelle session, appuyez d'abord sur `ctrl+x`, puis sur `n`. + +Vous n'avez pas besoin d'utiliser une touche leader pour vos raccourcis clavier, mais nous vous recommandons de le faire. + +--- + +## Désactiver le raccourci clavier + +Vous pouvez désactiver un raccourci clavier en ajoutant la clé à votre configuration avec la valeur `none`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## Raccourcis de saisie desktop + +Le champ de saisie de l'application de bureau OpenCode prend en charge les raccourcis courants de style Readline/Emacs pour l'édition de texte. Ceux-ci sont intégrés et actuellement non configurables via `opencode.json`. + +| Raccourci | Actions | +| --------- | --------------------------------------------------------- | +| `ctrl+a` | Déplacer au début de la ligne actuelle | +| `ctrl+e` | Aller à la fin de la ligne actuelle | +| `ctrl+b` | Reculer le curseur d'un caractère | +| `ctrl+f` | Avancer le curseur d'un caractère | +| `alt+b` | Reculer le curseur d'un mot | +| `alt+f` | Avancer le curseur d'un mot | +| `ctrl+d` | Supprimer le caractère sous le curseur | +| `ctrl+k` | Couper jusqu'à la fin de la ligne | +| `ctrl+u` | Couper jusqu'au début de la ligne | +| `ctrl+w` | Couper le mot précédent | +| `alt+d` | Couper le mot suivant | +| `ctrl+t` | Transposer les caractères | +| `ctrl+g` | Annuler les popovers/abandonner l'exécution de la réponse | + +--- + +## Maj+Entrée + +Certains terminaux n'envoient pas de touches de modification avec Entrée par défaut. Vous devrez peut-être configurer votre terminal pour envoyer `Shift+Enter` comme séquence d'échappement. + +### Windows Terminal + +Ouvrez votre `settings.json` à : + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +Ajoutez ceci au tableau `actions` de niveau racine : + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Ajoutez ceci au tableau `keybindings` de niveau racine : + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Enregistrez le fichier et redémarrez le terminal Windows ou ouvrez un nouvel onglet. diff --git a/packages/web/src/content/docs/fr/lsp.mdx b/packages/web/src/content/docs/fr/lsp.mdx new file mode 100644 index 00000000000..cf2dfb6180d --- /dev/null +++ b/packages/web/src/content/docs/fr/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: Serveurs LSP +description: OpenCode s'intègre à vos serveurs LSP. +--- + +OpenCode s'intègre via le protocole LSP (Language Server Protocol) pour aider le LLM à interagir avec votre base de code. Il utilise des diagnostics pour fournir des commentaires au LLM. + +--- + +## Serveurs intégrés + +OpenCode est livré avec plusieurs serveurs LSP intégrés pour les langages populaires : + +| Serveur LSP | Extensions | Prérequis | +| ------------------ | ------------------------------------------------------------------- | ----------------------------------------------------------------------- | +| astro | .astro | Installation automatique pour les projets Astro | +| bash | .sh, .bash, .zsh, .ksh | Installe automatiquement le serveur bash-language-server | +| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | Installation automatique pour les projets C/C++ | +| csharp | .cs | `.NET SDK` installé | +| clojure-lsp | .clj, .cljs, .cljc, .edn | Commande `clojure-lsp` disponible | +| dart | .dart | Commande `dart` disponible | +| deno | .ts, .tsx, .js, .jsx, .mjs | Commande `deno` disponible (détection automatique deno.json/deno.jsonc) | +| elixir-ls | .ex, .ex | Commande `elixir` disponible | +| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | Dépendance `eslint` dans le projet | +| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` installé | +| gleam | .gleam | Commande `gleam` disponible | +| gopls | .go | Commande `go` disponible | +| hls | .hs, .lhs | Commande `haskell-language-server-wrapper` disponible | +| jdtls | .java | `Java SDK (version 21+)` installé | +| kotlin-ls | .kt, .kts | Installation automatique pour les projets Kotlin | +| lua-ls | .lua | Installation automatique pour les projets Lua | +| nixd | .nix | Commande `nixd` disponible | +| ocaml-lsp | .ml, .mli | Commande `ocamllsp` disponible | +| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | Dépendance `oxlint` dans le projet | +| php intelephense | .php | Installation automatique pour les projets PHP | +| prisma | .prisma | Commande `prisma` disponible | +| pyright | .py, .pyi | Dépendance `pyright` installée | +| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | Commandes `ruby` et `gem` disponibles | +| rust | .rs | Commande `rust-analyzer` disponible | +| sourcekit-lsp | .swift, .objc, .objcpp | `swift` installé (`xcode` sur macOS) | +| svelte | .svelte | Installation automatique pour les projets Svelte | +| terraform | .tf, .tfvars | Installation automatique à partir des versions GitHub | +| tinymist | .typ, .typc | Installation automatique à partir des versions GitHub | +| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | Dépendance `typescript` dans le projet | +| vue | .vue | Installation automatique pour les projets Vue | +| yaml-ls | .yaml, .yml | Installe automatiquement le serveur yaml-language-server de Red Hat | +| zls | .zig, .zon | Commande `zig` disponible | + +Les serveurs LSP sont automatiquement activés lorsque l'une des extensions de fichier ci-dessus est détectée et que les exigences sont remplies. + +:::note +Vous pouvez désactiver les téléchargements automatiques du serveur LSP en définissant la variable d'environnement `OPENCODE_DISABLE_LSP_DOWNLOAD` sur `true`. +::: + +--- + +## Comment ça marche + +Lorsque opencode ouvre un fichier, il : + +1. Vérifie l'extension du fichier par rapport à tous les serveurs LSP activés. +2. Démarre le serveur LSP approprié s'il n'est pas déjà en cours d'exécution. + +--- + +## Configuration + +Vous pouvez personnaliser les serveurs LSP via la section `lsp` de votre configuration opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +Chaque serveur LSP prend en charge les éléments suivants : + +| Propriété | Type | Description | +| ---------------- | -------- | ---------------------------------------------------------------- | +| `disabled` | booléen | Définissez ceci sur `true` pour désactiver le serveur LSP | +| `command` | chaîne[] | La commande pour démarrer le serveur LSP | +| `extensions` | chaîne[] | Extensions de fichiers que ce serveur LSP doit gérer | +| `env` | objet | Variables d'environnement à définir lors du démarrage du serveur | +| `initialization` | objet | Options d'initialisation à envoyer au serveur LSP | + +Regardons quelques exemples. + +--- + +### Variables d'environnement + +Utilisez la propriété `env` pour définir les variables d'environnement lors du démarrage du serveur LSP : + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### Options d'initialisation + +Utilisez la propriété `initialization` pour transmettre les options d'initialisation au serveur LSP. Il s'agit de paramètres spécifiques au serveur envoyés lors de la requête LSP `initialize` : + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +Les options d'initialisation varient selon le serveur LSP. Consultez la documentation de votre serveur LSP pour connaître les options disponibles. +::: + +--- + +### Désactivation des serveurs LSP + +Pour désactiver **tous** les serveurs LSP globalement, définissez `lsp` sur `false` : + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +Pour désactiver un serveur LSP **spécifique**, définissez `disabled` sur `true` : + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### Serveurs LSP personnalisés + +Vous pouvez ajouter des serveurs LSP personnalisés en spécifiant les extensions de commande et de fichier : + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## Informations supplémentaires + +### PHP Intelephense + +PHP Intelephense offre des fonctionnalités premium via une clé de licence. Vous pouvez fournir une clé de licence en plaçant (uniquement) la clé dans un fichier texte à l'adresse : + +- macOS/Linux : `$HOME/intelephense/license.txt` +- Windows : `%USERPROFILE%/intelephense/license.txt` + +Le fichier doit contenir uniquement la clé de licence sans contenu supplémentaire. diff --git a/packages/web/src/content/docs/fr/mcp-servers.mdx b/packages/web/src/content/docs/fr/mcp-servers.mdx new file mode 100644 index 00000000000..e1d1f24e7c0 --- /dev/null +++ b/packages/web/src/content/docs/fr/mcp-servers.mdx @@ -0,0 +1,981 @@ +--- +title: Serveurs MCP +description: Ajoutez des outils MCP locaux et distants. +--- + +Vous pouvez ajouter des outils externes à OpenCode à l'aide du _Model Context Protocol_ ou MCP. OpenCode prend en charge les serveurs locaux et distants. + +Une fois ajoutés, les outils MCP sont automatiquement disponibles pour le LLM aux côtés des outils intégrés. + +--- + +#### Mises en garde + +Lorsque vous utilisez un serveur MCP, cela ajoute au contexte. Cela peut vite s’additionner si vous disposez de beaucoup d’outils. Nous vous recommandons donc de faire attention aux serveurs MCP que vous utilisez. + +:::tip +Les serveurs MCP s'ajoutent à votre contexte, vous devez donc faire attention à ceux que vous activez. +::: + +Certains serveurs MCP, comme le serveur GitHub MCP, ont tendance à ajouter beaucoup de jetons et peuvent facilement dépasser la limite de contexte. + +--- + +## Activation + +Vous pouvez définir des serveurs MCP dans votre [OpenCode Config](https://opencode.ai/docs/config/) sous `mcp`. Ajoutez chaque MCP avec un nom unique. Vous pouvez faire référence à ce MCP par son nom lorsque vous demandez le LLM. + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +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 définissant `type` sur `"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 prompts. + +```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 | Type | Obligatoire | Description | +| ------------- | ------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------- | +| `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). | + +--- + +## Distant + +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 | Type | Obligatoire | Description | +| --------- | ------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------- | +| `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étecte la réponse 401 et lance le flux OAuth +2. Utilise **Enregistrement client dynamique (RFC 7591)** s'il est pris en charge par le serveur. +3. Stocke 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é-enregistré + +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 d'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 | Type | Description | +| -------------- | ------------- | ---------------------------------------------------------------------------------------- | +| `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. + +--- + +## Gestion + +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 + } + } + } +} +``` + +--- + +#### Patterns glob + +Le pattern 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 prompts 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 +``` + +--- + +### Context7 + +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 prompts 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 prompts 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. +``` + +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/models.mdx b/packages/web/src/content/docs/fr/models.mdx new file mode 100644 index 00000000000..6dd91435c73 --- /dev/null +++ b/packages/web/src/content/docs/fr/models.mdx @@ -0,0 +1,222 @@ +--- +title: Modèles +description: Configuration d'un fournisseur et d'un modèle LLM. +--- + +OpenCode utilise [AI SDK](https://ai-sdk.dev/) et [Models.dev](https://models.dev) pour prendre en charge **75+ fournisseurs LLM** et prend en charge l'exécution de modèles locaux. + +--- + +## Fournisseurs + +Les fournisseurs les plus populaires sont préchargés par défaut. Si vous avez ajouté les informations d'identification d'un fournisseur via la commande `/connect`, elles seront disponibles lorsque vous démarrerez OpenCode. + +En savoir plus sur [fournisseurs](/docs/providers). + +--- + +## Sélection d'un modèle + +Une fois que vous avez configuré votre fournisseur, vous pouvez sélectionner le modèle souhaité en tapant : + +```bash frame="none" +/models +``` + +--- + +## Modèles recommandés + +Il existe de nombreux modèles et de nouveaux modèles sortent chaque semaine. + +:::tip +Pensez à utiliser l’un des modèles que nous recommandons. +::: + +Cependant, seuls quelques-uns d’entre eux savent à la fois générer du code et appeler des outils. + +Voici plusieurs modèles qui fonctionnent bien avec OpenCode, sans ordre particulier. (Cette liste n’est pas exhaustive et n’est pas nécessairement à jour) : + +- GPT 5.2 +- Codex GPT 5.1 +- Claude Opus 4.5 +- Claude Sonnet 4.5 +- Minimax M2.1 +- Gemini 3 Pro + +--- + +## Définir une valeur par défaut + +Pour définir l'un d'entre eux comme modèle par défaut, vous pouvez définir la clé `model` dans votre configuration OpenCode. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +Ici, l'identifiant complet est `provider_id/model_id`. Par exemple, si vous utilisez [OpenCode Zen](/docs/zen), vous utiliserez `opencode/gpt-5.1-codex` pour GPT 5.1 Codex. + +Si vous avez configuré un [fournisseur personnalisé](/docs/providers#custom), le `provider_id` est la clé de la partie `provider` de votre configuration et le `model_id` est la clé de `provider.models`. + +--- + +## Configuration des modèles + +Vous pouvez configurer globalement les options d'un modèle via le fichier config. + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +Ici, nous configurons les paramètres globaux pour deux modèles intégrés : `gpt-5` lorsqu'il est accessible via le fournisseur `openai` et `claude-sonnet-4-20250514` lorsqu'il est accessible via le fournisseur `anthropic`. +Les noms du fournisseur intégré et des modèles peuvent être trouvés sur [Models.dev](https://models.dev). + +Vous pouvez également configurer ces options pour tous les agents que vous utilisez. La configuration de l'agent remplace ici toutes les options globales. [En savoir plus](/docs/agents/#additional). + +Vous pouvez également définir des variantes personnalisées qui étendent celles intégrées. Les variantes vous permettent de configurer différents paramètres pour le même modèle sans créer d'entrées en double : + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## Variantes + +De nombreux modèles prennent en charge plusieurs variantes avec différentes configurations. OpenCode est livré avec des variantes par défaut intégrées pour les fournisseurs populaires. + +### Variantes intégrées + +OpenCode est livré avec des variantes par défaut pour de nombreux fournisseurs : + +**Anthropic** : + +- `high` - Budget de réflexion élevé (par défaut) +- `max` - Budget de réflexion maximum + +**OpenAI** : + +Varie selon le modèle mais en gros : + +- `none` - Aucun raisonnement +- `minimal` - Effort de raisonnement minimal +- `low` - Faible effort de raisonnement +- `medium` - Effort de raisonnement moyen +- `high` – Effort de raisonnement élevé +- `xhigh` - Effort de raisonnement très élevé + +**Google**: + +- `low` – Budget d'effort/jetons réduit +- `high` – Budget d'effort/de jetons plus élevé + +:::tip +Cette liste n'est pas exhaustive. De nombreux autres fournisseurs ont également des paramètres par défaut intégrés. +::: + +### Variantes personnalisées + +Vous pouvez remplacer les variantes existantes ou ajouter les vôtres : + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### Cycle des variantes + +Utilisez le raccourci clavier `variant_cycle` pour basculer rapidement entre les variantes. [En savoir plus](/docs/keybinds). + +--- + +## Chargement des modèles + +Lorsque OpenCode démarre, il recherche les modèles dans l'ordre de priorité suivant : + +1. Le flag de ligne de commande `--model` ou `-m`. Le format est le même que dans le fichier de configuration : `provider_id/model_id`. + +2. La liste des modèles dans la configuration OpenCode. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + +Le format ici est `provider/model`. + +3. Le dernier modèle utilisé. + +4. Le premier modèle utilisant une priorité interne. diff --git a/packages/web/src/content/docs/fr/modes.mdx b/packages/web/src/content/docs/fr/modes.mdx new file mode 100644 index 00000000000..340ce83bd2f --- /dev/null +++ b/packages/web/src/content/docs/fr/modes.mdx @@ -0,0 +1,329 @@ +--- +title: Modes +description: Différents modes pour différents cas d'utilisation. +--- + +:::caution +Les modes sont désormais configurés via l'option `agent` dans la configuration opencode. +L’option `mode` est désormais obsolète. [En savoir plus](/docs/agents). +::: + +Les modes dans opencode vous permettent de personnaliser le comportement, les outils et les prompts pour différents cas d'utilisation. + +Il est livré avec deux modes intégrés : **build** et **plan**. Vous pouvez personnaliser ceux-ci ou configurez les vôtres via la configuration opencode. + +Vous pouvez basculer entre les modes au cours d'une session ou les configurer dans votre fichier de configuration. + +--- + +## Modes intégrés + +opencode est livré avec deux modes intégrés. + +--- + +### Build + +Build est le mode **par défaut** avec tous les outils activés. Il s'agit du mode standard pour le travail de développement dans lequel vous avez besoin d'un accès complet aux opérations sur les fichiers et aux commandes système. + +--- + +### Plan + +Un mode restreint conçu pour la planification et l’analyse. En mode plan, les outils suivants sont désactivés par défaut : + +- `write` - Impossible de créer de nouveaux fichiers +- `edit` - Impossible de modifier les fichiers existants, à l'exception des fichiers situés à `.opencode/plans/*.md` pour détailler le plan lui-même +- `patch` - Impossible d'appliquer les correctifs +- `bash` - Impossible d'exécuter les commandes shell + +Ce mode est utile lorsque vous souhaitez que l'IA analyse le code, suggère des modifications ou crée des plans sans apporter de modifications réelles à votre base de code. + +--- + +## Changement de mode + +Vous pouvez basculer entre les modes au cours d'une session à l'aide de la touche _Tab_. Ou votre raccourci clavier `switch_mode` configuré. + +Voir également : [Formatters](/docs/formatters) pour plus d'informations sur la configuration du formatage du code. + +--- + +## Configuration + +Vous pouvez personnaliser les modes intégrés ou créer les vôtres via la configuration. Les modes peuvent être configurés de deux manières : + +### Configuration JSON + +Configurez les modes dans votre fichier de configuration `opencode.json` : + +```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 + } + } + } +} +``` + +### Configuration Markdown + +Vous pouvez également définir des modes à l'aide de fichiers markdown. Placez-les dans : + +- Global : `~/.config/opencode/modes/` +- Projet : `.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. +``` + +Le nom du fichier markdown devient le nom du mode (par exemple, `review.md` crée un mode `review`). + +Examinons ces options de configuration en détail. + +--- + +### Modèle + +Utilisez la configuration `model` pour remplacer le modèle par défaut pour ce mode. Utile pour utiliser différents modèles optimisés pour différentes tâches. Par exemple, un modèle de planification plus rapide, un modèle de mise en œuvre plus performant. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### Température + +Contrôlez le caractère aléatoire et la créativité des réponses de l'IA avec la configuration `temperature`. Des valeurs faibles rendent les réponses plus ciblées et déterministes, tandis que des valeurs plus élevées augmentent la créativité et la variabilité. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Les valeurs de température varient généralement de 0,0 à 1,0 : + +- **0,0-0,2** : réponses très ciblées et déterministes, idéales pour l'analyse et la planification du code +- **0,3-0,5** : réponses équilibrées avec une certaine créativité, idéales pour les tâches de développement générales +- **0,6-1,0** : réponses plus créatives et variées, utiles pour le brainstorming et l'exploration + +```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}" + } + } +} +``` + +Si aucune température n'est spécifiée, opencode utilise les valeurs par défaut spécifiques au modèle (généralement 0 pour la plupart des modèles, 0,55 pour les modèles Qwen). + +--- + +### Invite + +Spécifiez un fichier de prompt système personnalisé pour ce mode avec la configuration `prompt`. Le fichier de prompt doit contenir des instructions spécifiques à l'objectif du mode. + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Ce chemin est relatif à l'emplacement du fichier de configuration. Donc ça marche pour à la fois la configuration globale opencode et la configuration spécifique au projet. + +--- + +### Outils + +Contrôlez quels outils sont disponibles dans ce mode avec la configuration `tools`. Vous pouvez activer ou désactiver des outils spécifiques en les définissant sur `true` ou `false`. + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +Si aucun outil n'est spécifié, tous les outils sont activés par défaut. + +--- + +#### Outils disponibles + +Voici tous les outils pouvant être contrôlés via le mode config. + +| Outil | Description | +| ----------- | ------------------------------------- | +| `bash` | Exécuter des commandes shell | +| `edit` | Modifier des fichiers existants | +| `write` | Créer de nouveaux fichiers | +| `read` | Lire le contenu du fichier | +| `grep` | Rechercher le contenu du fichier | +| `glob` | Rechercher des fichiers par modèle | +| `list` | Liste du contenu du répertoire | +| `patch` | Appliquer des correctifs aux fichiers | +| `todowrite` | Gérer les listes de tâches | +| `todoread` | Lire les listes de tâches | +| `webfetch` | Récupérer du contenu Web | + +--- + +## Modes personnalisés + +Vous pouvez créer vos propres modes personnalisés en les ajoutant à la configuration. Voici des exemples utilisant les deux approches : + +### Utilisation de la configuration JSON + +```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 + } + } + } +} +``` + +### Utiliser des fichiers Markdown + +Créez des fichiers de mode dans `.opencode/modes/` pour les modes spécifiques au projet ou `~/.config/opencode/modes/` pour les modes globaux : + +```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 +``` + +--- + +### Cas d'utilisation + +Voici quelques cas d’utilisation courants pour différents modes. + +- **Mode Build** : travail de développement complet avec tous les outils activés +- **Mode Plan** : Analyse et planification sans apporter de modifications +- **Mode Review** : révision du code avec accès en lecture seule et outils de documentation +- **Mode Debug** : axé sur l'investigation avec les outils bash et read activés +- **Mode Docs** : écriture de documentation avec des opérations sur les fichiers mais pas de commandes système + +Vous constaterez peut-être également que différents modèles conviennent à différents cas d’utilisation. diff --git a/packages/web/src/content/docs/fr/network.mdx b/packages/web/src/content/docs/fr/network.mdx new file mode 100644 index 00000000000..0ebafea4427 --- /dev/null +++ b/packages/web/src/content/docs/fr/network.mdx @@ -0,0 +1,57 @@ +--- +title: Réseau +description: Configurez les proxys et les certificats personnalisés. +--- + +OpenCode prend en charge les variables d'environnement proxy standard et les certificats personnalisés pour les environnements réseau d'entreprise. + +--- + +## Proxy + +OpenCode respecte les variables d'environnement proxy standard. + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +Le TUI communique avec un serveur HTTP local. Vous devez contourner le proxy pour cette connexion afin d'éviter les boucles de routage. +::: + +Vous pouvez configurer le port et le nom d'hôte du serveur à l'aide de [CLI flags](/docs/cli#run). + +--- + +### Authentification + +Si votre proxy nécessite une authentification de base, incluez les informations d'identification dans l'URL. + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +Évitez de coder en dur les mots de passe. Utilisez des variables d’environnement ou un stockage sécurisé des informations d’identification. +::: + +Pour les proxys nécessitant une authentification avancée comme NTLM ou Kerberos, envisagez d'utiliser une passerelle LLM qui prend en charge votre méthode d'authentification. + +--- + +## Certificats personnalisés + +Si votre entreprise utilise des autorités de certification personnalisées pour les connexions HTTPS, configurez OpenCode pour leur faire confiance. + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +Cela fonctionne à la fois pour les connexions proxy et pour l'accès direct à l'API. diff --git a/packages/web/src/content/docs/fr/permissions.mdx b/packages/web/src/content/docs/fr/permissions.mdx new file mode 100644 index 00000000000..1533987f8de --- /dev/null +++ b/packages/web/src/content/docs/fr/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: Autorisations +description: Contrôlez quelles actions nécessitent une approbation pour être exécutées. +--- + +OpenCode utilise la configuration `permission` pour décider si une action donnée doit s'exécuter automatiquement, vous inviter ou être bloquée. + +Depuis `v1.1.1`, l'ancienne configuration booléenne `tools` est obsolète et a été fusionnée dans `permission`. L'ancienne configuration `tools` est toujours prise en charge pour des raisons de compatibilité ascendante. + +--- + +## Actions + +Chaque règle d'autorisation se résout en l'une des suivantes : + +- `"allow"` – exécuter sans approbation +- `"ask"` – demande d'approbation +- `"deny"` — bloque l'action + +--- + +## Configuration + +Vous pouvez définir des autorisations globalement (avec `*`) et remplacer des outils spécifiques. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +Vous pouvez également définir toutes les autorisations en même temps : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## Règles granulaires (syntaxe d'objet) + +Pour la plupart des autorisations, vous pouvez utiliser un objet pour appliquer différentes actions en fonction de l'entrée de l'outil. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +Les règles sont évaluées par correspondance de modèle, la **dernière règle correspondante étant gagnante**. Un modèle courant consiste à placer la règle fourre-tout `"*"` en premier, et les règles plus spécifiques après. + +### Caractères génériques + +Les modèles d'autorisation utilisent une simple correspondance de caractères génériques : + +- `*` correspond à zéro ou plusieurs caractères +- `?` correspond exactement à un caractère +- Tous les autres caractères correspondent littéralement + +### Extension du répertoire personnel + +Vous pouvez utiliser `~` ou `$HOME` au début d'un modèle pour référencer votre répertoire personnel. Ceci est particulièrement utile pour les règles [`external_directory`](#external-directories). + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### Répertoires externes + +Utilisez `external_directory` pour autoriser les appels d'outils qui touchent des chemins en dehors du répertoire de travail où OpenCode a été démarré. Cela s'applique à tout outil qui prend un chemin en entrée (par exemple `read`, `edit`, `list`, `glob`, `grep` et de nombreuses commandes `bash`). + +L'expansion du répertoire personnel (comme `~/...`) n'affecte que la façon dont un modèle est écrit. Cela n'intègre pas un chemin externe à l'espace de travail actuel, donc les chemins en dehors du répertoire de travail doivent toujours être autorisés via `external_directory`. + +Par exemple, cela permet d'accéder à tout ce qui se trouve sous `~/projects/personal/` : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +Tout répertoire autorisé ici hérite des mêmes valeurs par défaut que l'espace de travail actuel. Étant donné que [`read` est par défaut `allow`](#defaults), les lectures sont également autorisées pour les entrées sous `external_directory`, sauf dérogation. Ajoutez des règles explicites lorsqu'un outil doit être restreint dans ces chemins, comme bloquer les modifications tout en conservant les lectures : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +Gardez la liste centrée sur les chemins approuvés et superposez des règles d'autorisation ou de refus supplémentaires selon les besoins pour d'autres outils (par exemple `bash`). + +--- + +## Autorisations disponibles + +Les autorisations OpenCode sont classées par nom d'outil, plus quelques garde-fous de sécurité : + +- `read` — lecture d'un fichier (correspond au chemin du fichier) +- `edit` — toutes les modifications de fichiers (couvre `edit`, `write`, `patch`, `multiedit`) +- `glob` — globalisation de fichiers (correspond au modèle global) +- `grep` — recherche de contenu (correspond au modèle regex) +- `list` — listant les fichiers dans un répertoire (correspond au chemin du répertoire) +- `bash` - exécution de commandes shell (correspond aux commandes analysées comme `git status --porcelain`) +- `task` — lancement de sous-agents (correspond au type de sous-agent) +- `skill` — chargement d'une compétence (correspond au nom de la compétence) +- `lsp` — exécution de requêtes LSP (actuellement non granulaires) +- `todoread`, `todowrite` — lecture/mise à jour de la liste de tâches +- `webfetch` — récupérer une URL (correspond à l'URL) +- `websearch`, `codesearch` — recherche Web/code (correspond à la requête) +- `external_directory` - déclenché lorsqu'un outil touche des chemins en dehors du répertoire de travail du projet +- `doom_loop` — déclenché lorsque le même appel d'outil se répète 3 fois avec une entrée identique + +--- + +## Valeurs par défaut + +Si vous ne spécifiez rien, OpenCode démarre avec les valeurs par défaut permissives : + +- La plupart des autorisations sont par défaut `"allow"`. +- `doom_loop` et `external_directory` sont par défaut `"ask"`. +- `read` est `"allow"`, mais les fichiers `.env` sont refusés par défaut : + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## Que fait « Demander » ? + +Lorsque OpenCode demande l'approbation, l'interface utilisateur propose trois résultats : + +- `once` — approuve uniquement cette demande +- `always` — approuve les futures demandes correspondant aux modèles suggérés (pour le reste de la session OpenCode en cours) +- `reject` — refuser la demande + +L'ensemble des modèles que `always` approuverait est fourni par l'outil (par exemple, les approbations bash mettent généralement sur liste blanche un préfixe de commande sûr comme `git status*`). + +--- + +## Agents + +Vous pouvez remplacer les autorisations par agent. Les autorisations des agents sont fusionnées avec la configuration globale et les règles des agents sont prioritaires. [En savoir plus](/docs/agents#permissions) sur les autorisations des agents. + +:::note +Reportez-vous à la section [Règles granulaires (syntaxe d'objet)](#granular-rules-object-syntax) ci-dessus pour des exemples de correspondance de modèles plus détaillés. +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +Vous pouvez également configurer les autorisations des agents dans Markdown : + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +Utilisez la correspondance de modèles pour les commandes avec des arguments. `"grep *"` autorise `grep pattern file.txt`, tandis que `"grep"` seul le bloquerait. Les commandes comme `git status` fonctionnent pour le comportement par défaut mais nécessitent une autorisation explicite (comme `"git status *"`) lorsque des arguments sont passés. +::: diff --git a/packages/web/src/content/docs/fr/plugins.mdx b/packages/web/src/content/docs/fr/plugins.mdx new file mode 100644 index 00000000000..48cdc4d116d --- /dev/null +++ b/packages/web/src/content/docs/fr/plugins.mdx @@ -0,0 +1,384 @@ +--- +title: Plugins +description: Écrivez vos propres plugins pour étendre OpenCode. +--- + +Les plugins vous permettent d'étendre OpenCode en vous connectant à divers événements et en personnalisant le comportement. Vous pouvez créer des plugins pour ajouter de nouvelles fonctionnalités, intégrer des services externes ou modifier le comportement par défaut de OpenCode. + +Pour des exemples, consultez les [plugins](/docs/ecosystem#plugins) créés par la communauté. + +--- + +## Utiliser un plugin + +Il existe deux manières de charger des plugins. + +--- + +### À partir de fichiers locaux + +Placez les fichiers JavaScript ou TypeScript dans le répertoire du plugin. + +- `.opencode/plugins/` - Plugins au niveau du projet +- `~/.config/opencode/plugins/` - Plugins globaux + +Les fichiers de ces répertoires sont automatiquement chargés au démarrage. + +--- + +### Depuis npm + +Spécifiez les packages npm dans votre fichier de configuration. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +Les packages npm scopés et standards sont pris en charge. + +Parcourez les plugins disponibles dans le [ecosystem](/docs/ecosystem#plugins). + +--- + +### Comment les plugins sont installés + +Les **plugins npm** sont installés automatiquement à l'aide de Bun au démarrage. Les packages et leurs dépendances sont mis en cache dans `~/.cache/opencode/node_modules/`. + +Les **plugins locaux** sont chargés directement depuis le répertoire des plugins. Pour utiliser des packages externes, vous devez créer un `package.json` dans votre répertoire de configuration (voir [Dépendances](#dependencies)), ou publier le plugin sur npm et [l'ajouter à votre config](/docs/config#plugins). + +--- + +### Ordre de chargement + +Les plugins sont chargés à partir de toutes les sources et tous les hooks s'exécutent dans l'ordre. L'ordre de chargement est le suivant : + +1. Configuration globale (`~/.config/opencode/opencode.json`) +2. Configuration du projet (`opencode.json`) +3. Répertoire global des plugins (`~/.config/opencode/plugins/`) +4. Répertoire des plugins du projet (`.opencode/plugins/`) + +Les packages npm en double avec le même nom et la même version sont chargés une fois. Cependant, un plugin local et un plugin npm portant des noms similaires sont tous deux chargés séparément. + +--- + +## Créer un plugin + +Un plugin est un **module JavaScript/TypeScript** qui exporte une ou plusieurs fonctions de plugin. Chaque fonction reçoit un objet contextuel et renvoie un objet hooks. + +--- + +### Dépendances + +Les plugins locaux et les outils personnalisés peuvent utiliser des packages npm externes. Ajoutez un `package.json` à votre répertoire de configuration avec les dépendances dont vous avez besoin. + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +OpenCode exécute `bun install` au démarrage pour les installer. Vos plugins et outils peuvent ensuite les importer. + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### Structure de base + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +La fonction plugin reçoit : + +- `project` : informations sur le projet actuel. +- `directory` : le répertoire de travail actuel. +- `worktree` : le chemin de l'arbre de travail git. +- `client` : un client SDK opencode pour interagir avec l'IA. +- `$` : [shell API](https://bun.com/docs/runtime/shell) de Bun pour l'exécution de commandes. + +--- + +### Prise en charge de TypeScript + +Pour les plugins TypeScript, vous pouvez importer des types à partir du package du plugin : + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### Événements + +Les plugins peuvent s'abonner à des événements comme indiqué ci-dessous dans la section Exemples. Voici une liste des différents événements disponibles. + +#### Événements de commande + +- `command.executed` + +#### Événements de fichier + +- `file.edited` +- `file.watcher.updated` + +#### Événements d'installation + +- `installation.updated` + +#### LSP Événements + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### Événements de messages + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### Événements d'autorisation + +- `permission.asked` +- `permission.replied` + +#### Événements du serveur + +- `server.connected` + +#### Événements de session + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### Événements à faire + +- `todo.updated` + +#### Événements Shell + +- `shell.env` + +#### Événements d'outils + +- `tool.execute.after` +- `tool.execute.before` + +#### TUI Événements + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## Exemples + +Voici quelques exemples de plugins que vous pouvez utiliser pour étendre opencode. + +--- + +### Envoyer des notifications + +Envoyez des notifications lorsque certains événements se produisent : + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +Nous utilisons `osascript` pour exécuter AppleScript sur macOS. Ici, nous l'utilisons pour envoyer des notifications. + +:::note +Si vous utilisez l'application de bureau OpenCode, elle peut envoyer automatiquement des notifications système lorsqu'une réponse est prête ou en cas d'erreur de session. +::: + +--- + +### Protection .env + +Empêchez opencode de lire les fichiers `.env` : + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### Injecter des variables d'environnement + +Injectez des variables d'environnement dans toutes les exécutions du shell (outils d'IA et terminal utilisateur) : + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### Outils personnalisés + +Les plugins peuvent également ajouter des outils personnalisés à opencode : + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +L'assistant `tool` crée un outil personnalisé que opencode peut appeler. Il prend une fonction de schéma Zod et renvoie une définition d'outil avec : + +- `description` : ce que fait l'outil +- `args` : schéma Zod pour les arguments de l'outil +- `execute` : Fonction qui s'exécute lorsque l'outil est appelé + +Vos outils personnalisés seront disponibles pour opencode aux côtés des outils intégrés. + +--- + +### Journalisation + +Utilisez `client.app.log()` au lieu de `console.log` pour la journalisation structurée : + +```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" }, + }, + }) +} +``` + +Niveaux : `debug`, `info`, `warn`, `error`. Voir la [documentation du SDK](https://opencode.ai/docs/sdk) pour plus de détails. + +--- + +### Hooks de compactage + +Personnalisez le contexte inclus lorsqu'une session est compactée : + +```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 +`) + }, + } +} +``` + +Le hook `experimental.session.compacting` se déclenche avant que le LLM ne génère un résumé de continuation. Utilisez-le pour injecter un contexte spécifique au domaine que le prompt de compactage par défaut manquerait. + +Vous pouvez également remplacer entièrement le prompt de compactage en définissant `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. +` + }, + } +} +``` + +Lorsque `output.prompt` est défini, il remplace complètement le prompt de compactage par défaut. Le tableau `output.context` est ignoré dans ce cas. diff --git a/packages/web/src/content/docs/fr/providers.mdx b/packages/web/src/content/docs/fr/providers.mdx new file mode 100644 index 00000000000..b65e9c00a15 --- /dev/null +++ b/packages/web/src/content/docs/fr/providers.mdx @@ -0,0 +1,1897 @@ +--- +title: Fournisseurs +description: Utiliser n’importe quel fournisseur LLM en OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console + +OpenCode utilise [AI SDK](https://ai-sdk.dev/) et [Models.dev](https://models.dev) pour prendre en charge **75+ fournisseurs LLM** et prend en charge l'exécution de modèles locaux. + +Pour ajouter un fournisseur, vous devez : + +1. Ajoutez les clés API pour le fournisseur à l'aide de la commande `/connect`. +2. Configurez le fournisseur dans votre configuration OpenCode. + +--- + +### Informations d'identification + +Lorsque vous ajoutez les clés API d'un fournisseur avec la commande `/connect`, elles sont stockées +en `~/.local/share/opencode/auth.json`. + +--- + +### Configuration + +Vous pouvez personnaliser les fournisseurs via la section `provider` de votre OpenCode +configuration. + +--- + +#### Socle URL + +Vous pouvez personnaliser la base URL pour n'importe quel fournisseur en définissant l'option `baseURL`. Ceci est utile lors de l'utilisation de services proxy ou de points de terminaison personnalisés. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen est une liste de modèles fournis par l'équipe OpenCode qui ont été +testé et vérifié pour fonctionner correctement avec OpenCode. [En savoir plus](/docs/zen). + +:::tip +Si vous êtes nouveau, nous vous recommandons de commencer par OpenCode Zen. +::: + +1. Exécutez la commande `/connect` dans le TUI, sélectionnez opencode et dirigez-vous vers [opencode.ai/auth](https://opencode.ai/auth). + + ```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 +liste, n'hésitez pas à ouvrir un PR. + +:::note +Vous ne voyez pas de fournisseur ici ? Soumettez un PR. +::: + +--- + +### 302.AI + +1. Rendez-vous sur la [console 302.AI](https://302.ai/), créez un compte et générez une clé API. + +2. Exécutez la commande `/connect` et recherchez **302.AI**. + + ```txt + /connect + ``` + +3. Saisissez votre clé 302.AI API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle. + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +Pour utiliser Amazon Bedrock avec OpenCode : + +1. Rendez-vous sur le **Catalogue de modèles** dans la console Amazon Bedrock et demandez + accédez aux modèles que vous souhaitez. + + :::tip + Vous devez avoir accès au modèle souhaité dans Amazon Bedrock. + ::: + +2. **Configurez l'authentification** à l'aide de l'une des méthodes suivantes : + + #### Variables d'environnement (démarrage rapide) + +Définissez l'une de ces variables d'environnement lors de l'exécution de opencode : + +```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode +``` + +Ou ajoutez-les à votre profil bash : + +```bash title="~/.bash_profile" + export AWS_PROFILE=my-dev-profile + export AWS_REGION=us-east-1 +``` + +#### Fichier de configuration (recommandé) + +Pour une configuration spécifique au projet ou persistante, utilisez `opencode.json` : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile" + } + } + } +} +``` + +**Options disponibles :** + +- `region` - Région AWS (par exemple, `us-east-1`, `eu-west-1`) +- `profile` - Profil nommé AWS de `~/.aws/credentials` +- `endpoint` - URL de point de terminaison personnalisée pour les endpoints VPC (alias de l'option générique `baseURL`) + +:::tip +Les options du fichier de configuration sont prioritaires sur les variables d'environnement. +::: + +#### Avancé : points de terminaison d'un VPC + +Si vous utilisez des points de terminaison d'un VPC pour Bedrock : + +```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 +L'option `endpoint` est un alias pour l'option générique `baseURL`, utilisant la terminologie spécifique à AWS. Si `endpoint` et `baseURL` sont spécifiés, `endpoint` est prioritaire. +::: + +#### Méthodes d'authentification + +- **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`** : créez un utilisateur IAM et générez des clés d'accès dans la console AWS +- **`AWS_PROFILE`** : utilisez les profils nommés de `~/.aws/credentials`. Configurez d'abord avec `aws configure --profile my-profile` ou `aws sso login` +- **`AWS_BEARER_TOKEN_BEDROCK`** : Générez des clés API à long terme à partir de la console Amazon Bedrock +- **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`** : pour EKS IRSA (rôles IAM pour les comptes de service) ou d'autres environnements Kubernetes avec fédération OIDC. Ces variables d'environnement sont automatiquement injectées par Kubernetes lors de l'utilisation des annotations de compte de service. + +#### Priorité d'authentification + +Amazon Bedrock utilise la priorité d'authentification suivante : + +1. **Bearer Token** - Variable d'environnement `AWS_BEARER_TOKEN_BEDROCK` ou jeton de la commande `/connect` +2. **AWS Credential Chain** - Profil, clés d'accès, informations d'identification partagées, rôles IAM, jetons d'identité Web (EKS IRSA), métadonnées d'instance + +:::note +Lorsqu'un jeton de porteur est défini (via `/connect` ou `AWS_BEARER_TOKEN_BEDROCK`), il est prioritaire sur toutes les méthodes d'identification AWS, y compris les profils configurés. +::: + +3. Exécutez la commande `/models` pour sélectionner le modèle souhaité. + + ```txt + /models + ``` + +:::note +Pour les profils d'inférence personnalisés, utilisez le nom du modèle et du fournisseur dans la clé et définissez la propriété `id` sur l'arn. Cela garantit une mise en cache correcte : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. Une fois inscrit, exécutez la commande `/connect` et sélectionnez Anthropic. + + ```txt + /connect + ``` + +2. Ici, vous pouvez sélectionner l'option **Claude Pro/Max** et cela ouvrira votre navigateur. + et vous demande de vous authentifier. + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. Désormais, tous les modèles Anthropic devraient être disponibles lorsque vous utilisez la commande `/models`. + + ```txt + /models + ``` + +:::info +L'utilisation de votre abonnement Claude Pro/Max dans OpenCode n'est pas officiellement prise en charge par [Anthropic](https://anthropic.com). +::: + +##### Utilisation des clés API + +Vous pouvez également sélectionner **Créer une clé API** si vous n'avez pas d'abonnement Pro/Max. Il ouvrira également votre navigateur et vous demandera de vous connecter à Anthropic et vous donnera un code que vous pourrez coller dans votre terminal. + +Ou si vous disposez déjà d'une clé API, vous pouvez sélectionner **Entrer manuellement la clé API** et la coller dans votre terminal. + +--- + +### Azure OpenAI + +:::note +Si vous rencontrez des erreurs « Je suis désolé, mais je ne peux pas vous aider avec cette demande », essayez de modifier le filtre de contenu de **DefaultV2** à **Default** dans votre ressource Azure. +::: + +1. Rendez-vous sur le [portail Azure](https://portal.azure.com/) et créez une ressource **Azure OpenAI**. Vous aurez besoin de : + - **Nom de la ressource** : cela fait partie de votre point de terminaison API (`https://RESOURCE_NAME.openai.azure.com/`) + - **Clé API** : soit `KEY 1` ou `KEY 2` de votre ressource + +2. Accédez à [Azure AI Foundry](https://ai.azure.com/) et déployez un modèle. + + :::note + Le nom du déploiement doit correspondre au nom du modèle pour que opencode fonctionne correctement. + ::: + +3. Exécutez la commande `/connect` et recherchez **Azure**. + + ```txt + /connect + ``` + +4. Entrez votre clé API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Définissez le nom de votre ressource comme variable d'environnement : + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + +Ou ajoutez-le à votre profil bash : + +```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX +``` + +6. Exécutez la commande `/models` pour sélectionner votre modèle déployé. + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. Rendez-vous sur le [portail Azure](https://portal.azure.com/) et créez une ressource **Azure OpenAI**. Vous aurez besoin de : + - **Nom de la ressource** : cela fait partie de votre point de terminaison API (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) + - **Clé API** : soit `KEY 1` ou `KEY 2` de votre ressource + +2. Accédez à [Azure AI Foundry](https://ai.azure.com/) et déployez un modèle. + + :::note + Le nom du déploiement doit correspondre au nom du modèle pour que opencode fonctionne correctement. + ::: + +3. Exécutez la commande `/connect` et recherchez **Azure Cognitive Services**. + + ```txt + /connect + ``` + +4. Entrez votre clé API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Définissez le nom de votre ressource comme variable d'environnement : + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + +Ou ajoutez-le à votre profil bash : + +```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX +``` + +6. Exécutez la commande `/models` pour sélectionner votre modèle déployé. + + ```txt + /models + ``` + +--- + +### Baseten + +1. Rendez-vous sur [Baseten](https://app.baseten.co/), créez un compte et générez une clé API. + +2. Exécutez la commande `/connect` et recherchez **Baseten**. + + ```txt + /connect + ``` + +3. Entrez votre clé Baseten API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle. + + ```txt + /models + ``` + +--- + +### Cerebras + +1. Rendez-vous sur la [console Cerebras](https://inference.cerebras.ai/), créez un compte et générez une clé API. + +2. Exécutez la commande `/connect` et recherchez **Cerebras**. + + ```txt + /connect + ``` + +3. Entrez votre clé Cerebras API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle tel que _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +Cloudflare AI Gateway vous permet d'accéder aux modèles de OpenAI, Anthropic, Workers AI et bien plus encore via un point de terminaison unifié. Avec [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/), vous n'avez pas besoin de clés API distinctes pour chaque fournisseur. + +1. Rendez-vous sur le [tableau de bord Cloudflare](https://dash.cloudflare.com/), accédez à **AI** > **AI Gateway** et créez une nouvelle passerelle. + +2. Définissez votre ID de compte et votre ID de passerelle comme variables d'environnement. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. Exécutez la commande `/connect` et recherchez **Cloudflare AI Gateway**. + + ```txt + /connect + ``` + +4. Entrez votre jeton Cloudflare API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +Ou définissez-le comme variable d'environnement. + +```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token +``` + +5. Exécutez la commande `/models` pour sélectionner un modèle. + + ```txt + /models + ``` + +Vous pouvez également ajouter des modèles via votre configuration opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } +} +``` + +--- + +### Cortecs + +1. Rendez-vous sur la [console Cortecs](https://cortecs.ai/), créez un compte et générez une clé API. + +2. Exécutez la commande `/connect` et recherchez **Cortecs**. + + ```txt + /connect + ``` + +3. Entrez votre clé Cortecs API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle tel que _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. Rendez-vous sur la [console DeepSeek](https://platform.deepseek.com/), créez un compte et cliquez sur **Créer une nouvelle clé API**. + +2. Exécutez la commande `/connect` et recherchez **DeepSeek**. + + ```txt + /connect + ``` + +3. Entrez votre clé DeepSeek API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle DeepSeek tel que _DeepSeek Reasoner_. + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. Rendez-vous sur le [tableau de bord Deep Infra](https://deepinfra.com/dash), créez un compte et générez une clé API. + +2. Exécutez la commande `/connect` et recherchez **Deep Infra**. + + ```txt + /connect + ``` + +3. Entrez votre clé Deep Infra API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle. + + ```txt + /models + ``` + +--- + +### Firmware + +1. Rendez-vous sur le [Tableau de bord du micrologiciel](https://app.firmware.ai/signup), créez un compte et générez une clé API. + +2. Exécutez la commande `/connect` et recherchez **Firmware**. + + ```txt + /connect + ``` + +3. Entrez la clé API de votre micrologiciel. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle. + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. Rendez-vous sur la [console Fireworks AI](https://app.fireworks.ai/), créez un compte et cliquez sur **Créer une clé API**. + +2. Exécutez la commande `/connect` et recherchez **Fireworks AI**. + + ```txt + /connect + ``` + +3. Entrez votre clé Fireworks AI API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle tel que _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo fournit un chat agent basé sur l'IA avec des capacités d'appel d'outils natives via le proxy Anthropic de GitLab. + +1. Exécutez la commande `/connect` et sélectionnez GitLab. + + ```txt + /connect + ``` + +2. Choisissez votre méthode d'authentification : + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ + ``` + + #### Utilisation de OAuth (recommandé) + +Sélectionnez **OAuth** et votre navigateur s'ouvrira pour autorisation. + +#### Utilisation d'un jeton d'accès personnel + +1. Accédez à [GitLab Paramètres utilisateur > Jetons d'accès](https://gitlab.com/-/user_settings/personal_access_tokens) +2. Cliquez sur **Ajouter un nouveau jeton** +3. Nom : `OpenCode`, Portées : `api` +4. Copiez le jeton (commence par `glpat-`) +5. Entrez-le dans le terminal + +6. Exécutez la commande `/models` pour voir les modèles disponibles. + + ```txt + /models + ``` + +```` + +Trois modèles basés sur Claude sont disponibles : + +- **duo-chat-haiku-4-5** (Par défaut) - Réponses rapides pour des tâches rapides +- **duo-chat-sonnet-4-5** - Performances équilibrées pour la plupart des flux de travail +- **duo-chat-opus-4-5** - Le plus capable pour les analyses complexes + +:::note +Vous pouvez également spécifier la variable d'environnement 'GITLAB_TOKEN' si vous ne souhaitez pas +pour stocker le jeton dans le stockage d'authentification opencode. +::: + +##### GitLab auto-hébergé + +:::note[note de conformité] +OpenCode utilise un petit modèle pour certaines tâches d'IA telles que la génération du titre de la session. +Il est configuré pour utiliser gpt-5-nano par défaut, hébergé par Zen. Pour verrouiller OpenCode +pour utiliser uniquement votre propre instance hébergée par GitLab, ajoutez ce qui suit à votre +Fichier `opencode.json`. Il est également recommandé de désactiver le partage de session. + +```json +{ +"$schema": "https://opencode.ai/config.json", +"small_model": "gitlab/duo-chat-haiku-4-5", +"share": "disabled" +} +```` + +::: + +Pour les instances GitLab auto-hébergées : + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +Si votre instance exécute une AI Gateway personnalisée : + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +Ou ajoutez à votre profil bash : + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +Votre administrateur GitLab doit activer les éléments suivants : + +1. [Duo Agent Platform](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) pour l'utilisateur, le groupe ou l'instance +2. Indicateurs de fonctionnalités (via la console Rails) : + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: + +##### OAuth pour les instances auto-hébergées + +Afin que Oauth fonctionne pour votre instance auto-hébergée, vous devez créer +une nouvelle application (Paramètres → Applications) avec le +rappel URL `http://127.0.0.1:8080/callback` et étendues suivantes : + +- api (Accédez au API en votre nom) +- read_user (Lire vos informations personnelles) +- read_repository (Autorise l'accès en lecture seule au référentiel) + +Exposez ensuite l'ID de l'application en tant que variable d'environnement : + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +Plus de documentation sur la page d'accueil [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth). + +##### Configuration + +Personnalisez via `opencode.json` : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### Outils GitLab API (facultatif, mais fortement recommandé) + +Pour accéder aux outils GitLab (demandes de fusion, tickets, pipelines, CI/CD, etc.) : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +Ce plugin fournit des fonctionnalités complètes de gestion du référentiel GitLab, notamment les examens MR, le suivi des problèmes, la surveillance du pipeline, etc. + +--- + +### GitHub Copilot + +Pour utiliser votre abonnement GitHub Copilot avec opencode : + +:::note +Certains modèles peuvent avoir besoin d'un [Pro+ +abonnement](https://github.com/features/copilot/plans) à utiliser. + +Certains modèles doivent être activés manuellement dans vos [GitHub Copilot paramètres](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use). +::: + +1. Exécutez la commande `/connect` et recherchez GitHub Copilot. + + ```txt + /connect + ``` + +2. Accédez à [github.com/login/device](https://github.com/login/device) et entrez le code. + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + └ Waiting for authorization... + ``` + +3. Exécutez maintenant la commande `/models` pour sélectionner le modèle souhaité. + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +Pour utiliser Google Vertex AI avec OpenCode : + +1. Rendez-vous sur **Model Garden** dans Google Cloud Console et vérifiez les + modèles disponibles dans votre région. + + :::note + Vous devez disposer d'un projet Google Cloud avec Vertex AI API activé. + ::: + +2. Définissez les variables d'environnement requises : + - `GOOGLE_CLOUD_PROJECT` : ID de votre projet Google Cloud + - `VERTEX_LOCATION` (facultatif) : région pour Vertex AI (par défaut : `global`) + - Authentification (au choix) : + - `GOOGLE_APPLICATION_CREDENTIALS` : chemin d'accès au fichier de clé JSON de votre compte de service + - Authentifiez-vous à l'aide de gcloud CLI : `gcloud auth application-default login` + +Définissez-les lors de l'exécution de opencode. + +```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode +``` + +Ou ajoutez-les à votre profil bash. + +```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 +La région `global` améliore la disponibilité et réduit les erreurs sans frais supplémentaires. Utilisez des points de terminaison régionaux (par exemple, `us-central1`) pour les exigences de résidence des données. [En savoir plus](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. Exécutez la commande `/models` pour sélectionner le modèle souhaité. + + ```txt + /models + ``` + +--- + +### Groq + +1. Rendez-vous sur la [console Groq](https://console.groq.com/), cliquez sur **Créer une clé API** et copiez la clé. + +2. Exécutez la commande `/connect` et recherchez Groq. + + ```txt + /connect + ``` + +3. Saisissez la clé API du fournisseur. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner celle que vous souhaitez. + + ```txt + /models + ``` + +--- + +### Hugging Face + +[Hugging Face Inference Providers](https://huggingface.co/docs/inference-providers) donne accès à des modèles ouverts pris en charge par plus de 17 fournisseurs. + +1. Rendez-vous sur [Hugging Face settings](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained) pour créer un jeton avec l'autorisation de passer des appels aux fournisseurs d'inférence. + +2. Exécutez la commande `/connect` et recherchez **Hugging Face**. + + ```txt + /connect + ``` + +3. Entrez votre jeton Hugging Face. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle comme _Kimi-K2-Instruct_ ou _GLM-4.6_. + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) est une plate-forme d'observabilité LLM qui fournit la journalisation, la surveillance et l'analyse de vos applications d'IA. L'Helicone AI Gateway achemine automatiquement vos demandes vers le fournisseur approprié en fonction du modèle. + +1. Rendez-vous sur [Helicone](https://helicone.ai), créez un compte et générez une clé API à partir de votre tableau de bord. + +2. Exécutez la commande `/connect` et recherchez **Helicone**. + + ```txt + /connect + ``` + +3. Entrez votre clé Helicone API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle. + + ```txt + /models + ``` + +Pour plus de fournisseurs et de fonctionnalités avancées telles que la mise en cache et la limitation de débit, consultez la [documentation Helicone](https://docs.helicone.ai). + +#### Configurations facultatives + +Si vous voyez une fonctionnalité ou un modèle d'Helicone qui n'est pas configuré automatiquement via opencode, vous pouvez toujours le configurer vous-même. + +Voici le [Répertoire des modèles d'Helicone](https://helicone.ai/models), vous en aurez besoin pour récupérer les identifiants des modèles que vous souhaitez ajouter. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### En-têtes personnalisés + +Helicone prend en charge les en-têtes personnalisés pour des fonctionnalités telles que la mise en cache, le suivi des utilisateurs et la gestion des sessions. Ajoutez-les à la configuration de votre fournisseur en utilisant `options.headers` : + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### Suivi des sessions + +La fonctionnalité [Sessions](https://docs.helicone.ai/features/sessions) d'Helicone vous permet de regrouper les requêtes LLM associées. Utilisez le plugin [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) pour enregistrer automatiquement chaque conversation OpenCode en tant que session dans Helicone. + +```bash +npm install -g opencode-helicone-session +``` + +Ajoutez-le à votre configuration. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +Le plugin injecte les en-têtes `Helicone-Session-Id` et `Helicone-Session-Name` dans vos requêtes. Sur la page Sessions d'Helicone, vous verrez chaque conversation OpenCode répertoriée comme une session distincte. + +##### En-têtes Helicone communs + +| En-tête | Descriptif | +| -------------------------- | ------------------------------------------------------------------------------------ | +| `Helicone-Cache-Enabled` | Activer la mise en cache des réponses (`true`/`false`) | +| `Helicone-User-Id` | Suivre les métriques par utilisateur | +| `Helicone-Property-[Name]` | Ajouter des propriétés personnalisées (par exemple, `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | Associer les requêtes aux versions d'invite | + +Consultez le [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory) pour tous les en-têtes disponibles. + +--- + +### llama.cpp + +Vous pouvez configurer opencode pour utiliser des modèles locaux via l'utilitaire llama-server de [llama.cpp's](https://github.com/ggml-org/llama.cpp) + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +Dans cet exemple : + +- `llama.cpp` est l'ID du fournisseur personnalisé. Cela peut être n’importe quelle chaîne de votre choix. +- `npm` spécifie le package à utiliser pour ce fournisseur. Ici, `@ai-sdk/openai-compatible` est utilisé pour tout API compatible OpenAI. +- `name` est le nom d'affichage du fournisseur dans l'interface utilisateur. +- `options.baseURL` est le point de terminaison du serveur local. +- `models` est une carte des ID de modèle avec leurs configurations. Le nom du modèle sera affiché dans la liste de sélection du modèle. + +--- + +### IO.NET + +IO.NET propose 17 modèles optimisés pour différents cas d'utilisation : + +1. Rendez-vous sur la [console IO.NET](https://ai.io.net/), créez un compte et générez une clé API. + +2. Exécutez la commande `/connect` et recherchez **IO.NET**. + + ```txt + /connect + ``` + +3. Entrez votre clé IO.NET API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle. + + ```txt + /models + ``` + +--- + +### LM Studio + +Vous pouvez configurer opencode pour utiliser des modèles locaux via LM Studio. + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +Dans cet exemple : + +- `lmstudio` est l'ID du fournisseur personnalisé. Cela peut être n’importe quelle chaîne de votre choix. +- `npm` spécifie le package à utiliser pour ce fournisseur. Ici, `@ai-sdk/openai-compatible` est utilisé pour tout API compatible OpenAI. +- `name` est le nom d'affichage du fournisseur dans l'interface utilisateur. +- `options.baseURL` est le point de terminaison du serveur local. +- `models` est une carte des ID de modèle avec leurs configurations. Le nom du modèle sera affiché dans la liste de sélection du modèle. + +--- + +### Moonshot AI + +Pour utiliser Kimi K2 de Moonshot AI : + +1. Rendez-vous sur la [console Moonshot AI](https://platform.moonshot.ai/console), créez un compte et cliquez sur **Créer une clé API**. + +2. Exécutez la commande `/connect` et recherchez **Moonshot AI**. + + ```txt + /connect + ``` + +3. Entrez votre clé Moonshot API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner _Kimi K2_. + + ```txt + /models + ``` + +--- + +### MiniMax + +1. Rendez-vous sur la [Console MiniMax API](https://platform.minimax.io/login), créez un compte et générez une clé API. + +2. Exécutez la commande `/connect` et recherchez **MiniMax**. + + ```txt + /connect + ``` + +3. Entrez votre clé MiniMax API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle tel que _M2.1_. + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. Rendez-vous sur la [console Nebius Token Factory](https://tokenfactory.nebius.com/), créez un compte et cliquez sur **Ajouter une clé**. + +2. Exécutez la commande `/connect` et recherchez **Nebius Token Factory**. + + ```txt + /connect + ``` + +3. Entrez votre clé Nebius Token Factory API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle tel que _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Ollama + +Vous pouvez configurer opencode pour utiliser des modèles locaux via Ollama. + +:::tip +Ollama peut se configurer automatiquement pour OpenCode. Voir les [documents d'intégration Ollama](https://docs.ollama.com/integrations/opencode) pour plus de détails. +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +Dans cet exemple : + +- `ollama` est l'ID du fournisseur personnalisé. Cela peut être n’importe quelle chaîne de votre choix. +- `npm` spécifie le package à utiliser pour ce fournisseur. Ici, `@ai-sdk/openai-compatible` est utilisé pour tout API compatible OpenAI. +- `name` est le nom d'affichage du fournisseur dans l'interface utilisateur. +- `options.baseURL` est le point de terminaison du serveur local. +- `models` est une carte des ID de modèle avec leurs configurations. Le nom du modèle sera affiché dans la liste de sélection du modèle. + +:::tip +Si les appels d'outils ne fonctionnent pas, essayez d'augmenter `num_ctx` dans Ollama. Commencez vers 16k - 32k. +::: + +--- + +### Ollama Cloud + +Pour utiliser Ollama Cloud avec OpenCode : + +1. Rendez-vous sur [https://ollama.com/](https://ollama.com/) et connectez-vous ou créez un compte. + +2. Accédez à **Paramètres** > **Clés** et cliquez sur **Ajouter une clé API** pour générer une nouvelle clé API. + +3. Copiez la clé API à utiliser dans OpenCode. + +4. Exécutez la commande `/connect` et recherchez **Ollama Cloud**. + + ```txt + /connect + ``` + +5. Entrez votre clé Ollama Cloud API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **Important** : Avant d'utiliser des modèles cloud dans OpenCode, vous devez extraire les informations du modèle localement : + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. Exécutez la commande `/models` pour sélectionner votre modèle Ollama Cloud. + + ```txt + /models + ``` + +--- + +### OpenAI + +Nous vous recommandons de vous inscrire à [ChatGPT Plus ou Pro](https://chatgpt.com/pricing). + +1. Une fois inscrit, exécutez la commande `/connect` et sélectionnez OpenAI. + + ```txt + /connect + ``` + +2. Ici, vous pouvez sélectionner l'option **ChatGPT Plus/Pro** et cela ouvrira votre navigateur. + et vous demande de vous authentifier. + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. Désormais, tous les modèles OpenAI devraient être disponibles lorsque vous utilisez la commande `/models`. + + ```txt + /models + ``` + +##### Utilisation des clés API + +Si vous disposez déjà d'une clé API, vous pouvez sélectionner **Entrer manuellement la clé API** et la coller dans votre terminal. + +--- + +### OpenCode Zen + +OpenCode Zen est une liste de modèles testés et vérifiés fournie par l'équipe OpenCode. [En savoir plus](/docs/zen). + +1. Connectez-vous à **OpenCode Zen** et cliquez sur **Créer une clé API**. + +2. Exécutez la commande `/connect` et recherchez **OpenCode Zen**. + + ```txt + /connect + ``` + +3. Entrez votre clé OpenCode API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle tel que _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### OpenRouter + +1. Rendez-vous sur le [tableau de bord OpenRouter](https://openrouter.ai/settings/keys), cliquez sur **Créer une clé API** et copiez la clé. + +2. Exécutez la commande `/connect` et recherchez OpenRouter. + + ```txt + /connect + ``` + +3. Saisissez la clé API du fournisseur. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. De nombreux modèles OpenRouter sont préchargés par défaut, exécutez la commande `/models` pour sélectionner celui que vous souhaitez. + + ```txt + /models + ``` + +Vous pouvez également ajouter des modèles supplémentaires via votre configuration opencode. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "somecoolnewmodel": {} + } + } + } +} +``` + +5. Vous pouvez également les personnaliser via votre configuration opencode. Voici un exemple de spécification d'un fournisseur + + ```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 donne accès à plus de 40 modèles de OpenAI, Anthropic, Google, Amazon, Meta, Mistral et AI21 via une plateforme unifiée. + +1. Accédez à votre [SAP BTP Cockpit](https://account.hana.ondemand.com/), accédez à votre instance de service SAP AI Core et créez une clé de service. + + :::tip + La clé de service est un objet JSON contenant `clientid`, `clientsecret`, `url` et `serviceurls.AI_API_URL`. Vous pouvez trouver votre instance AI Core sous **Services** > **Instances et abonnements** dans le cockpit BTP. + ::: + +2. Exécutez la commande `/connect` et recherchez **SAP AI Core**. + + ```txt + /connect + ``` + +3. Entrez votre clé de service JSON. + + ```txt + ┌ Service key + │ + │ + └ enter + ``` + +Ou définissez la variable d'environnement `AICORE_SERVICE_KEY` : + +```bash + AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode +``` + +Ou ajoutez-le à votre profil bash : + +```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' +``` + +4. Définissez éventuellement l'ID de déploiement et le groupe de ressources : + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + Ces paramètres sont facultatifs et doivent être configurés en fonction de votre configuration SAP AI Core. + ::: + +5. Exécutez la commande `/models` pour sélectionner parmi plus de 40 modèles disponibles. + + ```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**. + +2. Exécutez la commande `/connect` et recherchez **OVHcloud AI Endpoints**. + + ```txt + /connect + ``` + +3. Saisissez votre clé OVHcloud AI Endpoints API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle tel que _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Scaleway + +Pour utiliser [Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/) avec Opencode : + +1. Rendez-vous dans les [Paramètres IAM de la console Scaleway](https://console.scaleway.com/iam/api-keys) pour générer une nouvelle clé API. + +2. Exécutez la commande `/connect` et recherchez **Scaleway**. + + ```txt + /connect + ``` + +3. Entrez votre clé Scaleway API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle tel que _devstral-2-123b-instruct-2512_ ou _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Together AI + +1. Rendez-vous sur [Together AI console](https://api.together.ai), créez un compte et cliquez sur **Ajouter une clé**. + +2. Exécutez la commande `/connect` et recherchez **Together AI**. + + ```txt + /connect + ``` + +3. Entrez votre clé Together AI API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle tel que _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Venice AI + +1. Rendez-vous sur la [Venice AI console](https://venice.ai), créez un compte et générez une clé API. + +2. Exécutez la commande `/connect` et recherchez **Venice AI**. + + ```txt + /connect + ``` + +3. Entrez votre clé Venise AI API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle tel que _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + +### Vercel AI Gateway + +Vercel AI Gateway vous permet d'accéder aux modèles de OpenAI, Anthropic, Google, xAI et plus encore via un point de terminaison unifié. Les modèles sont proposés au prix catalogue sans majoration. + +1. Rendez-vous sur le [tableau de bord Vercel](https://vercel.com/), accédez à l'onglet **AI Gateway** et cliquez sur **API Keys** pour créer une nouvelle clé API. + +2. Exécutez la commande `/connect` et recherchez **Vercel AI Gateway**. + + ```txt + /connect + ``` + +3. Entrez votre clé Vercel AI Gateway API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle. + + ```txt + /models + ``` + +Vous pouvez également personnaliser les modèles via votre configuration opencode. Voici un exemple de spécification de l'ordre de routage du fournisseur. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "vercel": { + "models": { + "anthropic/claude-sonnet-4": { + "options": { + "order": ["anthropic", "vertex"] + } + } + } + } + } +} +``` + +Quelques options de routage utiles : + +| Options | Descriptif | +| ------------------- | ------------------------------------------------------------------------------------------- | +| `order` | Séquence de fournisseur à essayer | +| `only` | Restreindre à des fournisseurs spécifiques | +| `zeroDataRetention` | Utilisez uniquement des fournisseurs avec des politiques de conservation des données nulles | + +--- + +### xAI + +1. Rendez-vous sur la [console xAI](https://console.x.ai/), créez un compte et générez une clé API. + +2. Exécutez la commande `/connect` et recherchez **xAI**. + + ```txt + /connect + ``` + +3. Entrez votre clé xAI API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle tel que _Grok Beta_. + + ```txt + /models + ``` + +--- + +### Z.AI + +1. Rendez-vous sur la [console Z.AI API](https://z.ai/manage-apikey/apikey-list), créez un compte et cliquez sur **Créer une nouvelle clé API**. + +2. Exécutez la commande `/connect` et recherchez **Z.AI**. + + ```txt + /connect + ``` + +Si vous êtes abonné au **Plan de codage GLM**, sélectionnez **Plan de codage Z.AI**. + +3. Entrez votre clé Z.AI API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner un modèle tel que _GLM-4.7_. + + ```txt + /models + ``` + +--- + +### ZenMux + +1. Rendez-vous sur le [tableau de bord ZenMux](https://zenmux.ai/settings/keys), cliquez sur **Créer une clé API** et copiez la clé. + +2. Exécutez la commande `/connect` et recherchez ZenMux. + + ```txt + /connect + ``` + +3. Saisissez la clé API du fournisseur. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. De nombreux modèles ZenMux sont préchargés par défaut, exécutez la commande `/models` pour sélectionner celui que vous souhaitez. + + ```txt + /models + ``` + +Vous pouvez également ajouter des modèles supplémentaires via votre configuration opencode. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "zenmux": { + "models": { + "somecoolnewmodel": {} + } + } + } +} +``` + +--- + +## Fournisseur personnalisé + +Pour ajouter un fournisseur **OpenAI-compatible** qui n'est pas répertorié dans la commande `/connect` : + +:::tip +Vous pouvez utiliser n'importe quel fournisseur compatible OpenAI avec opencode. La plupart des fournisseurs d'IA modernes proposent des API compatibles OpenAI. +::: + +1. Exécutez la commande `/connect` et faites défiler jusqu'à **Autre**. + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. Saisissez un identifiant unique pour le fournisseur. + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::note + Choisissez un identifiant mémorable, vous l'utiliserez dans votre fichier de configuration. + ::: + +3. Entrez votre clé API pour le fournisseur. + + ```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. Créez ou mettez à jour votre fichier `opencode.json` dans le répertoire de votre projet : + + ```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" + } + } + } + } + } + ``` + +Voici les options de configuration : + +- **npm** : package AI SDK à utiliser, `@ai-sdk/openai-compatible` pour les fournisseurs compatibles OpenAI +- **nom** : nom à afficher dans l'interface utilisateur. +- **modèles** : Modèles disponibles. +- **options.baseURL** : URL de l'endpoint API. +- **options.apiKey** : définissez éventuellement la clé API, si vous n'utilisez pas d'authentification. +- **options.headers** : définissez éventuellement des en-têtes personnalisés. + +En savoir plus sur les options avancées dans l'exemple ci-dessous. + +5. Exécutez la commande `/models` et votre fournisseur et vos modèles personnalisés apparaîtront dans la liste de sélection. + +--- + +##### Exemple + +Voici un exemple de définition des options `apiKey`, `headers` et modèle `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 + } + } + } + } + } +} +``` + +Détails de configuration : + +- **apiKey** : défini à l'aide de la syntaxe de variable `env`, [en savoir plus](/docs/config#env-vars). +- **headers** : en-têtes personnalisés envoyés avec chaque requête. +- **limit.context** : nombre maximal de jetons d'entrée acceptés par le modèle. +- **limit.output** : nombre maximal de jetons que le modèle peut générer. + +Les champs `limit` permettent à OpenCode de comprendre la quantité de contexte qu'il vous reste. Les fournisseurs standard les extraient automatiquement de models.dev. + +--- + +## Dépannage + +Si vous rencontrez des difficultés lors de la configuration d'un fournisseur, vérifiez les points suivants : + +1. **Vérifiez la configuration de l'authentification** : exécutez `opencode auth list` pour voir si les informations d'identification + pour le fournisseur sont ajoutés à votre configuration. + +Cela ne s'applique pas aux fournisseurs comme Amazon Bedrock, qui s'appuient sur des variables d'environnement pour leur authentification. + +2. Pour les fournisseurs personnalisés, vérifiez la configuration opencode et : + - Assurez-vous que l'ID du fournisseur utilisé dans la commande `/connect` correspond à l'ID de votre configuration opencode. + - Le bon package npm est utilisé pour le fournisseur. Par exemple, utilisez `@ai-sdk/cerebras` pour Cerebras. Et pour tous les autres fournisseurs compatibles OpenAI, utilisez `@ai-sdk/openai-compatible`. + - Vérifiez que le point de terminaison API correct est utilisé dans le champ `options.baseURL`. diff --git a/packages/web/src/content/docs/fr/rules.mdx b/packages/web/src/content/docs/fr/rules.mdx new file mode 100644 index 00000000000..2b0d13c7246 --- /dev/null +++ b/packages/web/src/content/docs/fr/rules.mdx @@ -0,0 +1,180 @@ +--- +title: Règles +description: Définissez des instructions personnalisées pour opencode. +--- + +Vous pouvez fournir des instructions personnalisées à opencode en créant un fichier `AGENTS.md`. Ceci est similaire aux règles du curseur. Il contient des instructions qui seront incluses dans le contexte du LLM pour personnaliser son comportement pour votre projet spécifique. + +--- + +## Initialiser + +Pour créer un nouveau fichier `AGENTS.md`, vous pouvez exécuter la commande `/init` dans opencode. + +:::tip +Vous devez valider le fichier `AGENTS.md` de votre projet dans Git. +::: + +Cela analysera votre projet et tout son contenu pour comprendre de quoi il s'agit et générera un fichier `AGENTS.md` avec celui-ci. Cela aide opencode à mieux naviguer dans le projet. + +Si vous avez un fichier `AGENTS.md` existant, cela tentera de l'ajouter. + +--- + +## Exemple + +Vous pouvez également simplement créer ce fichier manuellement. Voici un exemple de certaines choses que vous pouvez mettre dans un fichier `AGENTS.md`. + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +Nous ajoutons ici des instructions spécifiques au projet et celles-ci seront partagées au sein de votre équipe. + +--- + +## Types + +opencode prend également en charge la lecture du fichier `AGENTS.md` à partir de plusieurs emplacements. Et cela répond à des objectifs différents. + +### Projet + +Placez un `AGENTS.md` à la racine de votre projet pour les règles spécifiques au projet. Celles-ci ne s'appliquent que lorsque vous travaillez dans ce répertoire ou ses sous-répertoires. + +### Mondial + +Vous pouvez également avoir des règles globales dans un fichier `~/.config/opencode/AGENTS.md`. Ceci est appliqué à toutes les sessions opencode. + +Étant donné que cela n'est pas validé par Git ni partagé avec votre équipe, nous vous recommandons de l'utiliser pour spécifier les règles personnelles que le LLM doit suivre. + +### Compatibilité des codes Claude + +Pour les utilisateurs migrant depuis Claude Code, OpenCode prend en charge les conventions de fichiers de Claude Code comme solutions de secours : + +- **Règles du projet** : `CLAUDE.md` dans le répertoire de votre projet (utilisé si aucun `AGENTS.md` n'existe) +- **Règles globales** : `~/.claude/CLAUDE.md` (utilisé si aucun `~/.config/opencode/AGENTS.md` n'existe) +- **Compétences** : `~/.claude/skills/` — voir [Compétences de l'agent](/docs/skills/) pour plus de détails + +Pour désactiver la compatibilité Claude Code, définissez l'une de ces variables d'environnement : + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## Priorité + +Lorsque opencode démarre, il recherche les fichiers de règles dans cet ordre : + +1. **Fichiers locaux** en parcourant le répertoire actuel (`AGENTS.md`, `CLAUDE.md`) +2. **Fichier global** à `~/.config/opencode/AGENTS.md` +3. **Fichier Claude Code** à `~/.claude/CLAUDE.md` (sauf si désactivé) + +Le premier fichier correspondant gagne dans chaque catégorie. Par exemple, si vous possédez à la fois `AGENTS.md` et `CLAUDE.md`, seul `AGENTS.md` est utilisé. De même, `~/.config/opencode/AGENTS.md` a priorité sur `~/.claude/CLAUDE.md`. + +--- + +## Instructions personnalisées + +Vous pouvez spécifier des fichiers d'instructions personnalisés dans votre `opencode.json` ou dans le `~/.config/opencode/opencode.json` global. Cela vous permet, à vous et à votre équipe, de réutiliser les règles existantes plutôt que d'avoir à les dupliquer dans AGENTS.md. + +Exemple: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Vous pouvez également utiliser des URL distantes pour charger des instructions à partir du Web. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +Les instructions à distance sont récupérées avec un délai d'attente de 5 secondes. + +Tous les fichiers d'instructions sont combinés avec vos fichiers `AGENTS.md`. + +--- + +## Référencement de fichiers externes + +Bien que opencode n'analyse pas automatiquement les références de fichiers dans `AGENTS.md`, vous pouvez obtenir des fonctionnalités similaires de deux manières : + +### Utilisation de opencode.json + +L'approche recommandée consiste à utiliser le champ `instructions` dans `opencode.json` : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### Instructions manuelles dans AGENTS.md + +Vous pouvez apprendre à opencode à lire des fichiers externes en fournissant des instructions explicites dans votre `AGENTS.md`. Voici un exemple pratique : + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +Cette approche vous permet de : + +- Créez des fichiers de règles modulaires et réutilisables +- Partagez des règles entre projets via des liens symboliques ou des sous-modules git +- Gardez AGENTS.md concis tout en faisant référence à des directives détaillées +- Assurez-vous que opencode charge les fichiers uniquement lorsque cela est nécessaire pour une tâche spécifique. + +:::tip +Pour les monorepos ou les projets avec des normes partagées, l'utilisation de `opencode.json` avec des modèles globaux (comme `packages/*/AGENTS.md`) est plus maintenable que les instructions manuelles. +::: diff --git a/packages/web/src/content/docs/fr/sdk.mdx b/packages/web/src/content/docs/fr/sdk.mdx new file mode 100644 index 00000000000..0e67aebd00a --- /dev/null +++ b/packages/web/src/content/docs/fr/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: Client JS de type sécurisé pour le serveur opencode. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +Le SDK opencode JS/TS fournit un client de type sécurisé pour interagir avec le serveur. +Utilisez-le pour créer des intégrations et contrôler opencode par programme. + +[En savoir plus](/docs/server) sur le fonctionnement du serveur. Pour des exemples, consultez les [projects](/docs/ecosystem#projects) construits par la communauté. + +--- + +## Installer + +Installez le SDK à partir de npm : + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## Créer un client + +Créez une instance de opencode : + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +Cela démarre à la fois un serveur et un client + +#### Options + +| Options | Tapez | Descriptif | Par défaut | +| ---------- | ------------- | -------------------------------------------------- | ----------- | +| `hostname` | `string` | Nom d'hôte du serveur | `127.0.0.1` | +| `port` | `number` | Port du serveur | `4096` | +| `signal` | `AbortSignal` | Signal d'abandon pour annulation | `undefined` | +| `timeout` | `number` | Délai d'attente en ms pour le démarrage du serveur | `5000` | +| `config` | `Config` | Objet de configuration | `{}` | + +--- + +## Configuration + +Vous pouvez transmettre un objet de configuration pour personnaliser le comportement. L'instance récupère toujours votre `opencode.json`, mais vous pouvez remplacer ou ajouter une configuration en ligne : + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## Client uniquement + +Si vous disposez déjà d'une instance en cours d'exécution de opencode, vous pouvez créer une instance client pour vous y connecter : + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### Options + +| Options | Tapez | Descriptif | Par défaut | +| --------------- | ---------- | -------------------------------------------- | ----------------------- | +| `baseUrl` | `string` | URL du serveur | `http://localhost:4096` | +| `fetch` | `function` | Implémentation de récupération personnalisée | `globalThis.fetch` | +| `parseAs` | `string` | Méthode d'analyse des réponses | `auto` | +| `responseStyle` | `string` | Style de retour : `data` ou `fields` | `fields` | +| `throwOnError` | `boolean` | Lancez des erreurs au lieu de return | `false` | + +--- + +## Types + +Le SDK inclut des définitions TypeScript pour tous les types API. Importez-les directement : + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +Tous les types sont générés à partir de la spécification OpenAPI du serveur et disponibles dans le fichier de types. + +--- + +## Erreurs + +Le SDK peut générer des erreurs que vous pouvez détecter et gérer : + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## APIs + +Le SDK expose toutes les API du serveur via un client de type sécurisé. + +--- + +### Mondial + +| Méthode | Descriptif | Réponse | +| ----------------- | ---------------------------------------- | ------------------------------------ | +| `global.health()` | Vérifier l'état et la version du serveur | `{ healthy: true, version: string }` | + +--- + +#### Exemples + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### Application + +| Méthode | Descriptif | Réponse | +| -------------- | --------------------------------- | ------------------------------------------- | +| `app.log()` | Écrire une entrée de journal | `boolean` | +| `app.agents()` | Liste tous les agents disponibles | Agent[] | + +--- + +#### Exemples + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### Projet + +| Méthode | Descriptif | Réponse | +| ------------------- | -------------------------- | --------------------------------------------- | +| `project.list()` | Lister tous les projets | Project[] | +| `project.current()` | Obtenir le projet en cours | Project | + +--- + +#### Exemples + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### Chemin + +| Méthode | Descriptif | Réponse | +| ------------ | ------------------------ | ---------------------------------------- | +| `path.get()` | Obtenir le chemin actuel | Path | + +--- + +#### Exemples + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### Configuration + +| Méthode | Descriptif | Réponse | +| -------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | Obtenir des informations de configuration | Config | +| `config.providers()` | Liste des fournisseurs et modèles par défaut | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### Exemples + +```javascript +const config = await client.config.get() + +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` | + +--- + +#### Exemples + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### Fichiers + +| Méthode | Descriptif | Réponse | +| ------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------- | +| `find.text({ query })` | Rechercher du texte dans des fichiers | Tableau d'objets correspondant avec `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `find.files({ query })` | Rechercher des fichiers et des répertoires par nom | `string[]` (chemins) | +| `find.symbols({ query })` | Rechercher des symboles d'espace de travail | Symbol[] | +| `file.read({ query })` | Lire un fichier | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | Obtenir le statut des fichiers suivis | File[] | + +`find.files` prend en charge quelques champs de requête facultatifs : + +- `type` : `"file"` ou `"directory"` +- `directory` : remplace la racine du projet pour la recherche +- `limit` : résultats maximum (1 à 200) + +--- + +#### Exemples + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| Méthode | Descriptif | Réponse | +| ------------------------------ | ---------------------------------- | --------- | +| `tui.appendPrompt({ body })` | Ajouter du texte à l'invite | `boolean` | +| `tui.openHelp()` | Ouvrir la boîte de dialogue d'aide | `boolean` | +| `tui.openSessions()` | Ouvrez le sélecteur de session | `boolean` | +| `tui.openThemes()` | Ouvrez le sélecteur de thème | `boolean` | +| `tui.openModels()` | Ouvrez le sélecteur de modèle | `boolean` | +| `tui.submitPrompt()` | Soumettre l'invite actuelle | `boolean` | +| `tui.clearPrompt()` | Effacez l'invite | `boolean` | +| `tui.executeCommand({ body })` | Exécuter une commande | `boolean` | +| `tui.showToast({ body })` | Afficher la notification toast | `boolean` | + +--- + +#### Exemples + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### Authentification + +| Méthode | Descriptif | Réponse | +| ------------------- | ------------------------------------------- | --------- | +| `auth.set({ ... })` | Définir les informations d'authentification | `boolean` | + +--- + +#### Exemples + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### Événements + +| Méthode | Descriptif | Réponse | +| ------------------- | ---------------------------------------- | ---------------------------------------- | +| `event.subscribe()` | Flux d'événements envoyés par le serveur | Flux d'événements envoyés par le serveur | + +--- + +#### Exemples + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/fr/server.mdx b/packages/web/src/content/docs/fr/server.mdx new file mode 100644 index 00000000000..a376f4a18cc --- /dev/null +++ b/packages/web/src/content/docs/fr/server.mdx @@ -0,0 +1,287 @@ +--- +title: Serveur +description: Interagissez avec le serveur opencode via HTTP. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +La commande `opencode serve` exécute un serveur HTTP sans tête qui expose un point de terminaison OpenAPI qu'un client opencode peut utiliser. + +--- + +### Usage + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### Options + +| Drapeau | Descriptif | Par défaut | +| --------------- | -------------------------------------------------- | ---------------- | +| `--port` | Port à écouter sur | `4096` | +| `--hostname` | Nom d'hôte sur lequel écouter | `127.0.0.1` | +| `--mdns` | Activer la découverte mDNS | `false` | +| `--mdns-domain` | Nom de domaine personnalisé pour le service mDNS | `opencode.local` | +| `--cors` | Origines de navigateur supplémentaires à autoriser | `[]` | + +`--cors` peut être transmis plusieurs fois : + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### Authentification + +Définissez `OPENCODE_SERVER_PASSWORD` pour protéger le serveur avec l'authentification de base HTTP. Le nom d'utilisateur est par défaut `opencode`, ou définissez `OPENCODE_SERVER_USERNAME` pour le remplacer. Cela s’applique à la fois à `opencode serve` et à `opencode web`. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### Comment ça marche + +Lorsque vous exécutez `opencode`, il démarre un TUI et un serveur. Où le TUI est le +client qui parle au serveur. Le serveur expose une spécification OpenAPI 3.1 +point final. Ce point de terminaison est également utilisé pour générer un [SDK](/docs/sdk). + +:::tip +Utilisez le serveur opencode pour interagir avec opencode par programmation. +::: + +Cette architecture permet à opencode de prendre en charge plusieurs clients et vous permet d'interagir avec opencode par programme. + +Vous pouvez exécuter `opencode serve` pour démarrer un serveur autonome. Si vous avez le +opencode TUI en cours d'exécution, `opencode serve` démarrera un nouveau serveur. + +--- + +#### Connectez-vous à un serveur existant + +Lorsque vous démarrez le TUI, il attribue de manière aléatoire un port et un nom d'hôte. Vous pouvez à la place transmettre les `--hostname` et `--port` [flags](/docs/cli). Utilisez-le ensuite pour vous connecter à son serveur. + +Le point de terminaison [`/tui`](#tui) peut être utilisé pour piloter le TUI via le serveur. Par exemple, vous pouvez pré-remplir ou exécuter une invite. Cette configuration est utilisée par les plugins OpenCode [IDE](/docs/ide). + +--- + +## Spécification + +Le serveur publie une spécification OpenAPI 3.1 qui peut être consultée à l'adresse : + +``` +http://:/doc +``` + +Par exemple, `http://localhost:4096/doc`. Utilisez la spécification pour générer des clients ou inspecter les types de requêtes et de réponses. Ou visualisez-le dans un explorateur Swagger. + +--- + +## APIs + +Le serveur opencode expose les API suivantes. + +--- + +### Mondial + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | ---------------- | ------------------------------------------ | ------------------------------------ | +| `GET` | `/global/health` | Obtenir l'état et la version du serveur | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | Obtenez des événements mondiaux (flux SSE) | Flux d'événements | + +--- + +### Projet + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | ------------------ | -------------------------- | --------------------------------------------- | +| `GET` | `/project` | Lister tous les projets | Project[] | +| `GET` | `/project/current` | Obtenez le projet en cours | Project | + +--- + +### Chemin et VCS + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | ------- | ---------------------------------------------------- | ------------------------------------------- | +| `GET` | `/path` | Obtenir le chemin actuel | Path | +| `GET` | `/vcs` | Obtenir des informations VCS pour le projet en cours | VcsInfo | + +--- + +### Exemple + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | ------------------- | ----------------------------- | --------- | +| `POST` | `/instance/dispose` | Supprimer l'instance actuelle | `boolean` | + +--- + +### Configuration + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | ------------------- | -------------------------------------------- | ---------------------------------------------------------------------------------------- | +| `GET` | `/config` | Obtenir des informations de configuration | Config | +| `PATCH` | `/config` | Mettre à jour la configuration | Config | +| `GET` | `/config/providers` | Liste des fournisseurs et modèles par défaut | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +### Fournisseur + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | -------------------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------- | +| `GET` | `/provider` | Liste de tous les fournisseurs | `{ all: `Provider[]`, default: {...}, connected: string[] }` | +| `GET` | `/provider/auth` | Obtenir les méthodes d'authentification du fournisseur | `{ [providerID: string]: `ProviderAuthMethod[]` }` | +| `POST` | `/provider/{id}/oauth/authorize` | Autoriser un fournisseur en utilisant OAuth | ProviderAuthAuthorization | +| `POST` | `/provider/{id}/oauth/callback` | Gérer le rappel OAuth pour un fournisseur | `boolean` | + +--- + +### Séances + +| Méthode | Chemin | Descriptif | Remarques | +| -------- | ---------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------ | +| `GET` | `/session` | Liste toutes les sessions | Renvoie Session[] | +| `POST` | `/session` | Créer une nouvelle session | corps : `{ parentID?, title? }`, renvoie Session | +| `GET` | `/session/status` | Obtenir l'état de la session pour toutes les sessions | Renvoie `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | Obtenez les détails de la session | Renvoie Session | +| `DELETE` | `/session/:id` | Supprimer une session et toutes ses données | Renvoie `boolean` | +| `PATCH` | `/session/:id` | Mettre à jour les propriétés de la session | corps : `{ title? }`, renvoie Session | +| `GET` | `/session/:id/children` | Obtenir les sessions enfants d'une session | Renvoie Session[] | +| `GET` | `/session/:id/todo` | Obtenez la liste de tâches pour une session | Renvoie Todo[] | +| `POST` | `/session/:id/init` | Analysez l'application et créez `AGENTS.md` | corps : `{ messageID, providerID, modelID }`, renvoie `boolean` | +| `POST` | `/session/:id/fork` | Forkez une session existante à un message | corps : `{ messageID? }`, renvoie Session | +| `POST` | `/session/:id/abort` | Abandonner une session en cours | Renvoie `boolean` | +| `POST` | `/session/:id/share` | Partager une séance | Renvoie Session | +| `DELETE` | `/session/:id/share` | Annuler le partage d'une session | Renvoie Session | +| `GET` | `/session/:id/diff` | Obtenez le diff pour cette session | requête : `messageID?`, renvoie FileDiff[] | +| `POST` | `/session/:id/summarize` | Résumer la séance | corps : `{ providerID, modelID }`, renvoie `boolean` | +| `POST` | `/session/:id/revert` | Rétablir un message | corps : `{ messageID, partID? }`, renvoie `boolean` | +| `POST` | `/session/:id/unrevert` | Restaurer tous les messages annulés | Renvoie `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | Répondre à une demande d'autorisation | corps : `{ response, remember? }`, renvoie `boolean` | + +--- + +### Messages + +| Méthode | Chemin | Descriptif | Remarques | +| ------- | --------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `GET` | `/session/:id/message` | Liste des messages dans une session | requête : `limit?`, renvoie `{ info: `Message`, parts: `Part[]`}[]` | +| `POST` | `/session/:id/message` | Envoyer un message et attendre une réponse | corps : `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, renvoie `{ info: `Message`, parts: `Part[]`}` | +| `GET` | `/session/:id/message/:messageID` | Obtenir les détails du message | Renvoie `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/prompt_async` | Envoyer un message de manière asynchrone (pas d'attente) | body : identique à `/session/:id/message`, renvoie `204 No Content` | +| `POST` | `/session/:id/command` | Exécuter une commande slash | corps : `{ messageID?, agent?, model?, command, arguments }`, renvoie `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/shell` | Exécuter une commande shell | corps : `{ agent, model?, command }`, renvoie `{ info: `Message`, parts: `Part[]`}` | + +--- + +### Commandes + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | ---------- | -------------------------- | --------------------------------------------- | +| `GET` | `/command` | Liste toutes les commandes | Command[] | + +--- + +### Fichiers + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | ------------------------ | -------------------------------------------------- | --------------------------------------------------------------------------------------------------- | +| `GET` | `/find?pattern=` | Rechercher du texte dans des fichiers | Tableau d'objets correspondant avec `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `GET` | `/find/file?query=` | Rechercher des fichiers et des répertoires par nom | `string[]` (chemins) | +| `GET` | `/find/symbol?query=` | Rechercher des symboles d'espace de travail | Symbol[] | +| `GET` | `/file?path=` | Liste des fichiers et répertoires | FileNode[] | +| `GET` | `/file/content?path=

` | Lire un fichier | FileContent | +| `GET` | `/file/status` | Obtenir le statut des fichiers suivis | File[] | + +#### Paramètres de requête `/find/file` + +- `query` (obligatoire) — chaîne de recherche (correspondance floue) +- `type` (facultatif) — limiter les résultats à `"file"` ou `"directory"` +- `directory` (facultatif) — remplace la racine du projet pour la recherche +- `limit` (facultatif) — résultats maximum (1 à 200) +- `dirs` (facultatif) — indicateur hérité (`"false"` renvoie uniquement les fichiers) + +--- + +### Outils (expérimentaux) + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | ------------------------------------------- | ----------------------------------------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | Répertorier tous les ID d'outils | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | Répertorier les outils avec des schémas JSON pour un modèle | ToolList | + +--- + +### LSP, formateurs et MCP + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | ------------ | ------------------------------------ | -------------------------------------------------------- | +| `GET` | `/lsp` | Obtenir l'état du serveur LSP | LSPStatus[] | +| `GET` | `/formatter` | Obtenir le statut du formateur | FormatterStatus[] | +| `GET` | `/mcp` | Obtenir l'état du serveur MCP | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | Ajouter dynamiquement le serveur MCP | corps : `{ name, config }`, renvoie l'objet d'état MCP | + +--- + +### Agents + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | -------- | --------------------------------- | ------------------------------------------- | +| `GET` | `/agent` | Liste tous les agents disponibles | Agent[] | + +--- + +### Enregistrement + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | ------ | --------------------------------------------------------------------------- | --------- | +| `POST` | `/log` | Écrire une entrée de journal. Corps : `{ service, level, message, extra? }` | `boolean` | + +--- + +### TUI + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | ----------------------- | -------------------------------------------------- | ---------------------------- | +| `POST` | `/tui/append-prompt` | Ajouter du texte à l'invite | `boolean` | +| `POST` | `/tui/open-help` | Ouvrir la boîte de dialogue d'aide | `boolean` | +| `POST` | `/tui/open-sessions` | Ouvrez le sélecteur de session | `boolean` | +| `POST` | `/tui/open-themes` | Ouvrez le sélecteur de thème | `boolean` | +| `POST` | `/tui/open-models` | Ouvrez le sélecteur de modèle | `boolean` | +| `POST` | `/tui/submit-prompt` | Soumettre l'invite actuelle | `boolean` | +| `POST` | `/tui/clear-prompt` | Effacez l'invite | `boolean` | +| `POST` | `/tui/execute-command` | Exécuter une commande (`{ command }`) | `boolean` | +| `POST` | `/tui/show-toast` | Afficher le toast (`{ title?, message, variant }`) | `boolean` | +| `GET` | `/tui/control/next` | Attendre la prochaine demande de contrôle | Objet de demande de contrôle | +| `POST` | `/tui/control/response` | Répondre à une demande de contrôle (`{ body }`) | `boolean` | + +--- + +### Authentification + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | ----------- | --------------------------------------------------------------------------------------------------- | --------- | +| `PUT` | `/auth/:id` | Définissez les informations d'authentification. Le corps doit correspondre au schéma du fournisseur | `boolean` | + +--- + +### Événements + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | -------- | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | +| `GET` | `/event` | Flux d’événements envoyés par le serveur. Le premier événement est `server.connected`, puis les événements de bus | Flux d'événements envoyés par le serveur | + +--- + +### Documents + +| Méthode | Chemin | Descriptif | Réponse | +| ------- | ------ | ------------------------- | ------------------------------------ | +| `GET` | `/doc` | Spécification OpenAPI 3.1 | Page HTML avec spécification OpenAPI | diff --git a/packages/web/src/content/docs/fr/share.mdx b/packages/web/src/content/docs/fr/share.mdx new file mode 100644 index 00000000000..acc7c03f83e --- /dev/null +++ b/packages/web/src/content/docs/fr/share.mdx @@ -0,0 +1,128 @@ +--- +title: Partager +description: Partagez vos conversations OpenCode. +--- + +La fonctionnalité de partage de OpenCode vous permet de créer des liens publics vers vos conversations OpenCode, afin que vous puissiez collaborer avec vos coéquipiers ou obtenir de l'aide d'autres personnes. + +:::note +Les conversations partagées sont accessibles publiquement à toute personne disposant du lien. +::: + +--- + +## Comment ça marche + +Lorsque vous partagez une conversation, OpenCode : + +1. Crée un URL public unique pour votre session +2. Synchronise l'historique de vos conversations avec nos serveurs +3. Rend la conversation accessible via le lien partageable — `opncd.ai/s/` + +--- + +## Partage + +OpenCode prend en charge trois modes de partage qui contrôlent la manière dont les conversations sont partagées : + +--- + +### Manuel (par défaut) + +Par défaut, OpenCode utilise le mode de partage manuel. Les sessions ne sont pas partagées automatiquement, mais vous pouvez les partager manuellement à l'aide de la commande `/share` : + +``` +/share +``` + +Cela générera un URL unique qui sera copié dans votre presse-papiers. + +Pour définir explicitement le mode manuel dans votre [fichier de configuration](/docs/config) : + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### Partage automatique + +Vous pouvez activer le partage automatique pour toutes les nouvelles conversations en définissant l'option `share` sur `"auto"` dans votre [fichier de configuration](/docs/config) : + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +Avec le partage automatique activé, chaque nouvelle conversation sera automatiquement partagée et un lien sera généré. + +--- + +### Désactivé + +Vous pouvez désactiver entièrement le partage en définissant l'option `share` sur `"disabled"` dans votre [fichier de configuration](/docs/config) : + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +Pour appliquer cela au sein de votre équipe pour un projet donné, ajoutez-le au `opencode.json` dans votre projet et enregistrez-vous dans Git. + +--- + +## Annuler le partage + +Pour arrêter de partager une conversation et la supprimer de l'accès public : + +``` +/unshare +``` + +Cela supprimera le lien de partage et supprimera les données liées à la conversation. + +--- + +## Confidentialité + +Il y a quelques points à garder à l’esprit lorsque vous partagez une conversation. + +--- + +### Conservation des données + +Les conversations partagées restent accessibles jusqu'à ce que vous les annuliez explicitement. Ce +comprend : + +- Historique complet des conversations +- Tous les messages et réponses +- Métadonnées de session + +--- + +### Recommandations + +- Partagez uniquement les conversations qui ne contiennent pas d'informations sensibles. +- Examinez le contenu de la conversation avant de la partager. +- Annulez le partage des conversations une fois la collaboration terminée. +- Évitez de partager des conversations avec du code propriétaire ou des données confidentielles. +- Pour les projets sensibles, désactivez complètement le partage. + +--- + +## Pour les entreprises + +Pour les déploiements en entreprise, la fonctionnalité de partage peut être : + +- **Désactivé** entièrement pour des raisons de conformité en matière de sécurité +- **Réservé** aux utilisateurs authentifiés via SSO uniquement +- **Auto-hébergé** sur votre propre infrastructure + +[En savoir plus](/docs/enterprise) sur l'utilisation de opencode dans votre organisation. diff --git a/packages/web/src/content/docs/fr/skills.mdx b/packages/web/src/content/docs/fr/skills.mdx new file mode 100644 index 00000000000..05f109d1721 --- /dev/null +++ b/packages/web/src/content/docs/fr/skills.mdx @@ -0,0 +1,222 @@ +--- +title: "Compétences des agents" +description: "Définir un comportement réutilisable via les définitions SKILL.md" +--- + +Les compétences d'agent permettent à OpenCode de découvrir des instructions réutilisables à partir de votre dépôt ou de votre répertoire personnel. +Les compétences sont chargées à la demande via l'outil natif `skill` : les agents voient les compétences disponibles et peuvent charger le contenu complet en cas de besoin. + +--- + +## Placer des fichiers + +Créez un dossier par nom de compétence et insérez-y un `SKILL.md`. +OpenCode recherche ces emplacements : + +- Configuration du projet : `.opencode/skills//SKILL.md` +- Configuration globale : `~/.config/opencode/skills//SKILL.md` +- Compatible Projet Claude : `.claude/skills//SKILL.md` +- Compatible Global Claude : `~/.claude/skills//SKILL.md` +- Compatible avec l'agent de projet : `.agents/skills//SKILL.md` +- Compatible avec les agents globaux : `~/.agents/skills//SKILL.md` + +--- + +## Comprendre la découverte + +Pour les chemins locaux du projet, OpenCode remonte de votre répertoire de travail actuel jusqu'à ce qu'il atteigne l'arbre de travail git. +Il charge tout `skills/*/SKILL.md` correspondant dans `.opencode/` et tout `.claude/skills/*/SKILL.md` ou `.agents/skills/*/SKILL.md` correspondant en cours de route. + +Les définitions globales sont également chargées à partir de `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md` et `~/.agents/skills/*/SKILL.md`. + +--- + +## Écrire un texte de présentation + +Chaque `SKILL.md` doit commencer par YAML frontmatter. +Seuls ces champs sont reconnus : + +- `name` (obligatoire) +- `description` (obligatoire) +- `license` (facultatif) +- `compatibility` (facultatif) +- `metadata` (facultatif, mappage chaîne à chaîne) + +Les champs de contenu inconnus sont ignorés. + +--- + +## Valider les noms + +`name` doit : + +- Comprenant entre 1 et 64 caractères +- Être alphanumérique en minuscules avec des séparateurs à tiret unique +- Ne commence ni ne termine par `-` +- Ne contient pas de `--` consécutifs +- Faites correspondre le nom du répertoire qui contient `SKILL.md` + +Expression régulière équivalente : + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## Suivez les règles de longueur + +`description` doit comporter entre 1 et 1 024 caractères. +Gardez-le suffisamment précis pour que l'agent puisse choisir correctement. + +--- + +## Utiliser un exemple + +Créez `.opencode/skills/git-release/SKILL.md` comme ceci : + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## Reconnaître la description de l'outil + +OpenCode répertorie les compétences disponibles dans la description de l'outil `skill`. +Chaque entrée comprend le nom et la description de la compétence : + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +L'agent charge une compétence en appelant l'outil : + +``` +skill({ name: "git-release" }) +``` + +--- + +## Configurer les autorisations + +Contrôlez les compétences auxquelles les agents peuvent accéder à l'aide d'autorisations basées sur des modèles dans `opencode.json` : + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| Autorisation | Comportement | +| ------------ | --------------------------------------------------------------------- | +| `allow` | Les compétences se chargent immédiatement | +| `deny` | Compétence masquée à l'agent, accès refusé | +| `ask` | L'utilisateur est invité à donner son approbation avant le chargement | + +Les modèles prennent en charge les caractères génériques : `internal-*` correspond à `internal-docs`, `internal-tools`, etc. + +--- + +## Remplacement par agent + +Accordez à des agents spécifiques des autorisations différentes de celles par défaut globales. + +**Pour les agents personnalisés** (dans la rubrique Agent) : + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**Pour les agents intégrés** (dans `opencode.json`) : + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## Désactiver l'outil de compétences + +Désactivez complètement les compétences pour les agents qui ne devraient pas les utiliser : + +**Pour les agents personnalisés** : + +```yaml +--- +tools: + skill: false +--- +``` + +**Pour les agents intégrés** : + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +Lorsqu'elle est désactivée, la section `` est entièrement omise. + +--- + +## Dépanner le chargement + +Si une compétence n'apparaît pas : + +1. Vérifiez que `SKILL.md` est écrit en majuscules +2. Vérifiez que le frontmatter inclut `name` et `description` +3. Assurez-vous que les noms des compétences sont uniques sur tous les sites +4. Vérifiez les autorisations : les compétences avec `deny` sont masquées aux agents diff --git a/packages/web/src/content/docs/fr/themes.mdx b/packages/web/src/content/docs/fr/themes.mdx new file mode 100644 index 00000000000..d17f2169c71 --- /dev/null +++ b/packages/web/src/content/docs/fr/themes.mdx @@ -0,0 +1,369 @@ +--- +title: Thèmes +description: Sélectionnez un thème intégré ou définissez le vôtre. +--- + +Avec OpenCode, vous pouvez choisir parmi plusieurs thèmes intégrés, utiliser un thème qui s'adapte au thème de votre terminal ou définir votre propre thème personnalisé. + +Par défaut, OpenCode utilise notre propre thème `opencode`. + +--- + +## Exigences des terminaux + +Pour que les thèmes s'affichent correctement avec leur palette de couleurs complète, votre terminal doit prendre en charge **truecolor** (couleur 24 bits). La plupart des terminaux modernes le prennent en charge par défaut, mais vous devrez peut-être l'activer : + +- **Vérifiez le support** : Exécutez `echo $COLORTERM` - il devrait afficher `truecolor` ou `24bit` +- **Activer truecolor** : définissez la variable d'environnement `COLORTERM=truecolor` dans votre profil shell +- **Compatibilité des terminaux** : assurez-vous que votre émulateur de terminal prend en charge les couleurs 24 bits (la plupart des terminaux modernes comme iTerm2, Alacritty, Kitty, Windows Terminal et les versions récentes de GNOME Terminal le font) + +Sans la prise en charge de TrueColor, les thèmes peuvent apparaître avec une précision des couleurs réduite ou revenir à l'approximation de 256 couleurs la plus proche. + +--- + +## Thèmes intégrés + +OpenCode est livré avec plusieurs thèmes intégrés. + +| Nom | Descriptif | +| ---------------------- | --------------------------------------------------------------------------- | +| `system` | S'adapte à la couleur de fond de votre terminal | +| `tokyonight` | Basé sur le thème [Tokyonight](https://github.com/folke/tokyonight.nvim) | +| `everforest` | Basé sur le thème [Everforest](https://github.com/sainnhe/everforest) | +| `ayu` | Basé sur le thème sombre [Ayu](https://github.com/ayu-theme) | +| `catppuccin` | Basé sur le thème [Catppuccin](https://github.com/catppuccin) | +| `catppuccin-macchiato` | Basé sur le thème [Catppuccin](https://github.com/catppuccin) | +| `gruvbox` | Basé sur le thème [Gruvbox](https://github.com/morhetz/gruvbox) | +| `kanagawa` | Basé sur le thème [Kanagawa](https://github.com/rebelot/kanagawa.nvim) | +| `nord` | Basé sur le thème [Nord](https://github.com/nordtheme/nord) | +| `matrix` | Vert style hacker sur thème noir | +| `one-dark` | Basé sur le thème [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark | + +De plus, nous ajoutons constamment de nouveaux thèmes. + +--- + +## Thème système + +Le thème `system` est conçu pour s'adapter automatiquement à la palette de couleurs de votre terminal. Contrairement aux thèmes traditionnels qui utilisent des couleurs fixes, le thème *system* : + +- **Génère une échelle de gris** : crée une échelle de gris personnalisée basée sur la couleur d'arrière-plan de votre terminal, garantissant un contraste optimal. +- **Utilise les couleurs ANSI** : exploite les couleurs ANSI standard (0-15) pour la coloration syntaxique et les éléments de l'interface utilisateur, qui respectent la palette de couleurs de votre terminal. +- **Préserve les paramètres par défaut du terminal** : utilise `none` pour les couleurs du texte et de l'arrière-plan afin de conserver l'apparence native de votre terminal. + +Le thème système est destiné aux utilisateurs qui : + +- Vous souhaitez que OpenCode corresponde à l'apparence de leur terminal +- Utiliser des schémas de couleurs de terminal personnalisés +- Préférez une apparence cohérente sur toutes les applications de terminal + +--- + +## 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). + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## Thèmes personnalisés + +OpenCode prend en charge un système de thèmes flexible basé sur JSON qui permet aux utilisateurs de créer et de personnaliser facilement des thèmes. + +--- + +### Hiérarchie + +Les thèmes sont chargés à partir de plusieurs répertoires dans l'ordre suivant, les répertoires ultérieurs remplaçant les précédents : + +1. **Thèmes intégrés** - Ceux-ci sont intégrés au binaire +2. **Répertoire de configuration utilisateur** - Défini dans `~/.config/opencode/themes/*.json` ou `$XDG_CONFIG_HOME/opencode/themes/*.json` +3. **Répertoire racine du projet** - Défini dans `/.opencode/themes/*.json` +4. **Répertoire de travail actuel** - Défini dans `./.opencode/themes/*.json` + +Si plusieurs répertoires contiennent un thème portant le même nom, le thème du répertoire ayant la priorité la plus élevée sera utilisé. + +--- + +### Création d'un thème + +Pour créer un thème personnalisé, créez un fichier JSON dans l'un des répertoires de thème. + +Pour les thèmes à l’échelle de l’utilisateur : + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +Et pour des thèmes spécifiques au projet. + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### Format JSON + +Les thèmes utilisent un format JSON flexible avec prise en charge de : + +- **Couleurs hexadécimales** : `"#ffffff"` +- **Couleurs ANSI** : `3` (0-255) +- **Références de couleurs** : `"primary"` ou définitions personnalisées +- **Variantes sombre/clair** : `{"dark": "#000", "light": "#fff"}` +- **Aucune couleur** : `"none"` - Utilise la couleur par défaut du terminal ou le transparent + +--- + +### Définitions des couleurs + +La section `defs` est facultative et elle permet de définir des couleurs réutilisables pouvant être référencées dans le thème. + +--- + +### Paramètres par défaut du terminal + +La valeur spéciale `"none"` peut être utilisée pour n'importe quelle couleur afin d'hériter de la couleur par défaut du terminal. Ceci est particulièrement utile pour créer des thèmes qui se fondent parfaitement dans la palette de couleurs de votre terminal : + +- `"text": "none"` - Utilise la couleur de premier plan par défaut du terminal +- `"background": "none"` - Utilise la couleur d'arrière-plan par défaut du terminal + +--- + +### Exemple + +Voici un exemple de thème personnalisé : + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/fr/tools.mdx b/packages/web/src/content/docs/fr/tools.mdx new file mode 100644 index 00000000000..20045e147c7 --- /dev/null +++ b/packages/web/src/content/docs/fr/tools.mdx @@ -0,0 +1,379 @@ +--- +title: Outils +description: Gérez les outils qu'un LLM peut utiliser. +--- + +Les outils permettent au LLM d'effectuer des actions dans votre base de code. OpenCode est livré avec un ensemble d'outils intégrés, mais vous pouvez l'étendre avec [outils personnalisés](/docs/custom-tools) ou [serveurs MCP](/docs/mcp-servers). + +Par défaut, tous les outils sont **activés** et n'ont pas besoin d'autorisation pour s'exécuter. Vous pouvez contrôler le comportement de l'outil via [permissions](/docs/permissions). + +--- + +## Configurer + +Utilisez le champ `permission` pour contrôler le comportement de l'outil. Vous pouvez autoriser, refuser ou exiger une approbation pour chaque outil. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +Vous pouvez également utiliser des caractères génériques pour contrôler plusieurs outils à la fois. Par exemple, pour exiger l'approbation de tous les outils d'un serveur MCP : + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[En savoir plus](/docs/permissions) sur la configuration des autorisations. + +--- + +## Intégré + +Voici tous les outils intégrés disponibles dans OpenCode. + +--- + +### frapper + +Exécutez des commandes shell dans votre environnement de projet. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +Cet outil permet au LLM d'exécuter des commandes de terminal telles que `npm install`, `git status` ou toute autre commande shell. + +--- + +### modifier + +Modifiez les fichiers existants en utilisant des remplacements de chaînes exacts. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Cet outil effectue des modifications précises des fichiers en remplaçant les correspondances de texte exactes. C'est la principale façon dont LLM modifie le code. + +--- + +### écrire + +Créez de nouveaux fichiers ou écrasez ceux existants. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Utilisez-le pour permettre au LLM de créer de nouveaux fichiers. Il écrasera les fichiers existants s'ils existent déjà. + +:::note +L'outil `write` est contrôlé par l'autorisation `edit`, qui couvre toutes les modifications de fichiers (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### lire + +Lisez le contenu du fichier à partir de votre base de code. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +Cet outil lit les fichiers et renvoie leur contenu. Il prend en charge la lecture de plages de lignes spécifiques pour les fichiers volumineux. + +--- + +### grep + +Recherchez le contenu du fichier à l’aide d’expressions régulières. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +Recherche rapide de contenu dans votre base de code. Prend en charge la syntaxe regex complète et le filtrage des modèles de fichiers. + +--- + +### globe + +Recherchez des fichiers par correspondance de modèles. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +Recherchez des fichiers à l'aide de modèles globaux tels que `**/*.js` ou `src/**/*.ts`. Renvoie les chemins de fichiers correspondants triés par heure de modification. + +--- + +### liste + +Répertoriez les fichiers et les répertoires dans un chemin donné. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +Cet outil répertorie le contenu du répertoire. Il accepte les modèles globaux pour filtrer les résultats. + +--- + +### lsp (expérimental) + +Interagissez avec vos serveurs LSP configurés pour obtenir des fonctionnalités d'intelligence du code telles que des définitions, des références, des informations de survol et une hiérarchie d'appels. + +:::note +Cet outil n'est disponible que lorsque `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (ou `OPENCODE_EXPERIMENTAL=true`). +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +Les opérations prises en charge incluent `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls` et `outgoingCalls`. + +Pour configurer les serveurs LSP disponibles pour votre projet, consultez [LSP Servers](/docs/lsp). + +--- + +### correctif + +Appliquez des correctifs aux fichiers. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Cet outil applique les fichiers de correctifs à votre base de code. Utile pour appliquer des différences et des correctifs provenant de diverses sources. + +:::note +L'outil `patch` est contrôlé par l'autorisation `edit`, qui couvre toutes les modifications de fichiers (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### compétence + +Chargez une [skill](/docs/skills) (un fichier `SKILL.md`) et renvoyez son contenu dans la conversation. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### à écrire + +Gérez les listes de tâches pendant les sessions de codage. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +Crée et met à jour des listes de tâches pour suivre la progression lors d'opérations complexes. Le LLM l'utilise pour organiser des tâches en plusieurs étapes. + +:::note +Cet outil est désactivé par défaut pour les sous-agents, mais vous pouvez l'activer manuellement. [En savoir plus](/docs/agents/#permissions) +::: + +--- + +### todore + +Lisez les listes de tâches existantes. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +Lit l'état actuel de la liste de tâches. Utilisé par le LLM pour suivre les tâches en attente ou terminées. + +:::note +Cet outil est désactivé par défaut pour les sous-agents, mais vous pouvez l'activer manuellement. [En savoir plus](/docs/agents/#permissions) +::: + +--- + +### récupération sur le Web + +Récupérer du contenu Web. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +Permet au LLM de récupérer et de lire des pages Web. Utile pour rechercher de la documentation ou rechercher des ressources en ligne. + +--- + +### recherche sur le Web + +Recherchez des informations sur le Web. + +:::note +Cet outil n'est disponible que lors de l'utilisation du fournisseur OpenCode ou lorsque la variable d'environnement `OPENCODE_ENABLE_EXA` est définie sur une valeur véridique (par exemple, `true` ou `1`). + +À activer lors du lancement de OpenCode : + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +Effectue des recherches sur le Web à l'aide d'Exa AI pour trouver des informations pertinentes en ligne. Utile pour rechercher des sujets, trouver des événements actuels ou collecter des informations au-delà de la limite des données de formation. + +Aucune clé API n'est requise : l'outil se connecte directement au service MCP hébergé d'Exa AI sans authentification. + +:::tip +Utilisez `websearch` lorsque vous avez besoin de rechercher des informations (découverte) et `webfetch` lorsque vous devez récupérer le contenu d'un URL spécifique (récupération). +::: + +--- + +### question + +Posez des questions à l'utilisateur pendant l'exécution. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +Cet outil permet au LLM de poser des questions à l'utilisateur lors d'une tâche. C'est utile pour : + +- Recueillir les préférences ou les exigences des utilisateurs +- Clarifier les instructions ambiguës +- Obtenir des décisions sur les choix de mise en œuvre +- Offrir des choix sur la direction à prendre + +Chaque question comprend un en-tête, le texte de la question et une liste d'options. Les utilisateurs peuvent choisir parmi les options proposées ou saisir une réponse personnalisée. Lorsqu'il y a plusieurs questions, les utilisateurs peuvent naviguer entre elles avant de soumettre toutes les réponses. + +--- + +## Outils personnalisés + +Les outils personnalisés vous permettent de définir vos propres fonctions que le LLM peut appeler. Ceux-ci sont définis dans votre fichier de configuration et peuvent exécuter du code arbitraire. + +[En savoir plus](/docs/custom-tools) sur la création d'outils personnalisés. + +--- + +## Serveurs MCP + +Les serveurs MCP (Model Context Protocol) vous permettent d'intégrer des outils et services externes. Cela inclut l'accès à la base de données, les intégrations API et les services tiers. + +[En savoir plus](/docs/mcp-servers) sur la configuration des serveurs MCP. + +--- + +## Internes + +En interne, des outils comme `grep`, `glob` et `list` utilisent [ripgrep](https://github.com/BurntSushi/ripgrep) sous le capot. Par défaut, ripgrep respecte les modèles `.gitignore`, ce qui signifie que les fichiers et répertoires répertoriés dans votre `.gitignore` seront exclus des recherches et des listes. + +--- + +### Ignorer les modèles + +Pour inclure des fichiers qui seraient normalement ignorés, créez un fichier `.ignore` à la racine de votre projet. Ce fichier peut autoriser explicitement certains chemins. + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +Par exemple, ce fichier `.ignore` permet à ripgrep de rechercher dans les répertoires `node_modules/`, `dist/` et `build/` même s'ils sont répertoriés dans `.gitignore`. diff --git a/packages/web/src/content/docs/fr/troubleshooting.mdx b/packages/web/src/content/docs/fr/troubleshooting.mdx new file mode 100644 index 00000000000..b33e476e2e4 --- /dev/null +++ b/packages/web/src/content/docs/fr/troubleshooting.mdx @@ -0,0 +1,300 @@ +--- +title: Dépannage +description: Problèmes courants et comment les résoudre. +--- + +Pour déboguer les problèmes avec OpenCode, commencez par vérifier les journaux et les données locales qu'il stocke sur le disque. + +--- + +## Journaux + +Les fichiers journaux sont écrits dans : + +- **macOS/Linux** : `~/.local/share/opencode/log/` +- **Windows** : appuyez sur `WIN+R` et collez `%USERPROFILE%\.local\share\opencode\log` + +Les fichiers journaux sont nommés avec des horodatages (par exemple, `2025-01-09T123456.log`) et les 10 fichiers journaux les plus récents sont conservés. + +Vous pouvez définir le niveau de journalisation avec l'option de ligne de commande `--log-level` pour obtenir des informations de débogage plus détaillées. Par exemple, `opencode --log-level DEBUG`. + +--- + +## Stockage + +opencode stocke les données de session et autres données d'application sur le disque à l'emplacement : + +- **macOS/Linux** : `~/.local/share/opencode/` +- **Windows** : appuyez sur `WIN+R` et collez `%USERPROFILE%\.local\share\opencode` + +Ce répertoire contient : + +- `auth.json` - Données d'authentification telles que les clés API, les jetons OAuth +- `log/` - Journaux d'applications +- `project/` - Données spécifiques au projet telles que les données de session et de message + - Si le projet se trouve dans un dépôt Git, il est stocké dans `.//storage/` + - S'il ne s'agit pas d'un dépôt Git, il est stocké dans `./global/storage/` + +--- + +## Application de bureau + +OpenCode Desktop exécute un serveur OpenCode local (le side-car `opencode-cli`) en arrière-plan. La plupart des problèmes sont causés par un plugin qui se comporte mal, un cache corrompu ou un mauvais paramètre du serveur. + +### Vérifications rapides + +- Quittez complètement et relancez l'application. +- Si l'application affiche un écran d'erreur, cliquez sur **Redémarrer** et copiez les détails de l'erreur. +- macOS uniquement : menu `OpenCode` -> **Recharger la vue Web** (aide si l'interface utilisateur est vide/gelée). + +--- + +### Désactiver les plugins + +Si l'application de bureau plante au lancement, se bloque ou se comporte étrangement, commencez par désactiver les plugins. + +#### Vérifiez la configuration globale + +Ouvrez votre fichier de configuration global et recherchez une clé `plugin`. + +- **macOS/Linux** : `~/.config/opencode/opencode.jsonc` (ou `~/.config/opencode/opencode.json`) +- **macOS/Linux** (anciennes installations) : `~/.local/share/opencode/opencode.jsonc` +- **Windows** : appuyez sur `WIN+R` et collez `%USERPROFILE%\.config\opencode\opencode.jsonc` + +Si vous avez configuré des plugins, désactivez-les temporairement en supprimant la clé ou en la définissant sur un tableau vide : + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### Vérifiez les répertoires des plugins + +OpenCode peut également charger des plugins locaux à partir du disque. Écartez-les temporairement (ou renommez le dossier) et redémarrez l'application de bureau : + +- **Plugins mondiaux** + - **macOS/Linux** : `~/.config/opencode/plugins/` + - **Windows** : appuyez sur `WIN+R` et collez `%USERPROFILE%\.config\opencode\plugins` +- **Plugins de projet** (uniquement si vous utilisez une configuration par projet) + - `/.opencode/plugins/` + +Si l'application recommence à fonctionner, réactivez les plugins un par un pour trouver celui à l'origine du problème. + +--- + +### Vider le cache + +Si la désactivation des plugins ne résout pas le problème (ou si l'installation d'un plugin est bloquée), videz le cache afin que OpenCode puisse le reconstruire. + +1. Quittez complètement OpenCode Desktop. +2. Supprimez le répertoire cache : + +- **macOS** : Finder -> `Cmd+Shift+G` -> coller `~/.cache/opencode` +- **Linux** : supprimez `~/.cache/opencode` (ou exécutez `rm -rf ~/.cache/opencode`) +- **Windows** : appuyez sur `WIN+R` et collez `%USERPROFILE%\.cache\opencode` + +3. Redémarrez le bureau OpenCode. + +--- + +### Résoudre les problèmes de connexion au serveur + +OpenCode Desktop peut soit démarrer son propre serveur local (par défaut), soit se connecter à un serveur URL que vous avez configuré. + +Si vous voyez une boîte de dialogue **« Échec de la connexion »** (ou si l'application ne dépasse jamais l'écran de démarrage), recherchez un serveur personnalisé URL. + +#### Effacer le serveur par défaut du bureau URL + +Depuis l'écran d'accueil, cliquez sur le nom du serveur (avec le point d'état) pour ouvrir le sélecteur de serveur. Dans la section **Serveur par défaut**, cliquez sur **Effacer**. + +#### Supprimez `server.port` / `server.hostname` de votre configuration + +Si votre `opencode.json(c)` contient une section `server`, supprimez-la temporairement et redémarrez l'application de bureau. + +#### Vérifier les variables d'environnement + +Si `OPENCODE_PORT` est défini dans votre environnement, l'application de bureau tentera d'utiliser ce port pour le serveur local. + +- Désactivez `OPENCODE_PORT` (ou choisissez un port libre) et redémarrez. + +--- + +### Linux : Problèmes Wayland / X11 + +Sur Linux, certaines configurations Wayland peuvent provoquer des fenêtres vides ou des erreurs de composition. + +- Si vous êtes sur Wayland et que l'application est vide/plante, essayez de la lancer avec `OC_ALLOW_WAYLAND=1`. +- Si cela aggrave les choses, supprimez-le et essayez plutôt de le lancer sous une session X11. + +--- + +### Windows : exécution WebView2 + +Sur Windows, OpenCode Desktop nécessite Microsoft Edge **WebView2 Runtime**. Si l'application s'ouvre sur une fenêtre vide ou ne démarre pas, installez/mettez à jour WebView2 et réessayez. + +--- + +### Windows : problèmes de performances généraux + +Si vous rencontrez des performances lentes, des problèmes d'accès aux fichiers ou des problèmes de terminal sur Windows, essayez d'utiliser [WSL (Windows Sous-système pour Linux)](/docs/windows-wsl). WSL fournit un environnement Linux qui fonctionne de manière plus transparente avec les fonctionnalités de OpenCode. + +--- + +### Les notifications ne s'affichent pas + +OpenCode Desktop affiche uniquement les notifications système lorsque : + +- les notifications sont activées pour OpenCode dans les paramètres de votre système d'exploitation, et +- la fenêtre de l'application n'est pas ciblée. + +--- + +### Réinitialiser le stockage des applications de bureau (dernier recours) + +Si l'application ne démarre pas et que vous ne pouvez pas effacer les paramètres depuis l'interface utilisateur, réinitialisez l'état enregistré de l'application de bureau. + +1. Quittez le bureau OpenCode. +2. Recherchez et supprimez ces fichiers (ils se trouvent dans le répertoire de données de l'application OpenCode Desktop) : + +- `opencode.settings.dat` (serveur de bureau par défaut URL) +- `opencode.global.dat` et `opencode.workspace.*.dat` (état de l'interface utilisateur comme les serveurs/projets récents) + +Pour trouver rapidement le répertoire : + +- **macOS** : Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (puis recherchez les noms de fichiers ci-dessus) +- **Linux** : recherchez sous `~/.local/share` les noms de fichiers ci-dessus +- **Windows** : appuyez sur `WIN+R` -> `%APPDATA%` (puis recherchez les noms de fichiers ci-dessus) + +--- + +## Obtenir de l'aide + +Si vous rencontrez des problèmes avec OpenCode : + +1. **Signaler les problèmes le GitHub** + +La meilleure façon de signaler des bogues ou de demander des fonctionnalités consiste à utiliser notre référentiel GitHub : + +[**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + +Avant de créer un nouveau problème, recherchez les problèmes existants pour voir si votre problème a déjà été signalé. + +2. **Rejoignez notre Discord** + +Pour obtenir de l'aide en temps réel et une discussion communautaire, rejoignez notre serveur Discord : + +[**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## Problèmes courants + +Voici quelques problèmes courants et comment les résoudre. + +--- + +### OpenCode ne démarre pas + +1. Vérifiez les journaux pour les messages d'erreur +2. Essayez d'exécuter avec `--print-logs` pour voir la sortie dans le terminal +3. Assurez-vous d'avoir la dernière version avec `opencode upgrade` + +--- + +### Problèmes d'authentification + +1. Essayez de vous réauthentifier avec la commande `/connect` dans le TUI +2. Vérifiez que vos clés API sont valides +3. Assurez-vous que votre réseau autorise les connexions au API du fournisseur. + +--- + +### Modèle non disponible + +1. Vérifiez que vous êtes authentifié auprès du fournisseur +2. Vérifiez que le nom du modèle dans votre configuration est correct +3. Certains modèles peuvent nécessiter un accès ou des abonnements spécifiques + +Si vous rencontrez `ProviderModelNotFoundError`, vous avez probablement tort +faire référence à un modèle quelque part. +Les modèles doivent être référencés comme suit : `/` + +Exemples : + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +Pour déterminer à quels modèles vous avez accès, exécutez `opencode models` + +--- + +### ErreurInit du fournisseur + +Si vous rencontrez une ProviderInitError, vous avez probablement une configuration non valide ou corrompue. + +Pour résoudre ce problème : + +1. Tout d'abord, vérifiez que votre fournisseur est correctement configuré en suivant le [guide du fournisseur](/docs/providers) +2. Si le problème persiste, essayez d'effacer votre configuration stockée : + + ```bash + rm -rf ~/.local/share/opencode + ``` + +Sur Windows, appuyez sur `WIN+R` et supprimez : `%USERPROFILE%\.local\share\opencode` + +3. Ré-authentifiez-vous auprès de votre fournisseur à l'aide de la commande `/connect` dans le TUI. + +--- + +### Problèmes liés à AI_APICallError et au package du fournisseur + +Si vous rencontrez des erreurs d’appel API, cela peut être dû à des packages de fournisseurs obsolètes. opencode installe dynamiquement les packages du fournisseur (OpenAI, Anthropic, Google, etc.) selon les besoins et les met en cache localement. + +Pour résoudre les problèmes liés au package du fournisseur : + +1. Videz le cache du package du fournisseur : + + ```bash + rm -rf ~/.cache/opencode + ``` + +Sur Windows, appuyez sur `WIN+R` et supprimez : `%USERPROFILE%\.cache\opencode` + +2. Redémarrez opencode pour réinstaller les derniers packages du fournisseur + +Cela forcera opencode à télécharger les versions les plus récentes des packages du fournisseur, ce qui résout souvent les problèmes de compatibilité avec les paramètres du modèle et les modifications de API. + +--- + +### Le copier/coller ne fonctionne pas sur Linux + +Les utilisateurs de Linux doivent disposer de l'un des utilitaires de presse-papiers suivants installés pour que la fonctionnalité copier/coller fonctionne : + +**Pour les systèmes X11 :** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**Pour les systèmes Wayland :** + +```bash +apt install -y wl-clipboard +``` + +**Pour les environnements sans tête :** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +opencode détectera si vous utilisez Wayland et préférez `wl-clipboard`, sinon il essaiera de trouver les outils du presse-papiers dans l'ordre : `xclip` et `xsel`. diff --git a/packages/web/src/content/docs/fr/tui.mdx b/packages/web/src/content/docs/fr/tui.mdx new file mode 100644 index 00000000000..f9078508dd5 --- /dev/null +++ b/packages/web/src/content/docs/fr/tui.mdx @@ -0,0 +1,390 @@ +--- +title: TUI +description: Utilisation de l’interface utilisateur du terminal OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode fournit une interface de terminal interactif ou TUI pour travailler sur vos projets avec un LLM. + +L’exécution de OpenCode démarre le TUI pour le répertoire actuel. + +```bash +opencode +``` + +Ou vous pouvez le démarrer pour un répertoire de travail spécifique. + +```bash +opencode /path/to/project +``` + +Une fois que vous êtes dans le TUI, vous pouvez lui envoyer un message. + +```text +Give me a quick summary of the codebase. +``` + +--- + +## Références de fichiers + +Vous pouvez référencer des fichiers dans vos messages en utilisant `@`. Cela effectue une recherche de fichier floue dans le répertoire de travail actuel. + +:::tip +Vous pouvez également utiliser `@` pour référencer des fichiers dans vos messages. +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +Le contenu du fichier est automatiquement ajouté à la conversation. + +--- + +## Commandes Bash + +Démarrez un message avec `!` pour exécuter une commande shell. + +```bash frame="none" +!ls -la +``` + +Le résultat de la commande est ajouté à la conversation en tant que résultat de l'outil. + +--- + +## Commandes + +Lorsque vous utilisez le OpenCode TUI, vous pouvez taper `/` suivi d'un nom de commande pour exécuter rapidement des actions. Par exemple: + +```bash frame="none" +/help +``` + +La plupart des commandes ont également une liaison clavier utilisant `ctrl+x` comme touche leader, où `ctrl+x` est la touche leader par défaut. [En savoir plus](/docs/keybinds). + +Voici toutes les commandes slash disponibles : + +--- + +### connect + +Ajoutez un fournisseur à OpenCode. Vous permet de sélectionner parmi les fournisseurs disponibles et d’ajouter leurs clés API. + +```bash frame="none" +/connect +``` + +--- + +### compact + +Compactez la session en cours. *Alias* : `/summarize` + +```bash frame="none" +/compact +``` + +**Reliure de touches :** `ctrl+x c` + +--- + +### details + +Basculer les détails d'exécution de l'outil. + +```bash frame="none" +/details +``` + +**Reliure de touches :** `ctrl+x d` + +--- + +### editor + +Ouvrez un éditeur externe pour rédiger des messages. Utilise l'éditeur défini dans votre variable d'environnement `EDITOR`. [En savoir plus](#editor-setup). + +```bash frame="none" +/editor +``` + +**Reliure de touches :** `ctrl+x e` + +--- + +### exit + +Quittez OpenCode. *Alias* : `/quit`, `/q` + +```bash frame="none" +/exit +``` + +**Reliure de touches :** `ctrl+x q` + +--- + +### export + +Exportez la conversation en cours vers Markdown et ouvrez-la dans votre éditeur par défaut. Utilise l'éditeur défini dans votre variable d'environnement `EDITOR`. [En savoir plus](#editor-setup). + +```bash frame="none" +/export +``` + +**Reliure de touches :** `ctrl+x x` + +--- + +### help + +Afficher la boîte de dialogue d'aide. + +```bash frame="none" +/help +``` + +**Reliure de touches :** `ctrl+x h` + +--- + +### init + +Créez ou mettez à jour le fichier `AGENTS.md`. [En savoir plus](/docs/rules). + +```bash frame="none" +/init +``` + +**Reliure de touches :** `ctrl+x i` + +--- + +### models + +Liste des modèles disponibles. + +```bash frame="none" +/models +``` + +**Reliure de touches :** `ctrl+x m` + +--- + +### new + +Démarrez une nouvelle session. *Alias* : `/clear` + +```bash frame="none" +/new +``` + +**Reliure de touches :** `ctrl+x n` + +--- + +### redo + +Refaire un message précédemment annulé. Disponible uniquement après avoir utilisé `/undo`. + +:::tip +Toutes les modifications de fichiers seront également restaurées. +::: + +En interne, cela utilise Git pour gérer les modifications de fichiers. Votre projet **doit donc +être un dépôt Git**. + +```bash frame="none" +/redo +``` + +**Reliure de touches :** `ctrl+x r` + +--- + +### sessions + +Répertoriez et basculez entre les sessions. *Alias* : `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +**Reliure de touches :** `ctrl+x l` + +--- + +### share + +Partager la session en cours. [En savoir plus](/docs/share). + +```bash frame="none" +/share +``` + +**Reliure de touches :** `ctrl+x s` + +--- + +### theme + +Répertoriez les thèmes disponibles. + +```bash frame="none" +/theme +``` + +**Reliure de touches :** `ctrl+x t` + +--- + +### thinking + +Activez/désactivez la visibilité des blocages de réflexion/raisonnement dans la conversation. Lorsque cette option est activée, vous pouvez voir le processus de raisonnement du modèle pour les modèles prenant en charge la réflexion étendue. + +:::note +Cette commande contrôle uniquement si les blocs de réflexion sont **affichés** ; elle n'active ni ne désactive les capacités de raisonnement du modèle. Pour basculer entre les capacités de raisonnement réelles, utilisez `ctrl+t` pour parcourir les variantes du modèle. +::: + +```bash frame="none" +/thinking +``` + +--- + +### undo + +Annuler le dernier message de la conversation. Supprime le message utilisateur le plus récent, toutes les réponses ultérieures et toutes les modifications de fichier. + +:::tip +Toutes les modifications apportées au fichier seront également annulées. +::: + +En interne, cela utilise Git pour gérer les modifications de fichiers. Votre projet **doit donc +être un dépôt Git**. + +```bash frame="none" +/undo +``` + +**Reliure de touches :** `ctrl+x u` + +--- + +### unshare + +Annuler le partage de la session en cours. [En savoir plus](/docs/share#un-sharing). + +```bash frame="none" +/unshare +``` + +--- + +## Configuration de l'éditeur + +Les commandes `/editor` et `/export` utilisent l'éditeur spécifié dans votre variable d'environnement `EDITOR`. + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + +Pour le rendre permanent, ajoutez-le à votre profil shell ; +`~/.bashrc`, `~/.zshrc`, etc. + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + +Pour le rendre permanent, utilisez **Propriétés système** > **Environnement +Variables**. + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + +Pour le rendre permanent, ajoutez-le à votre profil PowerShell. + + + + +Les options d'éditeur populaires incluent : + +- `code`-Code Visual Studio +- `cursor` - Curseur +- `windsurf` - Planche à voile +- `nvim` - Editeur Neovim +- `vim` - Éditeur Vim +- `nano` - Éditeur nano +- `notepad` - Windows Bloc-notes +- `subl` - Texte sublime + +:::note +Certains éditeurs comme VS Code doivent être démarrés avec le drapeau `--wait`. +::: + +Certains éditeurs ont besoin d'arguments de ligne de commande pour s'exécuter en mode blocage. L'indicateur `--wait` bloque le processus de l'éditeur jusqu'à sa fermeture. + +--- + +## Configurer + +Vous pouvez personnaliser le comportement de TUI via votre fichier de configuration OpenCode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### 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`.** + +--- + +## Personnalisation + +Vous pouvez personnaliser divers aspects de la vue TUI à l'aide de la palette de commandes (`ctrl+x h` ou `/help`). Ces paramètres persistent lors des redémarrages. + +--- + +#### Affichage du nom d'utilisateur + +Indiquez si votre nom d'utilisateur apparaît dans les messages de discussion. Accédez-y via : + +- Palette de commandes : recherchez "nom d'utilisateur" ou "masquer le nom d'utilisateur" +- Le paramètre persiste automatiquement et sera mémorisé au cours de TUI sessions. diff --git a/packages/web/src/content/docs/fr/web.mdx b/packages/web/src/content/docs/fr/web.mdx new file mode 100644 index 00000000000..c24a3095e96 --- /dev/null +++ b/packages/web/src/content/docs/fr/web.mdx @@ -0,0 +1,142 @@ +--- +title: Web +description: En utilisant OpenCode dans votre navigateur. +--- + +OpenCode peut s'exécuter comme une application Web dans votre navigateur, offrant la même expérience puissante de codage d'IA sans avoir besoin d'un terminal. + +![OpenCode Web - Nouvelle session](../../../assets/web/web-homepage-new-session.png) + +## Commencer + +Démarrez l'interface Web en exécutant : + +```bash +opencode web +``` + +Cela démarre un serveur local sur `127.0.0.1` avec un port disponible aléatoire et ouvre automatiquement OpenCode dans votre navigateur par défaut. + +:::caution +Si `OPENCODE_SERVER_PASSWORD` n'est pas défini, le serveur ne sera pas sécurisé. C'est bien pour une utilisation locale mais doit être défini pour l'accès au réseau. +::: + +:::tip[Windows Utilisateurs] +Pour une expérience optimale, exécutez `opencode web` à partir de [WSL](/docs/windows-wsl) plutôt que de PowerShell. Cela garantit un accès correct au système de fichiers et une intégration du terminal. +::: + +--- + +## Configuration + +Vous pouvez configurer le serveur Web à l'aide d'indicateurs de ligne de commande ou dans votre [fichier de configuration](/docs/config). + +### Port + +Par défaut, OpenCode sélectionne un port disponible. Vous pouvez spécifier un port : + +```bash +opencode web --port 4096 +``` + +### Nom d'hôte + +Par défaut, le serveur se lie à `127.0.0.1` (localhost uniquement). Pour rendre OpenCode accessible sur votre réseau : + +```bash +opencode web --hostname 0.0.0.0 +``` + +Lorsque vous utilisez `0.0.0.0`, OpenCode affichera les adresses locales et réseau : + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### Découverte mDNS + +Activez mDNS pour rendre votre serveur visible sur le réseau local : + +```bash +opencode web --mdns +``` + +Cela définit automatiquement le nom d'hôte sur `0.0.0.0` et annonce le serveur comme `opencode.local`. + +Vous pouvez personnaliser le nom de domaine mDNS pour exécuter plusieurs instances sur le même réseau : + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +Pour autoriser des domaines supplémentaires pour CORS (utile pour les frontends personnalisés) : + +```bash +opencode web --cors https://example.com +``` + +### Authentification + +Pour protéger l'accès, définissez un mot de passe à l'aide de la variable d'environnement `OPENCODE_SERVER_PASSWORD` : + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +Le nom d'utilisateur par défaut est `opencode` mais peut être modifié avec `OPENCODE_SERVER_USERNAME`. + +--- + +## Utilisation de l'interface Web + +Une fois démarrée, l'interface web permet d'accéder à vos sessions OpenCode. + +### Sessions + +Consultez et gérez vos sessions depuis la page d'accueil. Vous pouvez voir les sessions actives et en démarrer de nouvelles. + +![OpenCode Web - Session active](../../../assets/web/web-homepage-active-session.png) + +### Statut du serveur + +Cliquez sur "Voir les serveurs" pour afficher les serveurs connectés et leur état. + +![OpenCode Web - Voir Serveurs](../../../assets/web/web-homepage-see-servers.png) + +--- + +## Attacher un terminal + +Vous pouvez connecter un terminal TUI à un serveur Web en cours d'exécution : + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +Cela vous permet d'utiliser simultanément l'interface Web et le terminal, en partageant les mêmes sessions et le même état. + +--- + +## Fichier de configuration + +Vous pouvez également configurer les paramètres du serveur dans votre fichier de configuration `opencode.json` : + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +Les indicateurs de ligne de commande ont priorité sur les paramètres du fichier de configuration. diff --git a/packages/web/src/content/docs/fr/windows-wsl.mdx b/packages/web/src/content/docs/fr/windows-wsl.mdx new file mode 100644 index 00000000000..08563a16e42 --- /dev/null +++ b/packages/web/src/content/docs/fr/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: Exécutez OpenCode sur Windows avec WSL pour une expérience optimale. +--- + +import { Steps } from "@astrojs/starlight/components" + +Même si OpenCode peut fonctionner directement sur Windows, nous recommandons d'utiliser [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) pour la meilleure expérience. WSL fournit un environnement Linux qui s'intègre parfaitement aux fonctionnalités d'OpenCode. + +:::tip[Pourquoi WSL?] +WSL offre de meilleures performances du système de fichiers, une prise en charge complète du terminal et la compatibilité avec les outils de développement dont OpenCode dépend. +::: + +--- + +## Configuration + + + +1. **Installez WSL** + + Si ce n'est pas encore fait, [installez WSL](https://learn.microsoft.com/en-us/windows/wsl/install) à l'aide du guide officiel Microsoft. + +2. **Installez OpenCode dans WSL** + + Une fois WSL configuré, ouvrez votre terminal WSL et installez OpenCode avec l'une des [méthodes d'installation](/docs/). + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **Utilisez OpenCode depuis WSL** + + Allez dans votre dossier de projet (accédez aux fichiers Windows via `/mnt/c/`, `/mnt/d/`, etc.) et lancez OpenCode. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## Application bureau + serveur WSL + +Si vous préférez utiliser l'application Desktop OpenCode tout en exécutant le serveur dans WSL: + +1. **Démarrez le serveur dans WSL** avec `--hostname 0.0.0.0` pour autoriser les connexions externes: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **Connectez l'application Desktop** à `http://localhost:4096` + +:::note +Si `localhost` ne fonctionne pas dans votre configuration, utilisez plutôt l'adresse IP WSL (depuis WSL: `hostname -I`) et `http://:4096`. +::: + +:::caution +Lorsque vous utilisez `--hostname 0.0.0.0`, définissez `OPENCODE_SERVER_PASSWORD` pour sécuriser le serveur. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## Client web + WSL + +Pour la meilleure expérience web sous Windows: + +1. **Exécutez `opencode web` dans le terminal WSL** plutôt que dans PowerShell: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Accédez-y depuis votre navigateur Windows** à `http://localhost:` (OpenCode affiche l'URL) + +Lancer `opencode web` depuis WSL garantit un accès correct au système de fichiers et une bonne intégration terminal, tout en restant accessible depuis votre navigateur Windows. + +--- + +## Accéder aux fichiers Windows + +WSL peut accéder à tous vos fichiers Windows via le répertoire `/mnt/`: + +- Lecteur `C:` → `/mnt/c/` +- Lecteur `D:` → `/mnt/d/` +- Et ainsi de suite... + +Exemple: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +Pour une expérience plus fluide, vous pouvez cloner/copier votre dépôt dans le système de fichiers WSL (par exemple sous `~/code/`) et y exécuter OpenCode. +::: + +--- + +## Conseils + +- Gardez OpenCode dans WSL pour les projets stockés sur des lecteurs Windows: l'accès aux fichiers est fluide +- Utilisez l'[extension WSL de VS Code](https://code.visualstudio.com/docs/remote/wsl) avec OpenCode pour un flux de travail intégré +- Votre configuration OpenCode et vos sessions sont stockées dans l'environnement WSL à `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/fr/zen.mdx b/packages/web/src/content/docs/fr/zen.mdx new file mode 100644 index 00000000000..c69f2632f65 --- /dev/null +++ b/packages/web/src/content/docs/fr/zen.mdx @@ -0,0 +1,254 @@ +--- +title: Zen +description: Liste organisée de modèles fournis par OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen est une liste de modèles testés et vérifiés fournie par l'équipe OpenCode. + +:::note +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. + +--- + +## 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. + +:::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. + +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. + +OpenCode Zen est une passerelle IA qui vous donne accès à ces modèles. + +--- + +## Comment ça marche + +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. +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. + +Vous êtes facturé par demande et vous pouvez ajouter des crédits à votre compte. + +--- + +## Points de terminaison + +Vous pouvez également accéder à nos modèles via les points de terminaison API suivants. + +| Modèle | ID du modèle | Point de terminaison | Package SDK IA | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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. + +--- + +### Modèles + +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 +``` + +--- + +## Tarifs + +Nous soutenons un modèle de paiement à l'utilisation. Vous trouverez ci-dessous les prix **par 1 million de jetons**. + +| 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.1 | 0,30 $ | 1,20 $ | 0,10 $ | - | +| GLM 4.7 Free | Gratuit | Gratuit | Gratuit | - | +| 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 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 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 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 | Gratuit | Gratuit | Gratuit | - | + +Vous remarquerez peut-être _Claude Haiku 3.5_ dans votre historique d'utilisation. Il s'agit d'un [modèle low cost](/docs/config/#models) qui est utilisé pour générer les titres de vos sessions. + +:::note +Les frais de carte de crédit sont répercutés au prix coûtant (4,4 % + 0,30 $ par transaction) ; nous ne facturons rien au-delà. +::: + +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. +- 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. + +--- + +### Rechargement automatique + +Si votre solde descend en dessous de 5 $, Zen rechargera automatiquement 20 $. + +Vous pouvez modifier le montant du rechargement automatique. Vous pouvez également désactiver complètement le rechargement automatique. + +--- + +### 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. + +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 : + +- 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). + +--- + +## 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. + +:::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. + +--- + +### 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 + +Les administrateurs peuvent également définir des limites de dépenses mensuelles pour chaque membre afin de garder les coûts sous contrôle. + +--- + +### Accès au modèle + +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. + +--- + +### Apportez votre propre clé + +Vous pouvez utiliser vos propres clés OpenAI ou Anthropic API tout en accédant à d'autres modèles dans Zen. + +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. + +--- + +## Objectifs + +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. +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/it/acp.mdx b/packages/web/src/content/docs/it/acp.mdx new file mode 100644 index 00000000000..046aba5f25c --- /dev/null +++ b/packages/web/src/content/docs/it/acp.mdx @@ -0,0 +1,155 @@ +--- +title: Supporto ACP +description: Usa OpenCode in qualunque editor compatibile con ACP. +--- + +OpenCode supporta [Agent Client Protocol](https://agentclientprotocol.com) (ACP), permettendoti di usarlo direttamente in editor e IDE compatibili. + +:::tip +Per una lista di editor e tool che supportano ACP, vedi l'[ACP progress report](https://zed.dev/blog/acp-progress-report#available-now). +::: + +ACP e è un protocollo aperto che standardizza la comunicazione tra editor di codice e agenti di coding AI. + +--- + +## Configurazione + +Per usare OpenCode via ACP, configura l'editor in modo che esegua il comando `opencode acp`. + +Il comando avvia OpenCode come sottoprocesso compatibile con ACP che comunica con l'editor via JSON-RPC su stdio. + +Qui sotto trovi esempi per editor popolari che supportano ACP. + +--- + +### Zed + +Aggiungi alla configurazione di [Zed](https://zed.dev) (`~/.config/zed/settings.json`): + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +Per aprirlo, usa l'azione `agent: new thread` nella **Command Palette**. + +Puoi anche assegnare una scorciatoia da tastiera modificando `keymap.json`: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### JetBrains IDEs + +Aggiungi al tuo acp.json per [JetBrains IDE](https://www.jetbrains.com/) secondo la [documentazione](https://www.jetbrains.com/help/ai-assistant/acp.html): + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +Per aprirlo, seleziona il nuovo agente 'OpenCode' nel selettore agenti di AI Chat. + +--- + +### Avante.nvim + +Aggiungi alla configurazione di [Avante.nvim](https://github.com/yetone/avante.nvim): + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +Se devi passare variabili d'ambiente: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +Per usare OpenCode come agente ACP in [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim), aggiungi quanto segue alla config di Neovim: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +Questa config imposta CodeCompanion per usare OpenCode come agente ACP per la chat. + +Se devi passare variabili d'ambiente (come `OPENCODE_API_KEY`), vedi [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) nella documentazione di CodeCompanion.nvim. + +## Supporto + +OpenCode funziona via ACP come nel terminale. Tutte le funzionalita sono supportate: +:::note +Alcuni comandi slash integrati come `/undo` e `/redo` non sono attualmente supportati. +::: + +- Strumenti integrati (operazioni sui file, comandi da terminale, ecc.) +- Strumenti personalizzati e comandi slash +- Server MCP configurati nella tua configurazione OpenCode +- Regole specifiche del progetto da `AGENTS.md` +- Formatter e linter personalizzati +- Sistema di agenti e permessi diff --git a/packages/web/src/content/docs/it/agents.mdx b/packages/web/src/content/docs/it/agents.mdx new file mode 100644 index 00000000000..4ecc9fc2a29 --- /dev/null +++ b/packages/web/src/content/docs/it/agents.mdx @@ -0,0 +1,745 @@ +--- +title: Agenti +description: Configura e usa agenti specializzati. +--- + +Gli agenti sono assistenti AI specializzati che puoi configurare per task e workflow specifici. Ti permettono di creare strumenti mirati con prompt personalizzati, modelli e accesso agli strumenti. + +:::tip +Usa l'agente plan per analizzare codice e valutare suggerimenti senza apportare modifiche al codice. +::: + +Puoi passare da un agente all'altro durante una sessione oppure invocarli con la menzione `@`. + +--- + +## Tipi + +In OpenCode esistono due tipi di agenti: agenti primari e subagenti. + +--- + +### Agenti primari + +Gli agenti primari sono gli assistenti principali con cui interagisci direttamente. Puoi scorrerli usando il tasto **Tab** o la scorciatoia `switch_agent` configurata. Questi agenti gestiscono la conversazione principale. L'accesso agli strumenti si configura tramite i permessi: per esempio, Build ha tutti gli strumenti abilitati, mentre Plan è limitato. + +:::tip +Puoi usare **Tab** per passare tra gli agenti primari durante una sessione. +::: + +OpenCode include due agenti primari integrati: **Build** e **Plan**. Li vediamo sotto. + +--- + +### Subagenti + +I subagenti sono assistenti specializzati che gli agenti primari possono invocare per task specifici. Puoi anche invocarli manualmente **menzionandoli con @** nei tuoi messaggi. + +OpenCode include due subagenti integrati: **General** e **Explore**. Li vediamo sotto. + +--- + +## Integrati + +OpenCode include due agenti primari integrati e due subagenti integrati. + +--- + +### Build + +_Mode_: `primary` + +Build è l'agente primario **predefinito** con tutti gli strumenti abilitati. È l'agente standard per lavoro di sviluppo quando ti serve pieno accesso a operazioni sui file e comandi di sistema. + +--- + +### Plan + +_Mode_: `primary` + +Un agente limitato pensato per pianificazione e analisi. Usiamo un sistema di permessi per darti più controllo e prevenire modifiche non intenzionali. +Di default, tutte le seguenti sono impostate a `ask`: + +- `file edits`: tutte le scritture, patch ed edit +- `bash`: tutti i comandi bash + +Questo agente è utile quando vuoi che l'LLM analizzi il codice, suggerisca modifiche o crei piani senza effettuare alcuna modifica reale al codebase. + +--- + +### General + +_Mode_: `subagent` + +Un agente general-purpose per ricercare domande complesse ed eseguire task multi-step. Ha accesso completo agli strumenti (tranne todo), quindi può modificare file quando serve. Usalo per eseguire più unità di lavoro in parallelo. + +--- + +### Explore + +_Mode_: `subagent` + +Un agente rapido in sola lettura per esplorare codebase. Non può modificare file. Usalo quando devi trovare rapidamente file tramite pattern, cercare nel codice per keyword o rispondere a domande sul codebase. + +--- + +### Compaction + +_Mode_: `primary` + +Agente di sistema nascosto che compatta contesti lunghi in un riassunto più piccolo. Viene eseguito automaticamente quando serve e non è selezionabile nella UI. + +--- + +### Title + +_Mode_: `primary` + +Agente di sistema nascosto che genera titoli brevi per le sessioni. Viene eseguito automaticamente quando serve e non è selezionabile nella UI. + +--- + +### Summary + +_Mode_: `primary` + +Agente di sistema nascosto che crea riassunti di sessione. Viene eseguito automaticamente quando serve e non è selezionabile nella UI. + +--- + +## Utilizzo + +1. Per gli agenti primari, usa il tasto **Tab** per scorrerli durante una sessione. Puoi anche usare la scorciatoia `switch_agent` configurata. + +2. I subagenti possono essere invocati: + - **Automaticamente** dagli agenti primari per task specializzati in base alle loro descrizioni. + - Manualmente **menzionando con @** un subagente nel tuo messaggio. Per esempio: + + ```txt frame="none" + @general help me search for this function + ``` + 3. **Navigazione tra sessioni**: quando i subagenti creano le loro child session, puoi navigare tra la sessione padre e tutte le sessioni figlie usando: + - **\+Right** (o la scorciatoia `session_child_cycle` configurata) per ciclare in avanti tra parent → child1 → child2 → ... → parent + - **\+Left** (o la scorciatoia `session_child_cycle_reverse` configurata) per ciclare indietro tra parent ← child1 ← child2 ← ... ← parent + + Questo ti permette di passare senza soluzione di continuità tra la conversazione principale e il lavoro specializzato dei subagenti. + +--- + +## Configurazione + +Puoi personalizzare gli agenti integrati o crearne di tuoi tramite configurazione. Gli agenti possono essere configurati in due modi: + +--- + +### JSON + +Configura gli agenti nel file `opencode.json`: + +```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 + +Puoi anche definire agenti usando file markdown. Mettili in: + +- Globale: `~/.config/opencode/agents/` +- Per progetto: `.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. +``` + +Il nome del file markdown diventa il nome dell'agente. Per esempio, `review.md` crea un agente `review`. + +--- + +## Opzioni + +Vediamo nel dettaglio queste opzioni di configurazione. + +--- + +### Descrizione + +Usa l'opzione `description` per fornire una breve descrizione di cosa fa l'agente e quando usarlo. + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +Questa è un'opzione di configurazione **obbligatoria**. + +--- + +### Temperatura + +Controlla casualità e creatività delle risposte dell'LLM con la config `temperature`. + +Valori bassi rendono le risposte più focalizzate e deterministiche, mentre valori alti aumentano creatività e variabilità. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +I valori di temperature tipicamente vanno da 0.0 a 1.0: + +- **0.0-0.2**: risposte molto focalizzate e deterministiche, ideali per analisi del codice e pianificazione +- **0.3-0.5**: risposte bilanciate con un po' di creatività, adatte a task generali di sviluppo +- **0.6-1.0**: risposte più creative e varie, utili per brainstorming ed esplorazione + +```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}" + } + } +} +``` + +Se non specifichi una temperature, OpenCode usa i default specifici del modello; tipicamente 0 per la maggior parte dei modelli e 0.55 per i modelli Qwen. + +--- + +### Passi massimi + +Controlla il numero massimo di iterazioni agentiche che un agente può eseguire prima di essere forzato a rispondere solo con testo. Questo permette a chi vuole controllare i costi di impostare un limite alle azioni agentiche. + +Se non è impostato, l'agente continuerà a iterare finché il modello sceglie di fermarsi o l'utente interrompe la sessione. + +```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 + } + } +} +``` + +Quando viene raggiunto il limite, l'agente riceve un system prompt speciale che lo istruisce a rispondere con un riassunto del lavoro svolto e con i task rimanenti consigliati. + +:::caution +Il campo legacy `maxSteps` è deprecato. Usa `steps`. +::: + +--- + +### Disabilitazione + +Imposta a `true` per disabilitare l'agente. + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### Prompt + +Specifica un file di system prompt personalizzato per questo agente tramite la config `prompt`. Il file deve contenere istruzioni specifiche per lo scopo dell'agente. + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Questo path è relativo alla posizione del file di configurazione. Quindi funziona sia per la config globale di OpenCode sia per la config specifica del progetto. + +--- + +### Modello + +Usa la config `model` per sovrascrivere il modello per questo agente. Utile per usare modelli diversi ottimizzati per task diversi. Per esempio, un modello più veloce per la pianificazione e uno più capace per l'implementazione. + +:::tip +Se non specifichi un modello, gli agenti primari usano il [modello configurato globalmente](/docs/config#models), mentre i subagenti useranno il modello dell'agente primario che li ha invocati. +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +L'ID modello nella configurazione OpenCode usa il formato `provider/model-id`. Per esempio, se stai usando [OpenCode Zen](/docs/zen), useresti `opencode/gpt-5.1-codex` per GPT 5.1 Codex. + +--- + +### Strumenti + +Controlla quali strumenti sono disponibili per questo agente tramite la config `tools`. Puoi abilitare o disabilitare strumenti specifici impostandoli a `true` o `false`. + +```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 +La configurazione specifica dell'agente sovrascrive la configurazione globale. +::: + +Puoi anche usare wildcard per controllare più strumenti in una volta. Per esempio, per disabilitare tutti gli strumenti di un server MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[Scopri di più sugli strumenti](/docs/tools). + +--- + +### Permessi + +Puoi configurare i permessi per gestire quali azioni un agente può eseguire. Attualmente, i permessi per gli strumenti `edit`, `bash` e `webfetch` possono essere configurati come: + +- `"ask"` — chiede approvazione prima di eseguire lo strumento +- `"allow"` — consente tutte le operazioni senza approvazione +- `"deny"` — disabilita lo strumento + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +Puoi sovrascrivere questi permessi per agente. + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +Puoi anche impostare permessi negli agenti Markdown. + +```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. +``` + +Puoi impostare permessi per comandi bash specifici. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +Questo può usare un glob pattern. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +E puoi anche usare la wildcard `*` per gestire i permessi per tutti i comandi. +Dato che l'ultima regola che corrisponde ha la precedenza, metti prima la wildcard `*` e poi le regole specifiche. + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[Scopri di più sui permessi](/docs/permissions). + +--- + +### Modalità + +Controlla la modalità dell'agente con la config `mode`. L'opzione `mode` determina come l'agente può essere usato. + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +`mode` può essere `primary`, `subagent` o `all`. Se `mode` non è specificato, il default è `all`. + +--- + +### Nascosto + +Nascondi un subagente dal menu autocomplete di `@` con `hidden: true`. Utile per subagenti interni che dovrebbero essere invocati solo programmaticamente da altri agenti tramite lo strumento Task. + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +Questo influisce solo sulla visibilità per l'utente nel menu autocomplete. Gli agenti nascosti possono comunque essere invocati dal modello tramite lo strumento Task se i permessi lo consentono. + +:::note +Si applica solo ad agenti con `mode: subagent`. +::: + +--- + +### Permessi Task + +Controlla quali subagenti un agente può invocare tramite lo strumento Task con `permission.task`. Usa glob pattern per un matching flessibile. + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +Quando è impostato a `deny`, il subagente viene rimosso interamente dalla descrizione dello strumento Task, quindi il modello non proverà a invocarlo. + +:::tip +Le regole vengono valutate in ordine e **vince l'ultima regola che corrisponde**. Nell'esempio sopra, `orchestrator-planner` corrisponde sia a `*` (deny) sia a `orchestrator-*` (allow), ma dato che `orchestrator-*` viene dopo `*`, il risultato è `allow`. +::: + +:::tip +Gli utenti possono sempre invocare qualunque subagente direttamente dal menu autocomplete `@`, anche se i permessi task dell'agente lo negherebbero. +::: + +--- + +### Colore + +Personalizza l'aspetto visivo dell'agente nella UI con l'opzione `color`. Questo influisce su come l'agente appare nell'interfaccia. + +Usa un colore hex valido (ad es. `#FF5733`) o un colore tema: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +Controlla la diversità delle risposte con l'opzione `top_p`. Alternativa alla temperature per controllare la casualità. + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +I valori vanno da 0.0 a 1.0. Valori più bassi sono più focalizzati, valori più alti più diversi. + +--- + +### Opzioni aggiuntive + +Qualsiasi altra opzione che specifichi nella configurazione dell'agente verrà **passata direttamente** al provider come opzione del modello. Questo ti permette di usare feature e parametri specifici del provider. + +Per esempio, con i modelli di reasoning di OpenAI, puoi controllare lo sforzo di ragionamento: + +```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" + } + } +} +``` + +Queste opzioni aggiuntive sono specifiche per modello e provider. Controlla la documentazione del provider per i parametri disponibili. + +:::tip +Esegui `opencode models` per vedere la lista dei modelli disponibili. +::: + +--- + +## Creazione agenti + +Puoi creare nuovi agenti usando il comando seguente: + +```bash +opencode agent create +``` + +Questo comando interattivo: + +1. Chiede dove salvare l'agente: globale o specifico del progetto. +2. Chiede una descrizione di cosa dovrebbe fare l'agente. +3. Genera un system prompt appropriato e un identificatore. +4. Ti fa selezionare a quali strumenti l'agente può accedere. +5. Infine, crea un file markdown con la configurazione dell'agente. + +--- + +## Casi d'uso + +Ecco alcuni casi d'uso comuni per agenti diversi. + +- **Build agent**: sviluppo completo con tutti gli strumenti abilitati +- **Plan agent**: analisi e pianificazione senza apportare modifiche +- **Review agent**: code review con accesso in sola lettura più strumenti documentazione +- **Debug agent**: focalizzato sull'investigazione con strumenti bash e read abilitati +- **Docs agent**: scrittura documentazione con operazioni sui file ma senza comandi di sistema + +--- + +## Esempi + +Ecco alcuni agenti di esempio che potresti trovare utili. + +:::tip +Hai un agente che vorresti condividere? [Invia una PR](https://github.com/anomalyco/opencode). +::: + +--- + +### Agente documentazione + +```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 +``` + +--- + +### Auditor di sicurezza + +```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/it/cli.mdx b/packages/web/src/content/docs/it/cli.mdx new file mode 100644 index 00000000000..a97bbde1c96 --- /dev/null +++ b/packages/web/src/content/docs/it/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: Opzioni e comandi della CLI di OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +La CLI di OpenCode, per impostazione predefinita, avvia la [TUI](/docs/tui) quando viene eseguita senza argomenti. + +```bash +opencode +``` + +Ma accetta anche i comandi documentati in questa pagina. Questo ti permette di interagire con OpenCode in modo programmatico. + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +Avvia l'interfaccia testuale di OpenCode (interfaccia utente da terminale). + +```bash +opencode [project] +``` + +#### Flag + +| Flag | Breve | Descrizione | +| ------------ | ----- | ------------------------------------------------------------------------ | +| `--continue` | `-c` | Continua l'ultima sessione | +| `--session` | `-s` | ID sessione da continuare | +| `--fork` | | Duplica la sessione quando continui (usa con `--continue` o `--session`) | +| `--prompt` | | Prompt da usare | +| `--model` | `-m` | Modello nel formato provider/model | +| `--agent` | | Agente da usare | +| `--port` | | Porta su cui mettersi in ascolto | +| `--hostname` | | Hostname su cui mettersi in ascolto | + +--- + +## Comandi + +La CLI di OpenCode include anche i seguenti comandi. + +--- + +### agent + +Gestisci gli agenti per OpenCode. + +```bash +opencode agent [command] +``` + +--- + +### attach + +Collega un terminale a un backend server di OpenCode già in esecuzione avviato tramite i comandi `serve` o `web`. + +```bash +opencode attach [url] +``` + +Questo consente di usare la TUI con un backend OpenCode remoto. Per esempio: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In un altro terminale, collega la TUI al backend in esecuzione +opencode attach http://10.20.30.40:4096 +``` + +#### Flag + +| Flag | Breve | Descrizione | +| ----------- | ----- | --------------------------------------- | +| `--dir` | | Working directory in cui avviare la TUI | +| `--session` | `-s` | ID sessione da continuare | + +--- + +#### create + +Crea un nuovo agente con configurazione personalizzata. + +```bash +opencode agent create +``` + +Questo comando ti guida nella creazione di un nuovo agente con un system prompt personalizzato e configurazione degli strumenti. + +--- + +#### list + +Elenca tutti gli agenti disponibili. + +```bash +opencode agent list +``` + +--- + +### auth + +Comando per gestire le credenziali e il login dei provider. + +```bash +opencode auth [command] +``` + +--- + +#### login + +OpenCode si basa sull'elenco provider di [Models.dev](https://models.dev), quindi puoi usare `opencode auth login` per configurare le API key per qualunque provider tu voglia usare. Le credenziali vengono salvate in `~/.local/share/opencode/auth.json`. + +```bash +opencode auth login +``` + +Quando OpenCode si avvia, carica i provider dal file delle credenziali e, se presenti, anche eventuali key definite nell'ambiente o in un file `.env` nel progetto. + +--- + +#### list + +Elenca tutti i provider autenticati come salvati nel file delle credenziali. + +```bash +opencode auth list +``` + +Oppure la versione corta. + +```bash +opencode auth ls +``` + +--- + +#### logout + +Esegue il logout da un provider rimuovendolo dal file delle credenziali. + +```bash +opencode auth logout +``` + +--- + +### github + +Gestisci l'agente GitHub per l'automazione dei repository. + +```bash +opencode github [command] +``` + +--- + +#### install + +Installa l'agente GitHub nel tuo repository. + +```bash +opencode github install +``` + +Questo configura il workflow GitHub Actions necessario e ti guida nel processo di configurazione. [Scopri di più](/docs/github). + +--- + +#### run + +Esegui l'agente GitHub. Tipicamente usato in GitHub Actions. + +```bash +opencode github run +``` + +##### Flag + +| Flag | Descrizione | +| --------- | -------------------------------------------- | +| `--event` | Evento GitHub mock per cui eseguire l'agente | +| `--token` | GitHub personal access token | + +--- + +### mcp + +Gestisci i server Model Context Protocol. + +```bash +opencode mcp [command] +``` + +--- + +#### add + +Aggiungi un server MCP alla tua configurazione. + +```bash +opencode mcp add +``` + +Questo comando ti guida nell'aggiunta di un server MCP locale o remoto. + +--- + +#### list + +Elenca tutti i server MCP configurati e il loro stato di connessione. + +```bash +opencode mcp list +``` + +Oppure la versione corta. + +```bash +opencode mcp ls +``` + +--- + +#### auth + +Autentica con un server MCP con OAuth abilitato. + +```bash +opencode mcp auth [name] +``` + +Se non fornisci un nome server, ti verrà chiesto di selezionare tra i server OAuth-capable disponibili. + +Puoi anche elencare i server OAuth-capable e il loro stato di autenticazione. + +```bash +opencode mcp auth list +``` + +Oppure la versione corta. + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +Rimuovi le credenziali OAuth per un server MCP. + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +Esegui debug di problemi di connessione OAuth per un server MCP. + +```bash +opencode mcp debug +``` + +--- + +### models + +Elenca tutti i modelli disponibili dai provider configurati. + +```bash +opencode models [provider] +``` + +Questo comando mostra tutti i modelli disponibili tra i provider configurati nel formato `provider/model`. + +È utile per capire l'esatto nome del modello da usare nella [config](/docs/config/). + +Puoi anche passare opzionalmente un ID provider per filtrare i modelli a quel provider. + +```bash +opencode models anthropic +``` + +#### Flag + +| Flag | Descrizione | +| ----------- | -------------------------------------------------- | +| `--refresh` | Aggiorna la cache modelli da models.dev | +| `--verbose` | Output più verboso (include metadati come i costi) | + +Usa `--refresh` per aggiornare l'elenco modelli in cache. È utile quando nuovi modelli vengono aggiunti a un provider e vuoi vederli in OpenCode. + +```bash +opencode models --refresh +``` + +--- + +### run + +Esegui opencode in modalità non interattiva passando un prompt direttamente. + +```bash +opencode run [message..] +``` + +È utile per scripting, automazione o quando vuoi una risposta rapida senza avviare la TUI completa. Per esempio: + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +Puoi anche collegarti a una istanza `opencode serve` già in esecuzione per evitare i cold boot dei server MCP ad ogni esecuzione: + +```bash +# Avvia un server headless in un terminale +opencode serve + +# In un altro terminale, esegui comandi che si collegano ad esso +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### Flag + +| Flag | Breve | Descrizione | +| ------------ | ----- | ------------------------------------------------------------------------ | +| `--command` | | Il comando da eseguire; usa message per gli argomenti | +| `--continue` | `-c` | Continua l'ultima sessione | +| `--session` | `-s` | ID sessione da continuare | +| `--fork` | | Duplica la sessione quando continui (usa con `--continue` o `--session`) | +| `--share` | | Condividi la sessione | +| `--model` | `-m` | Modello nel formato provider/model | +| `--agent` | | Agente da usare | +| `--file` | `-f` | File da allegare al messaggio | +| `--format` | | Formato: default (formattato) o json (eventi JSON grezzi) | +| `--title` | | Titolo sessione (usa prompt troncato se non viene fornito un valore) | +| `--attach` | | Attach a un server opencode in esecuzione (es. http://localhost:4096) | +| `--port` | | Porta per il server locale (di default una porta casuale) | + +--- + +### serve + +Avvia un server OpenCode headless per accesso via API. Vedi le [server docs](/docs/server) per l'interfaccia HTTP completa. + +```bash +opencode serve +``` + +Avvia un server HTTP che espone accesso API alle funzionalità di opencode senza la TUI. Imposta `OPENCODE_SERVER_PASSWORD` per abilitare HTTP basic auth (username di default `opencode`). + +#### Flag + +| Flag | Descrizione | +| ------------ | ---------------------------------------------- | +| `--port` | Porta su cui mettersi in ascolto | +| `--hostname` | Hostname su cui mettersi in ascolto | +| `--mdns` | Abilita discovery mDNS | +| `--cors` | Origin browser addizionali per consentire CORS | + +--- + +### session + +Gestisci le sessioni OpenCode. + +```bash +opencode session [command] +``` + +--- + +#### list + +Elenca tutte le sessioni OpenCode. + +```bash +opencode session list +``` + +##### Flag + +| Flag | Breve | Descrizione | +| ------------- | ----- | ------------------------------------ | +| `--max-count` | `-n` | Limita alle N sessioni più recenti | +| `--format` | | Formato output: table o json (table) | + +--- + +### stats + +Mostra statistiche di utilizzo token e costo per le sessioni OpenCode. + +```bash +opencode stats +``` + +#### Flag + +| Flag | Descrizione | +| ----------- | ------------------------------------------------------------------------------------- | +| `--days` | Mostra statistiche per gli ultimi N giorni (all time) | +| `--tools` | Numero di strumenti da mostrare (all) | +| `--models` | Mostra breakdown di utilizzo modelli (nascosto di default). Passa un numero per top N | +| `--project` | Filtra per progetto (tutti i progetti; stringa vuota: progetto corrente) | + +--- + +### export + +Esporta i dati di sessione come JSON. + +```bash +opencode export [sessionID] +``` + +Se non fornisci un ID sessione, ti verrà chiesto di selezionare tra le sessioni disponibili. + +--- + +### import + +Importa i dati di sessione da un file JSON o da un URL di condivisione OpenCode. + +```bash +opencode import +``` + +Puoi importare da un file locale o da un URL di condivisione OpenCode. + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +Avvia un server OpenCode headless con interfaccia web. + +```bash +opencode web +``` + +Avvia un server HTTP e apre un browser per accedere a OpenCode tramite interfaccia web. Imposta `OPENCODE_SERVER_PASSWORD` per abilitare HTTP basic auth (username di default `opencode`). + +#### Flag + +| Flag | Descrizione | +| ------------ | ---------------------------------------------- | +| `--port` | Porta su cui mettersi in ascolto | +| `--hostname` | Hostname su cui mettersi in ascolto | +| `--mdns` | Abilita discovery mDNS | +| `--cors` | Origin browser addizionali per consentire CORS | + +--- + +### acp + +Avvia un server ACP (Agent Client Protocol). + +```bash +opencode acp +``` + +Questo comando avvia un server ACP che comunica via stdin/stdout usando nd-JSON. + +#### Flag + +| Flag | Descrizione | +| ------------ | ----------------------------------- | +| `--cwd` | Directory di lavoro | +| `--port` | Porta su cui mettersi in ascolto | +| `--hostname` | Hostname su cui mettersi in ascolto | + +--- + +### uninstall + +Disinstalla OpenCode e rimuove tutti i file correlati. + +```bash +opencode uninstall +``` + +#### Flag + +| Flag | Breve | Descrizione | +| --------------- | ----- | -------------------------------------------- | +| `--keep-config` | `-c` | Mantieni i file di configurazione | +| `--keep-data` | `-d` | Mantieni dati di sessione e snapshot | +| `--dry-run` | | Mostra cosa verrebbe rimosso senza rimuovere | +| `--force` | `-f` | Salta le richieste di conferma | + +--- + +### upgrade + +Aggiorna opencode all'ultima versione o a una versione specifica. + +```bash +opencode upgrade [target] +``` + +Per aggiornare all'ultima versione: + +```bash +opencode upgrade +``` + +Per aggiornare a una versione specifica: + +```bash +opencode upgrade v0.1.48 +``` + +#### Flag + +| Flag | Breve | Descrizione | +| ---------- | ----- | --------------------------------------------------------- | +| `--method` | `-m` | Metodo di installazione usato: curl, npm, pnpm, bun, brew | + +--- + +## Flag globali + +La CLI di opencode accetta i seguenti flag globali. + +| Flag | Breve | Descrizione | +| -------------- | ----- | -------------------------------------- | +| `--help` | `-h` | Mostra l'help | +| `--version` | `-v` | Stampa il numero di versione | +| `--print-logs` | | Stampa i log su stderr | +| `--log-level` | | Livello log (DEBUG, INFO, WARN, ERROR) | + +--- + +## Variabili d'ambiente + +OpenCode può essere configurato tramite variabili d'ambiente. + +| Variabile | Tipo | Descrizione | +| ------------------------------------- | ------- | ----------------------------------------------------------- | +| `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_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 | +| `OPENCODE_DISABLE_PRUNE` | boolean | Disabilita la potatura dei dati vecchi | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | Disabilita aggiornamenti automatici del titolo terminale | +| `OPENCODE_PERMISSION` | string | Config permessi JSON inline | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | Disabilita i plugin di default | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | Disabilita download automatico dei server LSP | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | Abilita modelli sperimentali | +| `OPENCODE_DISABLE_AUTOCOMPACT` | boolean | Disabilita compaction automatica del contesto | +| `OPENCODE_DISABLE_CLAUDE_CODE` | boolean | Disabilita lettura da `.claude` (prompt + skill) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | Disabilita lettura di `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | Disabilita caricamento di `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | boolean | Disabilita fetch dei modelli da fonti remote | +| `OPENCODE_FAKE_VCS` | string | Provider VCS finto per scopi di test | +| `OPENCODE_DISABLE_FILETIME_CHECK` | boolean | Disabilita controllo file time per ottimizzazione | +| `OPENCODE_CLIENT` | string | Identificatore client (default `cli`) | +| `OPENCODE_ENABLE_EXA` | boolean | Abilita gli strumenti di web search Exa | +| `OPENCODE_SERVER_PASSWORD` | string | Abilita basic auth per `serve`/`web` | +| `OPENCODE_SERVER_USERNAME` | string | Sovrascrive lo username basic auth (default `opencode`) | +| `OPENCODE_MODELS_URL` | string | URL personalizzato per recuperare la configurazione modelli | + +--- + +### Sperimentale + +Queste variabili d'ambiente abilitano funzionalità sperimentali che potrebbero cambiare o essere rimosse. + +| Variabile | Tipo | Descrizione | +| ----------------------------------------------- | ------- | ------------------------------------------ | +| `OPENCODE_EXPERIMENTAL` | boolean | Abilita tutte le funzionalità sperimentali | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | Abilita icon discovery | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | Disabilita copy on select nella TUI | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number | Timeout di default per comandi bash in ms | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | number | Massimo token di output per risposte LLM | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolean | Abilita file watcher per l'intera dir | +| `OPENCODE_EXPERIMENTAL_OXFMT` | boolean | Abilita formatter oxfmt | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolean | Abilita strumento LSP sperimentale | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | Disabilita file watcher | +| `OPENCODE_EXPERIMENTAL_EXA` | boolean | Abilita funzionalità Exa sperimentali | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolean | Abilita type checking LSP sperimentale | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolean | Abilita markdown sperimentale | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolean | Abilita plan mode | diff --git a/packages/web/src/content/docs/it/commands.mdx b/packages/web/src/content/docs/it/commands.mdx new file mode 100644 index 00000000000..bec4bf8deb1 --- /dev/null +++ b/packages/web/src/content/docs/it/commands.mdx @@ -0,0 +1,322 @@ +--- +title: Comandi +description: Crea comandi personalizzati per task ripetitivi. +--- + +I comandi personalizzati ti permettono di definire un prompt da eseguire quando quel comando viene lanciato nella TUI. + +```bash frame="none" +/my-command +``` + +I comandi personalizzati si aggiungono a quelli integrati come `/init`, `/undo`, `/redo`, `/share`, `/help`. [Scopri di piu](/docs/tui#commands). + +--- + +## Creazione file di comando + +Crea file markdown nella directory `commands/` per definire comandi personalizzati. + +Crea `.opencode/commands/test.md`: + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Il frontmatter definisce le proprieta del comando. Il contenuto diventa il template. + +Usa il comando digitando `/` seguito dal nome del comando. + +```bash frame="none" +"/test" +``` + +--- + +## Configurazione + +Puoi aggiungere comandi personalizzati tramite la config di OpenCode o creando file markdown nella directory `commands/`. + +--- + +### JSON + +Usa l'opzione `command` nella [config](/docs/config) di OpenCode: + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Ora puoi eseguire questo comando nella TUI: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +Puoi anche definire comandi usando file markdown. Mettili in: + +- Globale: `~/.config/opencode/commands/` +- Per progetto: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Il nome del file markdown diventa il nome del comando. Per esempio, `test.md` ti permette di eseguire: + +```bash frame="none" +/test +``` + +--- + +## Configurazione del prompt + +I prompt dei comandi personalizzati supportano diversi placeholder e sintassi speciali. + +--- + +### Argomenti + +Passa argomenti ai comandi usando il placeholder `$ARGUMENTS`. + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +Esegui il comando con argomenti: + +```bash frame="none" +/component Button +``` + +E `$ARGUMENTS` verra sostituito con `Button`. + +Puoi anche accedere ai singoli argomenti usando parametri posizionali: + +- `$1` - Primo argomento +- `$2` - Secondo argomento +- `$3` - Terzo argomento +- E cosi via... + +Per esempio: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +Esegui il comando: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +Questo sostituisce: + +- `$1` con `config.json` +- `$2` con `src` +- `$3` con `{ "key": "value" }` + +--- + +### Output della shell + +Usa _!`command`_ per inserire nel prompt l'output di un [comando bash](/docs/tui#bash-commands). + +Per esempio, per creare un comando personalizzato che analizzi la copertura dei test: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +Oppure per rivedere modifiche recenti: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +I comandi vengono eseguiti nella root del progetto e il loro output diventa parte del prompt. + +--- + +### Riferimenti ai file + +Includi file nel comando usando `@` seguito dal nome del file. + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +Il contenuto del file viene incluso automaticamente nel prompt. + +--- + +## Opzioni + +Vediamo le opzioni di configurazione nel dettaglio. + +--- + +### Template del prompt + +L'opzione `template` definisce il prompt che verra inviato all'LLM quando il comando viene eseguito. + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +Questa e un'opzione di config **obbligatoria**. + +--- + +### Descrizione + +Usa l'opzione `description` per fornire una breve descrizione di cosa fa il comando. + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +Questo viene mostrato come descrizione nella TUI quando digiti il comando. + +--- + +### Agente + +Usa la config `agent` per specificare opzionalmente quale [agente](/docs/agents) deve eseguire il comando. +Se e un [subagent](/docs/agents/#subagents), il comando attiva per default l'invocazione di un subagent. +Per disabilitare questo comportamento, imposta `subtask` a `false`. + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +Questa e un'opzione di config **opzionale**. Se non specificata, usa l'agente corrente. + +--- + +### Sottotask + +Usa il booleano `subtask` per forzare il comando ad attivare l'invocazione di un [subagent](/docs/agents/#subagents). +E utile se vuoi evitare che il comando inquini il contesto principale e **forza** l'agente ad agire come subagent, +anche se `mode` e impostato su `primary` nella configurazione dell'[agente](/docs/agents). + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +Questa e un'opzione di config **opzionale**. + +--- + +### Modello + +Usa la config `model` per sovrascrivere il modello predefinito per questo comando. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Questa e un'opzione di config **opzionale**. + +--- + +## Comandi integrati + +opencode include diversi comandi integrati come `/init`, `/undo`, `/redo`, `/share`, `/help`; [scopri di piu](/docs/tui#commands). + +:::note +I comandi personalizzati possono sovrascrivere quelli integrati. +::: + +Se definisci un comando personalizzato con lo stesso nome, sovrascrivera il comando integrato. diff --git a/packages/web/src/content/docs/it/config.mdx b/packages/web/src/content/docs/it/config.mdx new file mode 100644 index 00000000000..c94cc59a9b3 --- /dev/null +++ b/packages/web/src/content/docs/it/config.mdx @@ -0,0 +1,680 @@ +--- +title: Configurazione +description: Usa la configurazione JSON di OpenCode. +--- + +Puoi configurare OpenCode usando un file di configurazione JSON. + +--- + +## Formato + +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, +} +``` + +--- + +## Posizioni + +Puoi mettere la configurazione in diverse posizioni e ognuna ha un ordine di precedenza diverso. + +:::note +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. + +--- + +### Ordine di precedenza + +Le sorgenti di configurazione vengono caricate in questo ordine (le successive sovrascrivono le precedenti): + +1. **Config remota** (da `.well-known/opencode`) - default dell'organizzazione +2. **Config globale** (`~/.config/opencode/opencode.json`) - preferenze utente +3. **Config personalizzata** (variabile d'ambiente `OPENCODE_CONFIG`) - sovrascritture personalizzate +4. **Config di progetto** (`opencode.json` nel progetto) - impostazioni specifiche del progetto +5. **Directory `.opencode`** - agenti, comandi, plugin +6. **Config inline** (variabile d'ambiente `OPENCODE_CONFIG_CONTENT`) - sovrascritture a runtime + +Questo significa che la configurazione di progetto puo sovrascrivere i default globali, e la configurazione globale puo sovrascrivere i default remoti dell'organizzazione. + +:::note +Le directory `.opencode` e `~/.config/opencode` usano **nomi al plurale** per le sottodirectory: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/` e `themes/`. I nomi al singolare (ad es. `agent/`) sono supportati per retrocompatibilita. +::: + +--- + +### Configurazione remota + +Le organizzazioni possono fornire una configurazione predefinita tramite l'endpoint `.well-known/opencode`. Viene recuperata automaticamente quando ti autentichi con un provider che lo supporta. + +La configurazione remota viene caricata per prima e fa da livello base. Tutte le altre sorgenti (globale, progetto) possono sovrascrivere questi default. + +Per esempio, se la tua organizzazione fornisce server MCP disabilitati per impostazione predefinita: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +Puoi abilitare server specifici nella tua configurazione locale: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### 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). + +La configurazione globale sovrascrive i default remoti dell'organizzazione. + +--- + +### Configurazione di progetto + +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. + +:::tip +Metti la configurazione specifica del progetto nella root del progetto. +::: + +Quando OpenCode si avvia, cerca un file di configurazione nella directory corrente oppure risale fino alla directory Git piu vicina. + +Questo file puo essere tranquillamente versionato in Git e usa lo stesso schema di quello globale. + +--- + +### Percorso personalizzato + +Specifica un percorso personalizzato per il file di configurazione usando la variabile d'ambiente `OPENCODE_CONFIG`. + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +La configurazione personalizzata viene caricata tra quella globale e quella di progetto nell'ordine di precedenza. + +--- + +### Directory personalizzata + +Specifica una directory di configurazione personalizzata usando la variabile d'ambiente `OPENCODE_CONFIG_DIR`. Questa directory verra usata per cercare agenti, comandi, modalita e plugin proprio come la directory standard `.opencode` e dovrebbe seguire la stessa struttura. + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +La directory personalizzata viene caricata dopo la configurazione globale e le directory `.opencode`, quindi **puo sovrascrivere** le loro impostazioni. + +--- + +## Schema + +Il file di configurazione ha uno schema definito in [**`opencode.ai/config.json`**](https://opencode.ai/config.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`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +Opzioni disponibili: + +- `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. + +[Scopri di piu sull'uso della TUI](/docs/tui). + +--- + +### Server + +Puoi configurare le impostazioni del server per i comandi `opencode serve` e `opencode web` tramite l'opzione `server`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +Opzioni disponibili: + +- `port` - Porta su cui ascoltare. +- `hostname` - Nome host su cui ascoltare. Quando `mdns` e abilitato e non e impostato alcun hostname, il default e `0.0.0.0`. +- `mdns` - Abilita la scoperta del servizio mDNS. Questo permette ad altri dispositivi sulla rete di scoprire il tuo server OpenCode. +- `mdnsDomain` - Nome di dominio personalizzato per il servizio mDNS. Predefinito: `opencode.local`. Utile per eseguire piu istanze sulla stessa rete. +- `cors` - Origini aggiuntive da consentire per CORS quando usi il server HTTP da un client basato su browser. I valori devono essere origini complete (schema + host + porta opzionale), ad es. `https://app.example.com`. + +[Scopri di piu sul server](/docs/server). + +--- + +### Strumenti + +Puoi gestire gli strumenti che un LLM puo usare tramite l'opzione `tools`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[Scopri di piu sugli strumenti](/docs/tools). + +--- + +### Modelli + +Puoi configurare provider e modelli da usare in OpenCode tramite le opzioni `provider`, `model` e `small_model`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +L'opzione `small_model` configura un modello separato per task leggeri come la generazione dei titoli. Per impostazione predefinita, OpenCode prova a usare un modello più economico se disponibile dal tuo provider, altrimenti fa fallback sul tuo modello principale. + +Le opzioni del provider possono includere `timeout` e `setCacheKey`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` - Timeout della richiesta in millisecondi (predefinito: 300000). Imposta a `false` per disabilitare. +- `setCacheKey` - Assicura che venga sempre impostata una cache key per il provider indicato. + +Puoi anche configurare i [modelli locali](/docs/models#local). [Scopri di piu](/docs/models). + +--- + +#### Opzioni specifiche del provider + +Alcuni provider supportano opzioni di configurazione aggiuntive oltre alle impostazioni generiche `timeout` e `apiKey`. + +##### Amazon Bedrock + +Amazon Bedrock supporta una configurazione specifica per AWS: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` - Regione AWS per Bedrock (default: variabile d'ambiente `AWS_REGION` oppure `us-east-1`) +- `profile` - Profilo AWS nominato da `~/.aws/credentials` (default: variabile d'ambiente `AWS_PROFILE`) +- `endpoint` - URL endpoint personalizzato per gli endpoint VPC. E un alias dell'opzione generica `baseURL` usando la terminologia AWS. Se sono specificati sia `endpoint` sia `baseURL`, `endpoint` ha precedenza. + +:::note +I bearer token (`AWS_BEARER_TOKEN_BEDROCK` o `/connect`) hanno precedenza sull'autenticazione basata su profilo. Vedi [ordine di precedenza dell'autenticazione](/docs/providers#authentication-precedence) per i dettagli. +::: + +[Scopri di piu sulla configurazione di Amazon Bedrock](/docs/providers#amazon-bedrock). + +--- + +### Temi + +Puoi configurare il tema da usare in OpenCode tramite l'opzione `theme`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[Scopri di piu](/docs/themes). + +--- + +### Agenti + +Puoi configurare agenti specializzati per task specifici tramite l'opzione `agent`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +Puoi anche definire agenti usando file markdown in `~/.config/opencode/agents/` o `.opencode/agents/`. [Scopri di piu](/docs/agents). + +--- + +### Agente predefinito + +Puoi impostare l'agente predefinito usando l'opzione `default_agent`. Questo determina quale agente viene usato quando non ne specifichi uno esplicitamente. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +L'agente predefinito deve essere un agente primary (non un subagent). Puo essere un agente integrato come `"build"` o `"plan"`, oppure un [agente personalizzato](/docs/agents) che hai definito. Se l'agente specificato non esiste o e un subagent, OpenCode fara fallback su `"build"` mostrando un avviso. + +Questa impostazione si applica a tutte le interfacce: TUI, CLI (`opencode run`), app desktop e GitHub Action. + +--- + +### Condivisione + +Puoi configurare la funzione di [condivisione](/docs/share) tramite l'opzione `share`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +Valori supportati: + +- `"manual"` - Consenti la condivisione manuale tramite comandi (predefinito) +- `"auto"` - Condividi automaticamente le nuove conversazioni +- `"disabled"` - Disabilita completamente la condivisione + +Per impostazione predefinita, la condivisione e in modalita manuale e devi condividere esplicitamente le conversazioni usando il comando `/share`. + +--- + +### Comandi + +Puoi configurare comandi personalizzati per task ripetitivi tramite l'opzione `command`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +Puoi anche definire comandi usando file markdown in `~/.config/opencode/commands/` o `.opencode/commands/`. [Scopri di piu](/docs/commands). + +--- + +### Scorciatoie + +Puoi personalizzare i keybind tramite l'opzione `keybinds`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[Scopri di piu](/docs/keybinds). + +--- + +### Aggiornamenti automatici + +OpenCode scarichera automaticamente eventuali aggiornamenti quando si avvia. Puoi disabilitare questa funzione con l'opzione `autoupdate`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +Se non vuoi aggiornamenti automatici ma vuoi essere avvisato quando e disponibile una nuova versione, imposta `autoupdate` a `"notify"`. +Nota che questo funziona solo se non e stato installato con un package manager come Homebrew. + +--- + +### Formatter + +Puoi configurare i formatter di codice tramite l'opzione `formatter`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[Scopri di piu sui formatter](/docs/formatters). + +--- + +### Permessi + +Per impostazione predefinita, opencode **consente tutte le operazioni** senza richiedere un'approvazione esplicita. Puoi cambiarlo usando l'opzione `permission`. + +Per esempio, per fare in modo che gli strumenti `edit` e `bash` richiedano l'approvazione dell'utente: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[Scopri di piu sui permessi](/docs/permissions). + +--- + +### Compattazione + +Puoi controllare il comportamento di compattazione del contesto tramite l'opzione `compaction`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto` - Compatta automaticamente la sessione quando il contesto e pieno (predefinito: `true`). +- `prune` - Rimuove output vecchi degli strumenti per risparmiare token (predefinito: `true`). + +--- + +### Monitoraggio file + +Puoi configurare i pattern di ignoramento del file watcher tramite l'opzione `watcher`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +I pattern seguono la sintassi glob. Usali per escludere directory rumorose dal monitoraggio dei file. + +--- + +### Server MCP + +Puoi configurare i server MCP che vuoi usare tramite l'opzione `mcp`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[Scopri di piu](/docs/mcp-servers). + +--- + +### Plugin + +[I plugin](/docs/plugins) estendono OpenCode con strumenti personalizzati, hook e integrazioni. + +Metti i file dei plugin in `.opencode/plugins/` o `~/.config/opencode/plugins/`. Puoi anche caricare plugin da npm tramite l'opzione `plugin`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[Scopri di piu](/docs/plugins). + +--- + +### Istruzioni + +Puoi configurare le istruzioni per il modello che stai usando tramite l'opzione `instructions`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Accetta un array di percorsi e pattern glob verso file di istruzioni. [Scopri di piu sulle regole](/docs/rules). + +--- + +### Provider disabilitati + +Puoi disabilitare i provider caricati automaticamente tramite l'opzione `disabled_providers`. E utile quando vuoi impedire il caricamento di alcuni provider anche se le credenziali sono disponibili. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +`disabled_providers` ha priorita su `enabled_providers`. +::: + +L'opzione `disabled_providers` accetta un array di ID provider. Quando un provider e disabilitato: + +- Non verra caricato anche se sono impostate variabili d'ambiente. +- Non verra caricato anche se le chiavi API sono configurate tramite il comando `/connect`. +- I modelli del provider non appariranno nella lista di selezione dei modelli. + +--- + +### Provider abilitati + +Puoi specificare un'allowlist di provider tramite l'opzione `enabled_providers`. Se impostata, solo i provider indicati verranno abilitati e tutti gli altri saranno ignorati. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +E utile quando vuoi limitare OpenCode a usare solo alcuni provider invece di disabilitarli uno per uno. + +:::note +`disabled_providers` ha priorita su `enabled_providers`. +::: + +Se un provider appare sia in `enabled_providers` sia in `disabled_providers`, `disabled_providers` ha priorita per retrocompatibilita. + +--- + +### Sperimentale + +La chiave `experimental` contiene opzioni in sviluppo attivo. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +Le opzioni sperimentali non sono stabili. Possono cambiare o essere rimosse senza preavviso. +::: + +--- + +## Variabili + +Puoi usare la sostituzione di variabili nei file di configurazione per referenziare variabili d'ambiente e contenuti di file. + +--- + +### Variabili d'ambiente + +Usa `{env:VARIABLE_NAME}` per sostituire variabili d'ambiente: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +Se la variabile d'ambiente non e impostata, verra sostituita con una stringa vuota. + +--- + +### File + +Usa `{file:path/to/file}` per sostituire il contenuto di un file: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +I percorsi dei file possono essere: + +- Relativi alla directory del file di configurazione +- Oppure percorsi assoluti che iniziano con `/` o `~` + +Sono utili per: + +- Tenere dati sensibili (come chiavi API) in file separati. +- Includere file di istruzioni grandi senza appesantire la configurazione. +- Condividere snippet di configurazione comuni tra piu file di configurazione. diff --git a/packages/web/src/content/docs/it/custom-tools.mdx b/packages/web/src/content/docs/it/custom-tools.mdx new file mode 100644 index 00000000000..43f69c43c6c --- /dev/null +++ b/packages/web/src/content/docs/it/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: Strumenti personalizzati +description: Crea strumenti che l'LLM puo chiamare in opencode. +--- + +Gli strumenti personalizzati sono funzioni che crei e che l'LLM puo chiamare durante le conversazioni. Funzionano insieme agli [strumenti integrati](/docs/tools) di opencode come `read`, `write` e `bash`. + +--- + +## Creazione di uno strumento + +Gli strumenti sono definiti come file **TypeScript** o **JavaScript**. Tuttavia, la definizione dello strumento puo invocare script scritti in **qualsiasi linguaggio**: TypeScript o JavaScript vengono usati solo per la definizione in se. + +--- + +### Posizione + +Possono essere definiti: + +- In locale, mettendoli nella directory `.opencode/tools/` del progetto. +- Oppure in globale, mettendoli in `~/.config/opencode/tools/`. + +--- + +### Struttura + +Il modo piu semplice per creare strumenti e usare l'helper `tool()` che fornisce type-safety e validazione. + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +Il **nome del file** diventa il **nome dello strumento**. L'esempio sopra crea lo strumento `database`. + +--- + +#### Strumenti multipli per file + +Puoi anche esportare piu strumenti da un singolo file. Ogni export diventa **uno strumento separato** con nome **`_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +Questo crea due strumenti: `math_add` e `math_multiply`. + +--- + +### Argomenti + +Puoi usare `tool.schema`, che e semplicemente [Zod](https://zod.dev), per definire i tipi degli argomenti. + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +Puoi anche importare [Zod](https://zod.dev) direttamente e restituire un oggetto semplice: + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### Contesto + +Gli strumenti ricevono un contesto sulla sessione corrente: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +Usa `context.directory` per la working directory della sessione. +Usa `context.worktree` per la root del worktree git. + +--- + +## Esempi + +### Scrivere uno strumento in Python + +Puoi scrivere gli strumenti in qualunque linguaggio. Ecco un esempio che somma due numeri usando Python. + +Per prima cosa, crea lo strumento come script Python: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +Poi crea la definizione dello strumento che lo invoca: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +Qui usiamo l'utility [`Bun.$`](https://bun.com/docs/runtime/shell) per eseguire lo script Python. diff --git a/packages/web/src/content/docs/it/ecosystem.mdx b/packages/web/src/content/docs/it/ecosystem.mdx new file mode 100644 index 00000000000..54fcdb8dbd9 --- /dev/null +++ b/packages/web/src/content/docs/it/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: Ecosistema +description: Progetti e integrazioni costruiti con OpenCode. +--- + +Una raccolta di progetti della comunita costruiti su OpenCode. + +:::note +Vuoi aggiungere il tuo progetto legato a OpenCode a questa lista? Apri una PR. +::: + +Puoi anche dare un'occhiata a [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) e [opencode.cafe](https://opencode.cafe), una comunita che aggrega ecosistema e community. + +--- + +## Plugin + +| Nome | Descrizione | +| --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | Esegue automaticamente sessioni OpenCode in sandbox Daytona isolate con sync git e anteprime live | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | Inietta automaticamente gli header di sessione Helicone per raggruppare le richieste | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | Inietta automaticamente tipi TypeScript/Svelte nelle letture dei file con tool di lookup | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | Usa il tuo abbonamento ChatGPT Plus/Pro invece dei crediti API | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | Usa il tuo piano Gemini esistente invece della fatturazione API | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | Usa i modelli gratuiti di Antigravity invece della fatturazione API | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Isolamento devcontainer multi-branch con shallow clone e porte assegnate automaticamente | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Plugin OAuth Google Antigravity, con supporto a Google Search e gestione API piu robusta | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Ottimizza l'uso dei token eliminando output obsoleti degli strumenti | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Aggiunge supporto websearch nativo per provider supportati con stile grounded di Google | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Permette agli agenti AI di eseguire processi in background in una PTY e inviare input interattivo | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Istruzioni per comandi shell non interattivi: evita blocchi dovuti a operazioni dipendenti da TTY | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Traccia l'uso di OpenCode con Wakatime | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Ripulisce le tabelle markdown prodotte dai LLM | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | Editing del codice 10x piu veloce con Morph Fast Apply API e marker lazy edit | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Agenti in background, tool LSP/AST/MCP predefiniti, agenti curati, compatibile con Claude Code | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | Notifiche desktop e avvisi sonori per le sessioni OpenCode | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Notifiche desktop e avvisi sonori per eventi di permesso, completamento ed errore | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | Naming automatico delle sessioni Zellij basato sul contesto OpenCode | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Permette agli agenti OpenCode di caricare prompt al bisogno con discovery e injection di skill | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Memoria persistente tra sessioni usando Supermemory | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Revisione interattiva dei piani con annotazione visiva e condivisione privata/offline | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Estende opencode /commands in un sistema di orchestrazione con controllo di flusso granulare | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | Pianifica job ricorrenti con launchd (Mac) o systemd (Linux) usando sintassi cron | +| [micode](https://github.com/vtemian/micode) | Workflow strutturato Brainstorm → Plan → Implement con continuita di sessione | +| [octto](https://github.com/vtemian/octto) | UI browser interattiva per brainstorming AI con moduli multi-domanda | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | Agenti in background stile Claude Code con delega async e persistenza del contesto | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | Notifiche native del sistema per OpenCode: sai quando i task finiscono | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | Harness di orchestrazione multi-agente bundle: 16 componenti, una installazione | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | Git worktree senza attriti per OpenCode | + +--- + +## Progetti + +| Nome | Descrizione | +| ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- | +| [kimaki](https://github.com/remorses/kimaki) | Bot Discord per controllare sessioni OpenCode, costruito sull'SDK | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Plugin Neovim per prompt consapevoli dell'editor, costruito sull'API | +| [portal](https://github.com/hosenur/portal) | Web UI mobile-first per OpenCode su Tailscale/VPN | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | Template per costruire plugin OpenCode | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Frontend Neovim per opencode: un agente di coding AI per terminale | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Provider Vercel AI SDK per usare OpenCode tramite @opencode-ai/sdk | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | App Web/Desktop ed estensione VS Code per OpenCode | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Plugin Obsidian che integra OpenCode nella UI di Obsidian | +| [OpenWork](https://github.com/different-ai/openwork) | Alternativa open source a Claude Cowork, alimentata da OpenCode | +| [ocx](https://github.com/kdcokenny/ocx) | Gestore di estensioni OpenCode con profili portabili e isolati | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | App client Desktop, Web, Mobile e remota per OpenCode | + +--- + +## Agenti + +| Nome | Descrizione | +| ----------------------------------------------------------------- | --------------------------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | Agenti AI modulari e comandi per uno sviluppo strutturato | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | Config, prompt, agenti e plugin per workflow migliorati | diff --git a/packages/web/src/content/docs/it/enterprise.mdx b/packages/web/src/content/docs/it/enterprise.mdx new file mode 100644 index 00000000000..bd142e709a1 --- /dev/null +++ b/packages/web/src/content/docs/it/enterprise.mdx @@ -0,0 +1,165 @@ +--- +title: Enterprise +description: Usa OpenCode in sicurezza nella tua organizzazione. +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +OpenCode Enterprise e pensato per organizzazioni che vogliono assicurarsi che codice e dati non escano mai dalla propria infrastruttura. Questo e possibile grazie a una config centralizzata che si integra con SSO e con il gateway AI interno. + +:::note +OpenCode non memorizza alcun tuo codice o dato di contesto. +::: + +Per iniziare con OpenCode Enterprise: + +1. Fai una prova interna con il tuo team. +2. **Contattaci** per parlare di prezzi e opzioni di implementazione. + +--- + +## Prova + +OpenCode e open source e non memorizza alcun tuo codice o dato di contesto, quindi i tuoi sviluppatori possono semplicemente [iniziare](/docs/) e fare una prova. + +--- + +### Gestione dati + +**OpenCode non memorizza il tuo codice o i tuoi dati di contesto.** Tutta l'elaborazione avviene in locale o tramite chiamate API dirette al tuo provider AI. + +Questo significa che, finche usi un provider di cui ti fidi o un gateway AI interno, puoi usare OpenCode in modo sicuro. + +L'unica eccezione e la funzione opzionale `/share`. + +--- + +#### Condivisione conversazioni + +Se un utente abilita la funzione `/share`, la conversazione e i dati associati vengono inviati al servizio che usiamo per ospitare queste pagine di condivisione su opencode.ai. + +I dati sono serviti tramite la rete edge della nostra CDN e vengono messi in cache vicino ai tuoi utenti. + +Ti consigliamo di disabilitarla durante la prova. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[Scopri di più sulla condivisione](/docs/share). + +--- + +### Proprietà del codice + +**Sei proprietario di tutto il codice prodotto da OpenCode.** Non ci sono restrizioni di licenza o rivendicazioni di proprieta. + +--- + +## Prezzi + +Usiamo un modello per-seat per OpenCode Enterprise. Se hai un tuo gateway LLM, non addebitiamo i token usati. Per maggiori dettagli su prezzi e opzioni di implementazione, **contattaci**. + +--- + +## Distribuzione + +Quando hai completato la prova e sei pronto a usare OpenCode nella tua organizzazione, puoi **contattarci** per discutere prezzi e opzioni di implementazione. + +--- + +### Configurazione centralizzata + +Possiamo configurare OpenCode per usare un'unica config centralizzata per tutta l'organizzazione. + +Questa config centralizzata puo integrarsi col provider SSO e garantisce che tutti gli utenti accedano solo al gateway AI interno. + +--- + +### Integrazione SSO + +Tramite la config centralizzata, OpenCode puo integrarsi col provider SSO della tua organizzazione per l'autenticazione. + +Questo consente a OpenCode di ottenere credenziali per il gateway AI interno tramite il sistema di identity management esistente. + +--- + +### Gateway AI interno + +Con la config centralizzata, OpenCode puo anche essere configurato per usare solo il tuo gateway AI interno. + +Puoi anche disabilitare tutti gli altri provider AI, assicurandoti che tutte le richieste passino dall'infrastruttura approvata dalla tua organizzazione. + +--- + +### Hosting autonomo + +Anche se consigliamo di disabilitare le pagine di condivisione per assicurarti che i dati non escano mai dall'organizzazione, possiamo anche aiutarti a ospitarle sulla tua infrastruttura. + +Questa funzionalita e nella nostra roadmap. Se ti interessa, **faccelo sapere**. + +--- + +## FAQ + +

+Che cos'e OpenCode Enterprise? + +OpenCode Enterprise e pensato per organizzazioni che vogliono assicurarsi che codice e dati non escano mai dalla propria infrastruttura. Questo e possibile grazie a una config centralizzata che si integra con SSO e con il gateway AI interno. + +
+ +
+Come posso iniziare con OpenCode Enterprise? + +Inizia semplicemente con una prova interna con il tuo team. Per impostazione predefinita OpenCode non memorizza il tuo codice o i dati di contesto, quindi e facile partire. + +Poi **contattaci** per discutere prezzi e opzioni di implementazione. + +
+ +
+Come funziona il pricing enterprise? + +Offriamo pricing enterprise per-seat. Se hai un tuo gateway LLM, non addebitiamo i token usati. Per maggiori dettagli, **contattaci** per un preventivo su misura in base alle esigenze della tua organizzazione. + +
+ +
+I miei dati sono al sicuro con OpenCode Enterprise? + +Si. OpenCode non memorizza il tuo codice o i dati di contesto. Tutta l'elaborazione avviene in locale o tramite chiamate API dirette al tuo provider AI. Con config centralizzata e integrazione SSO, i dati restano all'interno dell'infrastruttura della tua organizzazione. + +
+ +
+Possiamo usare un registry NPM privato? + +OpenCode supporta registry npm privati tramite il supporto nativo di Bun per i file `.npmrc`. Se la tua organizzazione usa un registry privato, come JFrog Artifactory, Nexus o simili, assicurati che gli sviluppatori siano autenticati prima di eseguire OpenCode. + +Per configurare l'autenticazione col registry privato: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +Questo crea `~/.npmrc` con i dettagli di autenticazione. OpenCode lo rilevera automaticamente. + +:::caution +Devi essere autenticato nel registry privato prima di eseguire OpenCode. +::: + +In alternativa, puoi configurare manualmente un file `.npmrc`: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +Gli sviluppatori devono essere autenticati nel registry privato prima di eseguire OpenCode per garantire che i pacchetti possano essere installati dal registry enterprise. + +
diff --git a/packages/web/src/content/docs/it/formatters.mdx b/packages/web/src/content/docs/it/formatters.mdx new file mode 100644 index 00000000000..b662db47eba --- /dev/null +++ b/packages/web/src/content/docs/it/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: Formattatori +description: OpenCode usa formattatori specifici per linguaggio. +--- + +OpenCode formatta automaticamente i file dopo che vengono scritti o modificati usando formattatori specifici per linguaggio. Questo assicura che il codice generato segua lo stile del tuo progetto. + +--- + +## Integrati + +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 | +| 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 | + +Quindi, se il progetto ha `prettier` in `package.json`, OpenCode lo usera automaticamente. + +--- + +## Come funziona + +Quando OpenCode scrive o modifica un file: + +1. Controlla l'estensione del file rispetto a tutti i formattatori abilitati. +2. Esegue il comando del formattatore appropriato sul file. +3. Applica automaticamente le modifiche di formattazione. + +Questo processo avviene in background, mantenendo lo stile del codice senza passaggi manuali. + +--- + +## Configurazione + +Puoi personalizzare i formattatori nella sezione `formatter` della config di OpenCode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +Ogni configurazione di formattatore supporta: + +| Proprieta | Tipo | Descrizione | +| ------------- | -------- | --------------------------------------------------- | +| `disabled` | boolean | Impostalo a `true` per disabilitare il formattatore | +| `command` | string[] | Il comando da eseguire per la formattazione | +| `environment` | object | Variabili d'ambiente da impostare quando si esegue | +| `extensions` | string[] | Estensioni file gestite da questo formattatore | + +Vediamo alcuni esempi. + +--- + +### Disabilitare i formattatori + +Per disabilitare **tutti** i formattatori globalmente, imposta `formatter` a `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +Per disabilitare un formattatore **specifico**, imposta `disabled` a `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### Formattatori personalizzati + +Puoi sovrascrivere i formattatori integrati o aggiungerne di nuovi specificando comando, variabili d'ambiente ed estensioni file: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +Il **placeholder `$FILE`** nel comando viene sostituito con il percorso del file in fase di formattazione. diff --git a/packages/web/src/content/docs/it/github.mdx b/packages/web/src/content/docs/it/github.mdx new file mode 100644 index 00000000000..81bbd593378 --- /dev/null +++ b/packages/web/src/content/docs/it/github.mdx @@ -0,0 +1,321 @@ +--- +title: GitHub +description: Usa OpenCode in issue e pull request su GitHub. +--- + +OpenCode si integra nel tuo workflow GitHub. Menziona `/opencode` o `/oc` in un commento e OpenCode eseguira' i task dentro il runner di GitHub Actions. + +--- + +## Funzionalità + +- **Triage delle issue**: chiedi a OpenCode di indagare su una issue e spiegartela. +- **Fix e implementazioni**: chiedi a OpenCode di risolvere una issue o implementare una feature. Lavorera' su un nuovo branch e inviera' una PR con tutte le modifiche. +- **Sicuro**: OpenCode gira all'interno dei runner GitHub. + +--- + +## Installazione + +Esegui il comando seguente in un progetto che si trova in un repo GitHub: + +```bash +opencode github install +``` + +Questo ti guidera' nell'installazione della GitHub app, nella creazione del workflow e nella configurazione dei secret. + +--- + +### Configurazione manuale + +In alternativa, puoi configurarlo manualmente. + +1. **Installa la GitHub app** + + Vai su [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). Assicurati che sia installata sul repository di destinazione. + +2. **Aggiungi il workflow** + + Aggiungi il seguente file workflow in `.github/workflows/opencode.yml` nel tuo repo. Assicurati di impostare il `model` appropriato e le API key richieste in `env`. + + ```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx + ``` + +3. **Salva le API key nei secret** + + Nelle **impostazioni** della tua organizzazione o progetto, espandi **Secrets and variables** sulla sinistra e seleziona **Actions**. Poi aggiungi le API key richieste. + +--- + +## Configurazione + +- `model`: il modello da usare con OpenCode. Usa il formato `provider/model`. E' **obbligatorio**. +- `agent`: l'agente da usare. Deve essere un agente primario. Se non trovato, usa `default_agent` dalla config o `"build"`. +- `share`: se condividere la sessione OpenCode. Di default e' **true** per repository pubblici. +- `prompt`: prompt personalizzato opzionale per sovrascrivere il comportamento di default. Usalo per personalizzare come OpenCode processa le richieste. +- `token`: token di accesso GitHub opzionale per eseguire operazioni come creare commenti, committare modifiche e aprire pull request. Di default, OpenCode usa l'installation access token della OpenCode GitHub App, quindi commit, commenti e pull request risultano provenire dalla app. + + In alternativa, puoi usare il [token integrato `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) del runner GitHub Actions senza installare la OpenCode GitHub App. Assicurati solo di concedere i permessi necessari nel workflow: + + ```yaml + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + ``` + + Se preferisci, puoi anche usare un [personal access tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT). + +--- + +## Eventi supportati + +OpenCode puo' essere attivato dai seguenti eventi GitHub: + +| Tipo evento | Attivato da | Dettagli | +| ----------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| `issue_comment` | Commento su una issue o PR | Menziona `/opencode` o `/oc` nel commento. OpenCode legge il contesto e puo' creare branch, aprire PR o rispondere. | +| `pull_request_review_comment` | Commento su specifiche righe in una PR | Menziona `/opencode` o `/oc` durante una review. OpenCode riceve path file, numeri di riga e contesto del diff. | +| `issues` | Issue aperta o modificata | Attiva automaticamente OpenCode quando le issue vengono create o modificate. Richiede l'input `prompt`. | +| `pull_request` | PR aperta o aggiornata | Attiva automaticamente OpenCode quando le PR vengono aperte, sincronizzate o riaperte. Utile per review automatiche. | +| `schedule` | Pianificazione basata su cron | Esegue OpenCode a pianificazione. Richiede l'input `prompt`. Output nei log e nelle PR (nessuna issue su cui commentare). | +| `workflow_dispatch` | Trigger manuale dalla UI GitHub | Attiva OpenCode on-demand dalla tab Actions. Richiede l'input `prompt`. Output nei log e nelle PR. | + +### Esempio con schedule + +Esegui OpenCode a pianificazione per eseguire task automatizzati: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +Per gli eventi schedulati, l'input `prompt` e' **obbligatorio** dato che non c'e' un commento da cui estrarre le istruzioni. I workflow schedulati girano senza un contesto utente per i controlli di permesso, quindi il workflow deve concedere `contents: write` e `pull-requests: write` se ti aspetti che OpenCode crei branch o PR. + +--- + +### Esempio di pull request + +Review automatica delle PR quando vengono aperte o aggiornate: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Per gli eventi `pull_request`, se non viene fornito alcun `prompt`, OpenCode fa di default la review della pull request. + +--- + +### Esempio di triage delle issue + +Triage automatico delle nuove issue. Questo esempio filtra gli account piu' vecchi di 30 giorni per ridurre lo spam: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +Per gli eventi `issues`, l'input `prompt` e' **obbligatorio** dato che non c'e' un commento da cui estrarre le istruzioni. + +--- + +## Prompt personalizzati + +Sovrascrivi il prompt di default per personalizzare il comportamento di OpenCode nel tuo workflow. + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +E' utile per imporre criteri specifici di review, standard di codice o aree di focus rilevanti per il progetto. + +--- + +## Esempi + +Ecco alcuni esempi di come puoi usare OpenCode su GitHub. + +- **Spiega una issue** + + Aggiungi questo commento in una issue GitHub. + + ``` + /opencode explain this issue + ``` + + OpenCode leggera' l'intero thread, inclusi tutti i commenti, e rispondera' con una spiegazione chiara. + +- **Risolvi una issue** + + In una issue GitHub, scrivi: + + ``` + /opencode fix this + ``` + + OpenCode creera' un nuovo branch, implementera' le modifiche e aprira' una PR con i cambiamenti. + +- **Rivedi PR e fai modifiche** + + Lascia il seguente commento su una PR GitHub. + + ``` + Delete the attachment from S3 when the note is removed /oc + ``` + + OpenCode implementera' la modifica richiesta e la committera' nella stessa PR. + +- **Rivedi righe specifiche di codice** + + Lascia un commento direttamente sulle righe di codice nella tab "Files" della PR. OpenCode rileva automaticamente file, numeri di riga e contesto del diff per fornire risposte precise. + + ``` + [Comment on specific lines in Files tab] + /oc add error handling here + ``` + + Quando commenti su righe specifiche, OpenCode riceve: + - Il file esatto in review + - Le righe di codice specifiche + - Il contesto del diff circostante + - Informazioni sul numero di riga + + Questo permette richieste piu' mirate senza dover specificare manualmente path file o numeri di riga. diff --git a/packages/web/src/content/docs/it/gitlab.mdx b/packages/web/src/content/docs/it/gitlab.mdx new file mode 100644 index 00000000000..479f7db9e73 --- /dev/null +++ b/packages/web/src/content/docs/it/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: Usa OpenCode in issue e merge request su GitLab. +--- + +OpenCode si integra nel tuo workflow GitLab tramite la pipeline GitLab CI/CD o con GitLab Duo. + +In entrambi i casi, OpenCode girera' sui tuoi runner GitLab. + +--- + +## GitLab CI + +OpenCode funziona in una pipeline GitLab standard. Puoi integrarlo nella pipeline come [componente CI](https://docs.gitlab.com/ee/ci/components/). + +Qui usiamo un componente CI/CD creato dalla community per OpenCode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### Funzionalità + +- **Configurazione personalizzata per job**: configura OpenCode con una directory di configurazione personalizzata, ad esempio `./config/#custom-directory`, per abilitare o disabilitare funzionalita' per ogni invocazione di OpenCode. +- **Setup minimo**: il componente CI prepara OpenCode in background; devi solo creare la configurazione OpenCode e il prompt iniziale. +- **Flessibile**: il componente CI supporta diversi input per personalizzarne il comportamento. + +--- + +### Configurazione + +1. Salva il JSON di autenticazione di OpenCode come variabile d'ambiente CI di tipo File in **Settings** > **CI/CD** > **Variables**. Assicurati di marcarla come "Masked and hidden". +2. Aggiungi quanto segue al tuo file `.gitlab-ci.yml`. + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +Per altri input e casi d'uso, [consulta la documentazione](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) di questo componente. + +--- + +## GitLab Duo + +OpenCode si integra nel tuo workflow GitLab. +Menziona `@opencode` in un commento e OpenCode eseguira' i task dentro la tua pipeline GitLab CI. + +--- + +### Funzionalità + +- **Triage delle issue**: chiedi a OpenCode di indagare su una issue e spiegartela. +- **Fix e implementazioni**: chiedi a OpenCode di risolvere una issue o implementare una feature. + Creera' un nuovo branch e aprira' una merge request con le modifiche. +- **Sicuro**: OpenCode gira sui tuoi runner GitLab. + +--- + +### Configurazione + +OpenCode gira nella pipeline GitLab CI/CD. Ecco cosa ti serve per configurarlo: + +:::tip +Dai un'occhiata alle [**GitLab docs**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) per istruzioni aggiornate. +::: + +1. Configura l'ambiente GitLab +2. Configura CI/CD +3. Ottieni una API key di un provider di modelli AI +4. Crea un service account +5. Configura le variabili CI/CD +6. Crea un file di configurazione del flow, ecco un esempio: + +
+ + Flow configuration + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +Puoi fare riferimento alla [documentazione GitLab CLI agents](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) per istruzioni dettagliate. + +--- + +### Esempi + +Ecco alcuni esempi di come puoi usare OpenCode in GitLab. + +:::tip +Puoi configurare una frase trigger diversa da `@opencode`. +::: + +- **Spiega una issue** + + Aggiungi questo commento in una issue GitLab. + + ``` + @opencode explain this issue + ``` + + OpenCode leggera' la issue e rispondera' con una spiegazione chiara. + +- **Risolvi una issue** + + In una issue GitLab, scrivi: + + ``` + @opencode fix this + ``` + + OpenCode creera' un nuovo branch, implementera' le modifiche e aprira' una merge request con i cambiamenti. + +- **Rivedi merge request** + + Lascia il seguente commento su una merge request GitLab. + + ``` + @opencode review this merge request + ``` + + OpenCode rivedra' la merge request e fornira' feedback. diff --git a/packages/web/src/content/docs/it/ide.mdx b/packages/web/src/content/docs/it/ide.mdx new file mode 100644 index 00000000000..37948acc1da --- /dev/null +++ b/packages/web/src/content/docs/it/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: L'estensione OpenCode per VS Code, Cursor e altri IDE +--- + +OpenCode si integra con VS Code, Cursor o qualunque IDE che supporti un terminale. Basta eseguire `opencode` nel terminale per iniziare. + +--- + +## Utilizzo + +- **Avvio rapido**: usa `Cmd+Esc` (Mac) o `Ctrl+Esc` (Windows/Linux) per aprire OpenCode in una vista terminale divisa, oppure per mettere a fuoco una sessione esistente se e gia in esecuzione. +- **Nuova sessione**: usa `Cmd+Shift+Esc` (Mac) o `Ctrl+Shift+Esc` (Windows/Linux) per avviare una nuova sessione di OpenCode, anche se ne esiste gia una aperta. Puoi anche cliccare il pulsante OpenCode nell'interfaccia. +- **Consapevolezza del contesto**: condividi automaticamente con OpenCode la selezione corrente o la scheda attiva. +- **Scorciatoie per riferimenti file**: usa `Cmd+Option+K` (Mac) o `Alt+Ctrl+K` (Linux/Windows) per inserire riferimenti a file. Per esempio, `@File#L37-42`. + +--- + +## Installazione + +Per installare OpenCode su VS Code e fork popolari come Cursor, Windsurf, VSCodium: + +1. Apri VS Code +2. Apri il terminale integrato +3. Esegui `opencode` - l'estensione si installa automaticamente + +Se invece vuoi usare il tuo IDE quando esegui `/editor` o `/export` dalla TUI, devi impostare `export EDITOR="code --wait"`. [Scopri di piu](/docs/tui/#editor-setup). + +--- + +### Installazione manuale + +Cerca **OpenCode** nel Marketplace delle estensioni e clicca **Install**. + +--- + +### Risoluzione dei problemi + +Se l'estensione non si installa automaticamente: + +- Assicurati di eseguire `opencode` nel terminale integrato. +- Verifica che la CLI del tuo IDE sia installata: + - Per VS Code: comando `code` + - Per Cursor: comando `cursor` + - Per Windsurf: comando `windsurf` + - Per VSCodium: comando `codium` + - In caso contrario, esegui `Cmd+Shift+P` (Mac) o `Ctrl+Shift+P` (Windows/Linux) e cerca "Shell Command: Install 'code' command in PATH" (o l'equivalente per il tuo IDE) +- Assicurati che VS Code abbia i permessi per installare estensioni diff --git a/packages/web/src/content/docs/it/index.mdx b/packages/web/src/content/docs/it/index.mdx new file mode 100644 index 00000000000..685bdf0c57a --- /dev/null +++ b/packages/web/src/content/docs/it/index.mdx @@ -0,0 +1,343 @@ +--- +title: Introduzione +description: Inizia con OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**OpenCode**](/) e un agente di programmazione AI open source. E disponibile come interfaccia per terminale, app desktop o estensione per IDE. + +![OpenCode TUI con il tema opencode](../../../assets/lander/screenshot.png) + +Iniziamo. + +--- + +#### Prerequisiti + +Per usare OpenCode nel terminale, ti serve: + +1. Un emulatore di terminale moderno, come: + - [WezTerm](https://wezterm.org), cross-platform + - [Alacritty](https://alacritty.org), cross-platform + - [Ghostty](https://ghostty.org), Linux and macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux and macOS + +2. Le chiavi API dei provider LLM che vuoi usare. + +--- + +## Installa + +Il modo piu semplice per installare OpenCode e usare lo script di installazione. + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +Puoi anche installarlo con i seguenti comandi: + +- **Con Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **Con Homebrew su macOS e Linux** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > Ti consigliamo di usare il tap di OpenCode per avere le release piu aggiornate. La formula ufficiale `brew install opencode` e mantenuta dal team Homebrew e viene aggiornata meno spesso. + +- **Con Paru su Arch Linux** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[Consigliato: usa WSL] +Per la migliore esperienza su Windows, ti consigliamo di usare [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Offre prestazioni migliori e piena compatibilita con le funzionalita di OpenCode. +::: + +- **Con Chocolatey** + + ```bash + choco install opencode + ``` + +- **Con Scoop** + + ```bash + scoop install opencode + ``` + +- **Con NPM** + + ```bash + npm install -g opencode-ai + ``` + +- **Con Mise** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **Con Docker** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +Il supporto per installare OpenCode su Windows usando Bun e attualmente in lavorazione. + +Puoi anche scaricare il binario dalle [Releases](https://github.com/anomalyco/opencode/releases). + +--- + +## Configura + +Con OpenCode puoi usare qualsiasi provider LLM configurando le relative chiavi API. + +Se e la prima volta che usi provider LLM, ti consigliamo [OpenCode Zen](/docs/zen). +E una lista curata di modelli testati e verificati dal team di OpenCode. + +1. Esegui il comando `/connect` nella TUI, seleziona opencode e vai su [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. Accedi, aggiungi i dettagli di fatturazione e copia la tua chiave API. + +3. Incolla la tua chiave API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +In alternativa, puoi selezionare uno degli altri provider. [Scopri di piu](/docs/providers#directory). + +--- + +## Inizializza + +Ora che hai configurato un provider, puoi spostarti in un progetto su cui vuoi lavorare. + +```bash +cd /path/to/project +``` + +E avviare OpenCode. + +```bash +opencode +``` + +Poi inizializza OpenCode per il progetto eseguendo il comando seguente. + +```bash frame="none" +/init +``` + +Questo fara analizzare il progetto a OpenCode e creera un file `AGENTS.md` nella root del progetto. + +:::tip +Dovresti committare il file `AGENTS.md` del progetto su Git. +::: + +Questo aiuta OpenCode a capire la struttura del progetto e gli stili di codice usati. + +--- + +## Utilizzo + +Ora sei pronto a usare OpenCode sul tuo progetto. Sentiti libero di chiedergli qualsiasi cosa! + +Se e la prima volta che usi un agente di programmazione AI, ecco alcuni esempi che possono aiutare. + +--- + +### Fai domande + +Puoi chiedere a OpenCode di spiegarti la codebase. + +:::tip +Usa il tasto `@` per fare una ricerca fuzzy dei file nel progetto. +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +Questo e utile se c'e una parte della codebase su cui non hai lavorato. + +--- + +### Aggiungi funzionalità + +Puoi chiedere a OpenCode di aggiungere nuove funzionalita al progetto. Pero ti consigliamo prima di chiedergli di creare un piano. + +1. **Crea un piano** + + OpenCode ha una _Plan mode_ che disabilita la possibilita di fare modifiche e si limita a suggerire _come_ implementera la funzionalita. + + Passaci con il tasto **Tab**. Vedrai un indicatore nell'angolo in basso a destra. + + ```bash frame="none" title="Switch to Plan mode" + + ``` + + Ora descriviamo cosa vogliamo che faccia. + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + Devi dare a OpenCode abbastanza dettagli per capire cosa vuoi. Aiuta parlargli come se stessi parlando a uno sviluppatore junior del tuo team. + + :::tip + Dai a OpenCode molto contesto ed esempi per aiutarlo a capire cosa vuoi. + ::: + +2. **Itera sul piano** + + Una volta che ti da un piano, puoi dargli feedback o aggiungere piu dettagli. + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + + :::tip + Trascina e rilascia le immagini nel terminale per aggiungerle al prompt. + ::: + + OpenCode puo analizzare le immagini che gli dai e aggiungerle al prompt. Puoi farlo trascinando e rilasciando un'immagine nel terminale. + +3. **Implementa la funzionalita** + + Quando ti senti a tuo agio con il piano, torna in _Build mode_ premendo di nuovo il tasto **Tab**. + + ```bash frame="none" + + ``` + + E chiedigli di fare le modifiche. + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### Apporta modifiche + +Per modifiche piu semplici, puoi chiedere a OpenCode di implementarle direttamente senza dover prima rivedere un piano. + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +Assicurati di fornire abbastanza dettagli, cosi OpenCode fa le modifiche giuste. + +--- + +### Annulla modifiche + +Mettiamo che tu chieda a OpenCode di fare alcune modifiche. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Ma ti accorgi che non e quello che volevi. Puoi **annullare** le modifiche usando il comando `/undo`. + +```bash frame="none" +/undo +``` + +OpenCode ora ripristina le modifiche e mostra di nuovo il tuo messaggio originale. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Da qui puoi modificare il prompt e chiedere a OpenCode di riprovare. + +:::tip +Puoi eseguire `/undo` piu volte per annullare piu modifiche. +::: + +Oppure puoi **rifare** le modifiche usando il comando `/redo`. + +```bash frame="none" +/redo +``` + +--- + +## Condividi + +Le conversazioni che fai con OpenCode possono essere [condivise con il tuo team](/docs/share). + +```bash frame="none" +/share +``` + +Questo creera un link alla conversazione corrente e lo copiera negli appunti. + +:::note +Le conversazioni non vengono condivise per impostazione predefinita. +::: + +Ecco un'[esempio di conversazione](https://opencode.ai/s/4XP1fce5) con OpenCode. + +--- + +## Personalizza + +E tutto qui! Ora sei un pro nell'usare OpenCode. + +Per renderlo davvero tuo, ti consigliamo di [scegliere un tema](/docs/themes), [personalizzare i tasti rapidi](/docs/keybinds), [configurare i formatter](/docs/formatters), [creare comandi personalizzati](/docs/commands) o sperimentare con la [configurazione di OpenCode](/docs/config). diff --git a/packages/web/src/content/docs/it/keybinds.mdx b/packages/web/src/content/docs/it/keybinds.mdx new file mode 100644 index 00000000000..eb08c2c286a --- /dev/null +++ b/packages/web/src/content/docs/it/keybinds.mdx @@ -0,0 +1,192 @@ +--- +title: Scorciatoie +description: Personalizza le scorciatoie da tastiera. +--- + +OpenCode ha una lista di scorciatoie che puoi personalizzare tramite la configurazione di OpenCode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## Tasto leader + +OpenCode usa un tasto `leader` per la maggior parte delle scorciatoie. Questo evita conflitti nel terminale. + +Per impostazione predefinita, `ctrl+x` e il tasto leader e la maggior parte delle azioni richiede di premere prima il leader e poi la scorciatoia. Per esempio, per avviare una nuova sessione premi `ctrl+x` e poi `n`. + +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". + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## Scorciatoie del prompt desktop + +Il campo di input del prompt nell'app desktop di OpenCode supporta scorciatoie comuni in stile Readline/Emacs per modificare il testo. Sono integrate e al momento non configurabili tramite `opencode.json`. + +| Scorciatoia | Azione | +| ----------- | ------------------------------------------ | +| `ctrl+a` | Vai all'inizio della riga corrente | +| `ctrl+e` | Vai alla fine della riga corrente | +| `ctrl+b` | Sposta il cursore indietro di un carattere | +| `ctrl+f` | Sposta il cursore avanti di un carattere | +| `alt+b` | Sposta il cursore indietro di una parola | +| `alt+f` | Sposta il cursore avanti di una parola | +| `ctrl+d` | Elimina il carattere sotto il cursore | +| `ctrl+k` | Elimina fino alla fine della riga | +| `ctrl+u` | Elimina fino all'inizio della riga | +| `ctrl+w` | Elimina la parola precedente | +| `alt+d` | Elimina la parola successiva | +| `ctrl+t` | Scambia i caratteri | +| `ctrl+g` | Annulla popover / interrompe la risposta | + +--- + +## Shift+Enter + +Alcuni terminali non inviano di default i tasti modificatori insieme a Invio. Potrebbe essere necessario configurare il terminale per inviare `Shift+Enter` come sequenza di escape. + +### Windows Terminal + +Apri il tuo `settings.json` in: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +Aggiungi questo all'array `actions` a livello root: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Aggiungi questo all'array `keybindings` a livello root: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Salva il file e riavvia Windows Terminal oppure apri una nuova scheda. diff --git a/packages/web/src/content/docs/it/lsp.mdx b/packages/web/src/content/docs/it/lsp.mdx new file mode 100644 index 00000000000..765475dba07 --- /dev/null +++ b/packages/web/src/content/docs/it/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: Server LSP +description: OpenCode si integra con i tuoi server LSP. +--- + +OpenCode si integra con il tuo Language Server Protocol (LSP) per aiutare l'LLM a interagire con la tua codebase. Usa le diagnostiche per fornire feedback all'LLM. + +--- + +## Integrati + +OpenCode include diversi server LSP integrati per linguaggi popolari: + +| Server LSP | Estensioni | Requisiti | +| ------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| astro | .astro | Installazione automatica per progetti Astro | +| bash | .sh, .bash, .zsh, .ksh | Installazione automatica di bash-language-server | +| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | Installazione automatica per progetti C/C++ | +| csharp | .cs | `.NET SDK` installato | +| clojure-lsp | .clj, .cljs, .cljc, .edn | comando `clojure-lsp` disponibile | +| dart | .dart | comando `dart` disponibile | +| deno | .ts, .tsx, .js, .jsx, .mjs | comando `deno` disponibile (rileva automaticamente deno.json/deno.jsonc) | +| elixir-ls | .ex, .exs | comando `elixir` disponibile | +| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | dipendenza `eslint` nel progetto | +| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` installato | +| gleam | .gleam | comando `gleam` disponibile | +| gopls | .go | comando `go` disponibile | +| hls | .hs, .lhs | comando `haskell-language-server-wrapper` disponibile | +| jdtls | .java | `Java SDK (version 21+)` installato | +| kotlin-ls | .kt, .kts | Installazione automatica per progetti Kotlin | +| lua-ls | .lua | Installazione automatica per progetti Lua | +| nixd | .nix | comando `nixd` disponibile | +| ocaml-lsp | .ml, .mli | comando `ocamllsp` disponibile | +| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | dipendenza `oxlint` nel progetto | +| php intelephense | .php | Installazione automatica per progetti PHP | +| prisma | .prisma | comando `prisma` disponibile | +| pyright | .py, .pyi | dipendenza `pyright` installata | +| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | comandi `ruby` e `gem` disponibili | +| rust | .rs | comando `rust-analyzer` disponibile | +| sourcekit-lsp | .swift, .objc, .objcpp | `swift` installato (`xcode` su macOS) | +| svelte | .svelte | Installazione automatica per progetti Svelte | +| terraform | .tf, .tfvars | Installazione automatica dalle release GitHub | +| tinymist | .typ, .typc | Installazione automatica dalle release GitHub | +| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | dipendenza `typescript` nel progetto | +| vue | .vue | Installazione automatica per progetti Vue | +| yaml-ls | .yaml, .yml | Installazione automatica di Red Hat yaml-language-server | +| zls | .zig, .zon | comando `zig` disponibile | + +I server LSP vengono abilitati automaticamente quando viene rilevata una delle estensioni qui sopra e i requisiti sono soddisfatti. + +:::note +Puoi disabilitare il download automatico dei server LSP impostando la variabile d'ambiente `OPENCODE_DISABLE_LSP_DOWNLOAD` a `true`. +::: + +--- + +## Come funziona + +Quando opencode apre un file: + +1. Controlla l'estensione del file rispetto a tutti i server LSP abilitati. +2. Avvia il server LSP appropriato se non e gia in esecuzione. + +--- + +## Configura + +Puoi personalizzare i server LSP tramite la sezione `lsp` nella configurazione di opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +Ogni server LSP supporta i seguenti campi: + +| Proprieta | Tipo | Descrizione | +| ---------------- | -------- | ------------------------------------------------ | +| `disabled` | boolean | Imposta a `true` per disabilitare il server LSP | +| `command` | string[] | Il comando per avviare il server LSP | +| `extensions` | string[] | Estensioni file gestite da questo server LSP | +| `env` | object | Variabili d'ambiente da impostare all'avvio | +| `initialization` | object | Opzioni di inizializzazione da inviare al server | + +Vediamo alcuni esempi. + +--- + +### Variabili d'ambiente + +Usa la proprieta `env` per impostare variabili d'ambiente quando avvii il server LSP: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### Opzioni di inizializzazione + +Usa la proprieta `initialization` per passare opzioni di inizializzazione al server LSP. Sono impostazioni specifiche del server inviate durante la richiesta LSP `initialize`: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +Le opzioni di inizializzazione variano da server a server. Consulta la documentazione del tuo server LSP per le opzioni disponibili. +::: + +--- + +### Disabilitare i server LSP + +Per disabilitare **tutti** i server LSP globalmente, imposta `lsp` a `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +Per disabilitare un server LSP **specifico**, imposta `disabled` a `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### Server LSP personalizzati + +Puoi aggiungere server LSP personalizzati specificando il comando e le estensioni file: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## Informazioni aggiuntive + +### PHP Intelephense + +PHP Intelephense offre funzionalita premium tramite una chiave di licenza. Puoi fornire la chiave inserendo (solo) la chiave in un file di testo in: + +- Su macOS/Linux: `$HOME/intelephense/license.txt` +- Su Windows: `%USERPROFILE%/intelephense/license.txt` + +Il file deve contenere solo la chiave di licenza, senza contenuti aggiuntivi. diff --git a/packages/web/src/content/docs/it/mcp-servers.mdx b/packages/web/src/content/docs/it/mcp-servers.mdx new file mode 100644 index 00000000000..a067d99639e --- /dev/null +++ b/packages/web/src/content/docs/it/mcp-servers.mdx @@ -0,0 +1,511 @@ +--- +title: Server MCP +description: Aggiungi strumenti MCP locali e remoti. +--- + +Puoi aggiungere strumenti esterni a OpenCode usando il _Model Context Protocol_, o MCP. OpenCode supporta sia server locali sia remoti. + +Una volta aggiunti, gli strumenti MCP sono automaticamente disponibili all'LLM insieme agli strumenti integrati. + +--- + +#### Avvertenze + +Quando usi un server MCP, aggiunge contenuto al contesto. Questo puo' crescere rapidamente se hai molti strumenti. Per questo consigliamo di fare attenzione a quali server MCP abiliti. + +:::tip +I server MCP aumentano il contesto, quindi e' meglio essere prudenti su quali abilitare. +::: + +Alcuni server MCP, come il server MCP di GitHub, tendono ad aggiungere molti token e possono facilmente superare il limite di contesto. + +--- + +## Abilita + +Puoi definire server MCP nella tua [OpenCode Config](https://opencode.ai/docs/config/) sotto `mcp`. Aggiungi ogni MCP con un nome univoco. Puoi riferirti a quell'MCP per nome quando fai prompt all'LLM. + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +Puoi anche disabilitare un server impostando `enabled` a `false`. E' utile se vuoi disabilitare temporaneamente un server senza rimuoverlo dalla configurazione. + +--- + +### Sovrascrivere i default remoti + +Le organizzazioni possono fornire server MCP predefiniti tramite l'endpoint `.well-known/opencode`. Questi server possono essere disabilitati di default, lasciando agli utenti la possibilita' di fare opt-in su quelli necessari. + +Per abilitare un server specifico dalla configurazione remota dell'organizzazione, aggiungilo alla configurazione locale con `enabled: true`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +I valori della configurazione locale sovrascrivono i default remoti. Vedi [config precedence](/docs/config#precedence-order) per maggiori dettagli. + +--- + +## Locali + +Aggiungi server MCP locali impostando `type` a `"local"` dentro l'oggetto `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", + }, + }, + }, +} +``` + +Il comando e' come viene avviato il server MCP locale. Puoi anche passare un elenco di variabili d'ambiente. + +Per esempio, ecco come aggiungere il server MCP di test [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything). + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "mcp_everything": { + "type": "local", + "command": ["npx", "-y", "@modelcontextprotocol/server-everything"], + }, + }, +} +``` + +E per usarlo posso aggiungere `use the mcp_everything tool` ai miei prompt. + +```txt "mcp_everything" +use the mcp_everything tool to add the number 3 and 4 +``` + +--- + +#### Opzioni + +Ecco tutte le opzioni per configurare un server MCP locale. + +| Opzione | Tipo | Richiesto | Descrizione | +| ------------- | ------- | --------- | ------------------------------------------------------------------------------------ | +| `type` | String | Y | Tipo di connessione del server MCP, deve essere `"local"`. | +| `command` | Array | Y | Comando e argomenti per eseguire il server MCP. | +| `environment` | Object | | Variabili d'ambiente da impostare quando si esegue il server. | +| `enabled` | Boolean | | Abilita o disabilita il server MCP all'avvio. | +| `timeout` | Number | | Timeout in ms per recuperare gli strumenti dal server MCP. Default 5000 (5 secondi). | + +--- + +## Remoti + +Aggiungi server MCP remoti impostando `type` a `"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" + } + } + } +} +``` + +`url` e' l'URL del server MCP remoto e con l'opzione `headers` puoi passare un elenco di header. + +--- + +#### Opzioni + +| Opzione | Tipo | Richiesto | Descrizione | +| --------- | ------- | --------- | ------------------------------------------------------------------------------------ | +| `type` | String | Y | Tipo di connessione del server MCP, deve essere `"remote"`. | +| `url` | String | Y | URL del server MCP remoto. | +| `enabled` | Boolean | | Abilita o disabilita il server MCP all'avvio. | +| `headers` | Object | | Header da inviare con la richiesta. | +| `oauth` | Object | | Configurazione autenticazione OAuth. Vedi sezione [OAuth](#oauth) sotto. | +| `timeout` | Number | | Timeout in ms per recuperare gli strumenti dal server MCP. Default 5000 (5 secondi). | + +--- + +## OAuth + +OpenCode gestisce automaticamente l'autenticazione OAuth per i server MCP remoti. Quando un server richiede autenticazione, OpenCode: + +1. Rileva la risposta 401 e avvia il flusso OAuth +2. Usa **Dynamic Client Registration (RFC 7591)** se supportato dal server +3. Memorizza i token in modo sicuro per richieste future + +--- + +### Automatico + +Per la maggior parte dei server MCP con OAuth, non serve alcuna configurazione speciale. Basta configurare il server remoto: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "my-oauth-server": { + "type": "remote", + "url": "https://mcp.example.com/mcp" + } + } +} +``` + +Se il server richiede autenticazione, OpenCode ti chiedera' di autenticarti la prima volta che provi a usarlo. In caso contrario, puoi [attivare manualmente il flusso](#authenticating) con `opencode mcp auth `. + +--- + +### Pre-registrato + +Se hai credenziali client dal provider del server MCP, puoi configurarle: + +```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" + } + } + } +} +``` + +--- + +### Autenticazione + +Puoi avviare manualmente l'autenticazione o gestire le credenziali. + +Autentica con un server MCP specifico: + +```bash +opencode mcp auth my-oauth-server +``` + +Elenca tutti i server MCP e il loro stato di autenticazione: + +```bash +opencode mcp list +``` + +Rimuovi credenziali memorizzate: + +```bash +opencode mcp logout my-oauth-server +``` + +Il comando `mcp auth` aprira' il browser per l'autorizzazione. Dopo l'autorizzazione, OpenCode memorizzera' i token in modo sicuro in `~/.local/share/opencode/mcp-auth.json`. + +--- + +#### Disabilitare OAuth + +Se vuoi disabilitare l'OAuth automatico per un server (ad esempio per server che usano API key), imposta `oauth` a `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}" + } + } + } +} +``` + +--- + +#### Opzioni OAuth + +| Opzione | Tipo | Descrizione | +| -------------- | --------------- | --------------------------------------------------------------------------- | +| `oauth` | Object \| false | Oggetto config OAuth, o `false` per disabilitare l'auto-detection di OAuth. | +| `clientId` | String | OAuth client ID. Se non fornito, si prova la dynamic client registration. | +| `clientSecret` | String | OAuth client secret, se richiesto dal server di autorizzazione. | +| `scope` | String | Scope OAuth da richiedere durante l'autorizzazione. | + +#### Debug + +Se un server MCP remoto non riesce ad autenticarsi, puoi diagnosticare i problemi con: + +```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 +``` + +Il comando `mcp debug` mostra lo stato di autenticazione corrente, testa la connettivita' HTTP e prova il flusso di discovery OAuth. + +--- + +## Gestione + +I tuoi MCP sono disponibili come strumenti in OpenCode insieme agli strumenti integrati. Quindi puoi gestirli tramite la configurazione OpenCode come qualunque altro strumento. + +--- + +### Globale + +Questo significa che puoi abilitarli o disabilitarli globalmente. + +```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 + } +} +``` + +Possiamo anche usare un pattern glob per disabilitare tutti gli MCP corrispondenti. + +```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 + } +} +``` + +Qui stiamo usando il pattern glob `my-mcp*` per disabilitare tutti gli MCP. + +--- + +### Per agente + +Se hai molti server MCP, potresti volerli abilitare solo per agente e disabilitarli globalmente. Per farlo: + +1. Disabilitalo globalmente come strumento. +2. Nella tua [config dell'agente](/docs/agents#tools), abilita il server MCP come strumento. + +```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 + } + } + } +} +``` + +--- + +#### Pattern glob + +Il pattern glob usa semplici regole di globbing: + +- `*` corrisponde a zero o piu' caratteri qualsiasi (ad esempio `"my-mcp*"` corrisponde a `my-mcp_search`, `my-mcp_list`, ecc.) +- `?` corrisponde esattamente a un carattere +- Tutti gli altri caratteri corrispondono letteralmente + +:::note +Gli strumenti del server MCP vengono registrati con il nome del server come prefisso, quindi per disabilitare tutti gli strumenti di un server e' sufficiente usare: + +``` +"mymcpservername_*": false +``` + +::: + +--- + +## Esempi + +Qui sotto trovi esempi di alcuni server MCP comuni. Puoi inviare una PR se vuoi documentare altri server. + +--- + +### Sentry + +Aggiungi il [server MCP di Sentry](https://mcp.sentry.dev) per interagire con i tuoi progetti e le issue di Sentry. + +```json title="opencode.json" {4-8} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "sentry": { + "type": "remote", + "url": "https://mcp.sentry.dev/mcp", + "oauth": {} + } + } +} +``` + +Dopo aver aggiunto la configurazione, autentica con Sentry: + +```bash +opencode mcp auth sentry +``` + +Questo aprira' una finestra del browser per completare il flusso OAuth e collegare OpenCode al tuo account Sentry. + +Una volta autenticato, puoi usare gli strumenti Sentry nei tuoi prompt per interrogare issue, progetti e dati sugli errori. + +```txt "use sentry" +Show me the latest unresolved issues in my project. use sentry +``` + +--- + +### Context7 + +Aggiungi il [server MCP Context7](https://github.com/upstash/context7) per cercare nella documentazione. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "context7": { + "type": "remote", + "url": "https://mcp.context7.com/mcp" + } + } +} +``` + +Se ti sei registrato per un account gratuito, puoi usare la tua API key e ottenere rate limit piu' alti. + +```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}" + } + } + } +} +``` + +Qui assumiamo che tu abbia impostato la variabile d'ambiente `CONTEXT7_API_KEY`. + +Aggiungi `use context7` ai tuoi prompt per usare il server MCP Context7. + +```txt "use context7" +Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 +``` + +In alternativa, puoi aggiungere qualcosa del genere al tuo [AGENTS.md](/docs/rules/). + +```md title="AGENTS.md" +When you need to search docs, use `context7` tools. +``` + +--- + +### Grep by Vercel + +Aggiungi il server MCP [Grep by Vercel](https://grep.app) per cercare snippet di codice su GitHub. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "gh_grep": { + "type": "remote", + "url": "https://mcp.grep.app" + } + } +} +``` + +Dato che abbiamo chiamato il nostro server MCP `gh_grep`, puoi aggiungere `use the gh_grep tool` ai tuoi prompt per fare in modo che l'agente lo usi. + +```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 +``` + +In alternativa, puoi aggiungere qualcosa del genere al tuo [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/it/models.mdx b/packages/web/src/content/docs/it/models.mdx new file mode 100644 index 00000000000..7ac17115e76 --- /dev/null +++ b/packages/web/src/content/docs/it/models.mdx @@ -0,0 +1,222 @@ +--- +title: Modelli +description: Configurare un provider LLM e un modello. +--- + +OpenCode usa [AI SDK](https://ai-sdk.dev/) e [Models.dev](https://models.dev) per supportare **75+ provider LLM** e supporta anche l'esecuzione di modelli locali. + +--- + +## Provider + +I provider piu popolari sono precaricati per impostazione predefinita. Se hai aggiunto le credenziali di un provider tramite il comando `/connect`, saranno disponibili quando avvii OpenCode. + +[Scopri di piu](/docs/providers) sui provider. + +--- + +## Seleziona un modello + +Dopo aver configurato il provider, puoi selezionare il modello che vuoi digitando: + +```bash frame="none" +/models +``` + +--- + +## Modelli consigliati + +Esistono moltissimi modelli, e ne escono di nuovi ogni settimana. + +:::tip +Valuta di usare uno dei modelli che consigliamo. +::: + +Tuttavia, solo alcuni sono davvero bravi sia a generare codice sia a chiamare strumenti. + +Ecco alcuni modelli che funzionano bene con OpenCode, in nessun ordine particolare. (Non e una lista esaustiva e potrebbe non essere aggiornata): + +- GPT 5.2 +- GPT 5.1 Codex +- Claude Opus 4.5 +- Claude Sonnet 4.5 +- Minimax M2.1 +- Gemini 3 Pro + +--- + +## Imposta un predefinito + +Per impostarne uno come modello predefinito, puoi impostare la chiave `model` nella config di OpenCode. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +Qui l'ID completo e `provider_id/model_id`. Per esempio, se usi [OpenCode Zen](/docs/zen), useresti `opencode/gpt-5.1-codex` per GPT 5.1 Codex. + +Se hai configurato un [provider personalizzato](/docs/providers#custom), `provider_id` e la chiave nella sezione `provider` della config e `model_id` e la chiave in `provider.models`. + +--- + +## Configurazione modelli + +Puoi configurare globalmente le opzioni di un modello tramite la config. + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +Qui stiamo configurando impostazioni globali per due modelli integrati: `gpt-5` quando viene usato tramite il provider `openai` e `claude-sonnet-4-20250514` quando viene usato tramite il provider `anthropic`. +I nomi di provider e modelli integrati si trovano su [Models.dev](https://models.dev). + +Puoi anche configurare queste opzioni per gli agenti che usi. La config dell'agente sovrascrive le opzioni globali definite qui. [Scopri di piu](/docs/agents/#additional). + +Puoi anche definire varianti personalizzate che estendono quelle integrate. Le varianti ti permettono di configurare impostazioni diverse per lo stesso modello senza creare voci duplicate: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## Varianti + +Molti modelli supportano piu varianti con configurazioni diverse. OpenCode include varianti predefinite integrate per i provider piu comuni. + +### Varianti integrate + +OpenCode include varianti predefinite per molti provider: + +**Anthropic**: + +- `high` - High thinking budget (default) +- `max` - Maximum thinking budget + +**OpenAI**: + +Varies by model but roughly: + +- `none` - No reasoning +- `minimal` - Minimal reasoning effort +- `low` - Low reasoning effort +- `medium` - Medium reasoning effort +- `high` - High reasoning effort +- `xhigh` - Extra high reasoning effort + +**Google**: + +- `low` - Lower effort/token budget +- `high` - Higher effort/token budget + +:::tip +Questa lista non e completa. Anche molti altri provider hanno default integrati. +::: + +### Varianti personalizzate + +Puoi sovrascrivere varianti esistenti o aggiungerne di tue: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### Ciclare tra varianti + +Usa il keybind `variant_cycle` per passare rapidamente tra le varianti. [Scopri di piu](/docs/keybinds). + +--- + +## Caricamento modelli + +Quando OpenCode si avvia, controlla i modelli in questo ordine di priorita: + +1. Il flag da riga di comando `--model` o `-m`. Il formato e lo stesso della config: `provider_id/model_id`. + +2. La lista dei modelli nella config di OpenCode. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + + Qui il formato e `provider/model`. + +3. L'ultimo modello usato. + +4. Il primo modello in base a una priorita interna. diff --git a/packages/web/src/content/docs/it/modes.mdx b/packages/web/src/content/docs/it/modes.mdx new file mode 100644 index 00000000000..82e2058700f --- /dev/null +++ b/packages/web/src/content/docs/it/modes.mdx @@ -0,0 +1,330 @@ +--- +title: Modalità +description: Modalita diverse per casi d'uso diversi. +--- + +:::caution +Le modalita ora si configurano tramite l'opzione `agent` nella configurazione di opencode. L'opzione +`mode` e ora deprecata. [Scopri di piu](/docs/agents). +::: + +Le modalita in opencode ti permettono di personalizzare comportamento, strumenti e prompt per casi d'uso diversi. + +Include due modalita integrate: **build** e **plan**. Puoi personalizzarle oppure configurarne di tue tramite la configurazione di opencode. + +Puoi passare da una modalita all'altra durante una sessione oppure configurarle nel file di configurazione. + +--- + +## Integrate + +opencode include due modalita integrate. + +--- + +### Build + +Build e la modalita **predefinita** con tutti gli strumenti abilitati. E la modalita standard per il lavoro di sviluppo quando ti serve accesso completo alle operazioni sui file e ai comandi di sistema. + +--- + +### Plan + +Una modalita limitata pensata per pianificazione e analisi. In modalita plan, i seguenti strumenti sono disabilitati per impostazione predefinita: + +- `write` - Non puo creare nuovi file +- `edit` - Non puo modificare file esistenti, tranne i file in `.opencode/plans/*.md` per dettagliare il piano +- `patch` - Non puo applicare patch +- `bash` - Non puo eseguire comandi shell + +Questa modalita e utile quando vuoi che l'AI analizzi il codice, suggerisca modifiche o crei piani senza apportare modifiche effettive alla codebase. + +--- + +## Cambiare modalità + +Puoi cambiare modalita durante una sessione usando il tasto _Tab_. In alternativa, puoi usare il keybind `switch_mode` che hai configurato. + +Vedi anche: [Formatter](/docs/formatters) per informazioni sulla configurazione della formattazione del codice. + +--- + +## Configurazione + +Puoi personalizzare le modalita integrate o crearne di tue tramite configurazione. Le modalita si possono configurare in due modi: + +### Configurazione JSON + +Configura le modalita nel file di configurazione `opencode.json`: + +```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 + } + } + } +} +``` + +### Configurazione Markdown + +Puoi anche definire modalita usando file markdown. Mettili in: + +- Globale: `~/.config/opencode/modes/` +- Progetto: `.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. +``` + +Il nome del file markdown diventa il nome della modalita (ad es. `review.md` crea una modalita `review`). + +Vediamo queste opzioni di configurazione nel dettaglio. + +--- + +### Modello + +Usa la configurazione `model` per sovrascrivere il modello predefinito per questa modalita. E utile per usare modelli diversi ottimizzati per task diversi: per esempio, un modello piu veloce per la pianificazione e uno piu capace per l'implementazione. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### Temperatura + +Controlla casualita e creativita delle risposte dell'AI con la configurazione `temperature`. Valori piu bassi rendono le risposte piu focalizzate e deterministiche, mentre valori piu alti aumentano creativita e variabilita. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +I valori di temperatura di solito vanno da 0.0 a 1.0: + +- **0.0-0.2**: risposte molto focalizzate e deterministiche, ideali per analisi del codice e pianificazione +- **0.3-0.5**: risposte bilanciate con un po' di creativita, buone per task di sviluppo generici +- **0.6-1.0**: risposte piu creative e variabili, utili per brainstorming ed esplorazione + +```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}" + } + } +} +``` + +Se non viene specificata alcuna temperatura, opencode usa i default specifici del modello (tipicamente 0 per la maggior parte dei modelli, 0.55 per i modelli Qwen). + +--- + +### Prompt + +Specifica un file di prompt di sistema personalizzato per questa modalita con la configurazione `prompt`. Il file dovrebbe contenere istruzioni specifiche per lo scopo della modalita. + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Questo percorso e relativo a dove si trova il file di configurazione. Quindi funziona +sia per la configurazione globale di opencode sia per quella specifica del progetto. + +--- + +### Strumenti + +Controlla quali strumenti sono disponibili in questa modalita con la configurazione `tools`. Puoi abilitare o disabilitare strumenti specifici impostandoli a `true` o `false`. + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +Se non specifichi gli strumenti, tutti gli strumenti sono abilitati per impostazione predefinita. + +--- + +#### Strumenti disponibili + +Ecco tutti gli strumenti che possono essere controllati tramite la configurazione della modalita. + +| Strumento | Descrizione | +| ----------- | --------------------------------- | +| `bash` | Esegue comandi shell | +| `edit` | Modifica file esistenti | +| `write` | Crea nuovi file | +| `read` | Legge contenuti dei file | +| `grep` | Cerca nei contenuti dei file | +| `glob` | Trova file per pattern | +| `list` | Elenca contenuti di una directory | +| `patch` | Applica patch ai file | +| `todowrite` | Gestisce liste todo | +| `todoread` | Legge liste todo | +| `webfetch` | Recupera contenuti web | + +--- + +## Modalità personalizzate + +Puoi creare modalita personalizzate aggiungendole alla configurazione. Ecco esempi con entrambi gli approcci: + +### Usando la configurazione JSON + +```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 + } + } + } +} +``` + +### Usando file markdown + +Crea file di modalita in `.opencode/modes/` per modalita specifiche del progetto oppure in `~/.config/opencode/modes/` per modalita globali: + +```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 +``` + +--- + +### Casi d'uso + +Ecco alcuni casi d'uso comuni per le diverse modalita. + +- **Modalita Build**: sviluppo completo con tutti gli strumenti abilitati +- **Modalita Plan**: analisi e pianificazione senza apportare modifiche +- **Modalita Review**: code review con accesso in sola lettura piu strumenti di documentazione +- **Modalita Debug**: focalizzata sull'investigazione con strumenti bash e read abilitati +- **Modalita Docs**: scrittura di documentazione con operazioni sui file ma senza comandi di sistema + +Potresti anche trovare che modelli diversi funzionano meglio per casi d'uso diversi. diff --git a/packages/web/src/content/docs/it/network.mdx b/packages/web/src/content/docs/it/network.mdx new file mode 100644 index 00000000000..866494430a8 --- /dev/null +++ b/packages/web/src/content/docs/it/network.mdx @@ -0,0 +1,57 @@ +--- +title: Rete +description: Configura proxy e certificati personalizzati. +--- + +OpenCode supporta le variabili d'ambiente standard per i proxy e certificati personalizzati per ambienti di rete enterprise. + +--- + +## Proxy + +OpenCode rispetta le variabili d'ambiente standard dei proxy. + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +La TUI comunica con un server HTTP locale. Devi bypassare il proxy per questa connessione per evitare loop di instradamento. +::: + +Puoi configurare porta e hostname del server usando i [flag della CLI](/docs/cli#run). + +--- + +### Autenticazione + +Se il proxy richiede autenticazione basic, includi le credenziali nell'URL. + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +Evita di hardcodare le password. Usa variabili d'ambiente o un archivio sicuro per le credenziali. +::: + +Per proxy che richiedono autenticazioni avanzate come NTLM o Kerberos, valuta l'uso di un LLM Gateway che supporti il tuo metodo di autenticazione. + +--- + +## Certificati personalizzati + +Se la tua organizzazione usa CA personalizzate per connessioni HTTPS, configura OpenCode in modo che si fidi di esse. + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +Questo funziona sia per connessioni tramite proxy sia per l'accesso diretto alle API. diff --git a/packages/web/src/content/docs/it/permissions.mdx b/packages/web/src/content/docs/it/permissions.mdx new file mode 100644 index 00000000000..d0f014a8415 --- /dev/null +++ b/packages/web/src/content/docs/it/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: Permessi +description: Controlla quali azioni richiedono approvazione prima di essere eseguite. +--- + +OpenCode usa la configurazione `permission` per decidere se una determinata azione deve essere eseguita automaticamente, se deve chiederti conferma o se deve essere bloccata. + +A partire da `v1.1.1`, la vecchia configurazione booleana `tools` e' deprecata ed e' stata incorporata in `permission`. La vecchia configurazione `tools` e' ancora supportata per retrocompatibilita'. + +--- + +## Azioni + +Ogni regola di permesso si risolve in uno tra: + +- `"allow"` — esegui senza approvazione +- `"ask"` — chiedi approvazione +- `"deny"` — blocca l'azione + +--- + +## Configurazione + +Puoi impostare i permessi globalmente (con `*`) e sovrascrivere quelli di strumenti specifici. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +Puoi anche impostare tutti i permessi in una sola volta: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## Regole granulari (sintassi a oggetto) + +Per la maggior parte dei permessi, puoi usare un oggetto per applicare azioni diverse in base all'input dello strumento. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +Le regole vengono valutate per corrispondenza di pattern e **vince l'ultima regola che corrisponde**. Un pattern comune e' mettere prima la regola jolly `"*"` e poi regole piu' specifiche. + +### Wildcard + +I pattern dei permessi usano un semplice matching con wildcard: + +- `*` corrisponde a zero o piu' caratteri qualsiasi +- `?` corrisponde esattamente a un carattere +- Tutti gli altri caratteri corrispondono letteralmente + +### Espansione della home directory + +Puoi usare `~` o `$HOME` all'inizio di un pattern per riferirti alla tua home directory. Questo e' particolarmente utile per le regole [`external_directory`](#external-directories). + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### Directory esterne + +Usa `external_directory` per consentire chiamate a strumenti che toccano percorsi al di fuori della directory di lavoro da cui e' stato avviato OpenCode. Si applica a qualsiasi strumento che accetta un path come input (ad esempio `read`, `edit`, `list`, `glob`, `grep` e molti comandi `bash`). + +L'espansione della home (come `~/...`) influisce solo su come viene scritto un pattern. Non rende un percorso esterno parte della workspace corrente, quindi i path fuori dalla directory di lavoro devono comunque essere consentiti tramite `external_directory`. + +Per esempio, questo consente l'accesso a tutto sotto `~/projects/personal/`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +Qualsiasi directory consentita qui eredita gli stessi default della workspace corrente. Dato che [`read` di default e' `allow`](#defaults), anche le letture sono consentite per le voci sotto `external_directory` a meno di sovrascritture. Aggiungi regole esplicite quando uno strumento deve essere limitato su questi path, ad esempio bloccando le modifiche ma lasciando consentite le letture: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +Mantieni l'elenco limitato a percorsi fidati e aggiungi regole extra di allow/deny quando serve per altri strumenti (ad esempio `bash`). + +--- + +## Permessi disponibili + +I permessi di OpenCode sono indicizzati per nome dello strumento, piu' un paio di guardrail di sicurezza: + +- `read` — lettura di un file (corrisponde al percorso del file) +- `edit` — tutte le modifiche ai file (include `edit`, `write`, `patch`, `multiedit`) +- `glob` — ricerca file tramite glob (corrisponde al pattern glob) +- `grep` — ricerca nel contenuto (corrisponde al pattern regex) +- `list` — elenco file in una directory (corrisponde al path della directory) +- `bash` — esecuzione comandi di shell (corrisponde a comandi parsati come `git status --porcelain`) +- `task` — avvio subagenti (corrisponde al tipo di subagente) +- `skill` — caricamento di una skill (corrisponde al nome della skill) +- `lsp` — esecuzione query LSP (attualmente non granulare) +- `todoread`, `todowrite` — lettura/aggiornamento della todo list +- `webfetch` — fetch di un URL (corrisponde all'URL) +- `websearch`, `codesearch` — ricerca web/codice (corrisponde alla query) +- `external_directory` — si attiva quando uno strumento tocca percorsi fuori dalla working directory del progetto +- `doom_loop` — si attiva quando la stessa chiamata a uno strumento si ripete 3 volte con input identico + +--- + +## Default + +Se non specifichi nulla, OpenCode parte da default permissivi: + +- La maggior parte dei permessi di default e' `"allow"`. +- `doom_loop` ed `external_directory` di default sono `"ask"`. +- `read` e' `"allow"`, ma i file `.env` sono negati di default: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## Cosa fa "Ask" + +Quando OpenCode chiede approvazione, la UI offre tre esiti: + +- `once` — approva solo questa richiesta +- `always` — approva richieste future che corrispondono ai pattern suggeriti (per il resto della sessione corrente di OpenCode) +- `reject` — nega la richiesta + +L'insieme di pattern che `always` approverebbe e' fornito dallo strumento (ad esempio, le approvazioni per bash in genere mettono in whitelist un prefisso di comando sicuro come `git status*`). + +--- + +## Agenti + +Puoi sovrascrivere i permessi per agente. I permessi dell'agente vengono uniti alla configurazione globale e le regole dell'agente hanno precedenza. [Scopri di piu'](/docs/agents#permissions) sui permessi degli agenti. + +:::note +Fai riferimento alla sezione [Regole granulari (sintassi a oggetto)](#granular-rules-object-syntax) per esempi piu' dettagliati di pattern matching. +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +Puoi anche configurare i permessi dell'agente in Markdown: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +Usa il pattern matching per comandi con argomenti. `"grep *"` consente `grep pattern file.txt`, mentre `"grep"` da solo lo bloccherebbe. Comandi come `git status` funzionano per il comportamento di default ma richiedono un permesso esplicito (come `"git status *"`) quando vengono passati argomenti. +::: diff --git a/packages/web/src/content/docs/it/plugins.mdx b/packages/web/src/content/docs/it/plugins.mdx new file mode 100644 index 00000000000..ea73f40ffdd --- /dev/null +++ b/packages/web/src/content/docs/it/plugins.mdx @@ -0,0 +1,384 @@ +--- +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. + +Per esempi, dai un'occhiata ai [plugin](/docs/ecosystem#plugins) creati dalla community. + +--- + +## Usare un plugin + +Ci sono due modi per caricare i plugin. + +--- + +### Da file locali + +Metti file JavaScript o TypeScript nella directory dei plugin. + +- `.opencode/plugins/` - plugin a livello progetto +- `~/.config/opencode/plugins/` - plugin globali + +I file in queste directory vengono caricati automaticamente all'avvio. + +--- + +### Da npm + +Specifica i pacchetti npm nel tuo file di configurazione. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +Sono supportati sia pacchetti npm normali sia scoped. + +Sfoglia i plugin disponibili nell'[ecosistema](/docs/ecosystem#plugins). + +--- + +### Come vengono installati i plugin + +I **plugin npm** vengono installati automaticamente usando Bun all'avvio. I pacchetti e le loro dipendenze vengono cache-ati in `~/.cache/opencode/node_modules/`. + +I **plugin locali** vengono caricati direttamente dalla directory dei plugin. Per usare pacchetti esterni, devi creare un `package.json` nella directory di configurazione (vedi [Dipendenze](#dependencies)) oppure pubblicare il plugin su npm e [aggiungerlo alla configurazione](/docs/config#plugins). + +--- + +### Ordine di caricamento + +I plugin vengono caricati da tutte le sorgenti e tutti gli hook vengono eseguiti in sequenza. L'ordine di caricamento e': + +1. Config globale (`~/.config/opencode/opencode.json`) +2. Config di progetto (`opencode.json`) +3. Directory plugin globale (`~/.config/opencode/plugins/`) +4. Directory plugin di progetto (`.opencode/plugins/`) + +I pacchetti npm duplicati con lo stesso nome e versione vengono caricati una sola volta. Tuttavia, un plugin locale e un plugin npm con nomi simili vengono entrambi caricati separatamente. + +--- + +## 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. + +--- + +### Dipendenze + +I plugin locali e gli strumenti personalizzati possono usare pacchetti npm esterni. Aggiungi un `package.json` alla tua directory di configurazione con le dipendenze di cui hai bisogno. + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +OpenCode esegue `bun install` all'avvio per installarle. I tuoi plugin e strumenti potranno poi importarle. + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### Struttura base + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +La funzione del plugin riceve: + +- `project`: informazioni sul progetto corrente. +- `directory`: la working directory corrente. +- `worktree`: il path del worktree git. +- `client`: un client SDK di opencode per interagire con l'AI. +- `$`: la [shell API](https://bun.com/docs/runtime/shell) di Bun per eseguire comandi. + +--- + +### Supporto TypeScript + +Per i plugin TypeScript, puoi importare i tipi dal pacchetto plugin: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### Eventi + +I plugin possono sottoscrivere eventi come mostrato sotto nella sezione Esempi. Ecco l'elenco dei diversi eventi disponibili. + +#### Eventi dei comandi + +- `command.executed` + +#### Eventi dei file + +- `file.edited` +- `file.watcher.updated` + +#### Eventi di installazione + +- `installation.updated` + +#### Eventi LSP + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### Eventi dei messaggi + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### Eventi dei permessi + +- `permission.asked` +- `permission.replied` + +#### Eventi del server + +- `server.connected` + +#### Eventi delle sessioni + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### Eventi della todo + +- `todo.updated` + +#### Eventi della shell + +- `shell.env` + +#### Eventi degli strumenti + +- `tool.execute.after` +- `tool.execute.before` + +#### Eventi TUI + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## Esempi + +Ecco alcuni esempi di plugin che puoi usare per estendere opencode. + +--- + +### Invia notifiche + +Invia notifiche quando avvengono certi eventi: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +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. +::: + +--- + +### Protezione .env + +Impedisci a opencode di leggere i file `.env`: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### Inietta variabili d'ambiente + +Inietta variabili d'ambiente in tutte le esecuzioni di shell (strumenti AI e terminale utente): + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### Strumenti personalizzati + +I plugin possono anche aggiungere strumenti personalizzati a opencode: + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +L'helper `tool` crea uno strumento personalizzato che opencode puo' 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 +- `execute`: funzione eseguita quando lo strumento viene chiamato + +I tuoi strumenti personalizzati saranno disponibili in opencode insieme agli strumenti integrati. + +--- + +### Logging + +Usa `client.app.log()` invece di `console.log` per logging strutturato: + +```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" }, + }, + }) +} +``` + +Livelli: `debug`, `info`, `warn`, `error`. Vedi la [documentazione SDK](https://opencode.ai/docs/sdk) per i dettagli. + +--- + +### Hook di compaction + +Personalizza il contesto incluso quando una sessione viene compattata: + +```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 +`) + }, + } +} +``` + +L'hook `experimental.session.compacting` scatta prima che l'LLM generi un riassunto di continuazione. Usalo per iniettare contesto specifico di dominio che il prompt di compaction predefinito potrebbe non includere. + +Puoi anche sostituire completamente il prompt di compaction impostando `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. +` + }, + } +} +``` + +Quando `output.prompt` e' 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 new file mode 100644 index 00000000000..11ed9e141f0 --- /dev/null +++ b/packages/web/src/content/docs/it/providers.mdx @@ -0,0 +1,1886 @@ +--- +title: Provider +description: Usa qualsiasi provider LLM in OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console + +OpenCode usa [AI SDK](https://ai-sdk.dev/) e [Models.dev](https://models.dev) per supportare **oltre 75 provider LLM** e anche modelli locali. + +Per aggiungere un provider devi: + +1. Aggiungere le API key del provider con il comando `/connect`. +2. Configurare il provider nella configurazione di OpenCode. + +--- + +### Credenziali + +Quando aggiungi le API key di un provider con `/connect`, vengono salvate +in `~/.local/share/opencode/auth.json`. + +--- + +### Configurazione + +Puoi personalizzare i provider tramite la sezione `provider` nella +configurazione di OpenCode. + +--- + +#### URL base + +Puoi personalizzare l'URL base per qualsiasi provider impostando l'opzione `baseURL`. E utile quando usi servizi proxy o endpoint personalizzati. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen e una lista di modelli forniti dal team OpenCode, testati e +verificati per funzionare bene con OpenCode. [Scopri di piu](/docs/zen). + +:::tip +Se sei all'inizio, ti consigliamo di partire da OpenCode Zen. +::: + +1. Esegui `/connect` nella TUI, seleziona opencode e vai su [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. Accedi, aggiungi i dati di fatturazione e copia la tua API key. + +3. Incolla la tua API key. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui `/models` nella TUI per vedere la lista di modelli consigliati. + + ```txt + /models + ``` + +Funziona come qualsiasi altro provider in OpenCode ed e totalmente opzionale. + +--- + +## Elenco + +Vediamo alcuni provider nel dettaglio. Se vuoi aggiungerne uno +all'elenco, apri pure una PR. + +:::note +Non vedi un provider qui? Invia una PR. +::: + +--- + +### 302.AI + +1. Vai alla [console di 302.AI](https://302.ai/), crea un account e genera una chiave API. + +2. Esegui il comando `/connect` e cerca **302.AI**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di 302.AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello. + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +Per usare Amazon Bedrock con OpenCode: + +1. Vai al **Model catalog** nella console Amazon Bedrock e richiedi + accesso ai modelli che vuoi usare. + + :::tip + Devi avere accesso al modello che vuoi in Amazon Bedrock. + ::: + +2. **Configura l'autenticazione** usando uno dei seguenti metodi: + + #### Variabili d'ambiente (Avvio rapido) + + Imposta una di queste variabili d'ambiente mentre esegui opencode: + + ```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode + ``` + + Oppure aggiungile al tuo profilo bash: + + ```bash title="~/.bash_profile" + export AWS_PROFILE=my-dev-profile + export AWS_REGION=us-east-1 + ``` + + #### File di configurazione (Consigliato) + + Per configurazione specifica del progetto o persistente, usa `opencode.json`: + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile" + } + } + } + } + ``` + + **Opzioni disponibili:** + - `region` - Regione AWS (ad es. `us-east-1`, `eu-west-1`) + - `profile` - Profilo AWS nominato da `~/.aws/credentials` + - `endpoint` - URL endpoint personalizzato per VPC endpoints (alias per l'opzione generica `baseURL`) + + :::tip + Le opzioni del file di configurazione hanno la precedenza sulle variabili d'ambiente. + ::: + + #### Avanzato: VPC Endpoints + + Se stai usando VPC endpoints per Bedrock: + + ```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 + L'opzione `endpoint` è un alias per l'opzione generica `baseURL`, usando terminologia specifica AWS. Se vengono specificati sia `endpoint` sia `baseURL`, `endpoint` ha la precedenza. + ::: + + #### Metodi di autenticazione + - **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: Crea un utente IAM e genera chiavi di accesso nella Console AWS + - **`AWS_PROFILE`**: Usa profili nominati da `~/.aws/credentials`. Configura prima con `aws configure --profile my-profile` o `aws sso login` + - **`AWS_BEARER_TOKEN_BEDROCK`**: Genera chiavi API a lungo termine dalla console Amazon Bedrock + - **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: Per EKS IRSA (IAM Roles for Service Accounts) o altri ambienti Kubernetes con federazione OIDC. Queste variabili d'ambiente vengono iniettate automaticamente da Kubernetes quando usi le annotazioni del service account. + + #### Precedenza autenticazione + + Amazon Bedrock usa la seguente priorità di autenticazione: + 1. **Bearer Token** - Variabile d'ambiente `AWS_BEARER_TOKEN_BEDROCK` o token dal comando `/connect` + 2. **AWS Credential Chain** - Profilo, chiavi di accesso, credenziali condivise, ruoli IAM, Web Identity Tokens (EKS IRSA), metadati istanza + + :::note + Quando è impostato un bearer token (tramite `/connect` o `AWS_BEARER_TOKEN_BEDROCK`), ha la precedenza su tutti i metodi di credenziali AWS inclusi i profili configurati. + ::: + +3. Esegui il comando `/models` per selezionare il modello che vuoi. + + ```txt + /models + ``` + +:::note +Per profili di inferenza personalizzati, usa il nome del modello e del provider nella chiave e imposta la proprietà `id` all'arn. Questo assicura una cache corretta: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. Una volta registrato, esegui il comando `/connect` e seleziona Anthropic. + + ```txt + /connect + ``` + +2. Qui puoi selezionare l'opzione **Claude Pro/Max**: aprirà il tuo browser + e ti chiederà di autenticarti. + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. Ora tutti i modelli Anthropic dovrebbero essere disponibili quando usi il comando `/models`. + + ```txt + /models + ``` + +:::info +L'uso dell'abbonamento Claude Pro/Max in OpenCode non è ufficialmente supportato da [Anthropic](https://anthropic.com). +::: + +##### Usare chiavi API + +Puoi anche selezionare **Create an API Key** se non hai un abbonamento Pro/Max. Aprirà il browser, ti chiederà di accedere ad Anthropic e ti darà un codice da incollare nel terminale. + +Oppure se hai già una chiave API, puoi selezionare **Manually enter API Key** e incollarla nel terminale. + +--- + +### Azure OpenAI + +:::note +Se incontri errori "I'm sorry, but I cannot assist with that request", prova a cambiare il filtro contenuti da **DefaultV2** a **Default** nella tua risorsa Azure. +::: + +1. Vai al [portale Azure](https://portal.azure.com/) e crea una risorsa **Azure OpenAI**. Ti serviranno: + - **Resource name**: Diventa parte del tuo endpoint API (`https://RESOURCE_NAME.openai.azure.com/`) + - **API key**: O `KEY 1` o `KEY 2` dalla tua risorsa + +2. Vai su [Azure AI Foundry](https://ai.azure.com/) e fai il deploy di un modello. + + :::note + Il nome del deployment deve corrispondere al nome del modello affinché opencode funzioni correttamente. + ::: + +3. Esegui il comando `/connect` e cerca **Azure**. + + ```txt + /connect + ``` + +4. Inserisci la tua chiave API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Imposta il nome della risorsa come variabile d'ambiente: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + Oppure aggiungilo al tuo profilo bash: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. Esegui il comando `/models` per selezionare il tuo modello deployato. + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. Vai al [portale Azure](https://portal.azure.com/) e crea una risorsa **Azure OpenAI**. Ti serviranno: + - **Resource name**: Diventa parte del tuo endpoint API (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) + - **API key**: O `KEY 1` o `KEY 2` dalla tua risorsa + +2. Vai su [Azure AI Foundry](https://ai.azure.com/) e fai il deploy di un modello. + + :::note + Il nome del deployment deve corrispondere al nome del modello affinché opencode funzioni correttamente. + ::: + +3. Esegui il comando `/connect` e cerca **Azure Cognitive Services**. + + ```txt + /connect + ``` + +4. Inserisci la tua chiave API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Imposta il nome della risorsa come variabile d'ambiente: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + Oppure aggiungilo al tuo profilo bash: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. Esegui il comando `/models` per selezionare il tuo modello deployato. + + ```txt + /models + ``` + +--- + +### Baseten + +1. Vai su [Baseten](https://app.baseten.co/), crea un account e genera una chiave API. + +2. Esegui il comando `/connect` e cerca **Baseten**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di Baseten. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello. + + ```txt + /models + ``` + +--- + +### Cerebras + +1. Vai alla [console di Cerebras](https://inference.cerebras.ai/), crea un account e genera una chiave API. + +2. Esegui il comando `/connect` e cerca **Cerebras**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di Cerebras. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello come _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +Cloudflare AI Gateway ti permette di accedere a modelli di OpenAI, Anthropic, Workers AI e altri tramite un endpoint unificato. Con la [fatturazione unificata](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) non hai bisogno di chiavi API separate per ogni provider. + +1. Vai alla [dashboard di Cloudflare](https://dash.cloudflare.com/), naviga in **AI** > **AI Gateway** e crea un nuovo gateway. + +2. Imposta il tuo Account ID e Gateway ID come variabili d'ambiente. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. Esegui il comando `/connect` e cerca **Cloudflare AI Gateway**. + + ```txt + /connect + ``` + +4. Inserisci il tuo API token di Cloudflare. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + Oppure impostalo come variabile d'ambiente. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. Esegui il comando `/models` per selezionare un modello. + + ```txt + /models + ``` + + Puoi anche aggiungere modelli tramite la tua configurazione di opencode. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +### Cortecs + +1. Vai alla [console di Cortecs](https://cortecs.ai/), crea un account e genera una chiave API. + +2. Esegui il comando `/connect` e cerca **Cortecs**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di Cortecs. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello come _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. Vai alla [console di DeepSeek](https://platform.deepseek.com/), crea un account e clicca **Create new API key**. + +2. Esegui il comando `/connect` e cerca **DeepSeek**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di DeepSeek. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello DeepSeek come _DeepSeek Reasoner_. + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. Vai alla [dashboard di Deep Infra](https://deepinfra.com/dash), crea un account e genera una chiave API. + +2. Esegui il comando `/connect` e cerca **Deep Infra**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di Deep Infra. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello. + + ```txt + /models + ``` + +--- + +### Firmware + +1. Vai alla [dashboard di Firmware](https://app.firmware.ai/signup), crea un account e genera una chiave API. + +2. Esegui il comando `/connect` e cerca **Firmware**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di Firmware. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello. + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. Vai alla [console di Fireworks AI](https://app.fireworks.ai/), crea un account e clicca **Create API Key**. + +2. Esegui il comando `/connect` e cerca **Fireworks AI**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di Fireworks AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello come _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo fornisce una chat agentic basata su AI con capacità di chiamata strumenti nativa tramite il proxy Anthropic di GitLab. + +1. Esegui il comando `/connect` e seleziona GitLab. + + ```txt + /connect + ``` + +2. Scegli il tuo metodo di autenticazione: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ + ``` + + #### Usando OAuth (Consigliato) + + Seleziona **OAuth** e il tuo browser si aprirà per l'autorizzazione. + + #### Usando Personal Access Token + 1. Vai a [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens) + 2. Clicca **Add new token** + 3. Nome: `OpenCode`, Scopes: `api` + 4. Copia il token (inizia con `glpat-`) + 5. Inseriscilo nel terminale + +3. Esegui il comando `/models` per vedere i modelli disponibili. + + ```txt + /models + ``` + + Sono disponibili tre modelli basati su Claude: + - **duo-chat-haiku-4-5** (Default) - Risposte veloci per task rapidi + - **duo-chat-sonnet-4-5** - Prestazioni bilanciate per la maggior parte dei flussi di lavoro + - **duo-chat-opus-4-5** - Più capace per analisi complesse + +:::note +Puoi anche specificare la variabile d'ambiente 'GITLAB_TOKEN' se non vuoi +salvare il token nello storage di auth di opencode. +::: + +##### GitLab Self-Hosted + +:::note[nota di compliance] +OpenCode usa un modello piccolo per alcuni task AI come generare il titolo della sessione. +È configurato per usare gpt-5-nano di default, ospitato da Zen. Per bloccare OpenCode +a usare solo la tua istanza GitLab self-hosted, aggiungi quanto segue al tuo +file `opencode.json`. Si raccomanda anche di disabilitare la condivisione sessioni. + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +Per istanze GitLab self-hosted: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +Se la tua istanza esegue un AI Gateway personalizzato: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +Oppure aggiungi al tuo profilo bash: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +Il tuo amministratore GitLab deve abilitare quanto segue: + +1. [Duo Agent Platform](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) per l'utente, gruppo o istanza +2. Feature flags (via Rails console): + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: + +##### OAuth per istanze Self-Hosted + +Per far funzionare OAuth per la tua istanza self-hosted, devi creare +una nuova applicazione (Settings → Applications) con l' +URL di callback `http://127.0.0.1:8080/callback` e i seguenti scope: + +- api (Accedi all'API per tuo conto) +- read_user (Leggi le tue informazioni personali) +- read_repository (Consenti accesso in sola lettura al repository) + +Poi esponi l'ID applicazione come variabile d'ambiente: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +Maggior documentazione sulla homepage di [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth). + +##### Configurazione + +Personalizza tramite `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### Strumenti API GitLab (Opzionale, ma altamente raccomandato) + +Per accedere agli strumenti GitLab (merge requests, issues, pipelines, CI/CD, ecc.): + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +Questo plugin offre funzionalita complete per la gestione dei repository GitLab, incluse revisioni delle MR, tracciamento dei problemi, monitoraggio delle pipeline e altro. + +--- + +### GitHub Copilot + +Per usare il tuo abbonamento GitHub Copilot con opencode: + +:::note +Alcuni modelli potrebbero richiedere un [abbonamento Pro+](https://github.com/features/copilot/plans) per essere utilizzati. + +Alcuni modelli devono essere abilitati manualmente nelle tue [impostazioni GitHub Copilot](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use). +::: + +1. Esegui il comando `/connect` e cerca GitHub Copilot. + + ```txt + /connect + ``` + +2. Vai su [github.com/login/device](https://github.com/login/device) e inserisci il codice. + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + └ Waiting for authorization... + ``` + +3. Ora esegui il comando `/models` per selezionare il modello che vuoi. + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +Per usare Google Vertex AI con OpenCode: + +1. Vai al **Model Garden** nella Google Cloud Console e controlla i + modelli disponibili nella tua regione. + + :::note + Devi avere un progetto Google Cloud con l'API Vertex AI abilitata. + ::: + +2. Imposta le variabili d'ambiente richieste: + - `GOOGLE_CLOUD_PROJECT`: Il tuo ID progetto Google Cloud + - `VERTEX_LOCATION` (opzionale): La regione per Vertex AI (predefinito `global`) + - Autenticazione (scegline una): + - `GOOGLE_APPLICATION_CREDENTIALS`: Percorso al file JSON della chiave del tuo service account + - Autenticati usando la CLI gcloud: `gcloud auth application-default login` + + Impostale mentre esegui opencode. + + ```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode + ``` + + Oppure aggiungile al tuo profilo bash. + + ```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 +La regione `global` migliora la disponibilità e riduce gli errori senza costi extra. Usa endpoint regionali (ad es. `us-central1`) per requisiti di residenza dei dati. [Scopri di più](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. Esegui il comando `/models` per selezionare il modello che vuoi. + + ```txt + /models + ``` + +--- + +### Groq + +1. Vai alla [console di Groq](https://console.groq.com/), clicca **Create API Key** e copia la chiave. + +2. Esegui il comando `/connect` e cerca Groq. + + ```txt + /connect + ``` + +3. Inserisci la chiave API per il provider. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare quello che vuoi. + + ```txt + /models + ``` + +--- + +### Hugging Face + +[Hugging Face Inference Providers](https://huggingface.co/docs/inference-providers) fornisce accesso a modelli open supportati da 17+ provider. + +1. Vai alle [impostazioni di Hugging Face](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained) per creare un token con il permesso di effettuare chiamate agli Inference Providers. + +2. Esegui il comando `/connect` e cerca **Hugging Face**. + + ```txt + /connect + ``` + +3. Inserisci il tuo token Hugging Face. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello come _Kimi-K2-Instruct_ o _GLM-4.6_. + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) è una piattaforma di osservabilità LLM che fornisce logging, monitoraggio e analisi per le tue applicazioni AI. L'AI Gateway di Helicone instrada automaticamente le tue richieste al provider appropriato in base al modello. + +1. Vai su [Helicone](https://helicone.ai), crea un account e genera una chiave API dalla tua dashboard. + +2. Esegui il comando `/connect` e cerca **Helicone**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di Helicone. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello. + + ```txt + /models + ``` + +Per altri provider e funzionalità avanzate come caching e rate limiting, controlla la [documentazione di Helicone](https://docs.helicone.ai). + +#### Config opzionali + +Nel caso vedessi una funzionalità o un modello di Helicone che non viene configurato automaticamente da opencode, puoi sempre configurarlo tu stesso. + +Ecco la [Model Directory di Helicone](https://helicone.ai/models), ti servirà per recuperare gli ID dei modelli che vuoi aggiungere. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### Header personalizzati + +Helicone supporta header personalizzati per funzionalità come caching, user tracking e gestione sessioni. Aggiungili alla configurazione del provider usando `options.headers`: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### Tracciamento sessioni + +La funzionalità [Sessions](https://docs.helicone.ai/features/sessions) di Helicone ti permette di raggruppare richieste LLM correlate. Usa il plugin [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) per loggare automaticamente ogni conversazione di OpenCode come una sessione in Helicone. + +```bash +npm install -g opencode-helicone-session +``` + +Aggiungilo alla tua configurazione. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +Il plugin inietta gli header `Helicone-Session-Id` e `Helicone-Session-Name` nelle tue richieste. Nella pagina Sessions di Helicone, vedrai ogni conversazione di OpenCode elencata come sessione separata. + +##### Header Helicone comuni + +| Header | Descrizione | +| -------------------------- | -------------------------------------------------------------------------- | +| `Helicone-Cache-Enabled` | Abilita response caching (`true`/`false`) | +| `Helicone-User-Id` | Traccia metriche per utente | +| `Helicone-Property-[Name]` | Aggiungi proprietà personalizzate (ad es. `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | Associa richieste con versioni dei prompt | + +Vedi la [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory) per tutti gli header disponibili. + +--- + +### llama.cpp + +Puoi configurare opencode per usare modelli locali tramite l'utility llama-server di [llama.cpp](https://github.com/ggml-org/llama.cpp) + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +In questo esempio: + +- `llama.cpp` è l'ID provider personalizzato. Può essere qualsiasi stringa tu voglia. +- `npm` specifica il pacchetto da usare per questo provider. Qui, `@ai-sdk/openai-compatible` è usato per qualsiasi API OpenAI-compatible. +- `name` è il nome visualizzato per il provider nella UI. +- `options.baseURL` è l'endpoint per il server locale. +- `models` è una mappa di ID modello e relative configurazioni. Il nome del modello verrà visualizzato nella lista di selezione modelli. + +--- + +### IO.NET + +IO.NET offre 17 modelli ottimizzati per vari casi d'uso: + +1. Vai alla [console di IO.NET](https://ai.io.net/), crea un account e genera una chiave API. + +2. Esegui il comando `/connect` e cerca **IO.NET**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di IO.NET. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello. + + ```txt + /models + ``` + +--- + +### LM Studio + +Puoi configurare opencode per usare modelli locali tramite LM Studio. + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +In questo esempio: + +- `lmstudio` è l'ID provider personalizzato. Può essere qualsiasi stringa tu voglia. +- `npm` specifica il pacchetto da usare per questo provider. Qui, `@ai-sdk/openai-compatible` è usato per qualsiasi API OpenAI-compatible. +- `name` è il nome visualizzato per il provider nella UI. +- `options.baseURL` è l'endpoint per il server locale. +- `models` è una mappa di ID modello e relative configurazioni. Il nome del modello verrà visualizzato nella lista di selezione modelli. + +--- + +### Moonshot AI + +Per usare Kimi K2 di Moonshot AI: + +1. Vai alla [console di Moonshot AI](https://platform.moonshot.ai/console), crea un account e clicca **Create API key**. + +2. Esegui il comando `/connect` e cerca **Moonshot AI**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di Moonshot. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare _Kimi K2_. + + ```txt + /models + ``` + +### MiniMax + +1. Vai alla [MiniMax API Console](https://platform.minimax.io/login), crea un account e genera una chiave API. + +2. Esegui il comando `/connect` e cerca **MiniMax**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di MiniMax. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello come _M2.1_. + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. Vai alla [console di Nebius Token Factory](https://tokenfactory.nebius.com/), crea un account e clicca **Add Key**. + +2. Esegui il comando `/connect` e cerca **Nebius Token Factory**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di Nebius Token Factory. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello come _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Ollama + +Puoi configurare opencode per usare modelli locali tramite Ollama. + +:::tip +Ollama può auto-configurarsi per OpenCode. Vedi la [documentazione di integrazione Ollama](https://docs.ollama.com/integrations/opencode) per dettagli. +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +In questo esempio: + +- `ollama` è l'ID provider personalizzato. Può essere qualsiasi stringa tu voglia. +- `npm` specifica il pacchetto da usare per questo provider. Qui, `@ai-sdk/openai-compatible` è usato per qualsiasi API OpenAI-compatible. +- `name` è il nome visualizzato per il provider nella UI. +- `options.baseURL` è l'endpoint per il server locale. +- `models` è una mappa di ID modello e relative configurazioni. Il nome del modello verrà visualizzato nella lista di selezione modelli. + +:::tip +Se le chiamate agli strumenti non funzionano, prova ad aumentare `num_ctx` in Ollama. Inizia da circa 16k - 32k. +::: + +--- + +### Ollama Cloud + +Per usare Ollama Cloud con OpenCode: + +1. Vai su [https://ollama.com/](https://ollama.com/) e accedi o crea un account. + +2. Naviga in **Settings** > **Keys** e clicca **Add API Key** per generare una nuova chiave API. + +3. Copia la chiave API da usare in OpenCode. + +4. Esegui il comando `/connect` e cerca **Ollama Cloud**. + + ```txt + /connect + ``` + +5. Inserisci la tua chiave API di Ollama Cloud. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **Importante**: Prima di usare modelli cloud in OpenCode, devi scaricare le informazioni del modello localmente: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. Esegui il comando `/models` per selezionare il tuo modello Ollama Cloud. + + ```txt + /models + ``` + +--- + +### OpenAI + +Consigliamo di iscriversi a [ChatGPT Plus o Pro](https://chatgpt.com/pricing). + +1. Una volta iscritto, esegui il comando `/connect` e seleziona OpenAI. + + ```txt + /connect + ``` + +2. Qui puoi selezionare l'opzione **ChatGPT Plus/Pro**: aprirà il tuo browser + e ti chiederà di autenticarti. + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. Ora tutti i modelli OpenAI dovrebbero essere disponibili quando usi il comando `/models`. + + ```txt + /models + ``` + +##### Usare chiavi API + +Se hai già una chiave API, puoi selezionare **Manually enter API Key** e incollarla nel terminale. + +--- + +### OpenCode Zen + +OpenCode Zen è una lista di modelli testati e verificati forniti dal team OpenCode. [Scopri di più](/docs/zen). + +1. Accedi a **OpenCode Zen** e clicca **Create API Key**. + +2. Esegui il comando `/connect` e cerca **OpenCode Zen**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di OpenCode. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello come _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### OpenRouter + +1. Vai alla [dashboard di OpenRouter](https://openrouter.ai/settings/keys), clicca **Create API Key** e copia la chiave. + +2. Esegui il comando `/connect` e cerca OpenRouter. + + ```txt + /connect + ``` + +3. Inserisci la chiave API per il provider. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Molti modelli OpenRouter sono precaricati di default, esegui il comando `/models` per selezionare quello che vuoi. + + ```txt + /models + ``` + + Puoi anche aggiungere modelli addizionali tramite la tua configurazione di opencode. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +5. Puoi anche personalizzarli tramite la configurazione di opencode. Ecco un esempio di specifica di un provider + + ```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 fornisce accesso a oltre 40 modelli di OpenAI, Anthropic, Google, Amazon, Meta, Mistral e AI21 tramite una piattaforma unificata. + +1. Vai al tuo [SAP BTP Cockpit](https://account.hana.ondemand.com/), naviga nella tua istanza di servizio SAP AI Core e crea una service key. + + :::tip + La service key è un oggetto JSON contenente `clientid`, `clientsecret`, `url` e `serviceurls.AI_API_URL`. Puoi trovare la tua istanza AI Core sotto **Services** > **Instances and Subscriptions** nel BTP Cockpit. + ::: + +2. Esegui il comando `/connect` e cerca **SAP AI Core**. + + ```txt + /connect + ``` + +3. Inserisci il JSON della tua service key. + + ```txt + ┌ Service key + │ + │ + └ enter + ``` + + Oppure imposta la variabile d'ambiente `AICORE_SERVICE_KEY`: + + ```bash + AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode + ``` + + Oppure aggiungila al tuo profilo bash: + + ```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' + ``` + +4. Facoltativamente imposta deployment ID e resource group: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + Queste impostazioni sono opzionali e dovrebbero essere configurate in base al tuo setup SAP AI Core. + ::: + +5. Esegui il comando `/models` per selezionare tra gli oltre 40 modelli disponibili. + + ```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**. + +2. Esegui il comando `/connect` e cerca **OVHcloud AI Endpoints**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di OVHcloud AI Endpoints. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello come _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Scaleway + +Per usare le [Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/) con Opencode: + +1. Vai alle [impostazioni IAM della Console Scaleway](https://console.scaleway.com/iam/api-keys) per generare una nuova chiave API. + +2. Esegui il comando `/connect` e cerca **Scaleway**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di Scaleway. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello come _devstral-2-123b-instruct-2512_ o _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Together AI + +1. Vai alla [console di Together AI](https://api.together.ai), crea un account e clicca **Add Key**. + +2. Esegui il comando `/connect` e cerca **Together AI**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di Together AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello come _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Venice AI + +1. Vai alla [console di Venice AI](https://venice.ai), crea un account e genera una chiave API. + +2. Esegui il comando `/connect` e cerca **Venice AI**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di Venice AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello come _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + +### Vercel AI Gateway + +Vercel AI Gateway ti permette di accedere a modelli di OpenAI, Anthropic, Google, xAI e altri tramite un endpoint unificato. I modelli sono offerti al prezzo di listino senza ricarichi. + +1. Vai alla [dashboard Vercel](https://vercel.com/), naviga nella scheda **AI Gateway** e clicca **API keys** per creare una nuova chiave API. + +2. Esegui il comando `/connect` e cerca **Vercel AI Gateway**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di Vercel AI Gateway. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello. + + ```txt + /models + ``` + +Puoi anche personalizzare i modelli tramite la tua configurazione di opencode. Ecco un esempio di come specificare l'ordine di routing dei provider. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "vercel": { + "models": { + "anthropic/claude-sonnet-4": { + "options": { + "order": ["anthropic", "vertex"] + } + } + } + } + } +} +``` + +Alcune opzioni di routing utili: + +| Opzione | Descrizione | +| ------------------- | --------------------------------------------------- | +| `order` | Sequenza di provider da provare | +| `only` | Restringi a provider specifici | +| `zeroDataRetention` | Usa solo provider con policy di zero data retention | + +--- + +### xAI + +1. Vai alla [console di xAI](https://console.x.ai/), crea un account e genera una chiave API. + +2. Esegui il comando `/connect` e cerca **xAI**. + + ```txt + /connect + ``` + +3. Inserisci la tua chiave API di xAI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello come _Grok Beta_. + + ```txt + /models + ``` + +--- + +### Z.AI + +1. Vai alla [console API di Z.AI](https://z.ai/manage-apikey/apikey-list), crea un account e clicca **Create a new API key**. + +2. Esegui il comando `/connect` e cerca **Z.AI**. + + ```txt + /connect + ``` + + Se sei iscritto al **GLM Coding Plan**, seleziona **Z.AI Coding Plan**. + +3. Inserisci la tua chiave API di Z.AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare un modello come _GLM-4.7_. + + ```txt + /models + ``` + +--- + +### ZenMux + +1. Vai alla [dashboard di ZenMux](https://zenmux.ai/settings/keys), clicca **Create API Key** e copia la chiave. + +2. Esegui il comando `/connect` e cerca ZenMux. + + ```txt + /connect + ``` + +3. Inserisci la chiave API per il provider. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Molti modelli ZenMux sono precaricati di default, esegui il comando `/models` per selezionare quello che vuoi. + + ```txt + /models + ``` + + Puoi anche aggiungere modelli addizionali tramite la tua configurazione di opencode. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "zenmux": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +--- + +## Provider personalizzato + +Per aggiungere qualsiasi provider **OpenAI-compatible** non elencato nel comando `/connect`: + +:::tip +Puoi usare qualsiasi provider OpenAI-compatible con opencode. La maggior parte dei provider AI moderni offre API OpenAI-compatible. +::: + +1. Esegui il comando `/connect` e scorri fino a **Other**. + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. Inserisci un ID univoco per il provider. + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::note + Scegli un ID facile da ricordare, lo userai nel tuo file di configurazione. + ::: + +3. Inserisci la tua chiave API per il provider. + + ```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. Crea o aggiorna il tuo file `opencode.json` nella directory del progetto: + + ```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" + } + } + } + } + } + ``` + + Ecco le opzioni di configurazione: + - **npm**: Pacchetto AI SDK da usare, `@ai-sdk/openai-compatible` per provider OpenAI-compatible + - **name**: Nome visualizzato nella UI. + - **models**: Modelli disponibili. + - **options.baseURL**: URL dell'endpoint API. + - **options.apiKey**: Opzionalmente imposta la chiave API, se non usi auth. + - **options.headers**: Opzionalmente imposta header personalizzati. + + Maggiori dettagli sulle opzioni avanzate nell'esempio sotto. + +5. Esegui il comando `/models`: il tuo provider personalizzato e i modelli appariranno nella lista di selezione. + +--- + +##### Esempio + +Ecco un esempio che imposta le opzioni `apiKey`, `headers` e `limit` del modello. + +```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 + } + } + } + } + } +} +``` + +Dettagli configurazione: + +- **apiKey**: Imposta usando la sintassi variabile `env`, [scopri di più](/docs/config#env-vars). +- **headers**: Header personalizzati inviati con ogni richiesta. +- **limit.context**: Massimi token di input accettati dal modello. +- **limit.output**: Massimi token che il modello può generare. + +I campi `limit` permettono a OpenCode di capire quanto contesto rimane. I provider standard recuperano questi dati da models.dev automaticamente. + +--- + +## Risoluzione dei problemi + +Se hai problemi con la configurazione di un provider, controlla quanto segue: + +1. **Controlla il setup auth**: Esegui `opencode auth list` per vedere se le credenziali + per il provider sono aggiunte alla tua configurazione. + + Questo non si applica a provider come Amazon Bedrock, che si basano su variabili d'ambiente per l'autenticazione. + +2. Per provider personalizzati, controlla la config di opencode e: + - Assicurati che l'ID provider usato nel comando `/connect` corrisponda all'ID nella tua config opencode. + - Che sia usato il pacchetto npm corretto per il provider. Per esempio, usa `@ai-sdk/cerebras` per Cerebras. E per tutti gli altri provider OpenAI-compatible, usa `@ai-sdk/openai-compatible`. + - Controlla che sia usato l'endpoint API corretto nel campo `options.baseURL`. diff --git a/packages/web/src/content/docs/it/rules.mdx b/packages/web/src/content/docs/it/rules.mdx new file mode 100644 index 00000000000..2534a991af9 --- /dev/null +++ b/packages/web/src/content/docs/it/rules.mdx @@ -0,0 +1,180 @@ +--- +title: Regole +description: Imposta istruzioni personalizzate per opencode. +--- + +Puoi fornire istruzioni personalizzate a opencode creando un file `AGENTS.md`. E' simile alle regole di Cursor. Contiene istruzioni che verranno incluse nel contesto dell'LLM per personalizzarne il comportamento per il tuo progetto. + +--- + +## Inizializza + +Per creare un nuovo file `AGENTS.md`, puoi eseguire il comando `/init` in opencode. + +:::tip +Dovresti committare il file `AGENTS.md` del progetto in Git. +::: + +Questo scansiona il progetto e tutti i suoi contenuti per capire di cosa si tratta e generare un file `AGENTS.md`. Questo aiuta opencode a orientarsi meglio nel progetto. + +Se hai gia' un file `AGENTS.md` esistente, cerchera' di aggiungervi contenuti. + +--- + +## Esempio + +Puoi anche creare questo file manualmente. Ecco un esempio di alcune cose che puoi inserire in un file `AGENTS.md`. + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +Qui stiamo aggiungendo istruzioni specifiche del progetto e saranno condivise con il tuo team. + +--- + +## Tipi + +opencode supporta anche la lettura del file `AGENTS.md` da piu' posizioni, e questo serve a scopi diversi. + +### Progetto + +Metti un `AGENTS.md` nella root del progetto per regole specifiche del progetto. Si applicano solo quando stai lavorando in questa directory o nelle sue sottodirectory. + +### Globale + +Puoi anche avere regole globali in un file `~/.config/opencode/AGENTS.md`. Queste si applicano a tutte le sessioni di opencode. + +Dato che questo non viene committato in Git o condiviso con il team, consigliamo di usarlo per specificare regole personali che l'LLM deve seguire. + +### Compatibilita Claude Code + +Per gli utenti che migrano da Claude Code, OpenCode supporta come fallback le convenzioni di file di Claude Code: + +- **Regole di progetto**: `CLAUDE.md` nella directory del progetto (usato se non esiste `AGENTS.md`) +- **Regole globali**: `~/.claude/CLAUDE.md` (usato se non esiste `~/.config/opencode/AGENTS.md`) +- **Skill**: `~/.claude/skills/` — vedi [Skill agente](/docs/skills/) per i dettagli + +Per disabilitare la compatibilita' con Claude Code, imposta una di queste variabili d'ambiente: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## Priorita + +Quando opencode si avvia, cerca i file di regole in questo ordine: + +1. **File locali** risalendo dalla directory corrente (`AGENTS.md`, `CLAUDE.md`) +2. **File globale** in `~/.config/opencode/AGENTS.md` +3. **File Claude Code** in `~/.claude/CLAUDE.md` (se non disabilitato) + +In ogni categoria vince il primo file corrispondente. Per esempio, se hai sia `AGENTS.md` sia `CLAUDE.md`, viene usato solo `AGENTS.md`. Allo stesso modo, `~/.config/opencode/AGENTS.md` ha priorita' su `~/.claude/CLAUDE.md`. + +--- + +## Istruzioni personalizzate + +Puoi specificare file di istruzioni personalizzati nel tuo `opencode.json` o nel globale `~/.config/opencode/opencode.json`. Questo permette a te e al tuo team di riusare regole esistenti invece di doverle duplicare in AGENTS.md. + +Esempio: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Puoi anche usare URL remoti per caricare istruzioni dal web. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +Le istruzioni remote vengono recuperate con un timeout di 5 secondi. + +Tutti i file di istruzioni vengono combinati con i tuoi file `AGENTS.md`. + +--- + +## Riferisci file esterni + +Anche se opencode non interpreta automaticamente i riferimenti a file in `AGENTS.md`, puoi ottenere una funzionalita' simile in due modi: + +### Usa opencode.json + +L'approccio consigliato e' usare il campo `instructions` in `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### Istruzioni manuali in AGENTS.md + +Puoi insegnare a opencode a leggere file esterni fornendo istruzioni esplicite nel tuo `AGENTS.md`. Ecco un esempio pratico: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +Questo approccio ti permette di: + +- Crea file di regole modulari e riutilizzabili +- Condividi regole tra progetti con symlink o submodule Git +- Mantieni AGENTS.md conciso riferendoti a linee guida dettagliate +- Assicurati che opencode carichi file solo quando servono per il task specifico + +:::tip +Per monorepo o progetti con standard condivisi, usare `opencode.json` con pattern glob (come `packages/*/AGENTS.md`) e' piu' manutenibile rispetto alle istruzioni manuali. +::: diff --git a/packages/web/src/content/docs/it/sdk.mdx b/packages/web/src/content/docs/it/sdk.mdx new file mode 100644 index 00000000000..9cf7e4eae52 --- /dev/null +++ b/packages/web/src/content/docs/it/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: Client JS type-safe per il server opencode. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +L'SDK JS/TS di opencode fornisce un client type-safe per interagire con il server. +Usalo per creare integrazioni e controllare opencode in modo programmatico. + +[Scopri di piu](/docs/server) su come funziona il server. Per esempi, guarda i [progetti](/docs/ecosystem#projects) creati dalla comunita. + +--- + +## Installa + +Installa l'SDK da npm: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## Crea un client + +Crea un'istanza di opencode: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +Questo avvia sia un server sia un client + +#### Opzioni + +| Opzione | Tipo | Descrizione | Predefinito | +| ---------- | ------------- | ------------------------------ | ----------- | +| `hostname` | `string` | Hostname del server | `127.0.0.1` | +| `port` | `number` | Porta del server | `4096` | +| `signal` | `AbortSignal` | Segnale di abort per annullare | `undefined` | +| `timeout` | `number` | Timeout in ms per avvio server | `5000` | +| `config` | `Config` | Oggetto di configurazione | `{}` | + +--- + +## Configurazione + +Puoi passare un oggetto di configurazione per personalizzare il comportamento. L'istanza legge comunque `opencode.json`, ma puoi sovrascrivere o aggiungere configurazione inline: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## Solo client + +Se hai gia un'istanza di opencode in esecuzione, puoi creare un client per collegarti: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### Opzioni + +| Opzione | Tipo | Descrizione | Predefinito | +| --------------- | ---------- | ----------------------------------- | ----------------------- | +| `baseUrl` | `string` | URL del server | `http://localhost:4096` | +| `fetch` | `function` | Implementazione fetch custom | `globalThis.fetch` | +| `parseAs` | `string` | Metodo di parsing della risposta | `auto` | +| `responseStyle` | `string` | Stile di ritorno: `data` o `fields` | `fields` | +| `throwOnError` | `boolean` | Lancia errori invece di restituirli | `false` | + +--- + +## Tipi + +L'SDK include definizioni TypeScript per tutti i tipi API. Importale direttamente: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +Tutti i tipi sono generati dalla specifica OpenAPI del server e disponibili nel file dei tipi. + +--- + +## Errori + +L'SDK puo lanciare errori che puoi intercettare e gestire: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## API + +L'SDK espone tutte le API del server tramite un client type-safe. + +--- + +### Globale + +| Metodo | Descrizione | Risposta | +| ----------------- | --------------------------------- | ------------------------------------ | +| `global.health()` | Controlla stato e versione server | `{ healthy: true, version: string }` | + +--- + +#### Esempi + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### App + +| Metodo | Descrizione | Risposta | +| -------------- | ----------------------- | ------------------------------------------- | +| `app.log()` | Scrive una voce di log | `boolean` | +| `app.agents()` | Elenca tutti gli agenti | Agent[] | + +--- + +#### Esempi + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### Progetto + +| Metodo | Descrizione | Risposta | +| ------------------- | ----------------- | --------------------------------------------- | +| `project.list()` | Elenca i progetti | Project[] | +| `project.current()` | Progetto corrente | Project | + +--- + +#### Esempi + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### Path + +| Metodo | Descrizione | Risposta | +| ------------ | ----------------- | ---------------------------------------- | +| `path.get()` | Percorso corrente | Path | + +--- + +#### Esempi + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### Config + +| Metodo | Descrizione | Risposta | +| -------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | Ottieni info config | Config | +| `config.providers()` | Elenca provider e modelli default | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### Esempi + +```javascript +const config = await client.config.get() + +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` | + +--- + +#### Esempi + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### File + +| Metodo | Descrizione | Risposta | +| ------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------- | +| `find.text({ query })` | Cerca testo nei file | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `find.files({ query })` | Trova file e directory per nome | `string[]` (paths) | +| `find.symbols({ query })` | Trova simboli nel workspace | Symbol[] | +| `file.read({ query })` | Legge un file | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | Stato dei file tracciati | File[] | + +`find.files` supporta alcuni campi query opzionali: + +- `type`: `"file"` or `"directory"` +- `directory`: sovrascrive la root del progetto per la ricerca +- `limit`: risultati massimi (1–200) + +--- + +#### Esempi + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| Metodo | Descrizione | Risposta | +| ------------------------------ | -------------------------- | --------- | +| `tui.appendPrompt({ body })` | Aggiunge testo al prompt | `boolean` | +| `tui.openHelp()` | Apre la finestra help | `boolean` | +| `tui.openSessions()` | Apre il selettore sessioni | `boolean` | +| `tui.openThemes()` | Apre il selettore temi | `boolean` | +| `tui.openModels()` | Apre il selettore modelli | `boolean` | +| `tui.submitPrompt()` | Invia il prompt corrente | `boolean` | +| `tui.clearPrompt()` | Pulisce il prompt | `boolean` | +| `tui.executeCommand({ body })` | Esegue un comando | `boolean` | +| `tui.showToast({ body })` | Mostra una notifica toast | `boolean` | + +--- + +#### Esempi + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### Autenticazione + +| Metodo | Descrizione | Risposta | +| ------------------- | ------------------------ | --------- | +| `auth.set({ ... })` | Imposta credenziali auth | `boolean` | + +--- + +#### Esempi + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### Eventi + +| Metodo | Descrizione | Risposta | +| ------------------- | ---------------------------- | ---------------------------- | +| `event.subscribe()` | Stream di server-sent events | Stream di server-sent events | + +--- + +#### Esempi + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/it/server.mdx b/packages/web/src/content/docs/it/server.mdx new file mode 100644 index 00000000000..df66d39fdc9 --- /dev/null +++ b/packages/web/src/content/docs/it/server.mdx @@ -0,0 +1,284 @@ +--- +title: Server +description: Interagisci con il server opencode via HTTP. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +Il comando `opencode serve` avvia un server HTTP headless che espone un endpoint OpenAPI utilizzabile da un client opencode. + +--- + +### Utilizzo + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### Opzioni + +| Flag | Descrizione | Predefinito | +| --------------- | --------------------------------------- | ---------------- | +| `--port` | Porta su cui ascoltare | `4096` | +| `--hostname` | Hostname su cui ascoltare | `127.0.0.1` | +| `--mdns` | Abilita la scoperta mDNS | `false` | +| `--mdns-domain` | Nome di dominio personalizzato mDNS | `opencode.local` | +| `--cors` | Origin browser aggiuntive da permettere | `[]` | + +`--cors` puo essere passato piu volte: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### Autenticazione + +Imposta `OPENCODE_SERVER_PASSWORD` per proteggere il server con HTTP basic auth. Lo username predefinito e `opencode`, oppure imposta `OPENCODE_SERVER_USERNAME` per sovrascriverlo. Questo vale sia per `opencode serve` sia per `opencode web`. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### Come funziona + +Quando esegui `opencode` avvia una TUI e un server. La TUI e il client che parla col server. Il server espone un endpoint con specifica OpenAPI 3.1. Questo endpoint viene anche usato per generare un [SDK](/docs/sdk). + +:::tip +Usa il server opencode per interagire con opencode in modo programmatico. +::: + +Questa architettura permette a opencode di supportare piu client e di essere usato in modo programmatico. + +Puoi eseguire `opencode serve` per avviare un server standalone. Se la TUI di opencode e gia in esecuzione, `opencode serve` avviera un nuovo server. + +--- + +#### Connettersi a un server esistente + +Quando avvii la TUI assegna casualmente porta e hostname. In alternativa puoi passare i [flag](/docs/cli) `--hostname` e `--port` e poi usare questi valori per connetterti al suo server. + +L'endpoint [`/tui`](#tui) puo essere usato per pilotare la TUI tramite il server. Per esempio, puoi precompilare o eseguire un prompt. Questa configurazione e usata dai plugin [IDE](/docs/ide) di OpenCode. + +--- + +## Specifica + +Il server pubblica una specifica OpenAPI 3.1 visualizzabile su: + +``` +http://:/doc +``` + +Per esempio, `http://localhost:4096/doc`. Usa la spec per generare client o ispezionare i tipi di request/response, oppure visualizzala in uno Swagger explorer. + +--- + +## API + +Il server opencode espone le seguenti API. + +--- + +### Globale + +| Metodo | Path | Descrizione | Response | +| ------ | ---------------- | --------------------------- | ------------------------------------ | +| `GET` | `/global/health` | Stato di salute e versione | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | Eventi globali (stream SSE) | Event stream | + +--- + +### Progetto + +| Metodo | Path | Descrizione | Response | +| ------ | ------------------ | ----------------------- | --------------------------------------------- | +| `GET` | `/project` | Elenca tutti i progetti | Project[] | +| `GET` | `/project/current` | Progetto corrente | Project | + +--- + +### Percorso e VCS + +| Metodo | Path | Descrizione | Response | +| ------ | ------- | --------------------------------- | ------------------------------------------- | +| `GET` | `/path` | Percorso corrente | Path | +| `GET` | `/vcs` | Info VCS per il progetto corrente | VcsInfo | + +--- + +### Istanza + +| Metodo | Path | Descrizione | Response | +| ------ | ------------------- | --------------------------- | --------- | +| `POST` | `/instance/dispose` | Rilascia l'istanza corrente | `boolean` | + +--- + +### Configurazione + +| Metodo | Path | Descrizione | Response | +| ------- | ------------------- | --------------------------------- | ---------------------------------------------------------------------------------------- | +| `GET` | `/config` | Info sulla config | Config | +| `PATCH` | `/config` | Aggiorna la config | Config | +| `GET` | `/config/providers` | Elenca provider e modelli default | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +### Fornitori + +| Metodo | Path | Descrizione | Response | +| ------ | -------------------------------- | ------------------------------- | ----------------------------------------------------------------------------------- | +| `GET` | `/provider` | Elenca tutti i provider | `{ all: `Provider[]`, default: {...}, connected: string[] }` | +| `GET` | `/provider/auth` | Metodi auth dei provider | `{ [providerID: string]: `ProviderAuthMethod[]` }` | +| `POST` | `/provider/{id}/oauth/authorize` | Autorizza un provider via OAuth | ProviderAuthAuthorization | +| `POST` | `/provider/{id}/oauth/callback` | Gestisce callback OAuth | `boolean` | + +--- + +### Sessioni + +| Metodo | Path | Descrizione | Note | +| -------- | ---------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------- | +| `GET` | `/session` | Elenca tutte le sessioni | Returns Session[] | +| `POST` | `/session` | Crea una nuova sessione | body: `{ parentID?, title? }`, returns Session | +| `GET` | `/session/status` | Stato di tutte le sessioni | Returns `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | Dettagli di sessione | Returns Session | +| `DELETE` | `/session/:id` | Elimina una sessione e i suoi dati | Returns `boolean` | +| `PATCH` | `/session/:id` | Aggiorna proprieta sessione | body: `{ title? }`, returns Session | +| `GET` | `/session/:id/children` | Sessioni figlie | Returns Session[] | +| `GET` | `/session/:id/todo` | Todo list della sessione | Returns Todo[] | +| `POST` | `/session/:id/init` | Analizza app e crea `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returns `boolean` | +| `POST` | `/session/:id/fork` | Fork di sessione su un messaggio | body: `{ messageID? }`, returns Session | +| `POST` | `/session/:id/abort` | Interrompe una sessione in esecuzione | Returns `boolean` | +| `POST` | `/session/:id/share` | Condivide una sessione | Returns Session | +| `DELETE` | `/session/:id/share` | Annulla condivisione | Returns Session | +| `GET` | `/session/:id/diff` | Diff della sessione | query: `messageID?`, returns FileDiff[] | +| `POST` | `/session/:id/summarize` | Riassume la sessione | body: `{ providerID, modelID }`, returns `boolean` | +| `POST` | `/session/:id/revert` | Ripristina un messaggio | body: `{ messageID, partID? }`, returns `boolean` | +| `POST` | `/session/:id/unrevert` | Ripristina tutti i messaggi revertiti | Returns `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | Risponde a una richiesta permessi | body: `{ response, remember? }`, returns `boolean` | + +--- + +### Messaggi + +| Metodo | Path | Descrizione | Note | +| ------ | --------------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `GET` | `/session/:id/message` | Elenca messaggi in una sessione | query: `limit?`, returns `{ info: `Message`, parts: `Part[]`}[]` | +| `POST` | `/session/:id/message` | Invia un messaggio e attende risposta | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, returns `{ info: `Message`, parts: `Part[]`}` | +| `GET` | `/session/:id/message/:messageID` | Dettagli messaggio | Returns `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/prompt_async` | Invia un messaggio in async (senza wait) | body: same as `/session/:id/message`, returns `204 No Content` | +| `POST` | `/session/:id/command` | Esegue un comando slash | body: `{ messageID?, agent?, model?, command, arguments }`, returns `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/shell` | Esegue un comando shell | body: `{ agent, model?, command }`, returns `{ info: `Message`, parts: `Part[]`}` | + +--- + +### Comandi + +| Metodo | Path | Descrizione | Response | +| ------ | ---------- | ---------------- | --------------------------------------------- | +| `GET` | `/command` | Elenca i comandi | Command[] | + +--- + +### File + +| Metodo | Path | Descrizione | Response | +| ------ | ------------------------ | ------------------------------- | ------------------------------------------------------------------------------------------- | +| `GET` | `/find?pattern=` | Cerca testo nei file | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `GET` | `/find/file?query=` | Trova file e directory per nome | `string[]` (paths) | +| `GET` | `/find/symbol?query=` | Trova simboli workspace | Symbol[] | +| `GET` | `/file?path=` | Elenca file e directory | FileNode[] | +| `GET` | `/file/content?path=

` | Legge un file | FileContent | +| `GET` | `/file/status` | Stato dei file tracciati | File[] | + +#### `/find/file` query parameters + +- `query` (required) — stringa di ricerca (fuzzy match) +- `type` (optional) — limita i risultati a `"file"` o `"directory"` +- `directory` (optional) — sovrascrive la root del progetto per la ricerca +- `limit` (optional) — massimo risultati (1–200) +- `dirs` (optional) — flag legacy (`"false"` restituisce solo file) + +--- + +### Strumenti (sperimentale) + +| Metodo | Path | Descrizione | Response | +| ------ | ------------------------------------------- | ------------------------------------------ | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | Elenca tutti i tool ID | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | Elenca tool con JSON schema per un modello | ToolList | + +--- + +### LSP, formatter e MCP + +| Metodo | Path | Descrizione | Response | +| ------ | ------------ | --------------------------- | -------------------------------------------------------- | +| `GET` | `/lsp` | Stato server LSP | LSPStatus[] | +| `GET` | `/formatter` | Stato formatter | FormatterStatus[] | +| `GET` | `/mcp` | Stato server MCP | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | Aggiunge server MCP runtime | body: `{ name, config }`, returns MCP status object | + +--- + +### Agenti + +| Metodo | Path | Descrizione | Response | +| ------ | -------- | ----------------------- | ------------------------------------------- | +| `GET` | `/agent` | Elenca tutti gli agenti | Agent[] | + +--- + +### Log + +| Metodo | Path | Descrizione | Response | +| ------ | ------ | ------------------------------------------------------------------- | --------- | +| `POST` | `/log` | Scrive una voce di log. Body: `{ service, level, message, extra? }` | `boolean` | + +--- + +### TUI + +| Metodo | Path | Descrizione | Response | +| ------ | ----------------------- | -------------------------------------------------- | ---------------------- | +| `POST` | `/tui/append-prompt` | Aggiunge testo al prompt | `boolean` | +| `POST` | `/tui/open-help` | Apre il dialog help | `boolean` | +| `POST` | `/tui/open-sessions` | Apre il selettore sessioni | `boolean` | +| `POST` | `/tui/open-themes` | Apre il selettore temi | `boolean` | +| `POST` | `/tui/open-models` | Apre il selettore modelli | `boolean` | +| `POST` | `/tui/submit-prompt` | Invia il prompt corrente | `boolean` | +| `POST` | `/tui/clear-prompt` | Pulisce il prompt | `boolean` | +| `POST` | `/tui/execute-command` | Esegue un comando (`{ command }`) | `boolean` | +| `POST` | `/tui/show-toast` | Mostra toast (`{ title?, message, variant }`) | `boolean` | +| `GET` | `/tui/control/next` | Attende la prossima richiesta di controllo | Control request object | +| `POST` | `/tui/control/response` | Risponde a una richiesta di controllo (`{ body }`) | `boolean` | + +--- + +### Autenticazione + +| Metodo | Path | Descrizione | Response | +| ------ | ----------- | -------------------------------------------------------------------- | --------- | +| `PUT` | `/auth/:id` | Imposta credenziali auth. Il body deve rispettare lo schema provider | `boolean` | + +--- + +### Eventi + +| Metodo | Path | Descrizione | Response | +| ------ | -------- | ----------------------------------------------------------- | ------------------------- | +| `GET` | `/event` | Stream SSE. Primo evento `server.connected`, poi eventi bus | Server-sent events stream | + +--- + +### Documentazione + +| Metodo | Path | Descrizione | Response | +| ------ | ------ | --------------------- | ---------------------------- | +| `GET` | `/doc` | Specifica OpenAPI 3.1 | Pagina HTML con spec OpenAPI | diff --git a/packages/web/src/content/docs/it/share.mdx b/packages/web/src/content/docs/it/share.mdx new file mode 100644 index 00000000000..f9eff6ca9bd --- /dev/null +++ b/packages/web/src/content/docs/it/share.mdx @@ -0,0 +1,127 @@ +--- +title: Condivisione +description: Condividi le tue conversazioni OpenCode. +--- + +La funzione di condivisione di OpenCode ti permette di creare link pubblici alle tue conversazioni, cosi puoi collaborare con i colleghi o chiedere aiuto ad altre persone. + +:::note +Le conversazioni condivise sono accessibili pubblicamente a chiunque abbia il link. +::: + +--- + +## Come funziona + +Quando condividi una conversazione, OpenCode: + +1. Crea un URL pubblico univoco per la sessione +2. Sincronizza la cronologia della conversazione sui nostri server +3. Rende la conversazione accessibile tramite il link condivisibile: `opncd.ai/s/` + +--- + +## Condivisione + +OpenCode supporta tre modalita di condivisione che controllano come vengono condivise le conversazioni: + +--- + +### Manuale (predefinito) + +Per impostazione predefinita, OpenCode usa la condivisione manuale. Le sessioni non vengono condivise automaticamente, ma puoi condividerle manualmente con il comando `/share`: + +``` +/share +``` + +Questo genera un URL univoco che viene copiato negli appunti. + +Per impostare esplicitamente la modalita manuale nel tuo [file di config](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### Automatico + +Puoi abilitare la condivisione automatica per tutte le nuove conversazioni impostando l'opzione `share` su `"auto"` nel tuo [file di config](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +Con la condivisione automatica attiva, ogni nuova conversazione verra condivisa automaticamente e verra generato un link. + +--- + +### Disabilitato + +Puoi disabilitare completamente la condivisione impostando l'opzione `share` su `"disabled"` nel tuo [file di config](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +Per applicarlo al tuo team in un progetto specifico, aggiungilo a `opencode.json` nel progetto e versionalo su Git. + +--- + +## Annullare la condivisione + +Per smettere di condividere una conversazione e rimuoverla dall'accesso pubblico: + +``` +/unshare +``` + +Questo rimuove il link di condivisione ed elimina i dati associati alla conversazione. + +--- + +## Privacy + +Ci sono alcune cose da tenere a mente quando condividi una conversazione. + +--- + +### Conservazione dati + +Le conversazioni condivise restano accessibili finche non le annulli esplicitamente. Questo include: + +- La cronologia completa della conversazione +- Tutti i messaggi e le risposte +- I metadati della sessione + +--- + +### Raccomandazioni + +- Condividi solo conversazioni che non contengono informazioni sensibili. +- Rivedi il contenuto della conversazione prima di condividerla. +- Annulla la condivisione quando la collaborazione e conclusa. +- Evita di condividere conversazioni con codice proprietario o dati riservati. +- Per progetti sensibili, disabilita completamente la condivisione. + +--- + +## Per le aziende + +Per deploy enterprise, la condivisione puo essere: + +- **Disabilitata** completamente per requisiti di conformita e sicurezza +- **Limitata** ai soli utenti autenticati tramite SSO +- **Self-hosted** sulla tua infrastruttura + +[Scopri di piu](/docs/enterprise) su come usare opencode nella tua organizzazione. diff --git a/packages/web/src/content/docs/it/skills.mdx b/packages/web/src/content/docs/it/skills.mdx new file mode 100644 index 00000000000..e65bdc94eed --- /dev/null +++ b/packages/web/src/content/docs/it/skills.mdx @@ -0,0 +1,222 @@ +--- +title: "Competenze dell'agente" +description: "Definisci comportamenti riutilizzabili tramite definizioni in SKILL.md" +--- + +Le skill degli agenti permettono a OpenCode di individuare istruzioni riutilizzabili dal tuo repo o dalla home directory. +Le skill vengono caricate on-demand tramite lo strumento nativo `skill`: gli agenti vedono le skill disponibili e possono caricarne il contenuto completo quando serve. + +--- + +## Posizione dei file + +Crea una cartella per ogni nome di skill e metti un `SKILL.md` al suo interno. +OpenCode cerca in queste posizioni: + +- Config di progetto: `.opencode/skills//SKILL.md` +- Config globale: `~/.config/opencode/skills//SKILL.md` +- Progetto compatibile con Claude: `.claude/skills//SKILL.md` +- Globale compatibile con Claude: `~/.claude/skills//SKILL.md` +- Progetto compatibile con agent: `.agents/skills//SKILL.md` +- Globale compatibile con agent: `~/.agents/skills//SKILL.md` + +--- + +## Discovery + +Per i percorsi locali al progetto, OpenCode risale dalla directory di lavoro corrente finche' non raggiunge il worktree git. +Carica qualsiasi `skills/*/SKILL.md` corrispondente in `.opencode/` e qualsiasi `.claude/skills/*/SKILL.md` o `.agents/skills/*/SKILL.md` corrispondente lungo il percorso. + +Le definizioni globali vengono caricate anche da `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md` e `~/.agents/skills/*/SKILL.md`. + +--- + +## Frontmatter + +Ogni `SKILL.md` deve iniziare con frontmatter YAML. +Sono riconosciuti solo questi campi: + +- `name` (obbligatorio) +- `description` (obbligatorio) +- `license` (opzionale) +- `compatibility` (opzionale) +- `metadata` (opzionale, mappa stringa-a-stringa) + +I campi di frontmatter sconosciuti vengono ignorati. + +--- + +## Validazione nomi + +`name` deve: + +- Essere lungo 1-64 caratteri +- Essere alfanumerico minuscolo con separatori `-` singoli +- Non iniziare o finire con `-` +- Non contenere `--` consecutivi +- Corrispondere al nome della directory che contiene `SKILL.md` + +Regex equivalente: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## Regole di lunghezza + +`description` deve essere lunga 1-1024 caratteri. +Tieni la descrizione abbastanza specifica da permettere all'agente di scegliere correttamente. + +--- + +## Esempio + +Crea `.opencode/skills/git-release/SKILL.md` cosi': + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## Descrizione strumento + +OpenCode elenca le skill disponibili nella descrizione dello strumento `skill`. +Ogni voce include il nome della skill e la descrizione: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +L'agente carica una skill chiamando lo strumento: + +``` +skill({ name: "git-release" }) +``` + +--- + +## Permessi + +Controlla a quali skill gli agenti possono accedere usando permessi basati su pattern in `opencode.json`: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| Permesso | Comportamento | +| -------- | -------------------------------------------- | +| `allow` | La skill viene caricata immediatamente | +| `deny` | Skill nascosta all'agente, accesso negato | +| `ask` | L'utente viene invitato ad approvare il load | + +I pattern supportano wildcard: `internal-*` corrisponde a `internal-docs`, `internal-tools`, ecc. + +--- + +## Sovrascrittura per agente + +Dai ad agenti specifici permessi diversi dai default globali. + +**Per agenti personalizzati** (nel frontmatter dell'agente): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**Per agenti integrati** (in `opencode.json`): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## Disabilitare skill + +Disabilita completamente le skill per agenti che non dovrebbero usarle: + +**Per agenti personalizzati**: + +```yaml +--- +tools: + skill: false +--- +``` + +**Per agenti integrati**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +Quando e' disabilitato, la sezione `` viene omessa completamente. + +--- + +## Risoluzione problemi + +Se una skill non compare: + +1. Verifica che `SKILL.md` sia scritto in maiuscolo +2. Controlla che il frontmatter includa `name` e `description` +3. Assicurati che i nomi delle skill siano unici in tutte le posizioni +4. Controlla i permessi: le skill con `deny` vengono nascoste agli agenti diff --git a/packages/web/src/content/docs/it/themes.mdx b/packages/web/src/content/docs/it/themes.mdx new file mode 100644 index 00000000000..6752470e0f1 --- /dev/null +++ b/packages/web/src/content/docs/it/themes.mdx @@ -0,0 +1,369 @@ +--- +title: Temi +description: Seleziona un tema integrato o definiscine uno tuo. +--- + +Con OpenCode puoi scegliere tra diversi temi integrati, usare un tema che si adatta al tema del tuo terminale oppure definire un tema personalizzato. + +Per impostazione predefinita, OpenCode usa il tema `opencode`. + +--- + +## Requisiti del terminale + +Per visualizzare correttamente i temi con l'intera palette, il terminale deve supportare **truecolor** (colore a 24 bit). La maggior parte dei terminali moderni lo supporta di default, ma potrebbe essere necessario abilitarlo: + +- **Verifica supporto**: esegui `echo $COLORTERM` - dovrebbe stampare `truecolor` o `24bit` +- **Abilita truecolor**: imposta la variabile d'ambiente `COLORTERM=truecolor` nel profilo della shell +- **Compatibilità del terminale**: assicurati che l'emulatore supporti il colore a 24 bit (la maggior parte dei terminali moderni come iTerm2, Alacritty, Kitty, Windows Terminal e le versioni recenti di GNOME Terminal) + +Senza truecolor, i temi potrebbero apparire con colori meno accurati oppure fare fallback alla migliore approssimazione a 256 colori. + +--- + +## Temi integrati + +OpenCode include diversi temi integrati. + +| Nome | Descrizione | +| ---------------------- | ------------------------------------------------------------------------- | +| `system` | Si adatta al colore di sfondo del terminale | +| `tokyonight` | Basato sul tema [Tokyonight](https://github.com/folke/tokyonight.nvim) | +| `everforest` | Basato sul tema [Everforest](https://github.com/sainnhe/everforest) | +| `ayu` | Basato sul tema scuro [Ayu](https://github.com/ayu-theme) | +| `catppuccin` | Basato sul tema [Catppuccin](https://github.com/catppuccin) | +| `catppuccin-macchiato` | Basato sul tema [Catppuccin](https://github.com/catppuccin) | +| `gruvbox` | Basato sul tema [Gruvbox](https://github.com/morhetz/gruvbox) | +| `kanagawa` | Basato sul tema [Kanagawa](https://github.com/rebelot/kanagawa.nvim) | +| `nord` | Basato sul tema [Nord](https://github.com/nordtheme/nord) | +| `matrix` | Tema verde su nero in stile hacker | +| `one-dark` | Basato sul tema Dark [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) | + +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_: + +- **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: + +- Vuole che OpenCode corrisponda all'aspetto del terminale +- Usa schemi colori personalizzati del terminale +- Preferisce un aspetto coerente tra tutte le applicazioni da terminale + +--- + +## Usare un tema + +Puoi selezionare un tema aprendo la selezione temi con il comando `/theme`. In alternativa, puoi specificarlo nella tua [configurazione](/docs/config). + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## Temi personalizzati + +OpenCode supporta un sistema di temi flessibile basato su JSON che permette di creare e personalizzare temi facilmente. + +--- + +### Gerarchia + +I temi vengono caricati da piu 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. + +--- + +### Creare un tema + +Per creare un tema personalizzato, crea un file JSON in una delle directory dei temi. + +Per temi a livello utente: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +E per temi specifici del progetto. + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### Formato JSON + +I temi usano un formato JSON flessibile che supporta: + +- **Colori hex**: `"#ffffff"` +- **Colori ANSI**: `3` (0-255) +- **Riferimenti colore**: `"primary"` o definizioni personalizzate +- **Varianti scuro/chiaro**: `{"dark": "#000", "light": "#fff"}` +- **Nessun colore**: `"none"` - usa il colore predefinito del terminale o trasparente + +--- + +### Definizioni dei colori + +La sezione `defs` e 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: + +- `"text": "none"` - usa il colore del testo predefinito del terminale +- `"background": "none"` - usa il colore di sfondo predefinito del terminale + +--- + +### Esempio + +Ecco un esempio di tema personalizzato: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/it/tools.mdx b/packages/web/src/content/docs/it/tools.mdx new file mode 100644 index 00000000000..afd10b33131 --- /dev/null +++ b/packages/web/src/content/docs/it/tools.mdx @@ -0,0 +1,379 @@ +--- +title: Strumenti +description: Gestisci gli strumenti che un LLM puo' usare. +--- + +Gli strumenti permettono all'LLM di eseguire azioni nel tuo codebase. OpenCode include un set di strumenti integrati, ma puoi estenderlo con [strumenti personalizzati](/docs/custom-tools) o con [server MCP](/docs/mcp-servers). + +Di default, tutti gli strumenti sono **abilitati** e non richiedono permessi per essere eseguiti. Puoi controllare il comportamento degli strumenti tramite i [permessi](/docs/permissions). + +--- + +## Configurazione + +Usa il campo `permission` per controllare il comportamento degli strumenti. Puoi consentire, negare o richiedere approvazione per ciascuno. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +Puoi anche usare wildcard per controllare piu' strumenti insieme. Per esempio, per richiedere approvazione per tutti gli strumenti di un server MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[Scopri di piu'](/docs/permissions) su come configurare i permessi. + +--- + +## Integrati + +Ecco tutti gli strumenti integrati disponibili in OpenCode. + +--- + +### bash + +Esegui comandi di shell nel tuo ambiente di progetto. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +Questo strumento permette all'LLM di eseguire comandi da terminale come `npm install`, `git status` o qualunque altro comando di shell. + +--- + +### edit + +Modifica file esistenti usando sostituzioni esatte di stringhe. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Questo strumento esegue modifiche precise ai file sostituendo corrispondenze di testo esatte. E' il modo principale con cui l'LLM modifica il codice. + +--- + +### write + +Crea nuovi file o sovrascrive quelli esistenti. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Usalo per consentire all'LLM di creare nuovi file. Sovrascrivera' i file esistenti se sono gia' presenti. + +:::note +Lo strumento `write` e' controllato dal permesso `edit`, che copre tutte le modifiche ai file (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### read + +Leggi il contenuto dei file dal tuo codebase. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +Questo strumento legge i file e ne restituisce il contenuto. Supporta la lettura di intervalli di righe specifici per file grandi. + +--- + +### grep + +Cerca nel contenuto dei file usando espressioni regolari. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +Ricerca rapida nel contenuto su tutto il codebase. Supporta la sintassi completa delle regex e il filtro per pattern di file. + +--- + +### glob + +Trova file tramite pattern matching. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +Cerca file usando pattern glob come `**/*.js` o `src/**/*.ts`. Restituisce i percorsi corrispondenti ordinati per data di modifica. + +--- + +### list + +Elenca file e directory in un percorso specifico. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +Questo strumento elenca il contenuto di una directory. Accetta pattern glob per filtrare i risultati. + +--- + +### lsp (experimental) + +Interagisci con i server LSP configurati per ottenere funzionalita' di code intelligence come definizioni, riferimenti, hover info e call hierarchy. + +:::note +Questo strumento e' disponibile solo quando `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (oppure `OPENCODE_EXPERIMENTAL=true`). +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +Le operazioni supportate includono `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls` e `outgoingCalls`. + +Per configurare quali server LSP sono disponibili per il tuo progetto, vedi [LSP Servers](/docs/lsp). + +--- + +### patch + +Applica patch ai file. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Questo strumento applica file patch al tuo codebase. Utile per applicare diff e patch da varie fonti. + +:::note +Lo strumento `patch` e' controllato dal permesso `edit`, che copre tutte le modifiche ai file (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### skill + +Carica una [skill](/docs/skills) (un file `SKILL.md`) e ne restituisce il contenuto nella conversazione. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +Gestisci todo list durante le sessioni di coding. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +Crea e aggiorna liste di task per tracciare i progressi durante operazioni complesse. L'LLM lo usa per organizzare attivita' multi-step. + +:::note +Questo strumento e' disabilitato per i subagenti di default, ma puoi abilitarlo manualmente. [Scopri di piu'](/docs/agents/#permissions) +::: + +--- + +### todoread + +Leggi le todo list esistenti. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +Legge lo stato corrente della todo list. Usato dall'LLM per tenere traccia di quali task sono in sospeso o completati. + +:::note +Questo strumento e' disabilitato per i subagenti di default, ma puoi abilitarlo manualmente. [Scopri di piu'](/docs/agents/#permissions) +::: + +--- + +### webfetch + +Recupera contenuti dal web. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +Permette all'LLM di recuperare e leggere pagine web. Utile per consultare documentazione o ricercare risorse online. + +--- + +### websearch + +Cerca informazioni sul web. + +:::note +Questo strumento e' disponibile solo quando usi il provider OpenCode o quando la variabile d'ambiente `OPENCODE_ENABLE_EXA` e' impostata a un valore truthy (ad esempio `true` o `1`). + +Per abilitarlo all'avvio di OpenCode: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +Esegue ricerche web usando Exa AI per trovare informazioni rilevanti online. Utile per ricercare argomenti, trovare eventi attuali o raccogliere informazioni oltre il cutoff dei dati di addestramento. + +Non e' richiesta alcuna API key: lo strumento si connette direttamente al servizio MCP ospitato da Exa AI senza autenticazione. + +:::tip +Usa `websearch` quando devi trovare informazioni (discovery) e `webfetch` quando devi recuperare contenuti da un URL specifico (retrieval). +::: + +--- + +### question + +Fai domande all'utente durante l'esecuzione. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +Questo strumento permette all'LLM di porre domande all'utente durante un task. E' utile per: + +- Raccogliere preferenze o requisiti dell'utente +- Chiarire istruzioni ambigue +- Ottenere decisioni sulle scelte di implementazione +- Offrire opzioni su che direzione prendere + +Ogni domanda include un header, il testo della domanda e una lista di opzioni. Gli utenti possono selezionare dalle opzioni fornite o digitare una risposta personalizzata. Quando ci sono piu' domande, gli utenti possono navigare tra di esse prima di inviare tutte le risposte. + +--- + +## Strumenti personalizzati + +Gli strumenti personalizzati ti permettono di definire funzioni che l'LLM puo' chiamare. Sono definiti nel tuo file di configurazione e possono eseguire codice arbitrario. + +[Scopri di piu'](/docs/custom-tools) su come creare strumenti personalizzati. + +--- + +## Server MCP + +I server MCP (Model Context Protocol) permettono di integrare strumenti e servizi esterni. Questo include accesso a database, integrazioni API e servizi di terze parti. + +[Scopri di piu'](/docs/mcp-servers) su come configurare i server MCP. + +--- + +## Interni + +Internamente, strumenti come `grep`, `glob` e `list` usano [ripgrep](https://github.com/BurntSushi/ripgrep) sotto al cofano. Di default, ripgrep rispetta i pattern di `.gitignore`, quindi i file e le directory elencati in `.gitignore` vengono esclusi da ricerche ed elenchi. + +--- + +### Pattern di ignore + +Per includere file che normalmente verrebbero ignorati, crea un file `.ignore` nella root del progetto. Questo file puo' consentire esplicitamente certi path. + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +Per esempio, questo file `.ignore` permette a ripgrep di cercare dentro `node_modules/`, `dist/` e `build/` anche se sono elencate in `.gitignore`. diff --git a/packages/web/src/content/docs/it/troubleshooting.mdx b/packages/web/src/content/docs/it/troubleshooting.mdx new file mode 100644 index 00000000000..51405715072 --- /dev/null +++ b/packages/web/src/content/docs/it/troubleshooting.mdx @@ -0,0 +1,299 @@ +--- +title: Risoluzione dei problemi +description: Problemi comuni e come risolverli. +--- + +Per diagnosticare problemi con OpenCode, inizia controllando i log e i dati locali che salva su disco. + +--- + +## Log + +I file di log vengono scritti in: + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: premi `WIN+R` e incolla `%USERPROFILE%\.local\share\opencode\log` + +I file di log hanno nomi con timestamp (ad es. `2025-01-09T123456.log`) e vengono conservati i 10 file di log piu recenti. + +Puoi impostare il livello di log con l'opzione a riga di comando `--log-level` per ottenere informazioni di debug piu dettagliate. Per esempio: `opencode --log-level DEBUG`. + +--- + +## Archiviazione + +opencode salva i dati delle sessioni e altri dati dell'applicazione su disco in: + +- **macOS/Linux**: `~/.local/share/opencode/` +- **Windows**: premi `WIN+R` e incolla `%USERPROFILE%\.local\share\opencode` + +Questa directory contiene: + +- `auth.json` - dati di autenticazione come chiavi API, token OAuth +- `log/` - log dell'applicazione +- `project/` - dati specifici del progetto come dati di sessione e messaggi + - Se il progetto e dentro un repository Git, viene salvato in `.//storage/` + - Se non e un repository Git, viene salvato in `./global/storage/` + +--- + +## App desktop + +OpenCode Desktop esegue in background un server locale di OpenCode (il sidecar `opencode-cli`). La maggior parte dei problemi e causata da un plugin che si comporta male, da una cache corrotta o da un'impostazione del server errata. + +### Controlli rapidi + +- Chiudi completamente l'app e riaprila. +- Se l'app mostra una schermata di errore, fai clic su **Restart** e copia i dettagli dell'errore. +- Solo macOS: menu `OpenCode` -> **Reload Webview** (utile se l'interfaccia e vuota o bloccata). + +--- + +### Disabilita i plugin + +Se l'app desktop va in crash all'avvio, si blocca o si comporta in modo strano, inizia disabilitando i plugin. + +#### Controlla la configurazione globale + +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` +- **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: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### Controlla le directory dei plugin + +OpenCode puo anche caricare plugin locali dal disco. Spostali temporaneamente altrove (o rinomina la cartella) e riavvia l'app desktop: + +- **Plugin globali** + - **macOS/Linux**: `~/.config/opencode/plugins/` +- **Windows**: premi `WIN+R` e incolla `%USERPROFILE%\.config\opencode\plugins` +- **Plugin del progetto** (solo se usi una configurazione per progetto) + - `/.opencode/plugins/` + +Se l'app ricomincia a funzionare, riabilita i plugin uno alla volta per capire quale stia causando il problema. + +--- + +### Svuota la cache + +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. +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. + +--- + +### Risolvi problemi di connessione al server + +OpenCode Desktop puo avviare il proprio server locale (predefinito) oppure connettersi a un URL server che hai configurato. + +Se vedi una finestra **"Connection Failed"** (o l'app non supera mai la schermata di avvio), controlla se hai impostato un URL server personalizzato. + +#### Cancella l'URL del server predefinito dell'app desktop + +Dalla schermata Home, fai clic sul nome del server (con il pallino di stato) per aprire il selettore dei server. Nella sezione **Default server**, fai clic su **Clear**. + +#### Rimuovi `server.port` / `server.hostname` dalla tua configurazione + +Se il tuo `opencode.json(c)` contiene una sezione `server`, rimuovila temporaneamente e riavvia l'app desktop. + +#### Controlla le variabili d'ambiente + +Se hai `OPENCODE_PORT` impostato nell'ambiente, l'app desktop provera a usare quella porta per il server locale. + +- Rimuovi `OPENCODE_PORT` (o scegli una porta libera) e riavvia. + +--- + +### Linux: problemi Wayland / X11 + +Su Linux, alcune configurazioni Wayland possono causare finestre vuote o errori del compositor. + +- Se sei su Wayland e l'app e vuota o va in crash, prova ad avviarla con `OC_ALLOW_WAYLAND=1`. +- Se peggiora la situazione, rimuovilo e prova invece ad avviare sotto una sessione X11. + +--- + +### Windows: runtime WebView2 + +Su Windows, OpenCode Desktop richiede **WebView2 Runtime** di Microsoft Edge. Se l'app si apre su una finestra vuota o non parte, installa/aggiorna WebView2 e riprova. + +--- + +### Windows: problemi generali di prestazioni + +Se riscontri prestazioni lente, problemi di accesso ai file o problemi del terminale su Windows, prova a usare [WSL (Windows Subsystem for Linux)](/docs/windows-wsl). WSL fornisce un ambiente Linux che funziona in modo piu fluido con le funzionalita di OpenCode. + +--- + +### Notifiche non visualizzate + +OpenCode Desktop mostra le notifiche di sistema solo quando: + +- le notifiche sono abilitate per OpenCode nelle impostazioni del sistema operativo, e +- la finestra dell'app non e in primo piano. + +--- + +### Reimposta lo stato dell'app desktop (ultima risorsa) + +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. +2. Trova ed elimina questi file (si trovano nella directory dati dell'app OpenCode Desktop): + +- `opencode.settings.dat` (desktop default server URL) +- `opencode.global.dat` e `opencode.workspace.*.dat` (stato dell'interfaccia come server/progetti recenti) + +Per trovare rapidamente la directory: + +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (poi cerca i nomi file qui sopra) +- **Linux**: cerca sotto `~/.local/share` i nomi file qui sopra +- **Windows**: premi `WIN+R` -> `%APPDATA%` (poi cerca i nomi file qui sopra) + +--- + +## Ottenere aiuto + +Se riscontri problemi con OpenCode: + +1. **Segnala i problemi su GitHub** + + Il modo migliore per segnalare bug o richiedere funzionalita e tramite il nostro repository GitHub: + + [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + + Prima di creare una nuova issue, cerca tra quelle esistenti per vedere se il problema e gia stato segnalato. + +2. **Unisciti al nostro Discord** + + Per supporto in tempo reale e discussioni con la community, unisciti al nostro server Discord: + + [**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## Problemi comuni + +Ecco alcuni problemi comuni e come risolverli. + +--- + +### OpenCode non si avvia + +1. Controlla i log per eventuali messaggi di errore +2. Prova a eseguire con `--print-logs` per vedere l'output nel terminale +3. Assicurati di avere l'ultima versione con `opencode upgrade` + +--- + +### Problemi di autenticazione + +1. Prova a riautenticarti con il comando `/connect` nella TUI +2. Controlla che le chiavi API siano valide +3. Assicurati che la rete permetta connessioni all'API del provider + +--- + +### Modello non disponibile + +1. Controlla di esserti autenticato con il provider +2. Verifica che il nome del modello nella configurazione sia corretto +3. Alcuni modelli potrebbero richiedere accessi o abbonamenti specifici + +Se incontri `ProviderModelNotFoundError`, probabilmente stai facendo riferimento a un modello in modo errato da qualche parte. +I modelli vanno indicati in questo formato: `/` + +Esempi: + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +Per capire a quali modelli hai accesso, esegui `opencode models` + +--- + +### ProviderInitError + +Se incontri un ProviderInitError, probabilmente la tua configurazione e invalida o corrotta. + +Per risolvere: + +1. Per prima cosa, verifica che il provider sia configurato correttamente seguendo la [guida ai provider](/docs/providers) +2. Se il problema persiste, prova a cancellare la configurazione salvata: + + ```bash + rm -rf ~/.local/share/opencode + ``` + + Su Windows, premi `WIN+R` ed elimina: `%USERPROFILE%\.local\share\opencode` + +3. Riautenticati con il provider usando il comando `/connect` nella TUI. + +--- + +### AI_APICallError e problemi dei pacchetti provider + +Se incontri errori nelle chiamate API, potrebbe dipendere da pacchetti provider non aggiornati. opencode installa dinamicamente i pacchetti provider (OpenAI, Anthropic, Google, ecc.) quando servono e li mette in cache localmente. + +Per risolvere problemi coi pacchetti provider: + +1. Svuota la cache dei pacchetti provider: + + ```bash + rm -rf ~/.cache/opencode + ``` + + Su Windows, premi `WIN+R` ed elimina: `%USERPROFILE%\.cache\opencode` + +2. Riavvia opencode per reinstallare i pacchetti provider piu recenti + +Questo forzera opencode a scaricare le versioni piu recenti dei pacchetti provider, cosa che spesso risolve problemi di compatibilita con parametri dei modelli e cambiamenti delle API. + +--- + +### Copia/incolla non funziona su Linux + +Su Linux e necessario avere installata una delle seguenti utility per gli appunti affinche copia/incolla funzioni: + +**Per sistemi X11:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**Per sistemi Wayland:** + +```bash +apt install -y wl-clipboard +``` + +**Per ambienti headless:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +opencode rilevera se stai usando Wayland e preferira `wl-clipboard`; altrimenti provera a trovare gli strumenti per gli appunti nell'ordine: `xclip` e `xsel`. diff --git a/packages/web/src/content/docs/it/tui.mdx b/packages/web/src/content/docs/it/tui.mdx new file mode 100644 index 00000000000..8a09c97a3ee --- /dev/null +++ b/packages/web/src/content/docs/it/tui.mdx @@ -0,0 +1,387 @@ +--- +title: TUI +description: Usa l'interfaccia utente da terminale (TUI) di OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode fornisce un'interfaccia interattiva da terminale (TUI) per lavorare sui tuoi progetti con un LLM. + +Eseguire OpenCode avvia la TUI per la directory corrente. + +```bash +opencode +``` + +Oppure puoi avviarla per una specifica working directory. + +```bash +opencode /path/to/project +``` + +Una volta nella TUI, puoi inviare un messaggio come prompt. + +```text +Give me a quick summary of the codebase. +``` + +--- + +## Riferimenti ai file + +Puoi riferirti ai file nei messaggi usando `@`. Questo esegue una ricerca fuzzy dei file nella working directory corrente. + +:::tip +Puoi anche usare `@` per riferirti ai file nei messaggi. +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +Il contenuto del file viene aggiunto automaticamente alla conversazione. + +--- + +## Comandi bash + +Inizia un messaggio con `!` per eseguire un comando shell. + +```bash frame="none" +!ls -la +``` + +L'output del comando viene aggiunto alla conversazione come risultato di uno strumento. + +--- + +## Comandi + +Quando usi la TUI di OpenCode, puoi digitare `/` seguito dal nome di un comando per eseguire rapidamente azioni. Per esempio: + +```bash frame="none" +/help +``` + +Molti comandi hanno anche una scorciatoia da tastiera che usa `ctrl+x` come tasto leader (predefinito). [Scopri di piu](/docs/keybinds). + +Ecco tutti i comandi slash disponibili: + +--- + +### connetti + +Aggiunge un provider a OpenCode. Ti permette di selezionare tra i provider disponibili e aggiungere le relative chiavi API. + +```bash frame="none" +/connect +``` + +--- + +### compatta + +Compatta la sessione corrente. _Alias_: `/summarize` + +```bash frame="none" +/compact +``` + +**Scorciatoia:** `ctrl+x c` + +--- + +### dettagli + +Attiva/disattiva i dettagli di esecuzione degli strumenti. + +```bash frame="none" +/details +``` + +**Scorciatoia:** `ctrl+x d` + +--- + +### editor + +Apre un editor esterno per comporre messaggi. Usa l'editor impostato nella variabile d'ambiente `EDITOR`. [Scopri di piu](#editor-setup). + +```bash frame="none" +/editor +``` + +**Scorciatoia:** `ctrl+x e` + +--- + +### esci + +Esce da OpenCode. _Alias_: `/quit`, `/q` + +```bash frame="none" +/exit +``` + +**Scorciatoia:** `ctrl+x 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). + +```bash frame="none" +/export +``` + +**Scorciatoia:** `ctrl+x x` + +--- + +### aiuto + +Mostra la finestra di aiuto. + +```bash frame="none" +/help +``` + +**Scorciatoia:** `ctrl+x h` + +--- + +### inizializza + +Crea o aggiorna il file `AGENTS.md`. [Scopri di piu](/docs/rules). + +```bash frame="none" +/init +``` + +**Scorciatoia:** `ctrl+x i` + +--- + +### modelli + +Elenca i modelli disponibili. + +```bash frame="none" +/models +``` + +**Scorciatoia:** `ctrl+x m` + +--- + +### nuovo + +Avvia una nuova sessione. _Alias_: `/clear` + +```bash frame="none" +/new +``` + +**Scorciatoia:** `ctrl+x n` + +--- + +### rifai + +Rifai un messaggio precedentemente annullato. Disponibile solo dopo aver usato `/undo`. + +:::tip +Vengono ripristinate anche eventuali modifiche ai file. +::: + +Internamente usa Git per gestire le modifiche ai file. Quindi il progetto **deve essere un repository Git**. + +```bash frame="none" +/redo +``` + +**Scorciatoia:** `ctrl+x r` + +--- + +### sessioni + +Elenca e passa tra le sessioni. _Alias_: `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +**Scorciatoia:** `ctrl+x l` + +--- + +### condividi + +Condivide la sessione corrente. [Scopri di piu](/docs/share). + +```bash frame="none" +/share +``` + +**Scorciatoia:** `ctrl+x s` + +--- + +### temi + +Elenca i temi disponibili. + +```bash frame="none" +/theme +``` + +**Scorciatoia:** `ctrl+x t` + +--- + +### 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. + +:::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. +::: + +```bash frame="none" +/thinking +``` + +--- + +### annulla + +Annulla l'ultimo messaggio nella conversazione. Rimuove l'ultimo messaggio utente, tutte le risposte successive e qualsiasi modifica ai file. + +:::tip +Vengono annullate anche eventuali modifiche ai file. +::: + +Internamente usa Git per gestire le modifiche ai file. Quindi il progetto **deve essere un repository Git**. + +```bash frame="none" +/undo +``` + +**Scorciatoia:** `ctrl+x u` + +--- + +### annulla condivisione + +Annulla la condivisione della sessione corrente. [Scopri di piu](/docs/share#un-sharing). + +```bash frame="none" +/unshare +``` + +--- + +## Configurazione dell'editor + +Sia `/editor` sia `/export` usano l'editor specificato nella variabile d'ambiente `EDITOR`. + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + + Per renderlo permanente, aggiungilo al profilo della shell; + `~/.bashrc`, `~/.zshrc`, ecc. + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + + Per renderlo permanente, usa **System Properties** > **Environment Variables**. + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + + Per renderlo permanente, aggiungilo al profilo PowerShell. + + + + +Opzioni comuni per l'editor includono: + +- `code` - Visual Studio Code +- `cursor` - Cursor +- `windsurf` - Windsurf +- `nvim` - Neovim editor +- `vim` - Vim editor +- `nano` - Nano editor +- `notepad` - Windows Notepad +- `subl` - Sublime Text + +:::note +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. + +--- + +## Configurazione + +Puoi personalizzare il comportamento della TUI tramite il file di config di OpenCode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### 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`.** + +--- + +## Personalizzazione + +Puoi personalizzare vari aspetti della vista TUI usando la palette dei comandi (`ctrl+x h` o `/help`). Queste impostazioni persistono tra i riavvii. + +--- + +#### Visualizzazione nome utente + +Attiva/disattiva se lo username appare nei messaggi della chat. Puoi farlo da: + +- Palette comandi: cerca "username" o "hide username" +- L'impostazione viene salvata automaticamente e ricordata tra le sessioni TUI diff --git a/packages/web/src/content/docs/it/web.mdx b/packages/web/src/content/docs/it/web.mdx new file mode 100644 index 00000000000..2ec48e8e939 --- /dev/null +++ b/packages/web/src/content/docs/it/web.mdx @@ -0,0 +1,142 @@ +--- +title: Web +description: Usa OpenCode nel browser. +--- + +OpenCode puo funzionare come applicazione web nel browser, offrendo la stessa potente esperienza di coding AI senza bisogno di un terminale. + +![OpenCode Web - Nuova sessione](../../../assets/web/web-homepage-new-session.png) + +## Per iniziare + +Avvia l'interfaccia web eseguendo: + +```bash +opencode web +``` + +Questo avvia un server locale su `127.0.0.1` con una porta disponibile scelta a caso e apre automaticamente OpenCode nel browser predefinito. + +:::caution +Se `OPENCODE_SERVER_PASSWORD` non e impostata, il server non sara protetto. Va bene per l'uso locale, ma va impostata per l'accesso in rete. +::: + +:::tip[Utenti Windows] +Per la migliore esperienza, esegui `opencode web` da [WSL](/docs/windows-wsl) invece che da PowerShell. Questo garantisce accesso corretto al file system e integrazione col terminale. +::: + +--- + +## Configurazione + +Puoi configurare il server web con i flag della riga di comando o nel tuo [file di config](/docs/config). + +### Porta + +Per impostazione predefinita, OpenCode sceglie una porta disponibile. Puoi specificare una porta: + +```bash +opencode web --port 4096 +``` + +### Nome host + +Per impostazione predefinita, il server si lega a `127.0.0.1` (solo localhost). Per rendere OpenCode accessibile sulla rete: + +```bash +opencode web --hostname 0.0.0.0 +``` + +Usando `0.0.0.0`, OpenCode mostrera sia l'indirizzo locale sia quello di rete: + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### Scoperta mDNS + +Abilita mDNS per rendere il server individuabile sulla rete locale: + +```bash +opencode web --mdns +``` + +Questo imposta automaticamente l'hostname a `0.0.0.0` e pubblicizza il server come `opencode.local`. + +Puoi personalizzare il nome di dominio mDNS per eseguire piu istanze sulla stessa rete: + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +Per consentire domini aggiuntivi per CORS (utile per frontend personalizzati): + +```bash +opencode web --cors https://example.com +``` + +### Autenticazione + +Per proteggere l'accesso, imposta una password usando la variabile d'ambiente `OPENCODE_SERVER_PASSWORD`: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +Lo username predefinito e `opencode`, ma puo essere cambiato con `OPENCODE_SERVER_USERNAME`. + +--- + +## Usa l'interfaccia web + +Una volta avviata, l'interfaccia web ti da accesso alle tue sessioni OpenCode. + +### Sessioni + +Visualizza e gestisci le sessioni dalla homepage. Puoi vedere le sessioni attive e avviarne di nuove. + +![OpenCode Web - Sessione attiva](../../../assets/web/web-homepage-active-session.png) + +### Stato del server + +Fai clic su "See Servers" per vedere i server connessi e il loro stato. + +![OpenCode Web - See Servers](../../../assets/web/web-homepage-see-servers.png) + +--- + +## Collegare un terminale + +Puoi collegare una TUI da terminale a un server web gia in esecuzione: + +```bash +# Avvia il web server +opencode web --port 4096 + +# In un altro terminale, collega la TUI +opencode attach http://localhost:4096 +``` + +Questo ti permette di usare contemporaneamente interfaccia web e terminale, condividendo le stesse sessioni e lo stesso stato. + +--- + +## File di configurazione + +Puoi anche configurare le impostazioni del server nel file di config `opencode.json`: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +I flag della riga di comando hanno precedenza sulle impostazioni del file di config. diff --git a/packages/web/src/content/docs/it/windows-wsl.mdx b/packages/web/src/content/docs/it/windows-wsl.mdx new file mode 100644 index 00000000000..a1a7aa4efc1 --- /dev/null +++ b/packages/web/src/content/docs/it/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: Esegui OpenCode su Windows con WSL per la migliore esperienza. +--- + +import { Steps } from "@astrojs/starlight/components" + +Anche se OpenCode puo essere eseguito direttamente su Windows, consigliamo di usare [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) per la migliore esperienza. WSL fornisce un ambiente Linux che funziona in modo ottimale con le funzionalita di OpenCode. + +:::tip[Perche WSL?] +WSL offre prestazioni migliori del file system, supporto completo del terminale e compatibilita con gli strumenti di sviluppo su cui OpenCode fa affidamento. +::: + +--- + +## Configurazione + + + +1. **Installa WSL** + + Se non l'hai ancora fatto, [installa WSL](https://learn.microsoft.com/en-us/windows/wsl/install) seguendo la guida ufficiale Microsoft. + +2. **Installa OpenCode in WSL** + + Dopo aver configurato WSL, apri il terminale WSL e installa OpenCode usando uno dei [metodi di installazione](/docs/). + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **Usa OpenCode da WSL** + + Vai nella directory del progetto (accedi ai file Windows tramite `/mnt/c/`, `/mnt/d/`, ecc.) ed esegui OpenCode. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## App desktop + server WSL + +Se preferisci usare l'app desktop di OpenCode ma vuoi eseguire il server in WSL: + +1. **Avvia il server in WSL** con `--hostname 0.0.0.0` per consentire connessioni esterne: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **Collega l'app desktop** a `http://localhost:4096` + +:::note +Se `localhost` non funziona nella tua configurazione, usa l'indirizzo IP di WSL (da WSL: `hostname -I`) e collega `http://:4096`. +::: + +:::caution +Quando usi `--hostname 0.0.0.0`, imposta `OPENCODE_SERVER_PASSWORD` per proteggere il server. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## Client web + WSL + +Per la migliore esperienza web su Windows: + +1. **Esegui `opencode web` nel terminale WSL** invece che in PowerShell: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Accedi dal browser Windows** su `http://localhost:` (OpenCode stampa l'URL) + +Eseguire `opencode web` da WSL garantisce accesso corretto al file system e integrazione del terminale, restando comunque accessibile dal browser Windows. + +--- + +## Accesso ai file Windows + +WSL puo accedere a tutti i file Windows tramite la directory `/mnt/`: + +- Unita `C:` → `/mnt/c/` +- Unita `D:` → `/mnt/d/` +- E cosi via... + +Esempio: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +Per un'esperienza piu fluida, valuta di clonare o copiare il repository nel file system di WSL (per esempio in `~/code/`) ed eseguire OpenCode li. +::: + +--- + +## Suggerimenti + +- Tieni OpenCode in esecuzione su WSL per i progetti salvati su unita Windows: l'accesso ai file e immediato +- Usa l'[estensione WSL di VS Code](https://code.visualstudio.com/docs/remote/wsl) insieme a OpenCode per un flusso di lavoro integrato +- Configurazione e sessioni di OpenCode sono salvate nell'ambiente WSL in `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/it/zen.mdx b/packages/web/src/content/docs/it/zen.mdx new file mode 100644 index 00000000000..8ea628aee2a --- /dev/null +++ b/packages/web/src/content/docs/it/zen.mdx @@ -0,0 +1,236 @@ +--- +title: Zen +description: Lista curata di modelli fornita da OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen e una lista di modelli testati e verificati dal team di OpenCode. + +:::note +OpenCode Zen e attualmente in beta. +::: + +Zen funziona come qualunque altro provider in OpenCode. Accedi a OpenCode Zen e ottieni la tua chiave API. E **completamente opzionale**: non devi usarlo per usare OpenCode. + +--- + +## Contesto + +Ci sono moltissimi modelli, ma solo pochi funzionano bene come agenti di coding. Inoltre, la maggior parte dei provider e configurata in modo molto diverso, quindi prestazioni e qualita possono variare parecchio. + +:::tip +Abbiamo testato un gruppo selezionato di modelli e provider che funzionano bene con OpenCode. +::: + +Quindi, se usi un modello tramite qualcosa come OpenRouter, non puoi mai essere sicuro di ottenere la migliore versione del modello che vuoi. + +Per risolvere, abbiamo fatto alcune cose: + +1. Abbiamo testato un gruppo selezionato di modelli e parlato coi loro team su come eseguirli al meglio. +2. Poi abbiamo lavorato con alcuni provider per assicurarci che venissero serviti correttamente. +3. Infine, abbiamo fatto benchmark delle combinazioni modello/provider e creato una lista che ci sentiamo di raccomandare. + +OpenCode Zen e un gateway AI che ti da accesso a questi modelli. + +--- + +## Come funziona + +OpenCode Zen funziona come qualunque altro provider in OpenCode. + +1. Accedi a **OpenCode Zen**, aggiungi i dettagli di fatturazione e copia la chiave API. +2. Esegui il comando `/connect` nella TUI, seleziona OpenCode Zen e incolla la chiave API. +3. Esegui `/models` nella TUI per vedere la lista dei modelli che consigliamo. + +Paghi per richiesta e puoi aggiungere credito al tuo account. + +--- + +## Endpoint + +Puoi anche accedere ai nostri modelli tramite i seguenti endpoint API. + +| Modello | ID modello | Endpoint | Pacchetto AI SDK | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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` | + +Il [model id](/docs/config/#models) nella config di OpenCode usa il formato `opencode/`. Per esempio, per GPT 5.2 Codex useresti `opencode/gpt-5.2-codex` nella config. + +--- + +### Modelli + +Puoi recuperare la lista completa dei modelli disponibili e i relativi metadati da: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## Prezzi + +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.1 | $0.30 | $1.20 | $0.10 | - | +| GLM 4.7 Free | Gratis | Gratis | Gratis | - | +| 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 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 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.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 | Gratis | Gratis | Gratis | - | + +Potresti notare _Claude Haiku 3.5_ nella cronologia d'uso. E un [modello a basso costo](/docs/config/#models) usato per generare i titoli delle sessioni. + +:::note +Le commissioni della carta di credito vengono ribaltate al costo (4.4% + $0.30 per transazione); non addebitiamo nulla oltre a questo. +::: + +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. +- 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. + +--- + +### Ricarica automatica + +Se il saldo scende sotto $5, Zen ricarica automaticamente $20. + +Puoi cambiare l'importo della ricarica automatica. Puoi anche disabilitare completamente l'auto-reload. + +--- + +### Limiti mensili + +Puoi anche impostare un limite mensile di utilizzo per l'intero workspace e per ogni membro del team. + +Per esempio, se imposti un limite mensile a $20, Zen non usera piu di $20 in un mese. Ma se hai l'auto-reload attivo, Zen potrebbe finire per addebitarti piu di $20 se il saldo scende sotto $5. + +--- + +## Privacy + +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. +- 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). + +--- + +## Per i team + +Zen funziona benissimo anche per i team. Puoi invitare colleghi, assegnare ruoli, curare i modelli usati dal team e altro. + +:::note +I workspace sono attualmente gratuiti per i team come parte della beta. +::: + +Gestire il workspace e attualmente gratuito per i team come parte della beta. Condivideremo presto piu dettagli sul pricing. + +--- + +### Ruoli + +Puoi invitare colleghi nel workspace e assegnare ruoli: + +- **Admin**: gestisce modelli, membri, chiavi API e fatturazione +- **Member**: gestisce solo le proprie chiavi API + +Gli admin possono anche impostare limiti mensili di spesa per ogni membro per tenere i costi sotto controllo. + +--- + +### Accesso ai modelli + +Gli admin possono abilitare o disabilitare modelli specifici per il workspace. Le richieste verso un modello disabilitato restituiscono un errore. + +Questo e utile quando vuoi disabilitare l'uso di un modello che raccoglie dati. + +--- + +### Usa le tue chiavi + +Puoi usare le tue chiavi API OpenAI o Anthropic continuando ad accedere agli altri modelli in Zen. + +Quando usi le tue chiavi, i token vengono fatturati direttamente dal provider, non da Zen. + +Per esempio, la tua organizzazione potrebbe avere gia una chiave per OpenAI o Anthropic e vuoi usare quella invece di quella fornita da Zen. + +--- + +## Obiettivi + +Abbiamo creato OpenCode Zen per: + +1. Fare **benchmark** dei migliori modelli/provider per agenti di coding. +2. Dare accesso alle opzioni di **massima qualita** senza ridurre le prestazioni o instradare verso provider piu economici. +3. Trasferire eventuali **riduzioni di prezzo** vendendo al costo; l'unico markup copre le commissioni di elaborazione. +4. Evitare **lock-in** permettendoti di usarlo con qualunque altro agente di coding e lasciandoti sempre usare anche altri provider con OpenCode. diff --git a/packages/web/src/content/docs/ja/acp.mdx b/packages/web/src/content/docs/ja/acp.mdx new file mode 100644 index 00000000000..f7b995bf39f --- /dev/null +++ b/packages/web/src/content/docs/ja/acp.mdx @@ -0,0 +1,155 @@ +--- +title: ACP サポート +description: ACP 互換エディターで OpenCode を使用します。 +--- + +OpenCode は [Agent Client Protocol](https://agentclientprotocol.com) または (ACP) をサポートしているため、互換性のあるエディターや IDE で直接使用できます。 + +:::tip +ACP をサポートするエディターとツールのリストについては、[ACP progress report](https://zed.dev/blog/acp-progress-report#available-now) を参照してください。 +::: +ACP は、コードエディターと AI コーディングエージェント間の通信を標準化するオープンプロトコルです。 + +--- + +## 設定 + +ACP 経由で OpenCode を使用するには、`opencode acp` コマンドを実行するようにエディタを設定します。 + +このコマンドは、stdio 経由で JSON-RPC 経由でエディターと通信する ACP 互換のサブプロセスとして OpenCode を開始します。 + +以下は、ACP をサポートする一般的なエディタの例です。 + +--- + +### Zed + +[Zed](https://zed.dev) 構成 (`~/.config/zed/settings.json`) に追加します。 + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +これを開くには、**コマンドパレット**の `agent: new thread` アクションを使用します。 + +`keymap.json` を編集してキーボードショートカットをバインドすることもできます。 + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### JetBrains IDE + +[documentation](https://www.jetbrains.com/help/ai-assistant/acp.html) に従って、[JetBrains IDE](https://www.jetbrains.com/) acp.json に追加します: + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +これを開くには、AI Chat エージェントセレクターで新しい「OpenCode」エージェントを使用します。 + +--- + +### Avante.nvim + +[Avante.nvim](https://github.com/yetone/avante.nvim) 設定に追加: + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +環境変数を渡す必要がある場合: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +[CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim) で OpenCode を ACP エージェントとして使用するには、以下を Neovim 構成に追加します。 + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +この構成は、OpenCode をチャットの ACP エージェントとして使用するように CodeCompanion をセットアップします。 + +環境変数 (`OPENCODE_API_KEY` など) を渡す必要がある場合、詳細については、CodeCompanion.nvim ドキュメントの「[アダプターの構成: 環境変数](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key)」を参照してください。 + +## サポート + +OpenCode は、ACP 経由でもターミナル内で動作するのと同じように動作します。すべての機能がサポートされています。 + +:::note +`/undo` や `/redo` などの一部の組み込みスラッシュコマンドは現在サポートされていません。 +::: + +- 組み込みツール (ファイル操作、ターミナルコマンドなど) +- カスタムツールとスラッシュコマンド +- OpenCode 設定で構成された MCP サーバー +- `AGENTS.md` のプロジェクト固有のルール +- カスタムフォーマッタとリンター +- エージェントと権限システム diff --git a/packages/web/src/content/docs/ja/agents.mdx b/packages/web/src/content/docs/ja/agents.mdx new file mode 100644 index 00000000000..879a43b057a --- /dev/null +++ b/packages/web/src/content/docs/ja/agents.mdx @@ -0,0 +1,743 @@ +--- +title: エージェント +description: 特殊なエージェントを構成して使用します。 +--- + +エージェントは、特定のタスクやワークフロー向けに構成できる特殊な AI アシスタントです。これらを使用すると、カスタムプロンプト、モデル、ツールアクセスを備えた焦点を絞ったツールを作成できます。 + +:::tip +Plan エージェントを使用すると、コードを変更せずにコードを分析し、提案を確認できます。 +::: + +セッション中にエージェントを切り替えたり、`@` メンションでエージェントを呼び出したりできます。 + +--- + +## 種類 + +OpenCode には 2 種類のエージェントがあります。プライマリエージェントとサブエージェント。 + +--- + +### プライマリエージェント + +プライマリエージェントは、直接対話する主要なアシスタントです。 **Tab** キー、または設定した `switch_agent` キーバインドを使用して、それらを切り替えることができます。これらのエージェントが主な会話を処理します。ツールへのアクセスは権限によって構成されます。たとえば、Build ではすべてのツールが有効になっていますが、Plan は制限されています。 + +:::tip +**Tab** キーを使用して、セッション中にプライマリエージェントを切り替えることができます。 +::: + +OpenCode には、**Build** と **Plan** という 2 つの組み込みプライマリエージェントが付属しています。これらについて以下で説明します。 + +--- + +### サブエージェント + +サブエージェントは、プライマリエージェントが特定のタスクのために呼び出すことができる特殊なアシスタントです。メッセージ内で **@ メンション**することで、手動で呼び出すこともできます。 + +OpenCode には、**General** と **Explore** という 2 つの組み込みサブエージェントが付属しています。これについては以下で見ていきます。 + +--- + +## 組み込み + +OpenCode には、2 つの組み込みプライマリエージェントと 2 つの組み込みサブエージェントが付属しています。 + +--- + +### Build + +_モード_: `primary` + +Build は、すべてのツールが有効になっている **デフォルト** プライマリエージェントです。これは、ファイル操作やシステムコマンドへの完全なアクセスが必要な開発作業用の標準エージェントです。 + +--- + +### Plan + +_モード_: `primary` + +計画と分析のために設計された制限付きエージェント。より詳細な制御を提供し、意図しない変更を防ぐために、許可システムを使用しています。 +デフォルトでは、次のすべてが `ask` に設定されます。 + +- `file edits`: すべての書き込み、パッチ、および編集 +- `bash`: すべての bash コマンド + +このエージェントは、コードベースに実際の変更を加えずに LLM にコードの分析、変更の提案、または計画の作成を行わせたい場合に役立ちます。 + +--- + +### General + +_モード_: `subagent` + +複雑な質問を調査し、複数ステップのタスクを実行するための汎用エージェント。完全なツールアクセス権 (todo を除く) があるため、必要に応じてファイルを変更できます。これを使用して、複数の作業単位を並行して実行します。 + +--- + +### Explore + +_モード_: `subagent` + +コードベースを探索するための高速な読み取り専用エージェント。ファイルを変更できません。これは、パターンでファイルをすばやく検索したり、コードでキーワードを検索したり、コードベースに関する質問に答えたりする必要がある場合に使用します。 + +--- + +### Compact + +_モード_: `primary` + +長いコンテキストを小さな要約に圧縮する隠しシステムエージェント。これは必要に応じて自動的に実行され、UI では選択できません。 + +--- + +### Title + +_モード_: `primary` + +短いセッションタイトルを生成する非表示のシステムエージェント。これは自動的に実行され、UI では選択できません。 + +--- + +### Summary + +_モード_: `primary` + +セッション概要を作成する非表示のシステムエージェント。これは自動的に実行され、UI では選択できません。 + +--- + +## 使用法 + +1. プライマリエージェントの場合は、セッション中に **Tab** キーを使用してエージェントを切り替えます。設定した `switch_agent` キーバインドを使用することもできます。 + +2. サブエージェントは次のように呼び出すことができます。 + - プライマリエージェントによって、説明に基づいて特殊なタスクを **自動的に** 実行されます。 + - メッセージ内でサブエージェントを **@ メンション**することで手動で実行できます。例えば。 + + ```txt frame="none" + @general help me search for this function + ``` + +3. **セッション間のナビゲーション**: サブエージェントが独自の子セッションを作成する場合、以下を使用して親セッションとすべての子セッションの間を移動できます。 + - **\+Right** (または設定した `session_child_cycle` キーバインド) で、親 → 子 1 → 子 2 → ... → 親と順に循環します。 + - **\+Left** (または設定した `session_child_cycle_reverse` キーバインド) で、親 ← 子 1 ← 子 2 ← ... ← 親を逆方向に循環します。 + +これにより、メインの会話と専門的なサブエージェントの作業をシームレスに切り替えることができます。 + +--- + +## 設定 + +組み込みエージェントをカスタマイズしたり、構成を通じて独自のエージェントを作成したりできます。エージェントは次の 2 つの方法で構成できます。 + +--- + +### JSON + +`opencode.json` 設定ファイルでエージェントを構成します。 + +```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 + +Markdown ファイルを使用してエージェントを定義することもできます。それらを次の場所に置きます。 + +- グローバル: `~/.config/opencode/agents/` +- プロジェクトごと: `.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 ファイル名がエージェント名になります。たとえば、`review.md` は `review` エージェントを作成します。 + +--- + +## オプション + +これらの設定オプションを詳しく見てみましょう。 + +--- + +### 説明 + +`description` オプションを使用して、エージェントの機能とそれをいつ使用するかについての簡単な説明を提供します。 + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +これは**必須**の設定オプションです。 + +--- + +### 温度 + +`temperature` 設定を使用して、LLM の応答のランダム性と創造性を制御します。 + +値が低いほど、応答はより集中的かつ決定的になりますが、値が高いほど、創造性と変動性が高まります。 + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +通常、温度値の範囲は 0.0 ~ 1.0 です。 + +- **0.0-0.2**: 非常に焦点が絞られた決定的な応答。コード分析と計画に最適です。 +- **0.3-0.5**: 創造性を備えたバランスの取れた応答。一般的な開発タスクに適しています。 +- **0.6-1.0**: より創造的で多様な応答。ブレーンストーミングや探索に役立ちます。 + +```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}" + } + } +} +``` + +温度が指定されていない場合、OpenCode はモデル固有のデフォルトを使用します。通常、ほとんどのモデルでは 0、Qwen モデルでは 0.55 です。 + +--- + +### ステップ数 + +エージェントが強制的にテキストのみで応答するまでに実行できるエージェントの反復の最大数を制御します。これにより、コストを管理したいユーザーは、エージェントのアクションに制限を設定できます。 + +これが設定されていない場合、エージェントは、モデルが停止を選択するか、ユーザーがセッションを中断するまで反復を続けます。 + +```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 + } + } +} +``` + +制限に達すると、エージェントは、作業の概要と推奨される残りのタスクを応答するように指示する特別なシステムプロンプトを受け取ります。 + +:::caution +従来の `maxSteps` フィールドは非推奨になりました。代わりに `steps` を使用してください。 +::: + +--- + +### 無効化 + +エージェントを無効にするには、`true` に設定します。 + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### プロンプト + +`prompt` 設定を使用して、このエージェントのカスタムシステムプロンプトファイルを指定します。プロンプトファイルには、エージェントの目的に固有の指示が含まれている必要があります。 + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +このパスは、設定ファイルが配置されている場所に対する相対パスです。したがって、これはグローバルな OpenCode 設定とプロジェクト固有の設定の両方で機能します。 + +--- + +### モデル + +`model` 設定を使用して、このエージェントのモデルをオーバーライドします。さまざまなタスクに最適化されたさまざまなモデルを使用する場合に役立ちます。たとえば、計画にはより高速なモデルを、実装にはより有能なモデルを使用します。 + +:::tip +モデルを指定しない場合、プライマリエージェントは [グローバルに設定されたモデル](/docs/config#models) を使用し、サブエージェントはサブエージェントを呼び出したプライマリエージェントのモデルを使用します。 +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +OpenCode 設定内のモデル ID は、`provider/model-id` という形式を使用します。たとえば、[OpenCode Zen](/docs/zen) を使用している場合、GPT 5.1 Codex には `opencode/gpt-5.1-codex` を使用します。 + +--- + +### ツール + +`tools` 設定を使用して、このエージェントで使用できるツールを制御します。特定のツールを `true` または `false` に設定することで、有効または無効にすることができます。 + +```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 +エージェント固有の設定はグローバル設定をオーバーライドします。 +::: +MCP サーバーからすべてのツールを無効にするには、次のようにします。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[ツール](/docs/tools) について詳しくはこちらをご覧ください。 + +--- + +### 権限 + +権限を設定して、エージェントが実行できるアクションを管理できます。現在、`edit`、`bash`、および `webfetch` ツールの権限は次のように構成できます。 + +- `"ask"` — ツールを実行する前に承認を求めるプロンプトを表示する +- `"allow"` — 承認なしですべての操作を許可する +- `"deny"` — ツールを無効にする + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +これらの権限はエージェントごとにオーバーライドできます。 + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +Markdown エージェントで権限を設定することもできます。 + +```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. +``` + +特定の bash コマンドに対するアクセス許可を設定できます。 + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +これにはグロブパターンを使用できます。 + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +また、`*` ワイルドカードを使用して、すべてのコマンドの権限を管理することもできます。 +最後に一致したルールが優先されるため、`*` ワイルドカードを最初に置き、特定のルールを後に置きます。 + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[権限](/docs/permissions)について詳しくはこちらをご覧ください。 + +--- + +### モード + +`mode` 設定を使用してエージェントのモードを制御します。 `mode` オプションは、エージェントの使用方法を決定するために使用されます。 + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +`mode` オプションは、`primary`、`subagent`、または `all` に設定できます。 `mode` が指定されていない場合、デフォルトは `all` になります。 + +--- + +### 非表示 + +`@` を使用して、`hidden: true` オートコンプリートメニューからサブエージェントを非表示にします。他のエージェントによってタスクツールを介してプログラム的にのみ呼び出す必要がある内部サブエージェントに役立ちます。 + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +これは、オートコンプリートメニューでのユーザーの表示にのみ影響します。権限が許可されていれば、非表示のエージェントをタスクツール経由でモデルから呼び出すことができます。 + +:::note +`mode: subagent` エージェントにのみ適用されます。 +::: + +--- + +### タスクの権限 + +`permission.task` を使用して、エージェントがタスクツール経由でどのサブエージェントを呼び出すことができるかを制御します。柔軟なマッチングのためにグロブパターンを使用します。 + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +`deny` に設定すると、サブエージェントはタスクツールの説明から完全に削除されるため、モデルはそれを呼び出そうとしません。 + +:::tip +ルールは順番に評価され、**最後に一致したルールが優先されます**。上記の例では、`orchestrator-planner` は `*` (拒否) と `orchestrator-*` (許可) の両方に一致しますが、`orchestrator-*` は `*` の後に来るため、結果は `allow` になります。 +:::tip +ユーザーは、エージェントのタスク権限が拒否する場合でも、`@` オートコンプリートメニューを介して、いつでもサブエージェントを直接呼び出すことができます。 +::: + +--- + +### 色 + +`color` オプションを使用して、UI でのエージェントの外観をカスタマイズします。これは、インターフェイスでのエージェントの表示方法に影響します。 + +有効な 16 進カラー (例: `#FF5733`) またはテーマカラー: `primary`、`secondary`、`accent`、`success`、`warning`、`error`、`info` を使用します。 + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +`top_p` オプションで応答の多様性を制御します。ランダム性を制御するための温度の代替手段。 + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +値の範囲は 0.0 ~ 1.0 です。値が低いほど集中力が高まり、値が高いほど多様性が高まります。 + +--- + +### 追加オプション + +エージェント設定で指定したその他のオプションはすべて、モデルオプションとしてプロバイダーに**直接渡されます**。これにより、プロバイダー固有の機能とパラメーターを使用できるようになります。 + +たとえば、OpenAI の推論モデルを使用すると、推論の労力を制御できます。 + +```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" + } + } +} +``` + +これらの追加オプションはモデルとプロバイダーに固有です。使用可能なパラメータについては、プロバイダのドキュメントを確認してください。 + +:::tip +`opencode models` を実行して、利用可能なモデルのリストを表示します。 +::: + +--- + +## エージェントの作成 + +次のコマンドを使用して、新しいエージェントを作成できます。 + +```bash +opencode agent create +``` + +この対話型コマンドは次のことを行います。 + +1. エージェントを保存する場所を尋ねます。グローバルまたはプロジェクト固有。 +2. エージェントが行うべきことの説明。 +3. 適切なシステムプロンプトと識別子を生成します。 +4. エージェントがアクセスできるツールを選択できます。 +5. 最後に、エージェント設定を含む Markdown ファイルを作成します。 + +--- + +## ユースケース + +さまざまなエージェントの一般的な使用例をいくつか示します。 + +- **ビルドエージェント**: すべてのツールを有効にした完全な開発作業 +- **計画エージェント**: 変更を加えずに分析および計画を立てる +- **レビューエージェント**: 読み取り専用アクセスとドキュメントツールを備えたコードレビュー +- **デバッグエージェント**: bash および読み取りツールを有効にして調査に重点を置きます +- **ドキュメントエージェント**: ファイル操作を使用してドキュメントを作成しますが、システムコマンドは使用しません + +--- + +## 例 + +以下に、役立つと思われるエージェントの例をいくつか示します。 + +:::tip +共有したいエージェントはいますか? [PR](https://github.com/anomalyco/opencode) を送信します。 +::: + +--- + +### ドキュメント作成エージェント + +```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 +``` + +--- + +### セキュリティ監査エージェント + +```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/ja/cli.mdx b/packages/web/src/content/docs/ja/cli.mdx new file mode 100644 index 00000000000..aeae74731f2 --- /dev/null +++ b/packages/web/src/content/docs/ja/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: OpenCode CLI のオプションとコマンド。 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode CLI は、引数なしで実行すると、デフォルトで [TUI](/docs/tui) を開始します。 + +```bash +opencode +``` + +ただし、このページに記載されているようにコマンドも受け入れます。これにより、OpenCode をプログラム的に操作できるようになります。 + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +OpenCode ターミナルユーザーインターフェイスを開始します。 + +```bash +opencode [project] +``` + +#### フラグ + +| フラグ | ショート | 説明 | +| ------------ | ----------- | ---------------------------------------------------------- | +| `--continue` | `-c` | 最後のセッションを続行 | +| `--session` | | 続行時にセッションをフォーク (`-s` または `--fork` と併用) | +| `--continue` | `--session` | 続行するセッション ID | +| `--prompt` | | 使用のプロンプト | +| `--model` | `-m` | プロバイダー/モデルの形式で使用するモデル | +| `--agent` | | 使用するエージェント | +| `--port` | | リッスンするポート | +| `--hostname` | | リッスンするホスト名 | + +--- + +## コマンド + +OpenCode CLI には次のコマンドもあります。 + +--- + +### agent + +OpenCode のエージェントを管理します。 + +```bash +opencode agent [command] +``` + +--- + +### attach + +`serve` または `web` コマンドを使用して起動された、すでに実行中の OpenCode バックエンドサーバーにターミナルを接続します。 + +```bash +opencode attach [url] +``` + +これにより、リモート OpenCode バックエンドで TUI を使用できるようになります。例えば: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### フラグ + +| フラグ | ショート | 説明 | +| ----------- | -------- | ------------------------------ | +| `--dir` | | TUI を開始する作業ディレクトリ | +| `--session` | `-s` | 続行するセッション ID | + +--- + +#### create + +カスタム構成で新しいエージェントを作成します。 + +```bash +opencode agent create +``` + +このコマンドは、カスタムシステムプロンプトとツール構成を使用して新しいエージェントを作成する手順を示します。 + +--- + +#### list + +利用可能なエージェントをすべてリストします。 + +```bash +opencode agent list +``` + +--- + +### auth + +プロバイダーの資格情報とログインを管理するコマンド。 + +```bash +opencode auth [command] +``` + +--- + +#### login + +OpenCode は [Models.dev](https://models.dev) のプロバイダーリストを利用しているため、`opencode auth login` を使用して、使用したいプロバイダーの API キーを構成できます。これは `~/.local/share/opencode/auth.json` に保存されます。 + +```bash +opencode auth login +``` + +OpenCode が起動すると、認証情報ファイルからプロバイダーがロードされます。また、環境またはプロジェクト内の `.env` ファイルで定義されたキーがあるかどうかも確認します。 + +--- + +#### list + +認証情報ファイルに保存されているすべての認証されたプロバイダーをリストします。 + +```bash +opencode auth list +``` + +またはショートバージョン。 + +```bash +opencode auth ls +``` + +--- + +#### logout + +資格情報ファイルからプロバイダーをクリアすることで、プロバイダーからログアウトします。 + +```bash +opencode auth logout +``` + +--- + +### github + +リポジトリ自動化のための GitHub エージェントを管理します。 + +```bash +opencode github [command] +``` + +--- + +#### install + +GitHub エージェントをリポジトリにインストールします。 + +```bash +opencode github install +``` + +これにより、必要な GitHub Actions ワークフローが設定され、構成プロセスがガイドされます。 [詳細はこちら](/docs/github)。 + +--- + +#### run + +GitHub エージェントを実行します。これは通常、GitHub Actions で使用されます。 + +```bash +opencode github run +``` + +##### フラグ + +| フラグ | 説明 | +| --------- | --------------------------------------------------- | +| `--event` | エージェントを実行するための GitHub モック イベント | +| `--token` | GitHub 個人アクセストークン | + +--- + +### mcp + +モデルコンテキストプロトコルサーバーを管理します。 + +```bash +opencode mcp [command] +``` + +--- + +#### add + +MCP サーバーを構成に追加します。 + +```bash +opencode mcp add +``` + +このコマンドは、ローカルまたはリモートの MCP サーバーを追加する手順を示します。 + +--- + +#### list + +構成されているすべての MCP サーバーとその接続ステータスをリストします。 + +```bash +opencode mcp list +``` + +または、短いバージョンを使用してください。 + +```bash +opencode mcp ls +``` + +--- + +#### auth + +OAuth 対応の MCP サーバーで認証します。 + +```bash +opencode mcp auth [name] +``` + +サーバー名を指定しない場合は、利用可能な OAuth 対応サーバーから選択するように求められます。 + +OAuth 対応サーバーとその認証ステータスを一覧表示することもできます。 + +```bash +opencode mcp auth list +``` + +または、短いバージョンを使用してください。 + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +MCP サーバーの OAuth 資格情報を削除します。 + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +MCP サーバーの OAuth 接続の問題をデバッグします。 + +```bash +opencode mcp debug +``` + +--- + +### models + +構成されたプロバイダーから利用可能なすべてのモデルをリストします。 + +```bash +opencode models [provider] +``` + +このコマンドは、構成されたプロバイダー全体で利用可能なすべてのモデルを `provider/model` の形式で表示します。 + +これは、[設定](/docs/config/) で使用する正確なモデル名を把握するのに役立ちます。 + +オプションでプロバイダー ID を渡して、そのプロバイダーによってモデルをフィルターできます。 + +```bash +opencode models anthropic +``` + +#### フラグ + +| フラグ | 説明 | +| ----------- | --------------------------------------------------------------- | +| `--refresh` | models.dev からモデルキャッシュを更新します。 | +| `--verbose` | より詳細なモデル出力を使用します (コストなどのメタデータを含む) | + +`--refresh` フラグを使用して、キャッシュされたモデルリストを更新します。これは、新しいモデルがプロバイダーに追加され、それを OpenCode で確認したい場合に便利です。 + +```bash +opencode models --refresh +``` + +--- + +### run + +プロンプトを直接渡して、非対話モードで opencode を実行します。 + +```bash +opencode run [message..] +``` + +これは、スクリプト作成、自動化、または完全な TUI を起動せずに迅速な回答が必要な場合に便利です。例えば。 + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +実行中の `opencode serve` インスタンスにアタッチして、実行ごとの MCP サーバーのコールドブート時間を回避することもできます。 + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +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` | | ローカルサーバーのポート (デフォルトはランダムポート) | + +--- + +### serve + +API アクセスのためにヘッドレス OpenCode サーバーを起動します。完全な HTTP インターフェイスについては、[サーバーのドキュメント](/docs/server) を確認してください。 + +```bash +opencode serve +``` + +これにより、TUI インターフェイスを使用せずに opencode 機能への API アクセスを提供する HTTP サーバーが起動します。 `OPENCODE_SERVER_PASSWORD` を設定して HTTP 基本認証を有効にします (ユーザー名のデフォルトは `opencode`)。 + +#### フラグ + +| フラグ | 説明 | +| ------------ | --------------------------------------- | +| `--port` | リッスンするポート | +| `--hostname` | リッスンするホスト名 | +| `--mdns` | mDNS 検出を有効にする | +| `--cors` | CORS を許可する追加のブラウザーオリジン | + +--- + +### session + +OpenCode セッションを管理します。 + +```bash +opencode session [command] +``` + +--- + +#### list + +すべての OpenCode セッションをリストします。 + +```bash +opencode session list +``` + +##### フラグ + +| フラグ | ショート | 説明 | +| ------------- | -------- | ---------------------------------------- | +| `--max-count` | `-n` | 最新のセッションを N 個に制限 | +| `--format` | | 出力形式: テーブルまたは json (テーブル) | + +--- + +### stats + +OpenCode セッションのトークンの使用状況とコストの統計を表示します。 + +```bash +opencode stats +``` + +#### フラグ + +| フラグ | 説明 | +| ----------- | ------------------------------------------------------------------------------------------ | +| `--days` | 過去 N 日間の統計を表示 (全期間) | +| `--tools` | 表示するツールの数 (すべて) | +| `--models` | モデルの使用状況の内訳を表示 (デフォルトでは非表示)。上位 N 件を表示するには数値を渡します | +| `--project` | プロジェクトでフィルタリング (全プロジェクト、空文字列: 現在のプロジェクト) | + +--- + +### export + +セッションデータを JSON としてエクスポートします。 + +```bash +opencode export [sessionID] +``` + +セッション ID を指定しない場合は、利用可能なセッションから選択するように求められます。 + +--- + +### import + +JSON ファイルまたは OpenCode 共有 URL からセッションデータをインポートします。 + +```bash +opencode import +``` + +ローカルファイルまたは OpenCode 共有 URL からインポートできます。 + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +Web インターフェイスを使用してヘッドレス OpenCode サーバーを起動します。 + +```bash +opencode web +``` + +これにより、HTTP サーバーが起動し、Web ブラウザが開き、Web インターフェイスを通じて OpenCode にアクセスします。 `OPENCODE_SERVER_PASSWORD` を設定して HTTP 基本認証を有効にします (ユーザー名のデフォルトは `opencode`)。 + +#### フラグ + +| フラグ | 説明 | +| ------------ | --------------------------------------- | +| `--port` | リッスンするポート | +| `--hostname` | リッスンするホスト名 | +| `--mdns` | mDNS 検出を有効にする | +| `--cors` | CORS を許可する追加のブラウザーオリジン | + +--- + +### acp + +ACP (エージェントクライアントプロトコル) サーバーを起動します。 + +```bash +opencode acp +``` + +このコマンドは、nd-JSON を使用して stdin/stdout 経由で通信する ACP サーバーを起動します。 + +#### フラグ + +| フラグ | 説明 | +| ------------ | -------------------- | +| `--cwd` | 作業ディレクトリ | +| `--port` | リッスンするポート | +| `--hostname` | リッスンするホスト名 | + +--- + +### uninstall + +OpenCode をアンインストールし、関連ファイルをすべて削除します。 + +```bash +opencode uninstall +``` + +#### フラグ + +| フラグ | ショート | 説明 | +| --------------- | -------- | -------------------------------------------- | +| `--keep-config` | `-c` | 構成ファイルを保持する | +| `--keep-data` | `-d` | セッションデータとスナップショットを保持する | +| `--dry-run` | | 削除せずに削除される内容を表示する | +| `--force` | `-f` | 確認プロンプトをスキップする | + +--- + +### upgrade + +opencode を最新バージョンまたは特定のバージョンに更新します。 + +```bash +opencode upgrade [target] +``` + +最新バージョンにアップグレードするには。 + +```bash +opencode upgrade +``` + +特定のバージョンにアップグレードするには。 + +```bash +opencode upgrade v0.1.48 +``` + +#### フラグ + +| フラグ | ショート | 説明 | +| ---------- | -------- | ------------------------------------------------------ | +| `--method` | `-m` | 使用されたインストール方法。curl, npm, pnpm, bun, brew | + +--- + +## グローバルフラグ + +opencode CLI は次のグローバルフラグを受け取ります。 + +| フラグ | ショート | 説明 | +| -------------- | -------- | ------------------------------------- | +| `--help` | `-h` | ヘルプを表示 | +| `--version` | `-v` | バージョン番号を出力 | +| `--print-logs` | | ログを標準エラー出力に出力 | +| `--log-level` | | ログレベル (DEBUG、INFO、WARN、ERROR) | + +--- + +## 環境変数 + +OpenCode は環境変数を使用して構成できます。 + +| 変数 | タイプ | 説明 | +| ------------------------------------- | -------- | ------------------------------------------------------------------- | +| `OPENCODE_AUTO_SHARE` | ブール値 | セッションを自動的に共有する | +| `OPENCODE_GIT_BASH_PATH` | 文字列 | Windows 上で実行可能な Git Bash へのパス | +| `OPENCODE_CONFIG` | 文字列 | 構成ファイルへのパス | +| `OPENCODE_CONFIG_DIR` | 文字列 | config ディレクトリへのパス | +| `OPENCODE_CONFIG_CONTENT` | 文字列 | インライン JSON 構成コンテンツ | +| `OPENCODE_DISABLE_AUTOUPDATE` | ブール値 | 自動更新チェックを無効にする | +| `OPENCODE_DISABLE_PRUNE` | ブール値 | 古いデータのプルーニングを無効にする | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | ブール値 | ターミナルタイトルの自動更新を無効にする | +| `OPENCODE_PERMISSION` | 文字列 | インライン化された json 権限設定 | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | ブール値 | デフォルトのプラグインを無効にする | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | ブール値 | LSP サーバーの自動ダウンロードを無効にする | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | ブール値 | 実験モデルを有効にする | +| `OPENCODE_DISABLE_AUTOCOMPACT` | ブール値 | 自動コンテキスト圧縮を無効にする | +| `OPENCODE_DISABLE_CLAUDE_CODE` | ブール値 | `.claude` からの読み取りを無効にする (プロンプト + スキル) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | ブール値 | `~/.claude/CLAUDE.md` の読み取りを無効にする | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | ブール値 | `.claude/skills` のロードを無効にする | +| `OPENCODE_DISABLE_MODELS_FETCH` | ブール値 | リモートソースからのモデルの取得を無効にする | +| `OPENCODE_FAKE_VCS` | 文字列 | テスト目的の偽の VCS プロバイダー | +| `OPENCODE_DISABLE_FILETIME_CHECK` | ブール値 | 最適化のためにファイル時間チェックを無効にする | +| `OPENCODE_CLIENT` | 文字列 | クライアント識別子 (デフォルトは `cli`) | +| `OPENCODE_ENABLE_EXA` | ブール値 | Exa Web 検索ツールを有効にする | +| `OPENCODE_SERVER_PASSWORD` | 文字列 | `serve`/`web` の基本認証を有効にする | +| `OPENCODE_SERVER_USERNAME` | 文字列 | 基本認証ユーザー名 (デフォルト `opencode`) をオーバーライドします。 | +| `OPENCODE_MODELS_URL` | 文字列 | モデル設定を取得するためのカスタム URL | + +--- + +### 実験的 + +これらの環境変数により、変更または削除される可能性のある実験的な機能が有効になります。 + +| 変数 | タイプ | 説明 | +| ----------------------------------------------- | -------- | ------------------------------------------------ | +| `OPENCODE_EXPERIMENTAL` | ブール値 | すべての実験的機能を有効にする | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | ブール値 | アイコン検出を有効にする | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | ブール値 | TUI で選択時のコピーを無効にする | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | 数値 | bash コマンドのデフォルトのタイムアウト (ミリ秒) | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | 数値 | LLM 応答の最大出力トークン | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | ブール値 | ディレクトリ全体のファイル監視を有効にする | +| `OPENCODE_EXPERIMENTAL_OXFMT` | ブール値 | oxfmt フォーマッタを有効にする | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | ブール値 | 実験的な LSP ツールを有効にする | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | ブール値 | ファイルウォッチャーを無効にする | +| `OPENCODE_EXPERIMENTAL_EXA` | ブール値 | 実験的な Exa 機能を有効にする | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | ブール値 | 実験的な LSP タイプチェックを有効にする | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | ブール値 | 試験的な Markdown 機能を有効にする | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | ブール値 | プランモードを有効にする | diff --git a/packages/web/src/content/docs/ja/commands.mdx b/packages/web/src/content/docs/ja/commands.mdx new file mode 100644 index 00000000000..bd2913a043e --- /dev/null +++ b/packages/web/src/content/docs/ja/commands.mdx @@ -0,0 +1,322 @@ +--- +title: コマンド +description: 反復的なタスク用のカスタムコマンドを作成します。 +--- + +カスタムコマンドを使用すると、TUI でコマンドを実行するときに実行するプロンプトを指定できます。 + +```bash frame="none" +/my-command +``` + +カスタムコマンドは、`/init`、`/undo`、`/redo`、`/share`、`/help` などの組み込みコマンドに追加されます。 [詳細はこちら](/docs/tui#commands)。 + +--- + +## コマンドファイルの作成 + +カスタムコマンドを定義するには、`commands/` ディレクトリに Markdown ファイルを作成します。 + +`.opencode/commands/test.md` を作成します。 + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +フロントマターはコマンドのプロパティを定義します。内容がテンプレートとなります。 + +`/` に続けてコマンド名を入力して、コマンドを使用します。 + +```bash frame="none" +"/test" +``` + +--- + +## 設定 + +カスタムコマンドは、OpenCode 設定を通じて、または `commands/` ディレクトリに Markdown ファイルを作成することによって追加できます。 + +--- + +### JSON + +OpenCode [設定](/docs/config)で `command` オプションを使用します: + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +これで、TUI で次のコマンドを実行できるようになります。 + +```bash frame="none" +/test +``` + +--- + +### Markdown + +Markdown ファイルを使用してコマンドを定義することもできます。それらを次の場所に置きます。 + +- グローバル: `~/.config/opencode/commands/` +- プロジェクトごと: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Markdown ファイル名がコマンド名になります。たとえば、`test.md` を使用すると、 +あなたは実行します: + +```bash frame="none" +/test +``` + +--- + +## プロンプト構成 + +カスタムコマンドのプロンプトは、いくつかの特別なプレースホルダーと構文をサポートしています。 + +--- + +### 引数 + +`$ARGUMENTS` プレースホルダーを使用してコマンドに引数を渡します。 + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +引数を指定してコマンドを実行します。 + +```bash frame="none" +/component Button +``` + +そして、`$ARGUMENTS` は `Button` に置き換えられます。 + +位置パラメータを使用して個々の引数にアクセスすることもできます。 + +- `$1` - 最初の引数 +- `$2` - 2 番目の引数 +- `$3` - 3 番目の引数 +- 等々... + +例えば: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +次のコマンドを実行します。 + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +これは以下を置き換えます。 + +- `$1` と `config.json` +- `$2` と `src` +- `$3` と `{ "key": "value" }` + +--- + +### シェル出力 + +_!`command`_ を使用して、[bash コマンド](/docs/tui#bash-commands) の出力をプロンプトに挿入します。 + +たとえば、テストカバレッジを分析するカスタムコマンドを作成するには、次のようにします。 + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +または、最近の変更を確認するには: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +コマンドはプロジェクトのルートディレクトリで実行され、その出力はプロンプトの一部になります。 + +--- + +### ファイル参照 + +`@` の後にファイル名を指定して、コマンドにファイルを含めます。 + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +ファイルの内容はプロンプトに自動的に含まれます。 + +--- + +## オプション + +設定オプションを詳しく見てみましょう。 + +--- + +### テンプレート + +`template` オプションは、コマンドの実行時に LLM に送信されるプロンプトを定義します。 + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +これは**必須**の設定オプションです。 + +--- + +### 説明 + +`description` オプションを使用して、コマンドの動作の簡単な説明を入力します。 + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +これは、コマンドを入力すると TUI に説明として表示されます。 + +--- + +### エージェント + +オプションで、`agent` 設定を使用して、このコマンドを実行する [agent](/docs/agents) を指定します。 +これが [subagent](/docs/agents/#subagents) の場合、コマンドはデフォルトでサブエージェントの呼び出しをトリガーします。 +この動作を無効にするには、`subtask` を `false` に設定します。 + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +これは**オプション**の設定オプションです。指定しない場合、デフォルトで現在のエージェントが使用されます。 + +--- + +### サブタスク + +`subtask` ブール値を使用して、コマンドが [subagent](/docs/agents/#subagents) 呼び出しを強制的にトリガーします。 +これは、コマンドがプライマリコンテキストを汚染せず、エージェントがサブエージェントとして動作するように**強制**する場合に便利です。 +[agent](/docs/agents) 設定で `mode` が `primary` に設定されている場合でも。 + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +これは**オプション**の設定オプションです。 + +--- + +### モデル + +`model` 設定を使用して、このコマンドのデフォルトモデルをオーバーライドします。 + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +これは**オプション**の設定オプションです。 + +--- + +## 組み込み + +OpenCode には、`/init`、`/undo`、`/redo`、`/share`、`/help` などのいくつかの組み込みコマンドが含まれています。 [詳細はこちら](/docs/tui#commands)。 + +:::note +カスタムコマンドは組み込みコマンドをオーバーライドできます。 +::: +同じ名前のカスタムコマンドを定義すると、組み込みコマンドがオーバーライドされます。 diff --git a/packages/web/src/content/docs/ja/config.mdx b/packages/web/src/content/docs/ja/config.mdx new file mode 100644 index 00000000000..114336d43c9 --- /dev/null +++ b/packages/web/src/content/docs/ja/config.mdx @@ -0,0 +1,680 @@ +--- +title: 設定 +description: OpenCode JSON 設定を使用します。 +--- + +JSON 設定ファイルを使用して OpenCode を構成できます。 + +--- + +## 形式 + +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, +} +``` + +--- + +## ファイルの場所 + +設定をいくつかの異なる場所に配置できます。 +優先順位が異なります。 + +:::note +設定ファイルは置き換えられるのではなく、**マージ**されます。設定は、次の構成場所から結合されます。後続の設定は、競合するキーに対してのみ以前の設定をオーバーライドします。すべての設定の競合しない設定は保持されます。 +::: + +たとえば、グローバル設定で `theme: "opencode"` と `autoupdate: true` が設定され、プロジェクト設定で `model: "anthropic/claude-sonnet-4-5"` が設定されている場合、最終的な設定には 3 つの設定がすべて含まれます。 + +--- + +### 優先順位 + +設定ソースは次の順序でロードされます (後のソースは前のソースをオーバーライドします)。 + +1. **リモート設定** (`.well-known/opencode` から) - 組織のデフォルト +2. **グローバル設定** (`~/.config/opencode/opencode.json`) - ユーザー設定 +3. **カスタム設定** (`OPENCODE_CONFIG` 環境変数) - カスタムオーバーライド +4. **プロジェクト設定** (プロジェクト内の `opencode.json`) - プロジェクト固有の設定 +5. **`.opencode` ディレクトリ** - エージェント、コマンド、プラグイン +6. **インライン設定** (`OPENCODE_CONFIG_CONTENT` 環境変数) - ランタイムオーバーライド + +つまり、プロジェクト設定はグローバルのデフォルトをオーバーライドでき、グローバル設定はリモート組織のデフォルトをオーバーライドできます。 + +:::note +`.opencode` および `~/.config/opencode` ディレクトリでは、サブディレクトリに **複数名** が使用されています: `agents/`、`commands/`、`modes/`、`plugins/`、`skills/`、`tools/`、および `themes/`。下位互換性のために、単数形の名前 (`agent/` など) もサポートされています。 +::: + +--- + +### リモート + +組織は、`.well-known/opencode` エンドポイント経由でデフォルト設定を提供できます。これは、それをサポートするプロバイダーで認証するときに自動的に取得されます。 + +リモート設定が最初にロードされ、基本層として機能します。他のすべての設定ソース (グローバル、プロジェクト) は、これらのデフォルトをオーバーライドできます。 + +たとえば、組織がデフォルトで無効になっている MCP サーバーを提供している場合: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +ローカル設定で特定のサーバーを有効にすることができます。 + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### グローバル + +グローバル OpenCode 設定を `~/.config/opencode/opencode.json` に配置します。テーマ、プロバイダー、キーバインドなどのユーザー全体の設定にはグローバル設定を使用します。 + +グローバル設定はリモート組織のデフォルトをオーバーライドします。 + +--- + +### プロジェクトごと + +プロジェクトのルートに `opencode.json` を追加します。プロジェクト設定は、標準設定ファイルの中で最も高い優先順位を持ち、グローバル設定とリモート設定の両方をオーバーライドします。 + +:::tip +プロジェクト固有の設定をプロジェクトのルートに配置します。 +::: + +OpenCode が起動すると、現在のディレクトリで設定ファイルを検索するか、最も近い Git ディレクトリまで移動します。 + +これは Git に安全にチェックインでき、グローバルスキーマと同じスキーマを使用します。 + +--- + +### カスタムパス + +`OPENCODE_CONFIG` 環境変数を使用してカスタム設定ファイルのパスを指定します。 + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +カスタム設定は、優先順位でグローバル設定とプロジェクト設定の間にロードされます。 + +--- + +### カスタムディレクトリ + +`OPENCODE_CONFIG_DIR` を使用してカスタム設定ディレクトリを指定します。 +環境変数。このディレクトリでは、エージェント、コマンド、 +モードとプラグインは標準の `.opencode` ディレクトリと同様であり、次のようにする必要があります。 +同じ構造に従います。 + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +カスタムディレクトリはグローバル config ディレクトリと `.opencode` ディレクトリの後にロードされるため、それらの設定を**オーバーライド**できます。 + +--- + +## スキーマ + +設定ファイルには、[**`opencode.ai/config.json`**](https://opencode.ai/config.json) を使用します。 + +エディターはスキーマに基づいて検証し、オートコンプリートできる必要があります。 + +--- + +### TUI + +`tui` オプションを使用して TUI 固有の設定を構成できます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +利用可能なオプション: + +- `scroll_acceleration.enabled` - macOS スタイルのスクロールアクセラレーションを有効にします。 **`scroll_speed` よりも優先されます。** +- `scroll_speed` - カスタムのスクロール速度乗数 (デフォルト: `3`、最小: `1`)。 `scroll_acceleration.enabled` が `true` の場合は無視されます。 +- `diff_style` - 差分レンダリングを制御します。 `"auto"` はターミナルの幅に適応し、`"stacked"` は常に 1 列を表示します。 + +[TUI の使用方法の詳細については、こちら](/docs/tui) をご覧ください。 + +--- + +### サーバー + +`opencode serve` オプションを使用して、`opencode web` および `server` コマンドのサーバー設定を構成できます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +利用可能なオプション: + +- `port` - リッスンするポート。 +- `hostname` - リッスンするホスト名。 `mdns` が有効でホスト名が設定されていない場合、デフォルトは `0.0.0.0` になります。 +- `mdns` - mDNS サービス検出を有効にします。これにより、ネットワーク上の他のデバイスが OpenCode サーバーを検出できるようになります。 +- `mdnsDomain` - mDNS サービスのカスタムドメイン名。デフォルトは `opencode.local` です。同じネットワーク上で複数のインスタンスを実行する場合に便利です。 +- `cors` - ブラウザベースのクライアントから HTTP サーバーを使用するときに CORS を許可する追加のオリジン。値は完全なオリジン (スキーム + ホスト + オプションのポート) である必要があります (例: `https://app.example.com`)。 + +[サーバーの詳細については、こちら](/docs/server)をご覧ください。 + +--- + +### ツール + +LLM が使用できるツールは、`tools` オプションを通じて管理できます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[ツールの詳細については、こちらをご覧ください](/docs/tools)。 + +--- + +### モデル + +`provider`、`model`、および `small_model` オプションを使用して、OpenCode 設定で使用するプロバイダーとモデルを構成できます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +`small_model` オプションは、タイトル生成などの軽量タスク用に別のモデルを構成します。デフォルトでは、OpenCode は、プロバイダーから安価なモデルが入手可能な場合は、より安価なモデルを使用しようとします。そうでない場合は、メインモデルにフォールバックします。 + +プロバイダーオプションには、`timeout` および `setCacheKey` を含めることができます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` - リクエストのタイムアウト (ミリ秒単位) (デフォルト: 300000)。無効にするには、`false` に設定します。 +- `setCacheKey` - 指定されたプロバイダーに対してキャッシュキーが常に設定されていることを確認します。 + +[ローカルモデル](/docs/models#local). [詳細はこちら](/docs/models)。 + +--- + +#### プロバイダー固有のオプション + +一部のプロバイダーは、一般的な `timeout` および `apiKey` 設定を超える追加の構成オプションをサポートしています。 + +##### Amazon Bedrock + +Amazon Bedrock は、AWS 固有の設定をサポートしています。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` - Bedrock の AWS リージョン (デフォルトは `AWS_REGION` 環境変数または `us-east-1`) +- `profile` - `~/.aws/credentials` からの AWS 名前付きプロファイル (デフォルトは `AWS_PROFILE` 環境変数) +- `endpoint` - VPC エンドポイントのカスタムエンドポイント URL。これは、AWS 固有の用語を使用した汎用 `baseURL` オプションのエイリアスです。両方を指定した場合は、`endpoint` が優先されます。 + +:::note +ベアラー トークン (`AWS_BEARER_TOKEN_BEDROCK` または `/connect`) は、プロファイルベースの認証より優先されます。詳細については、「認証優先順位](/docs/providers#authentication-precedence)」を参照してください。 +::: + +[Amazon Bedrock 設定 ](/docs/providers#amazon-bedrock) の詳細をご覧ください。 + +--- + +### テーマ + +`theme` オプションを使用して、OpenCode 設定で使用するテーマを構成できます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[詳細はこちら](/docs/themes)。 + +--- + +### エージェント + +`agent` オプションを使用して、特定のタスクに特化したエージェントを構成できます。 + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +`~/.config/opencode/agents/` または `.opencode/agents/` の Markdown ファイルを使用してエージェントを定義することもできます。 [詳細はこちら](/docs/agents)。 + +--- + +### デフォルトエージェント + +`default_agent` オプションを使用してデフォルトのエージェントを設定できます。これにより、明示的に何も指定されていない場合にどのエージェントが使用されるかが決まります。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +デフォルトのエージェントはプライマリエージェントである必要があります (サブエージェントではありません)。これは、`"build"` や `"plan"` のような組み込みエージェント、または定義した[カスタムエージェント](/docs/agents) にすることができます。指定されたエージェントが存在しないか、サブエージェントである場合、OpenCode は警告とともに `"build"` にフォールバックします。 + +この設定は、TUI、CLI (`opencode run`)、デスクトップアプリ、および GitHub Action のすべてのインターフェイスに適用されます。 + +--- + +### 共有 + +`share` オプションを使用して [share](/docs/share) 機能を設定できます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +これには以下が必要です: + +- `"manual"` - コマンドによる手動共有を許可します (デフォルト) +- `"auto"` - 新しい会話を自動的に共有します +- `"disabled"` - 共有を完全に無効にする + +デフォルトでは、共有は手動モードに設定されており、`/share` コマンドを使用して会話を明示的に共有する必要があります。 + +--- + +### コマンド + +`command` オプションを使用して、反復タスク用のカスタムコマンドを構成できます。 + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +`~/.config/opencode/commands/` または `.opencode/commands/` の Markdown ファイルを使用してコマンドを定義することもできます。 [詳細はこちら](/docs/commands)。 + +--- + +### キーバインド + +`keybinds` オプションを使用してキーバインドをカスタマイズできます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[詳細はこちら](/docs/keybinds)。 + +--- + +### 自動更新 + +OpenCode は起動時に新しいアップデートを自動的にダウンロードします。 `autoupdate` オプションを使用してこれを無効にできます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +更新は必要ないが、新しいバージョンが利用可能になったときに通知を受け取りたい場合は、`autoupdate` を `"notify"` に設定します。 +これは、Homebrew などのパッケージマネージャーを使用してインストールされていない場合にのみ機能することに注意してください。 + +--- + +### フォーマッタ + +`formatter` オプションを使用してコードフォーマッタを設定できます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[フォーマッタの詳細については、こちら](/docs/formatters) をご覧ください。 + +--- + +### 権限 + +デフォルトでは、opencode は明示的な承認を必要とせずに **すべての操作を許可**します。これは、`permission` オプションを使用して変更できます。 + +たとえば、`edit` ツールと `bash` ツールにユーザーの承認が必要であることを確認するには、次のようにします。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[権限の詳細については、こちら](/docs/permissions)をご覧ください。 + +--- + +### 圧縮 + +`compaction` オプションを使用してコンテキストの圧縮動作を制御できます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto` - コンテキストがいっぱいのときにセッションを自動的に圧縮します (デフォルト: `true`)。 +- `prune` - 古いツールの出力を削除してトークンを保存します (デフォルト: `true`)。 + +--- + +### ウォッチャー + +`watcher` オプションを使用して、ファイルウォッチャーの無視パターンを構成できます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +パターンは glob 構文に従います。これを使用して、ノイズの多いディレクトリをファイル監視から除外します。 + +--- + +### MCPサーバー + +`mcp` オプションを使用して、使用する MCP サーバーを構成できます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[詳細はこちら](/docs/mcp-servers)。 + +--- + +### プラグイン + +[Plugins](/docs/plugins) は、カスタムツール、フック、統合を使用して OpenCode を拡張します。 + +プラグインファイルを `.opencode/plugins/` または `~/.config/opencode/plugins/` に配置します。 `plugin` オプションを使用して npm からプラグインをロードすることもできます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[詳細はこちら](/docs/plugins)。 + +--- + +### 指示 + +`instructions` オプションを使用して、使用しているモデルの指示を構成できます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +これは、指示ファイルへのパスとグロブパターンの配列を受け取ります。 [ルールについて詳しくはこちら](/docs/rules)。 + +--- + +### 無効なプロバイダー + +`disabled_providers` オプションを使用して、自動的にロードされるプロバイダーを無効にすることができます。これは、認証情報が利用可能な場合でも、特定のプロバイダーが読み込まれないようにしたい場合に便利です。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +`disabled_providers` は `enabled_providers` よりも優先されます。 +::: +`disabled_providers` オプションは、プロバイダー ID の配列を受け入れます。プロバイダーが無効になっている場合: + +- 環境変数を設定してもロードされません。 +- `/connect` コマンドで API キーを設定してもロードされません。 +- プロバイダーのモデルはモデル選択リストに表示されません。 + +--- + +### 有効なプロバイダー + +`enabled_providers` オプションを使用してプロバイダーの許可リストを指定できます。設定すると、指定されたプロバイダーのみが有効になり、その他はすべて無視されます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +これは、OpenCode を 1 つずつ無効にするのではなく、特定のプロバイダーのみを使用するように制限したい場合に便利です。 + +:::note +`disabled_providers` は `enabled_providers` よりも優先されます。 +::: +プロバイダーが `enabled_providers` と `disabled_providers` の両方に表示される場合、下位互換性のために `disabled_providers` が優先されます。 + +--- + +### 実験的 + +`experimental` キーには、現在開発中のオプションが含まれています。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +実験的なオプションは安定していません。予告なく変更または削除される場合があります。 +::: + +--- + +## 変数 + +設定ファイル内で変数置換を使用して、環境変数とファイルの内容を参照できます。 + +--- + +### 環境変数 + +`{env:VARIABLE_NAME}` を使用して環境変数を置き換えます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +環境変数が設定されていない場合は、空の文字列に置き換えられます。 + +--- + +### ファイル + +`{file:path/to/file}` を使用してファイルの内容を置き換えます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +ファイルパスは次のとおりです。 + +- 設定ファイルのディレクトリからの相対パス +- または、`/` または `~` で始まる絶対パス + +これらは次の場合に役立ちます。 + +- API キーなどの機密データを別のファイルに保存します。 +- 設定を乱雑にすることなく、大きな指示ファイルを含めることができます。 +- 複数の設定ファイル間で共通の設定スニペットを共有します。 diff --git a/packages/web/src/content/docs/ja/custom-tools.mdx b/packages/web/src/content/docs/ja/custom-tools.mdx new file mode 100644 index 00000000000..badf50c627d --- /dev/null +++ b/packages/web/src/content/docs/ja/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: カスタムツール +description: LLM が OpenCode で呼び出すことができるツールを作成します。 +--- + +カスタムツールは、会話中に LLM が呼び出すことができる作成した関数です。これらは、OpenCode の[組み込みツール](/docs/tools) (`read`、`write`、`bash` など) と連携して動作します。 + +--- + +## ツールの作成 + +ツールは **TypeScript** または **JavaScript** ファイルとして定義されます。ただし、ツール定義では**任意の言語**で記述されたスクリプトを呼び出すことができます。TypeScript または JavaScript はツール定義自体にのみ使用されます。 + +--- + +### 場所 + +それらは次のように定義できます。 + +- ローカルでは、プロジェクトの `.opencode/tools/` ディレクトリに配置します。 +- または、グローバルに、それらを `~/.config/opencode/tools/` に配置します。 + +--- + +### 構造 + +ツールを作成する最も簡単な方法は、型安全性と検証を提供する `tool()` ヘルパーを使用することです。 + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +**ファイル名**は**ツール名**になります。上記により `database` ツールが作成されます。 + +--- + +#### ファイルごとに複数のツール + +単一のファイルから複数のツールをエクスポートすることもできます。各エクスポートは **`_`** という名前の **別のツール** になります。 + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +これにより、`math_add` と `math_multiply` という 2 つのツールが作成されます。 + +--- + +### 引数 + +引数の型を定義するには、`tool.schema` (つまり [Zod](https://zod.dev)) を使用できます。 + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +[Zod](https://zod.dev) を直接インポートしてプレーンオブジェクトを返すこともできます。 + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### コンテキスト + +ツールは現在のセッションに関するコンテキストを受け取ります。 + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +セッションの作業ディレクトリには `context.directory` を使用します。 +git ワークツリーのルートには `context.worktree` を使用します。 + +--- + +## 例 + +### Python でのツールの作成 + +ツールは任意の言語で作成できます。以下は、Python を使用して 2 つの数値を加算する例です。 + +まず、ツールを Python スクリプトとして作成します。 + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +次に、それを呼び出すツール定義を作成します。 + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +ここでは、[`Bun.$`](https://bun.com/docs/runtime/shell) ユーティリティを使用して Python スクリプトを実行しています。 diff --git a/packages/web/src/content/docs/ja/ecosystem.mdx b/packages/web/src/content/docs/ja/ecosystem.mdx new file mode 100644 index 00000000000..479fdfbdc34 --- /dev/null +++ b/packages/web/src/content/docs/ja/ecosystem.mdx @@ -0,0 +1,75 @@ +--- +title: エコシステム +description: OpenCode で構築されたプロジェクトと統合。 +--- + +OpenCode に基づいて構築されたコミュニティプロジェクトのコレクション。 + +:::note +OpenCode 関連プロジェクトをこのリストに追加したいですか? PR を送信してください。 +::: +[awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) および [opencode.cafe](https://opencode.cafe) もチェックしてください。 + +--- + +## プラグイン + +| 名前 | 説明 | +| --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | git sync とライブプレビューを使用して、隔離された Daytona サンドボックスで OpenCode セッションを自動的に実行します。 | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | リクエストのグループ化のために Helicone セッションヘッダーを自動的に挿入する | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | ルックアップツールを使用して TypeScript/Svelte 型をファイル読み取りに自動挿入する | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | API クレジットの代わりに ChatGPT Plus/Pro サブスクリプションを使用する | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | API 課金の代わりに既存の Gemini プランを使用する | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | API 課金の代わりに Antigravity の無料モデルを使用する | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | 浅いクローンと自動割り当てポートを使用したマルチブランチ devcontainer の分離 | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Google Antigravity OAuth プラグイン、Google 検索のサポート、およびより堅牢な API 処理 | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | 古いツールの出力を削除してトークンの使用を最適化する | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Google ベースのスタイルでサポートされているプロバイダーにネイティブ Web 検索サポートを追加 | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | AI エージェントが PTY でバックグラウンドプロセスを実行し、インタラクティブな入力を送信できるようにします。 | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | 非対話型シェルコマンドの手順 - TTY に依存する操作によるハングの防止 | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | wakatime で OpenCode の使用状況を追跡する | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | LLM によって生成された Markdown テーブルをクリーンアップする | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | Morph Fast apply API と遅延編集マーカーにより 10 倍高速なコード編集 | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | バックグラウンドエージェント、事前構築された LSP/AST/MCP ツール、厳選されたエージェント、Claude Code 互換 | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | OpenCode セッションのデスクトップ通知とサウンドアラート | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | 許可、完了、エラーイベントのデスクトップ通知とサウンドアラート | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | OpenCode コンテキストに基づいた AI による自動 Zellij セッション命名 | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | OpenCode エージェントがスキルの検出と挿入を使用してオンデマンドでプロンプトを遅延ロードできるようにする | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | スーパーメモリを使用したセッション間での永続メモリ | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | 視覚的な注釈とプライベート/オフライン共有による対話型の計画レビュー | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | OpenCode/コマンドをきめ細かいフロー制御を備えた強力なオーケストレーションシステムに拡張 | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | launchd (Mac) または systemd (Linux) を cron 構文で使用して、定期的なジョブをスケジュールする | +| [micode](https://github.com/vtemian/micode) | 構造化されたブレインストーミング → 計画 → セッション継続性のあるワークフローの実装 | +| [octto](https://github.com/vtemian/octto) | 複数の質問フォームを使用した AI ブレインストーミング用のインタラクティブなブラウザ UI | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | 非同期委任とコンテキスト永続性を備えた Claude Code スタイルのバックグラウンドエージェント | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | OpenCode のネイティブ OS 通知 – タスクがいつ完了したかを知る | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | バンドルされたマルチエージェントオーケストレーションハーネス – 16 コンポーネント、1 回のインストール | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | OpenCode 用のゼロフリクション Git ワークツリー | + +--- + +## プロジェクト + +| 名前 | 説明 | +| ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- | +| [kimaki](https://github.com/remorses/kimaki) | SDK 上に構築された OpenCode セッションを制御する Discord ボット | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | API に基づいて構築された、エディター対応プロンプト用の Neovim プラグイン | +| [portal](https://github.com/hosenur/portal) | Tailscale/VPN 上の OpenCode 向けモバイルファースト Web UI | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | OpenCode プラグインを構築するためのテンプレート | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Neovim OpenCode用フロントエンド - ターミナルベースの AI コーディングエージェント | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | @opencode-ai/sdk 経由で OpenCode を使用するための Vercel AI SDK プロバイダー | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | OpenCode 用の Web/デスクトップアプリと VS Code 拡張機能 | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Obsidian の UI に OpenCode を埋め込む Obsidian プラグイン | +| [OpenWork](https://github.com/different-ai/openwork) | OpenCode を利用した、Claude Cowork に代わるオープンソース | +| [ocx](https://github.com/kdcokenny/ocx) | 移植可能な独立したプロファイルを備えた OpenCode 拡張機能マネージャー。 | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | OpenCode 用のデスクトップ、Web、モバイル、およびリモートクライアントアプリ | + +--- + +## エージェント + +| 名前 | 説明 | +| ----------------------------------------------------------------- | ------------------------------------------------------------------------------ | +| [Agentic](https://github.com/Cluster444/agentic) | 構造化開発のためのモジュール型 AI エージェントとコマンド | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | 強化されたワークフローのための構成、プロンプト、エージェント、およびプラグイン | diff --git a/packages/web/src/content/docs/ja/enterprise.mdx b/packages/web/src/content/docs/ja/enterprise.mdx new file mode 100644 index 00000000000..d5144072ff5 --- /dev/null +++ b/packages/web/src/content/docs/ja/enterprise.mdx @@ -0,0 +1,166 @@ +--- +title: エンタープライズ +description: 組織内で OpenCode を安全に使用します。 +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +OpenCode Enterprise は、コードとデータがインフラストラクチャから決して流出しないようにしたい組織を対象としています。これは、SSO および内部 AI ゲートウェイと統合された一元化された設定を使用することで実現できます。 + +:::note +OpenCode は、コードやコンテキストデータを一切保存しません。 +::: +OpenCode Enterprise を始めるには: + +1. チーム内でトライアルを実施してください。 +2. 価格や実装オプションについては、**お問い合わせ**ください。 + +--- + +## トライアル + +OpenCode はオープンソースであり、コードやコンテキストデータは一切保存されないため、開発者は簡単に開始してトライアルを実行できます。 + +--- + +### データの取り扱い + +**OpenCode はコードやコンテキストデータを保存しません。** すべての処理はローカルで、または AI プロバイダーへの直接 API 呼び出しを通じて行われます。 + +つまり、信頼できるプロバイダー、または内部 AI ゲートウェイを使用している限り、OpenCode を安全に利用できます。 + +ここでの唯一の注意点は、オプションの `/share` 機能です。 + +--- + +#### 会話を共有する + +ユーザーが `/share` 機能を有効にすると、会話とそれに関連付けられたデータが、opencode.ai でこれらの共有ページをホストするために使用されるサービスに送信されます。 + +現在、データは CDN のエッジネットワークを通じて提供され、ユーザーの近くのエッジにキャッシュされます。 + +試用版ではこれを無効にすることをお勧めします。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[sharing](/docs/share) について詳しくはこちらをご覧ください。 + +--- + +### コードの所有権 + +**OpenCode によって生成されたすべてのコードはお客様が所有します。** ライセンスの制限や所有権の主張はありません。 + +--- + +## 価格 + +OpenCode Enterprise ではシートごとのモデルを使用します。独自の LLM ゲートウェイをお持ちの場合、使用されたトークンに対して料金はかかりません。価格と実装オプションの詳細については、**お問い合わせください**。 + +--- + +## 導入 + +トライアルが完了し、OpenCode を組織で使用する準備が整ったら、 +**お問い合わせ**して価格設定と実装オプションについてご相談ください。 + +--- + +### 中央設定 + +組織全体で単一の中央設定を使用するように OpenCode をセットアップできます。 + +この一元化された設定は SSO プロバイダーと統合でき、すべてのユーザーが内部 AI ゲートウェイのみにアクセスできるようにします。 + +--- + +### SSO統合 + +中央の設定を通じて、OpenCode は認証のために組織の SSO プロバイダーと統合できます。 + +これにより、OpenCode は既存の ID 管理システムを通じて内部 AI ゲートウェイの認証情報を取得できるようになります。 + +--- + +### 内部AIゲートウェイ + +中央設定を使用すると、内部 AI ゲートウェイのみを使用するように OpenCode を構成することもできます。 + +他のすべての AI プロバイダーを無効にして、すべてのリクエストが組織の承認されたインフラストラクチャを通過するようにすることもできます。 + +--- + +### セルフホスティング + +データが流出しないように共有ページを無効にすることをお勧めします。 +貴社のインフラストラクチャ上でセルフホストすることもお手伝いします。 + +これは現在ロードマップに載っています。ご興味がございましたら、**お知らせください**。 + +--- + +## よくある質問 + +

+OpenCode Enterpriseとは何ですか? + +OpenCode Enterprise は、コードとデータがインフラストラクチャから決して流出しないようにしたい組織を対象としています。これは、SSO および内部 AI ゲートウェイと統合された一元化された設定を使用することで実現できます。 + +
+ +
+OpenCode Enterpriseを始めるにはどうすればよいですか? + +まずはチームの内部トライアルから始めてください。 OpenCode はデフォルトでコードやコンテキストデータを保存しないため、簡単に開始できます。 + +その後、**お問い合わせ**いただき、価格や実装オプションについてご相談ください。 + +
+ +
+エンタープライズの価格設定はどのようになっていますか? + +エンタープライズ価格はシートごとに提供されます。独自の LLM ゲートウェイをお持ちの場合、使用されたトークンに対して料金はかかりません。詳細については、組織のニーズに基づいたカスタム見積もりをご希望の場合は、**お問い合わせください**。 + +
+ +
+OpenCode Enterpriseでデータは安全ですか? + +はい。 OpenCode はコードやコンテキストデータを保存しません。すべての処理はローカルで、または AI プロバイダーへの直接 API 呼び出しを通じて行われます。一元的な設定と SSO の統合により、データは組織のインフラストラクチャ内で安全に保たれます。 + +
+ +
+独自のプライベートnpmレジストリを使用できますか? + +OpenCode は、Bun のネイティブ `.npmrc` ファイルサポートを通じてプライベート npm レジストリをサポートします。組織が JFrog Artifactory、Nexus などのプライベートレジストリを使用している場合は、OpenCode を実行する前に開発者が認証されていることを確認してください。 + +プライベートレジストリを使用して認証を設定するには、次の手順を実行します。 + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +これにより、認証の詳細を含む `~/.npmrc` が作成されます。 OpenCode は自動的に +これを拾ってください。 + +:::caution +OpenCode を実行する前に、プライベートレジストリにログインする必要があります。 +::: +あるいは、.npmrc ファイルを手動で構成することもできます。 + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +開発者は、エンタープライズレジストリからパッケージを確実にインストールできるように、OpenCode を実行する前にプライベートレジストリにログインする必要があります。 + +
diff --git a/packages/web/src/content/docs/ja/formatters.mdx b/packages/web/src/content/docs/ja/formatters.mdx new file mode 100644 index 00000000000..04f5227e0e2 --- /dev/null +++ b/packages/web/src/content/docs/ja/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: フォーマッタ +description: OpenCode は言語固有のフォーマッタを使用します。 +--- + +OpenCode は、言語固有のフォーマッタを使用してファイルを作成または編集した後、ファイルを自動的にフォーマットします。これにより、生成されるコードがプロジェクトのコードスタイルに従っていることが保証されます。 + +--- + +## 組み込み + +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 | +| dart | .dart | `dart` 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 | + +したがって、プロジェクトの `prettier` に `package.json` が含まれている場合、OpenCode は自動的にそれを使用します。 + +--- + +## 仕組み + +OpenCode がファイルを書き込んだり編集したりすると、次のことが行われます。 + +1. 有効なすべてのフォーマッタに対してファイル拡張子をチェックします。 +2. ファイルに対して適切なフォーマッタコマンドを実行します。 +3. 書式の変更を自動的に適用します。 + +このプロセスはバックグラウンドで実行されるため、手動の手順を行わなくてもコードスタイルが維持されます。 + +--- + +## 設定 + +OpenCode 設定の `formatter` セクションを通じてフォーマッタをカスタマイズできます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +各フォーマッタ設定は以下をサポートします。 + +| プロパティ | タイプ | 説明 | +| ------------- | ------------ | ---------------------------------------------------------- | +| `disabled` | ブール値 | フォーマッタを無効にするには、これを `true` に設定します。 | +| `command` | 文字列[] | フォーマットのために実行するコマンド | +| `environment` | オブジェクト | フォーマッタの実行時に設定する環境変数 | +| `extensions` | 文字列[] | このフォーマッタが処理するファイル拡張子 | + +いくつかの例を見てみましょう。 + +--- + +### フォーマッタの無効化 + +**すべて**のフォーマッタをグローバルに無効にするには、`formatter` を `false` に設定します。 + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +**特定**のフォーマッタを無効にするには、`disabled` を `true` に設定します。 + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### カスタムフォーマッタ + +コマンド、環境変数、ファイル拡張子を指定することで、組み込みフォーマッタをオーバーライドしたり、新しいフォーマッタを追加したりできます。 + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +コマンド内の **`$FILE` プレースホルダー** は、フォーマットされるファイルへのパスに置き換えられます。 diff --git a/packages/web/src/content/docs/ja/github.mdx b/packages/web/src/content/docs/ja/github.mdx new file mode 100644 index 00000000000..d587094dc81 --- /dev/null +++ b/packages/web/src/content/docs/ja/github.mdx @@ -0,0 +1,322 @@ +--- +title: GitHub +description: GitHub の問題とプルリクエストで OpenCode を使用します。 +--- + +OpenCode は GitHub ワークフローと統合します。コメントで `/opencode` または `/oc` に言及すると、OpenCode が GitHub Actions ランナー内でタスクを実行します。 + +--- + +## 機能 + +- **問題のトリアージ**: OpenCode に問題を調べて説明してもらいます。 +- **修正と実装**: OpenCode に問題の修正または機能の実装を依頼します。そして、新しいブランチで動作し、すべての変更を含む PR を送信します。 +- **安全**: OpenCode は GitHub のランナー内で実行されます。 + +--- + +## インストール + +GitHub リポジトリにあるプロジェクトで次のコマンドを実行します。 + +```bash +opencode github install +``` + +ここでは、GitHub アプリのインストール、ワークフローの作成、シークレットの設定について説明します。 + +--- + +### 手動セットアップ + +または、手動で設定することもできます。 + +1. **GitHub アプリをインストールします** + +[**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent) にアクセスしてください。ターゲットリポジトリにインストールされていることを確認してください。 + +2. **ワークフローを追加** + +次のワークフローファイルをリポジトリの `.github/workflows/opencode.yml` に追加します。適切な `model` と必要な API キーを `env` に設定してください。 + +```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx +``` + +3. **API キーをシークレットに保存する** + +組織またはプロジェクトの**設定**で、左側の**シークレットと変数**を展開し、**アクション**を選択します。そして、必要な API キーを追加します。 + +--- + +## 設定 + +- `model`: OpenCode で使用するモデル。 `provider/model` の形式をとります。これは**必須**です。 +- `agent`: 使用するエージェント。プライマリエージェントである必要があります。見つからない場合は、設定から `default_agent` にフォールバックするか、`"build"` にフォールバックします。 +- `share`: OpenCode セッションを共有するかどうか。パブリックリポジトリのデフォルトは **true** です。 +- `prompt`: デフォルトの動作をオーバーライドするためのオプションのカスタムプロンプト。これを使用して、OpenCode がリクエストを処理する方法をカスタマイズします。 +- `token`: コメントの作成、変更のコミット、プルリクエストのオープンなどの操作を実行するためのオプションの GitHub アクセストークン。デフォルトでは、OpenCode は OpenCode GitHub アプリからのインストールアクセストークンを使用するため、コミット、コメント、プルリクエストはアプリからのものとして表示されます。 + +あるいは、OpenCode GitHub アプリをインストールせずに、GitHub Action ランナーの [組み込み `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) を使用することもできます。ワークフローで必要な権限を必ず付与してください。 + +```yaml +permissions: + id-token: write + contents: write + pull-requests: write + issues: write +``` + +必要に応じて、[パーソナルアクセストークン](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) を使用することもできます。 + +--- + +## サポートされているイベント + +OpenCode は、次の GitHub イベントによってトリガーできます。 + +| イベントの種類 | トリガー | 詳細 | +| ----------------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `issue_comment` | 問題または PR についてコメントする | コメントで `/opencode` または `/oc` について言及してください。 OpenCode はコンテキストを読み取り、ブランチを作成したり、PR を開いたり、返信したりできます。 | +| `pull_request_review_comment` | PR 内の特定のコード行にコメントする | コードをレビューするときに、`/opencode` または `/oc` について言及します。 OpenCode は、ファイルパス、行番号、および diff コンテキストを受け取ります。 | +| `issues` | 問題がオープンまたは編集されました | 問題が作成または変更されると、OpenCode が自動的にトリガーされます。 `prompt` 入力が必要です。 | +| `pull_request` | PR がオープンまたは更新されました | PR が開かれる、同期される、または再度開かれるときに、OpenCode を自動的にトリガーします。自動レビューに役立ちます。 | +| `schedule` | Cron ベースのスケジュール | スケジュールに従って OpenCode を実行します。 `prompt` 入力が必要です。出力はログと PR に送られます (コメントする問題はありません)。 | +| `workflow_dispatch` | GitHub UI からの手動トリガー | [アクション] タブから OpenCode をオンデマンドでトリガーします。 `prompt` 入力が必要です。出力はログと PR に送られます。 | + +### スケジュールの例 + +スケジュールに従って OpenCode を実行し、自動化されたタスクを実行します。 + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +スケジュールされたイベントの場合、指示を抽出するためのコメントがないため、`prompt` 入力は **必須** です。スケジュールされたワークフローは、権限チェックのためのユーザーコンテキストなしで実行されるため、OpenCode がブランチまたは PR を作成することが予想される場合、ワークフローは `contents: write` および `pull-requests: write` を付与する必要があります。 + +--- + +### プルリクエストの例 + +PR が開かれるか更新されるときに、PR を自動的にレビューします。 + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +`pull_request` イベントの場合、`prompt` が指定されていない場合、OpenCode はデフォルトでプルリクエストをレビューします。 + +--- + +### Issueのトリアージの例 + +新しい問題を自動的に優先順位付けします。この例では、スパムを減らすために 30 日より古いアカウントにフィルターを適用します。 + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +`issues` イベントの場合、指示を抽出するためのコメントがないため、`prompt` 入力は **必須** です。 + +--- + +## カスタムプロンプト + +デフォルトのプロンプトをオーバーライドして、ワークフローに合わせて OpenCode の動作をカスタマイズします。 + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +これは、プロジェクトに関連する特定のレビュー基準、コーディング標準、または重点分野を強制するのに役立ちます。 + +--- + +## 例 + +GitHub で OpenCode を使用する方法の例をいくつか示します。 + +- **Issueの説明** + +このコメントを GitHub の問題に追加します。 + +``` + /opencode explain this issue +``` + +OpenCode は、すべてのコメントを含むスレッド全体を読み取り、明確な説明を返信します。 + +- **Issueの修正** + +GitHub の問題で次のように言います。 + +``` + /opencode fix this +``` + +そして、OpenCode は新しいブランチを作成し、変更を実装し、変更を含む PR を開きます。 + +- **PR をレビューして変更を加える** + +GitHub PR に次のコメントを残してください。 + +``` + Delete the attachment from S3 when the note is removed /oc +``` + +OpenCode は要求された変更を実装し、同じ PR にコミットします。 + +- **特定のコード行のレビュー** + +PR の「ファイル」タブのコード行に直接コメントを残します。 OpenCode は、ファイル、行番号、および diff コンテキストを自動的に検出して、正確な応答を提供します。 + +``` + [Comment on specific lines in Files tab] + /oc add error handling here +``` + +特定の行にコメントすると、OpenCode は以下を受け取ります。 + +- レビューされている正確なファイル +- コードの特定の行 +- 周囲の差分コンテキスト +- 行番号情報 + +これにより、ファイルパスや行番号を手動で指定する必要がなく、よりターゲットを絞ったリクエストが可能になります。 diff --git a/packages/web/src/content/docs/ja/gitlab.mdx b/packages/web/src/content/docs/ja/gitlab.mdx new file mode 100644 index 00000000000..8560c950389 --- /dev/null +++ b/packages/web/src/content/docs/ja/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: GitLab の問題とマージリクエストで OpenCode を使用します。 +--- + +OpenCode は、GitLab CI/CD パイプラインまたは GitLab Duo を通じて GitLab ワークフローと統合します。 + +どちらの場合も、OpenCode は GitLab ランナー上で実行されます。 + +--- + +## GitLab CI + +OpenCode は通常の GitLab パイプラインで動作します。 [CI コンポーネント](https://docs.gitlab.com/ee/ci/components/) としてパイプラインに組み込むことができます。 + +ここでは、コミュニティが作成した OpenCode 用の CI/CD コンポーネント — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### 機能 + +- **ジョブごとにカスタム設定を使用する**: カスタム設定ディレクトリ (`./config/#custom-directory` など) を使用して OpenCode を構成し、OpenCode の呼び出しごとに機能を有効または無効にします。 +- **最小限のセットアップ**: CI コンポーネントはバックグラウンドで OpenCode をセットアップします。必要なのは、OpenCode 設定と初期プロンプトを作成することだけです。 +- **柔軟性**: CI コンポーネントは、動作をカスタマイズするための複数の入力をサポートしています。 + +--- + +### 設定 + +1. OpenCode 認証 JSON をファイルタイプ CI 環境変数として [**設定**] > [**CI/CD**] > [**変数**] に保存します。必ず「マスクして非表示」としてマークしてください。 +2. 以下を `.gitlab-ci.yml` ファイルに追加します。 + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +さらに多くの入力と使用例については、このコンポーネントの [ドキュメント](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) をチェックしてください。 + +--- + +## GitLab Duo + +OpenCode は GitLab ワークフローと統合します。 +コメントで `@opencode` に言及すると、OpenCode が GitLab CI パイプライン内でタスクを実行します。 + +--- + +### 機能 + +- **問題のトリアージ**: OpenCode に問題を調べて説明してもらいます。 +- **修正と実装**: OpenCode に問題の修正または機能の実装を依頼します。 + 新しいブランチを作成し、変更を加えたマージリクエストを発行します。 +- **安全**: OpenCode は GitLab ランナー上で実行されます。 + +--- + +### 設定 + +OpenCode は GitLab CI/CD パイプラインで実行されます。セットアップするには次のものが必要です。 + +:::tip +最新の手順については、[**GitLab ドキュメント**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) を参照してください。 +::: + +1. GitLab 環境を構成する +2. CI/CD のセットアップ +3. AI モデルプロバイダー API キーを取得する +4. サービスアカウントを作成する +5. CI/CD変数を構成する +6. フロー設定ファイルを作成します。例を次に示します。 + +
+ + フロー設定 + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +詳細な手順については、[GitLab CLI エージェント docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/)を参照してください。 + +--- + +### 例 + +GitLab で OpenCode を使用する方法の例をいくつか示します。 + +:::tip +`@opencode` とは異なるトリガーフレーズを使用するように設定できます。 +::: + +- **問題の説明** + +このコメントを GitLab の問題に追加します。 + +``` + @opencode explain this issue +``` + +OpenCode は問題を読み、明確な説明を返信します。 + +- **問題を修正** + +GitLab の問題では、次のように言います。 + +``` + @opencode fix this +``` + +OpenCode は新しいブランチを作成し、変更を実装し、変更を含むマージリクエストを開きます。 + +- **マージリクエストを確認する** + +GitLab マージリクエストに次のコメントを残してください。 + +``` + @opencode review this merge request +``` + +OpenCode はマージリクエストをレビューし、フィードバックを提供します。 diff --git a/packages/web/src/content/docs/ja/ide.mdx b/packages/web/src/content/docs/ja/ide.mdx new file mode 100644 index 00000000000..6003f6412c7 --- /dev/null +++ b/packages/web/src/content/docs/ja/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: VS Code、Cursor、およびその他の IDE 用の OpenCode 拡張機能 +--- + +OpenCode は、VS Code、Cursor、またはターミナルをサポートする任意の IDE と統合します。開始するには、ターミナルで `opencode` を実行するだけです。 + +--- + +## 使用法 + +- **クイック起動**: `Cmd+Esc` (Mac) または `Ctrl+Esc` (Windows/Linux) を使用して、分割ターミナルビューで OpenCode を開くか、既存のターミナルセッションが既に実行されている場合はそれにフォーカスします。 +- **新しいセッション**: すでに開いている場合でも、`Cmd+Shift+Esc` (Mac) または `Ctrl+Shift+Esc` (Windows/Linux) を使用して、新しい OpenCode ターミナルセッションを開始します。 UI の [OpenCode] ボタンをクリックすることもできます。 +- **コンテキスト認識**: 現在の選択またはタブを OpenCode と自動的に共有します。 +- **ファイル参照のショートカット**: ファイル参照を挿入するには、`Cmd+Option+K` (Mac) または `Alt+Ctrl+K` (Linux/Windows) を使用します。たとえば、`@File#L37-42`。 + +--- + +## インストール + +OpenCode を VS Code および Cursor、Windsurf、VSCodium などの一般的なフォークにインストールするには: + +1. VS Code を開く +2. 統合ターミナルを開きます +3. `opencode` を実行します - 拡張機能は自動的にインストールされます + +一方、TUI から `/editor` または `/export` を実行するときに独自の IDE を使用したい場合は、`export EDITOR="code --wait"` を設定する必要があります。 [詳細はこちら](/docs/tui/#editor-setup)。 + +--- + +### 手動インストール + +Extension Marketplace で **OpenCode** を検索し、**インストール** をクリックします。 + +--- + +### トラブルシューティング + +拡張機能が自動的にインストールされない場合: + +- 統合ターミナルで `opencode` を実行していることを確認してください。 +- IDE の CLI がインストールされていることを確認します。 + - VS Code の場合: `code` コマンド + - Cursor の場合: `cursor` コマンド + - Windsurf の場合: `windsurf` コマンド + - VSCodium の場合: `codium` コマンド + - そうでない場合は、`Cmd+Shift+P` (Mac) または `Ctrl+Shift+P` (Windows/Linux) を実行し、「Shell Command: Install 'code' command in PATH」(または IDE の同等のコマンド) を検索します。 +- VS Code に拡張機能をインストールする権限があることを確認してください diff --git a/packages/web/src/content/docs/ja/index.mdx b/packages/web/src/content/docs/ja/index.mdx new file mode 100644 index 00000000000..6a6612715fb --- /dev/null +++ b/packages/web/src/content/docs/ja/index.mdx @@ -0,0 +1,349 @@ +--- +title: はじめに +description: OpenCode を始めましょう。 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**OpenCode**](/) は、オープンソースの AI コーディングエージェントです。これは、ターミナルベースのインターフェイス、デスクトップアプリ、または IDE 拡張機能として利用できます。 + +![opencodeテーマ](../../../assets/lander/screenshot.png)を使用したOpenCode TUI + +始めましょう。 + +--- + +#### 前提条件 + +ターミナルで OpenCode を使用するには、次のものが必要です。 + +1. 次のような最新のターミナルエミュレータ: + - [WezTerm](https://wezterm.org)、クロスプラットフォーム + - [Alacritty](https://alacritty.org)、クロスプラットフォーム + - [Ghostty](https://ghostty.org)、Linux および macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/)、Linux および macOS + +2. 使用する LLM プロバイダーの API キー。 + +--- + +## インストール + +OpenCode をインストールする最も簡単な方法は、インストールスクリプトを使用することです。 + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +次のコマンドを使用してインストールすることもできます。 + +- **Node.js の使用** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **macOS および Linux での Homebrew の使用** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > 最新のリリースには OpenCode タップを使用することをお勧めします。公式の `brew install opencode` 式は Homebrew チームによって維持されており、更新頻度は低くなります。 + +- **Arch Linux での Paru の使用** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[推奨: WSL を使用する] +Windows で最高のエクスペリエンスを得るには、[Windows Subsystem for Linux (WSL)](/docs/windows-wsl) を使用することをお勧めします。これにより、パフォーマンスが向上し、OpenCode の機能との完全な互換性が提供されます。 +::: + +- **Chocolatey の使用** + + ```bash + choco install opencode + ``` + +- **Scoop の使用** + + ```bash + scoop install opencode + ``` + +- **npm の使用** + + ```bash + npm install -g opencode-ai + ``` + +- **Mise の使用** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **Docker の使用** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +Bun を使用して Windows に OpenCode をインストールするためのサポートは現在進行中です。 + +[Releases](https://github.com/anomalyco/opencode/releases). + +--- + +## 設定 + +OpenCode を使用すると、API キーを構成することで任意の LLM プロバイダーを使用できます。 + +LLM プロバイダーを初めて使用する場合は、[OpenCode Zen](/docs/zen) をお勧めします。 +これは、OpenCode チームによってテストおよび検証されたモデルの厳選されたリストです。 + +1. TUI で `/connect` コマンドを実行し、opencode を選択して、[opencode.ai/auth](https://opencode.ai/auth) で認証します。 + + ```txt + /connect + ``` + +2. サインインし、お支払いの詳細を追加し、API キーをコピーします。 + +3. API キーを貼り付けます。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +あるいは、他のプロバイダーのいずれかを選択することもできます。 [詳細はこちら](/docs/providers#directory)。 + +--- + +## 初期化 + +プロバイダーを構成したので、取り組みたいプロジェクトに移動できます。 + +```bash +cd /path/to/project +``` + +そしてOpenCodeを実行します。 + +```bash +opencode +``` + +次に、次のコマンドを実行して、プロジェクトの OpenCode を初期化します。 + +```bash frame="none" +/init +``` + +これにより、OpenCode がプロジェクトを分析し、プロジェクトのルートに `AGENTS.md` ファイルを作成します。 + +:::tip +プロジェクトの `AGENTS.md` ファイルを Git にコミットする必要があります。 +::: + +これは、OpenCode がプロジェクトの構造と使用されているコーディングパターンを理解するのに役立ちます。 + +--- + +## 使用法 + +これで、OpenCode を使用してプロジェクトに取り組む準備が整いました。何でもお気軽にお尋ねください! + +AI コーディングエージェントを初めて使用する場合は、次の例を参考にしてください。 + +--- + +### 質問する + +OpenCode にコードベースの説明を依頼できます。 + +:::tip +プロジェクト内のファイルをあいまい検索するには、`@` キーを使用します。 +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +これは、コードベースに作業していない部分がある場合に役立ちます。 + +--- + +### 機能を追加する + +OpenCode に新しい機能をプロジェクトに追加するよう依頼できます。ただし、最初は計画の作成を依頼することをお勧めします。 + +1. **計画を作成する** + +OpenCode には、変更を加える機能を無効にする _Plan mode_ があり、 +代わりに、その機能を*どのように*実装するかを提案します。 + +**Tab** キーを使用してそれに切り替えます。右下隅にこれを示すインジケーターが表示されます。 + +```bash frame="none" title="Switch to Plan mode" + +``` + +では、何をしたいのかを説明しましょう。 + +```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. +``` + +自分が何を望んでいるのかを理解するために、OpenCode に十分な詳細を提供したいと考えています。 +チームの若手開発者と話しているように話すと良いでしょう。 + +:::tip +OpenCode に多くのコンテキストと例を提供して、意図する内容を理解できるようにします。 +::: + +2. **計画を反復する** + +計画が示されたら、フィードバックを送信したり、詳細を追加したりできます。 + +```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. +``` + +:::tip +画像をターミナルにドラッグアンドドロップして、プロンプトに追加します。 +::: + +OpenCode は、指定された画像をスキャンしてプロンプトに追加できます。 +画像をターミナルにドラッグアンドドロップしてこれを行うことができます。 + +3. **機能を構築する** + +計画に慣れたら、*Build mode*に戻ります。 +**Tab** キーをもう一度押します。 + +```bash frame="none" + +``` + +そして変更を加えるように依頼します。 + +```bash frame="none" + Sounds good! Go ahead and make the changes. +``` + +--- + +### 変更を加える + +より単純な変更については、OpenCode に直接ビルドするよう依頼できます。 +最初に計画を見直す必要はありません。 + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +OpenCode が適切な変更を行えるように、十分な量の詳細を確実に提供する必要があります。 + +--- + +### 変更を元に戻す + +OpenCode にいくつかの変更を依頼するとします。 + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +しかし、それは自分が望んでいたものではないことに気づきます。変更は **元に戻すことができます** +`/undo` コマンドを使用します。 + +```bash frame="none" +/undo +``` + +OpenCode は加えた変更を元に戻し、元のメッセージを再度表示します。 + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +ここからプロンプトを調整し、OpenCode に再試行を依頼できます。 + +:::tip +`/undo` を複数回実行すると、複数の変更を元に戻すことができます。 +::: + +または、`/redo` コマンドを使用して変更を**やり直す**こともできます。 + +```bash frame="none" +/redo +``` + +--- + +## 共有 + +OpenCode との会話は [他のチームメンバーと共有できます](/docs/share)。 + +```bash frame="none" +/share +``` + +これにより、現在の会話へのリンクが作成され、クリップボードにコピーされます。 + +:::note +会話はデフォルトでは共有されません。 +::: + +これは [OpenCode を使用した会話 ](https://opencode.ai/s/4XP1fce5) の例です。 + +--- + +## カスタマイズ + +それで終わりです!これであなたは OpenCode の使い方のプロになりました。 + +独自のものにするには、[テーマ](/docs/themes) を選択する、[キーバインドをカスタマイズする](/docs/keybinds)、[コードフォーマッタ](/docs/formatters) を設定する、[カスタムコマンド](/docs/commands) を作成する、または [OpenCode設定](/docs/config) を試してみることをお勧めします。 diff --git a/packages/web/src/content/docs/ja/keybinds.mdx b/packages/web/src/content/docs/ja/keybinds.mdx new file mode 100644 index 00000000000..66466a7f72d --- /dev/null +++ b/packages/web/src/content/docs/ja/keybinds.mdx @@ -0,0 +1,192 @@ +--- +title: キーバインド +description: キーバインドをカスタマイズします。 +--- + +OpenCode には、OpenCode 設定を通じてカスタマイズできるキーバインドのリストがあります。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## リーダーキー + +OpenCode は、ほとんどのキーバインドに `leader` キーを使用します。これにより、ターミナルでの競合が回避されます。 + +デフォルトでは、`ctrl+x` がリーダーキーであり、ほとんどの操作では、最初にリーダーキーを押してからショートカットを押す必要があります。たとえば、新しいセッションを開始するには、まず `ctrl+x` を押してから、`n` を押します。 + +キーバインドにリーダーキーを使用する必要はありませんが、そうすることをお勧めします。 + +--- + +## キーバインドを無効にする + +キーバインドを無効にするには、値「none」を指定してキーを構成に追加します。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## デスクトッププロンプトのショートカット + +OpenCode デスクトップアプリのプロンプト入力は、テキストを編集するための一般的な Readline/Emacs スタイルのショートカットをサポートしています。これらは組み込みであり、現在 `opencode.json` を介して構成することはできません。 + +| ショートカット | アクション | +| -------------- | ------------------------------------------------- | +| `ctrl+a` | 現在の行の先頭に移動 | +| `ctrl+e` | 現在の行の末尾に移動 | +| `ctrl+b` | カーソルを 1 文字前に移動 | +| `ctrl+f` | カーソルを 1 文字後に移動 | +| `alt+b` | カーソルを 1 単語前に移動 | +| `alt+f` | カーソルを 1 単語後に移動 | +| `ctrl+d` | カーソル下の文字を削除 | +| `ctrl+k` | 行末まで強制終了 | +| `ctrl+u` | 行の先頭までキル | +| `ctrl+w` | 前の単語を削除 | +| `alt+d` | 次の単語を削除 | +| `ctrl+t` | 文字を入れ替える | +| `ctrl+g` | ポップオーバーをキャンセル/実行中の応答を中止する | + +--- + +## Shift+Enter + +一部のターミナルでは、デフォルトでは Enter キーを使用して修飾キーを送信しません。エスケープシーケンスとして `Shift+Enter` を送信するようにターミナルを設定する必要がある場合があります。 + +### Windows Terminal + +次の場所で `settings.json` を開きます。 + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +これをルートレベルの `actions` 配列に追加します。 + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +これをルートレベルの `keybindings` 配列に追加します。 + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +ファイルを保存し、Windows Terminal を再起動するか、新しいタブを開きます。 diff --git a/packages/web/src/content/docs/ja/lsp.mdx b/packages/web/src/content/docs/ja/lsp.mdx new file mode 100644 index 00000000000..7b42c373327 --- /dev/null +++ b/packages/web/src/content/docs/ja/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: LSPサーバー +description: OpenCode は LSP サーバーと統合します。 +--- + +OpenCode は言語サーバープロトコル (LSP) と統合して、LLM がコードベースと対話できるようにします。診断を使用して LLM にフィードバックを提供します。 + +--- + +## 組み込み + +OpenCode には、一般的な言語用のいくつかの組み込み LSP サーバーが付属しています。 + +| LSP Server | Extensions | Requirements | +| ------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------ | +| astro | .astro | Auto-installs for Astro projects | +| bash | .sh, .bash, .zsh, .ksh | Auto-installs bash-language-server | +| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | Auto-installs for C/C++ projects | +| csharp | .cs | `.NET SDK` installed | +| clojure-lsp | .clj, .cljs, .cljc, .edn | `clojure-lsp` command available | +| dart | .dart | `dart` command available | +| deno | .ts, .tsx, .js, .jsx, .mjs | `deno` command available (auto-detects deno.json/deno.jsonc) | +| elixir-ls | .ex, .exs | `elixir` command available | +| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | `eslint` dependency in project | +| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` installed | +| gleam | .gleam | `gleam` command available | +| gopls | .go | `go` command available | +| hls | .hs, .lhs | `haskell-language-server-wrapper` command available | +| jdtls | .java | `Java SDK (version 21+)` installed | +| kotlin-ls | .kt, .kts | Auto-installs for Kotlin projects | +| lua-ls | .lua | Auto-installs for Lua projects | +| nixd | .nix | `nixd` command available | +| ocaml-lsp | .ml, .mli | `ocamllsp` command available | +| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | `oxlint` dependency in project | +| php intelephense | .php | Auto-installs for PHP projects | +| prisma | .prisma | `prisma` command available | +| pyright | .py, .pyi | `pyright` dependency installed | +| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | `ruby` and `gem` commands available | +| rust | .rs | `rust-analyzer` command available | +| sourcekit-lsp | .swift, .objc, .objcpp | `swift` installed (`xcode` on macOS) | +| svelte | .svelte | Auto-installs for Svelte projects | +| terraform | .tf, .tfvars | Auto-installs from GitHub releases | +| tinymist | .typ, .typc | Auto-installs from GitHub releases | +| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` dependency in project | +| vue | .vue | Auto-installs for Vue projects | +| yaml-ls | .yaml, .yml | Auto-installs Red Hat yaml-language-server | +| zls | .zig, .zon | `zig` command available | + +上記のファイル拡張子のいずれかが検出され、要件が満たされると、LSP サーバーは自動的に有効になります。 + +:::note +`OPENCODE_DISABLE_LSP_DOWNLOAD` 環境変数を `true` に設定すると、LSP サーバーの自動ダウンロードを無効にできます。 +::: + +--- + +## 仕組み + +OpenCode がファイルを開くと、次のようになります。 + +1. 有効なすべての LSP サーバーに対してファイル拡張子をチェックします。 +2. 適切な LSP サーバーがまだ実行されていない場合は開始します。 + +--- + +## 設定 + +OpenCode 設定の `lsp` セクションを通じて LSP サーバーをカスタマイズできます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +各 LSP サーバーは以下をサポートします。 + +| プロパティ | タイプ | 説明 | +| ---------------- | ------------ | ---------------------------------------------------------- | +| `disabled` | ブール値 | LSP サーバーを無効にするには、これを `true` に設定します。 | +| `command` | 文字列[] | LSP サーバーを起動するコマンド | +| `extensions` | 文字列[] | この LSP サーバーが処理するファイル拡張子 | +| `env` | オブジェクト | サーバーの起動時に設定する環境変数 | +| `initialization` | オブジェクト | LSP サーバーに送信する初期化オプション | + +いくつかの例を見てみましょう。 + +--- + +### 環境変数 + +LSP サーバーの起動時に `env` プロパティを使用して環境変数を設定します。 + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### 初期化オプション + +`initialization` プロパティを使用して、初期化オプションを LSP サーバーに渡します。これらは、LSP `initialize` リクエスト中に送信されるサーバー固有の設定です。 + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +初期化オプションは LSP サーバーによって異なります。利用可能なオプションについては、LSP サーバーのドキュメントを確認してください。 +::: + +--- + +### LSPサーバーの無効化 + +**すべて** LSP サーバーをグローバルに無効にするには、`lsp` を `false` に設定します。 + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +**特定** LSP サーバーを無効にするには、`disabled` を `true` に設定します。 + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### カスタム LSP サーバー + +コマンドとファイル拡張子を指定して、カスタム LSP サーバーを追加できます。 + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## 追加情報 + +### PHP Intelephense + +PHP Intelephense は、ライセンスキーを通じてプレミアム機能を提供します。ライセンスキーを指定するには、次の場所にあるテキストファイルにキー (のみ) を配置します。 + +- macOS/Linux の場合: `$HOME/intelephense/license.txt` +- Windows の場合: `%USERPROFILE%/intelephense/license.txt` + +ファイルにはライセンスキーのみが含まれており、追加のコンテンツは含まれていません。 diff --git a/packages/web/src/content/docs/ja/mcp-servers.mdx b/packages/web/src/content/docs/ja/mcp-servers.mdx new file mode 100644 index 00000000000..a4b2485337e --- /dev/null +++ b/packages/web/src/content/docs/ja/mcp-servers.mdx @@ -0,0 +1,976 @@ +--- +title: MCPサーバー +description: ローカルおよびリモートの MCP ツールを追加します。 +--- + +_Model Context Protocol_ (MCP) を使用して、OpenCode に外部ツールを追加できます。 OpenCode は、ローカルサーバーとリモートサーバーの両方をサポートします。 + +MCP ツールを追加すると、組み込みツールとともに LLM で自動的に使用できるようになります。 + +--- + +#### 注意事項 + +MCP サーバーを使用すると、コンテキストが追加されます。多くのツールがある場合、これはすぐに増加する可能性があります。したがって、使用する MCP サーバーには注意することをお勧めします。 + +:::tip +MCP サーバーはコンテキストに追加されるため、どのサーバーを有効にするかには注意してください。 +::: +特定の MCP サーバーは、大量のトークンを追加する傾向があり、コンテキスト制限を簡単に超える可能性があります。 + +--- + +## 有効化 + +MCP サーバーは、`mcp` の下の [OpenCode 設定](https://opencode.ai/docs/config/) で定義できます。各 MCP を一意の名前で追加します。 LLM にプロンプ​​トを表示するときに、その MCP を名前で参照できます。 + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +`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 + } + } +} +``` + +ローカルの設定値はリモートのデフォルト値をオーバーライドします。詳細については、「[設定の優先順位](/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 設定を通じてそれらを管理できます。 + +--- + +### グローバル + +これは、それらをグローバルに有効または無効にできることを意味します。 + +```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. [エージェント設定](/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. +``` + +`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/models.mdx b/packages/web/src/content/docs/ja/models.mdx new file mode 100644 index 00000000000..caa7b817956 --- /dev/null +++ b/packages/web/src/content/docs/ja/models.mdx @@ -0,0 +1,221 @@ +--- +title: モデル +description: LLM プロバイダーとモデルを構成します。 +--- + +OpenCode は [AI SDK](https://ai-sdk.dev/) および [Models.dev](https://models.dev) を使用して **75 以上の LLM プロバイダー** をサポートし、ローカルモデルの実行をサポートします。 + +--- + +## プロバイダー + +最も一般的なプロバイダーはデフォルトでプリロードされています。 `/connect` コマンドを使用してプロバイダーの資格情報を追加した場合は、OpenCode を開始するときにそれらの資格情報を使用できるようになります。 + +[プロバイダー](/docs/providers). + +--- + +## モデルの選択 + +プロバイダーを構成したら、次のように入力して必要なモデルを選択できます。 + +```bash frame="none" +/models +``` + +--- + +## 推奨モデル + +たくさんのモデルがあり、毎週のように新しいモデルが登場します。 + +:::tip +当社が推奨するモデルのいずれかの使用を検討してください。 +::: +しかし、コード生成とツール呼び出しの両方に優れたものはほんのわずかしかありません。 + +ここでは、OpenCode で適切に動作するいくつかのモデルを順不同で示します。 (これは完全なリストではなく、必ずしも最新であるとは限りません): + +- GPT5.2 +- GPT 5.1 Codex +- Claude Opus 4.5 +- Claude Sonnet 4.5 +- MiniMax M2.1 +- Gemini 3 Pro + +--- + +## デフォルトの設定 + +これらのいずれかをデフォルトのモデルとして設定するには、`model` キーを OpenCode の設定に追加します。 + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +ここでの完全な ID は `provider_id/model_id` です。たとえば、[OpenCode Zen](/docs/zen) を使用している場合、GPT 5.1 Codex には `opencode/gpt-5.1-codex` を使用します。 + +[カスタムプロバイダー](/docs/providers#custom) を構成している場合、`provider_id` は構成の `provider` 部分のキーであり、`model_id` は `provider.models` のキーです。 + +--- + +## モデルの設定 + +config を通じてモデルのオプションをグローバルに設定できます。 + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +ここでは、2 つの組み込みモデル (`gpt-5` プロバイダー経由でアクセスする場合は `openai`、`claude-sonnet-4-20250514` プロバイダー経由でアクセスする場合は `anthropic`) のグローバル設定を構成しています。 +組み込みプロバイダーとモデル名は、[Models.dev](https://models.dev) で確認できます。 + +使用しているエージェントに対してこれらのオプションを構成することもできます。ここでエージェント設定はグローバルオプションをオーバーライドします。 [詳細はこちら](/docs/agents/#additional)。 + +組み込みバリアントを拡張するカスタムバリアントを定義することもできます。バリアントを使用すると、重複したエントリを作成せずに、同じモデルに対して異なる設定を構成できます。 + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## バリアント + +多くのモデルは、異なる構成の複数のバリアントをサポートしています。 OpenCode には、一般的なプロバイダーのデフォルトのバリアントが組み込まれています。 + +### 組み込みバリアント + +OpenCode には、多くのプロバイダーのデフォルトのバリアントが付属しています。 + +**Anthropic**: + +- `high` - 高度な思考予算 (デフォルト) +- `max` - 最大の思考予算 + +**OpenAI**: + +モデルによって異なりますが、おおよそ次のとおりです。 + +- `none` - 理由はありません +- `minimal` - 最小限の推論努力 +- `low` - 推論の労力が少ない +- `medium` - 中程度の推論努力 +- `high` - 高い推論努力 +- `xhigh` - 非常に高い推論努力 + +**Google**: + +- `low` - 労力/トークン予算の削減 +- `high` - より高い労力/トークン予算 + +:::tip +このリストは包括的なものではありません。他の多くのプロバイダーにもデフォルトが組み込まれています。 +::: + +### カスタムバリアント + +既存のバリアントをオーバーライドすることも、独自のバリアントを追加することもできます。 + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### バリアントの切り替え + +キーバインド `variant_cycle` を使用すると、バリアントをすばやく切り替えることができます。 [詳細はこちら](/docs/keybinds)。 + +--- + +## モデルのロード + +OpenCode が起動すると、次の優先順位でモデルがチェックされます。 + +1. `--model` または `-m` コマンドラインフラグ。形式は構成ファイルと同じです: `provider_id/model_id`。 + +2. OpenCode 構成内のモデルのリスト。 + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + +ここでの形式は `provider/model` です。 + +3. 最後に使用されたモデル。 + +4. 内部優先順位に基づく最初のモデル。 diff --git a/packages/web/src/content/docs/ja/modes.mdx b/packages/web/src/content/docs/ja/modes.mdx new file mode 100644 index 00000000000..6e7bc121b6f --- /dev/null +++ b/packages/web/src/content/docs/ja/modes.mdx @@ -0,0 +1,329 @@ +--- +title: モード +description: さまざまなユースケースに応じたさまざまなモード。 +--- + +:::caution +モードは、OpenCode 設定の `agent` オプションを通じて設定されるようになりました。 +`mode` オプションは非推奨になりました。 [詳細はこちら](/docs/agents)。 +::: +モードを使用すると、さまざまなユースケースに合わせて動作、ツール、プロンプトをカスタマイズできます。 + +**Build** と **Plan** という 2 つの組み込みモードが付属しています。カスタマイズできます +これらを使用するか、OpenCode 設定を通じて独自の設定を行います。 + +セッション中にモードを切り替えることも、設定ファイルでモードを構成することもできます。 + +--- + +## 組み込み + +OpenCode には 2 つの組み込みモードが付属しています。 + +--- + +### Build + +Build は、すべてのツールが有効になっている **デフォルト** モードです。これは、ファイル操作やシステムコマンドへのフルアクセスが必要な開発作業の標準モードです。 + +--- + +### Plan + +計画と分析のために設計された制限付きモード。Plan モードでは、次のツールはデフォルトで無効になっています。 + +- `write` - 新しいファイルを作成できません +- `edit` - 計画自体の詳細を示す `.opencode/plans/*.md` にあるファイルを除き、既存のファイルを変更できません +- `patch` - パッチを適用できません +- `bash` - シェルコマンドを実行できません + +このモードは、コードベースに実際の変更を加えずに、AI にコードを分析させたり、変更を提案したり、計画を作成させたい場合に便利です。 + +--- + +## 切り替え + +セッション中に _Tab_ キーを使用してモードを切り替えることができます。または、設定された `switch_mode` キーバインド。 + +参照: [コードのフォーマット設定については、Formatters](/docs/formatters)。 + +--- + +## 設定 + +組み込みモードをカスタマイズしたり、構成を通じて独自のモードを作成したりできます。モードは次の 2 つの方法で設定できます。 + +### JSON 設定 + +`opencode.json` 設定ファイルでモードを構成します。 + +```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 設定 + +Markdown ファイルを使用してモードを定義することもできます。それらを次の場所に置きます。 + +- グローバル: `~/.config/opencode/modes/` +- プロジェクト: `.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. +``` + +Markdown ファイル名はモード名になります (例: `review.md` は `review` モードを作成します)。 + +これらの設定オプションを詳しく見てみましょう。 + +--- + +### モデル + +`model` 設定を使用して、このモードのデフォルトモデルをオーバーライドします。さまざまなタスクに最適化されたさまざまなモデルを使用する場合に役立ちます。たとえば、計画にはより高速なモデルを、実装にはより有能なモデルを使用します。 + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### 温度 + +`temperature` 設定を使用して、AI の応答のランダム性と創造性を制御します。値が低いほど、応答はより集中的かつ決定的になりますが、値が高いほど、創造性と変動性が高まります。 + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +通常、温度値の範囲は 0.0 ~ 1.0 です。 + +- **0.0-0.2**: 非常に焦点が絞られた決定的な応答。コード分析と計画に最適です。 +- **0.3-0.5**: 創造性を備えたバランスの取れた応答。一般的な開発タスクに適しています。 +- **0.6-1.0**: より創造的で多様な応答。ブレーンストーミングや探索に役立ちます。 + +```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}" + } + } +} +``` + +温度が指定されていない場合、OpenCode はモデル固有のデフォルトを使用します (通常、ほとんどのモデルでは 0、Qwen モデルでは 0.55)。 + +--- + +### プロンプト + +`prompt` 設定を使用して、このモードのカスタムシステムプロンプトファイルを指定します。プロンプトファイルには、モードの目的に固有の指示が含まれている必要があります。 + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +このパスは、設定ファイルが配置されている場所に対する相対パスです。したがって、これはグローバルな OpenCode 設定とプロジェクト固有の設定の両方で機能します。 + +--- + +### ツール + +`tools` 設定を使用して、このモードでどのツールを使用できるかを制御します。特定のツールを `true` または `false` に設定することで、有効または無効にすることができます。 + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +ツールが指定されていない場合は、すべてのツールがデフォルトで有効になります。 + +--- + +#### 利用可能なツール + +ここでは、モード設定を通じて制御できるすべてのツールを示します。 + +| ツール | 説明 | +| ----------- | ------------------------------ | +| `bash` | シェルコマンドを実行する | +| `edit` | 既存のファイルを変更する | +| `write` | 新しいファイルを作成する | +| `read` | ファイルの内容を読み取る | +| `grep` | ファイルの内容を検索 | +| `glob` | パターンでファイルを検索 | +| `list` | ディレクトリの内容をリストする | +| `patch` | ファイルにパッチを適用する | +| `todowrite` | ToDo リストを管理する | +| `todoread` | ToDo リストを読む | +| `webfetch` | Web コンテンツを取得する | + +--- + +## カスタムモード + +構成に追加することで、独自のカスタムモードを作成できます。両方のアプローチを使用した例を次に示します。 + +### JSON 設定の使用 + +```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 + } + } + } +} +``` + +### Markdown ファイルの使用 + +モードファイルをプロジェクト固有モードの場合は `.opencode/modes/` に、グローバルモードの場合は `~/.config/opencode/modes/` に作成します。 + +```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 +``` + +--- + +### ユースケース + +さまざまなモードの一般的な使用例をいくつか示します。 + +- **ビルドモード**: すべてのツールを有効にした完全な開発作業 +- **計画モード**: 変更を加えずに分析および計画を立てる +- **レビューモード**: 読み取り専用アクセスとドキュメントツールによるコードレビュー +- **デバッグモード**: bash および読み取りツールを有効にして調査に重点を置きます +- **ドキュメントモード**: ファイル操作を使用してドキュメントを作成しますが、システムコマンドは使用しません + +また、さまざまなユースケースにさまざまなモデルが適していることがわかるかもしれません。 diff --git a/packages/web/src/content/docs/ja/network.mdx b/packages/web/src/content/docs/ja/network.mdx new file mode 100644 index 00000000000..fc9eb3ff05f --- /dev/null +++ b/packages/web/src/content/docs/ja/network.mdx @@ -0,0 +1,55 @@ +--- +title: ネットワーク +description: プロキシとカスタム証明書を構成します。 +--- + +OpenCode は、エンタープライズネットワーク環境の標準プロキシ環境変数とカスタム証明書をサポートしています。 + +--- + +## プロキシ + +OpenCode は標準のプロキシ環境変数を尊重します。 + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +TUI はローカル HTTP サーバーと通信します。ルーティングループを防ぐには、この接続のプロキシをバイパスする必要があります。 +::: +[CLI フラグ](/docs/cli#run) を使用して、サーバーのポートとホスト名を構成できます。 + +--- + +### 認証 + +プロキシで基本認証が必要な場合は、URL に認証情報を含めます。 + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +パスワードのハードコーディングは避けてください。環境変数または安全な認証情報ストレージを使用します。 +::: +NTLM や Kerberos などの高度な認証を必要とするプロキシの場合は、認証方法をサポートする LLM ゲートウェイの使用を検討してください。 + +--- + +## カスタム証明書 + +企業が HTTPS 接続にカスタム CA を使用している場合は、それらを信頼するように OpenCode を構成します。 + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +これは、プロキシ接続と直接 API アクセスの両方で機能します。 diff --git a/packages/web/src/content/docs/ja/permissions.mdx b/packages/web/src/content/docs/ja/permissions.mdx new file mode 100644 index 00000000000..93143f9ca2c --- /dev/null +++ b/packages/web/src/content/docs/ja/permissions.mdx @@ -0,0 +1,284 @@ +--- +title: 権限 +description: どのアクションの実行に承認が必要かを制御します。 +--- + +OpenCode は `permission` 設定を使用して、特定のアクションを自動的に実行するか、プロンプトを表示するか、ブロックするかを決定します。 + +`v1.1.1` 現在、従来の `tools` ブール値設定は非推奨となり、`permission` にマージされました。古い `tools` 設定は、下位互換性のために引き続きサポートされています。 + +--- + +## アクション + +各権限ルールは次のいずれかに解決されます。 + +- `"allow"` — 承認なしで実行します +- `"ask"` — 承認を求めるプロンプト +- `"deny"` — アクションをブロックする + +--- + +## 設定 + +権限をグローバルに (`*` を使用して) 設定し、特定のツールをオーバーライドできます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +すべての権限を一度に設定することもできます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## 詳細なルール (オブジェクト構文) + +ほとんどの権限では、オブジェクトを使用して、ツール入力に基づいてさまざまなアクションを適用できます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +ルールはパターンマッチによって評価され、**最後に一致したルールが優先されます**。一般的なパターンは、キャッチオール `"*"` ルールを最初に置き、その後により具体的なルールを置くことです。 + +### ワイルドカード + +許可パターンでは、単純なワイルドカードマッチングを使用します。 + +- `*` は 0 個以上の任意の文字と一致します +- `?` は 1 つの文字に正確に一致します +- 他のすべての文字は文字通り一致します + +### ホームディレクトリの展開 + +パターンの先頭で `~` または `$HOME` を使用して、ホームディレクトリを参照できます。これは、[`external_directory`](#external-directories) ルールに特に役立ちます。 + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### 外部ディレクトリ + +`external_directory` を使用して、OpenCode が開始された作業ディレクトリの外部のパスに触れるツール呼び出しを許可します。これは、パスを入力として受け取るすべてのツール (`read`、`edit`、`list`、`glob`、`grep`、および多くの `bash` コマンドなど) に適用されます。 + +ホーム展開 (`~/...` など) は、パターンの記述方法にのみ影響します。外部パスは現在のワークスペースの一部にはならないため、作業ディレクトリの外部のパスも `external_directory` 経由で許可する必要があります。 + +たとえば、これにより、`~/projects/personal/` の下にあるすべてのものへのアクセスが許可されます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +ここで許可されるディレクトリはすべて、現在のワークスペースと同じデフォルトを継承します。 [`read` のデフォルトは `allow`](#defaults) であるため、オーバーライドされない限り、`external_directory` の下のエントリの読み取りも許可されます。読み取りを保持しながら編集をブロックするなど、ツールをこれらのパスで制限する必要がある場合は、明示的なルールを追加します。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +信頼できるパスに重点を置いたリストを維持し、他のツール (`bash` など) の必要に応じて追加の許可または拒否ルールを追加します。 + +--- + +## 利用可能な権限 + +OpenCode の権限は、ツール名に加えて、いくつかの安全対策によってキー化されます。 + +- `read` — ファイルの読み取り (ファイルパスと一致) +- `edit` — すべてのファイル変更 (`edit`、`write`、`patch`、`multiedit` をカバー) +- `glob` — ファイルのグロビング (グロブパターンと一致) +- `grep` — コンテンツ検索 (正規表現パターンと一致) +- `list` — ディレクトリ内のファイルのリスト (ディレクトリパスと一致) +- `bash` — シェルコマンドの実行 (`git status --porcelain` などの解析されたコマンドと一致します) +- `task` — サブエージェントの起動 (サブエージェントのタイプと一致) +- `skill` — スキルをロードしています(スキル名と一致します) +- `lsp` — LSP クエリの実行 (現在は非細分性) +- `todoread`、`todowrite` — ToDo リストの読み取り/更新 +- `webfetch` — URL を取得します (URL と一致します) +- `websearch`、`codesearch` — Web/コード検索 (クエリと一致) +- `external_directory` — ツールがプロジェクトの作業ディレクトリ外のパスにアクセスするとトリガーされます。 +- `doom_loop` — 同じ入力で同じツール呼び出しが 3 回繰り返されたときにトリガーされます。 + +--- + +## デフォルト + +何も指定しない場合、OpenCode は許容的なデフォルトから開始します。 + +- ほとんどの権限はデフォルトで `"allow"` に設定されます。 +- `doom_loop` と `external_directory` のデフォルトは `"ask"` です。 +- `read` は `"allow"` ですが、`.env` ファイルはデフォルトで拒否されます。 + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## 承認の要求 + +OpenCode が承認を求めるプロンプトを表示すると、UI は 3 つの結果を提供します。 + +- `once` — このリクエストのみを承認します +- `always` — 提案されたパターンに一致する今後のリクエストを承認します(現在の OpenCode セッションの残りの部分) +- `reject` — リクエストを拒否します + +`always` が承認するパターンのセットは、ツールによって提供されます (たとえば、bash の承認では通常、`git status*` のような安全なコマンドプレフィックスがホワイトリストに登録されます)。 + +--- + +## エージェント + +エージェントごとに権限をオーバーライドできます。エージェントの権限はグローバル設定とマージされ、エージェントルールが優先されます。 [エージェントの権限について詳しくは、](/docs/agents#permissions) をご覧ください。 + +:::note +パターンマッチングの詳細な例については、上記の[詳細なルール (オブジェクト構文)](#detailed-rules-object-syntax)セクションを参照してください。 +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +Markdown でエージェントの権限を構成することもできます。 + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +引数のあるコマンドにはパターンマッチングを使用します。 `"grep *"` は `grep pattern file.txt` を許可しますが、`"grep"` だけではブロックされます。 `git status` のようなコマンドはデフォルトの動作で機能しますが、引数を渡すときに明示的な許可 (`"git status *"` など) が必要です。 +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +Markdownでエージェントの権限を構成することもできます。 + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +引数のあるコマンドにはパターン マッチングを使用します。 `"grep *"` は `grep pattern file.txt` を許可しますが、`"grep"` だけではブロックされます。 `git status` のようなコマンドはデフォルトの動作で機能しますが、引数を渡すときに明示的な許可 (`"git status *"` など) が必要です。 +::: diff --git a/packages/web/src/content/docs/ja/plugins.mdx b/packages/web/src/content/docs/ja/plugins.mdx new file mode 100644 index 00000000000..39fc1dda217 --- /dev/null +++ b/packages/web/src/content/docs/ja/plugins.mdx @@ -0,0 +1,385 @@ +--- +title: プラグイン +description: OpenCode を拡張する独自のプラグインを作成します。 +--- + +プラグインを使用すると、さまざまなイベントにフックして動作をカスタマイズすることで OpenCode を拡張できます。プラグインを作成して、新しい機能を追加したり、外部サービスと統合したり、OpenCode のデフォルトの動作を変更したりできます。 + +たとえば、コミュニティによって作成された [plugins](/docs/ecosystem#plugins) をチェックしてください。 + +--- + +## プラグインの使用 + +プラグインをロードするには 2 つの方法があります。 + +--- + +### ローカルファイルから + +JavaScript または TypeScript ファイルをプラグインディレクトリに配置します。 + +- `.opencode/plugins/` - プロジェクトレベルのプラグイン +- `~/.config/opencode/plugins/` - グローバルプラグイン + +これらのディレクトリ内のファイルは起動時に自動的にロードされます。 + +--- + +### npm から + +設定ファイルで npm パッケージを指定します。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +通常の npm パッケージとスコープ指定された npm パッケージの両方がサポートされています。 + +[ecosystem](/docs/ecosystem#plugins). + +--- + +### プラグインのインストール + +**npm プラグイン** は、起動時に Bun を使用して自動的にインストールされます。パッケージとその依存関係は `~/.cache/opencode/node_modules/` にキャッシュされます。 + +**ローカルプラグイン**は、プラグインディレクトリから直接ロードされます。外部パッケージを使用するには、config ディレクトリ内に `package.json` を作成するか ([Dependency](#dependencies) を参照)、プラグインを npm に公開して [config](/docs/config#plugins) に追加する必要があります。 + +--- + +### ロード順序 + +プラグインはすべてのソースからロードされ、すべてのフックが順番に実行されます。ロード順序は次のとおりです。 + +1. グローバル設定 (`~/.config/opencode/opencode.json`) +2. プロジェクト設定 (`opencode.json`) +3. グローバルプラグインディレクトリ (`~/.config/opencode/plugins/`) +4. プロジェクトプラグインディレクトリ (`.opencode/plugins/`) + +同じ名前とバージョンを持つ重複した npm パッケージは 1 回ロードされます。ただし、似た名前のローカルプラグインと npm プラグインは両方とも別々にロードされます。 + +--- + +## プラグインを作成する + +プラグインは、1 つ以上のプラグインをエクスポートする **JavaScript/TypeScript モジュール**です。 +各関数はコンテキストオブジェクトを受け取り、フックオブジェクトを返します。 + +--- + +### 依存関係 + +ローカルプラグインとカスタムツールは外部の npm パッケージを使用できます。必要な依存関係を含む `package.json` を config ディレクトリに追加します。 + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +OpenCode は起動時に `bun install` を実行してこれらをインストールします。プラグインとツールはそれらをインポートできるようになります。 + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### 基本構造 + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +プラグイン関数は以下を受け取ります。 + +- `project`: 現在のプロジェクト情報。 +- `directory`: 現在の作業ディレクトリ。 +- `worktree`: git ワークツリーのパス。 +- `client`: AI と対話するための OpenCode SDK クライアント。 +- `$`: Bun の [コマンドを実行するためのシェル API](https://bun.com/docs/runtime/shell)。 + +--- + +### TypeScript のサポート + +TypeScript プラグインの場合、プラグインパッケージから型をインポートできます。 + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### イベント + +以下の「例」セクションに示すように、プラグインはイベントをサブスクライブできます。利用可能なさまざまなイベントのリストは次のとおりです。 + +#### コマンドイベント + +- `command.executed` + +#### ファイルイベント + +- `file.edited` +- `file.watcher.updated` + +#### インストールイベント + +- `installation.updated` + +#### LSPイベント + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### メッセージイベント + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### 許可イベント + +- `permission.asked` +- `permission.replied` + +#### サーバーイベント + +- `server.connected` + +#### セッションイベント + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### ToDo イベント + +- `todo.updated` + +#### シェルイベント + +- `shell.env` + +#### ツールイベント + +- `tool.execute.after` +- `tool.execute.before` + +#### TUIイベント + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## 例 + +ここでは、OpenCode を拡張するために使用できるプラグインの例をいくつか示します。 + +--- + +### 通知を送信する + +特定のイベントが発生したときに通知を送信します。 + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +macOS 上で AppleScript を実行するために `osascript` を使用しています。ここでは通知を送信するために使用しています。 + +:::note +OpenCode デスクトップアプリを使用している場合は、応答の準備ができたとき、またはセッションエラーが発生したときにシステム通知を自動的に送信できます。 +::: + +--- + +### .env の保護 + +OpenCode が `.env` ファイルを読み取らないようにします。 + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### 環境変数を挿入する + +すべてのシェル実行 (AI ツールとユーザーターミナル) に環境変数を挿入します。 + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### カスタムツール + +プラグインは OpenCode にカスタムツールを追加することもできます。 + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +`tool` ヘルパーは、OpenCode が呼び出すことができるカスタムツールを作成します。 Zod スキーマ関数を受け取り、次のようなツール定義を返します。 + +- `description`: ツールの機能 +- `args`: ツールの引数の Zod スキーマ +- `execute`: ツールが呼び出されたときに実行される関数 + +カスタムツールは、組み込みツールと並行して OpenCode で使用できます。 + +--- + +### ロギング + +構造化ログには `client.app.log()` の代わりに `console.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` 配列は無視されます。 diff --git a/packages/web/src/content/docs/ja/providers.mdx b/packages/web/src/content/docs/ja/providers.mdx new file mode 100644 index 00000000000..2602f8ef22a --- /dev/null +++ b/packages/web/src/content/docs/ja/providers.mdx @@ -0,0 +1,1895 @@ +--- +title: プロバイダー +description: OpenCode で LLM プロバイダーを使用する。 +--- + +import config from "../../../../config.mjs" +export const console = config.console + +OpenCode は [AI SDK](https://ai-sdk.dev/) および [Models.dev](https://models.dev) を使用して **75 以上の LLM プロバイダー** をサポートし、ローカルモデルの実行をサポートします。 + +プロバイダーを追加するには、次のことを行う必要があります。 + +1. `/connect` コマンドを使用して、プロバイダーの API キーを追加します。 +2. OpenCode 設定でプロバイダーを構成します。 + +--- + +### 認証情報 + +`/connect` コマンドを使用してプロバイダーの API キーを追加すると、それらは保存されます +`~/.local/share/opencode/auth.json`で。 + +--- + +### 設定 + +OpenCode の `provider` セクションを通じてプロバイダーをカスタマイズできます。 +config. + +--- + +#### Base URL + +`baseURL` オプションを設定することで、任意のプロバイダーのベース URL をカスタマイズできます。これは、プロキシサービスまたはカスタムエンドポイントを使用する場合に便利です。 + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen は、OpenCode チームが提供するモデルのリストです。 +OpenCode で適切に動作することがテストおよび検証されています。 [詳細はこちら](/docs/zen)。 + +:::tip +初めての方は、OpenCode Zen から始めることをお勧めします。 +::: + +1. TUI で `/connect` コマンドを実行し、opencode を選択して、[opencode.ai/auth](https://opencode.ai/auth) で認証します。 + + ```txt + /connect + ``` + +2. サインインし、お支払いの詳細を追加し、API キーをコピーします。 + +3. API キーを貼り付けます。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. TUI で `/models` を実行すると、推奨されるモデルのリストが表示されます。 + + ```txt + /models + ``` + +これは OpenCode の他のプロバイダーと同様に機能し、使用は完全にオプションです。 + +--- + +## ディレクトリ + +いくつかのプロバイダーを詳しく見てみましょう。プロバイダーを追加したい場合は、 +リストにある場合は、お気軽に PR を開いてください。 + +:::note +ここにプロバイダーが表示されない場合は、 PRを送信してください。 +::: + +--- + +### 302.AI + +1. [302.AI console](https://302.ai/) に移動し、アカウントを作成し、API キーを生成します。 + +2. `/connect` コマンドを実行し、**302.AI** を検索します。 + + ```txt + /connect + ``` + +3. 302.AI API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行してモデルを選択します。 + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +OpenCode で Amazon Bedrock を使用するには: + +1. Amazon Bedrock コンソールの **モデルカタログ** に移動してリクエストします。 + 必要なモデルにアクセスします。 + +:::tip +Amazon Bedrock で必要なモデルにアクセスできる必要があります。 +::: + +2. **次のいずれかの方法を使用して認証を構成します**。 + + #### 環境変数 (クイックスタート) + +opencode の実行中に次の環境変数のいずれかを設定します。 + +```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode +``` + +または、それらを bash プロファイルに追加します。 + +```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" + } + } + } +} +``` + +**利用可能なオプション:** + +- `region` - AWS リージョン (例: `us-east-1`、`eu-west-1`) +- `profile` - `~/.aws/credentials` からの AWS 名前付きプロファイル +- `endpoint` - VPC エンドポイントのカスタムエンドポイント URL (汎用 `baseURL` オプションのエイリアス) + +:::tip +設定ファイルのオプションは環境変数より優先されます。 +::: + +#### 上級: 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" + } + } + } +} +``` + +:::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 によって自動的に挿入されます。 + +#### 認証の優先順位 + +Amazon Bedrock は次の認証優先度を使用します。 + +1. **ベアラー トークン** - `AWS_BEARER_TOKEN_BEDROCK` 環境変数または `/connect` コマンドからのトークン +2. **AWS 認証情報チェーン** - プロファイル、アクセスキー、共有認証情報、IAM ロール、Web ID トークン (EKS IRSA)、インスタンスメタデータ + +:::note +ベアラー トークンが (`/connect` または `AWS_BEARER_TOKEN_BEDROCK` 経由で) 設定されると、設定されたプロファイルを含むすべての AWS 認証情報方法よりも優先されます。 +::: + +3. `/models` コマンドを実行して、必要なモデルを選択します。 + + ```txt + /models + ``` + +:::note +カスタム推論プロファイルの場合、キーでモデルとプロバイダー名を使用し、`id` プロパティを arn に設定します。これにより、正しいキャッシュが保証されます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. サインアップしたら、`/connect` コマンドを実行し、[Anthropic] を選択します。 + + ```txt + /connect + ``` + +2. ここで **Claude Pro/Max** オプションを選択すると、ブラウザが開きます + そして認証を求められます。 + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. これで、`/models` コマンドを使用すると、すべての Anthropic モデルが利用できるようになります。 + + ```txt + /models + ``` + +:::info +OpenCode での Claude Pro/Max サブスクリプションの使用は、[Anthropic](https://anthropic.com) によって正式に許可されていませんが、一般的に機能します。 +::: + +##### APIキーの使用 + +Pro/Max サブスクリプションをお持ちでない場合は、[**API キーの作成**] を選択することもできます。また、ブラウザが開き、Anthropic にログインするよう求められ、ターミナルに貼り付けるコードが表示されます。 + +または、すでに API キーをお持ちの場合は、[**API キーを手動で入力**] を選択してターミナルに貼り付けることができます。 + +--- + +### Azure OpenAI + +:::note +「申し訳ありませんが、そのリクエストには対応できません」エラーが発生した場合は、Azure リソースのコンテンツフィルターを **DefaultV2** から **Default** に変更してみてください。 +::: + +1. [Azure portal](https://portal.azure.com/) に移動し、**Azure OpenAI** リソースを作成します。必要なものは次のとおりです。 + - **リソース名**: これは API エンドポイント (`https://RESOURCE_NAME.openai.azure.com/`) の一部になります。 + - **API キー**: リソースの `KEY 1` または `KEY 2` のいずれか + +2. [Azure AI Foundry](https://ai.azure.com/) に移動し、モデルをデプロイします。 + +:::note +OpenCode が正しく動作するには、デプロイメント名がモデル名と一致する必要があります。 +::: + +3. `/connect` コマンドを実行し、**Azure** を検索します。 + + ```txt + /connect + ``` + +4. API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. リソース名を環境変数として設定します。 + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + +または、bash プロファイルに追加します。 + +```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX +``` + +6. `/models` コマンドを実行して、デプロイされたモデルを選択します。 + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. [Azure portal](https://portal.azure.com/) に移動し、**Azure OpenAI** リソースを作成します。必要なものは次のとおりです。 + - **リソース名**: これは API エンドポイント (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) の一部になります。 + - **API キー**: リソースの `KEY 1` または `KEY 2` のいずれか + +2. [Azure AI Foundry](https://ai.azure.com/) に移動し、モデルをデプロイします。 + +:::note +OpenCode が正しく動作するには、デプロイメント名がモデル名と一致する必要があります。 +::: + +3. `/connect` コマンドを実行し、**Azure Cognitive Services** を検索します。 + + ```txt + /connect + ``` + +4. API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. リソース名を環境変数として設定します。 + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + +または、bash プロファイルに追加します。 + +```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX +``` + +6. `/models` コマンドを実行して、デプロイされたモデルを選択します。 + + ```txt + /models + ``` + +--- + +### Baseten + +1. [Baseten](https://app.baseten.co/) に移動し、アカウントを作成し、API キーを生成します。 + +2. `/connect` コマンドを実行し、**Baseten** を検索します。 + + ```txt + /connect + ``` + +3. Baseten API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行してモデルを選択します。 + + ```txt + /models + ``` + +--- + +### Cerebras + +1. [Cerebras console](https://inference.cerebras.ai/) に移動し、アカウントを作成し、API キーを生成します。 + +2. `/connect` コマンドを実行し、**Cerebras** を検索します。 + + ```txt + /connect + ``` + +3. Cerebras API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行して、_Qwen 3 Coder 480B_ のようなモデルを選択します。 + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +Cloudflare AI Gatewayを使用すると、統合エンドポイントを通じてOpenAI、Anthropic、Workers AIなどのモデルにアクセスできます。 [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) を使用すると、プロバイダーごとに個別の API キーは必要ありません。 + +1. [Cloudflare ダッシュボード ](https://dash.cloudflare.com/) に移動し、**AI** > **AI ゲートウェイ** に移動し、新しいゲートウェイを作成します。 + +2. アカウント ID とゲートウェイ ID を環境変数として設定します。 + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. `/connect` コマンドを実行し、**Cloudflare AI Gateway** を検索します。 + + ```txt + /connect + ``` + +4. Cloudflare API トークンを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +または環境変数として設定します。 + +```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token +``` + +5. `/models` コマンドを実行してモデルを選択します。 + + ```txt + /models + ``` + +OpenCode 設定を通じてモデルを追加することもできます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } +} +``` + +--- + +### Cortecs + +1. [Cortecs console](https://cortecs.ai/) に移動し、アカウントを作成し、API キーを生成します。 + +2. `/connect` コマンドを実行し、**Cortecs** を検索します。 + + ```txt + /connect + ``` + +3. Cortecs API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行して、_Kimi K2 Instruct_ のようなモデルを選択します。 + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. [DeepSeek コンソール ](https://platform.deepseek.com/) に移動し、アカウントを作成し、**新しい API キーの作成** をクリックします。 + +2. `/connect` コマンドを実行し、**DeepSeek** を検索します。 + + ```txt + /connect + ``` + +3. DeepSeek API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行して、_DeepSeek Reasoner_ のような DeepSeek モデルを選択します。 + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. [Deep Infra ダッシュボード](https://deepinfra.com/dash) に移動し、アカウントを作成し、API キーを生成します。 + +2. `/connect` コマンドを実行し、**Deep Infra** を検索します。 + + ```txt + /connect + ``` + +3. Deep Infra API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行してモデルを選択します。 + + ```txt + /models + ``` + +--- + +### Firmware + +1. [ファームウェアダッシュボード](https://app.firmware.ai/signup) に移動し、アカウントを作成し、API キーを生成します。 + +2. `/connect` コマンドを実行し、**ファームウェア**を検索します。 + + ```txt + /connect + ``` + +3. ファームウェア API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行してモデルを選択します。 + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. [Fireworks AI コンソール ](https://app.fireworks.ai/) に移動し、アカウントを作成し、**API キーの作成** をクリックします。 + +2. `/connect` コマンドを実行し、**Fireworks AI** を検索します。 + + ```txt + /connect + ``` + +3. Fireworks AI API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行して、_Kimi K2 Instruct_ のようなモデルを選択します。 + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo は、GitLab の Anthropic プロキシを介したネイティブツール呼び出し機能を備えた AI を活用したエージェントチャットを提供します。 + +1. `/connect` コマンドを実行し、GitLab を選択します。 + + ```txt + /connect + ``` + +2. 認証方法を選択してください: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ + ``` + + #### OAuthの使用(推奨) + +**OAuth** を選択すると、認証のためにブラウザが開きます。 + +#### パーソナルアクセストークンの使用 + +1. [GitLab ユーザー設定 > アクセス Tokens](https://gitlab.com/-/user_settings/personal_access_tokens) に移動します。 +2. **新しいトークンを追加** をクリックします +3. 名前: `OpenCode`、スコープ: `api` +4. トークンをコピーします(`glpat-`で始まる) +5. ターミナルに入力してください + +6. `/models` コマンドを実行して、利用可能なモデルを確認します。 + + ```txt + /models + ``` + +3 つの Claude ベースのモデルが利用可能です。 + +- **duo-chat-haiku-4-5** (デフォルト) - 素早いタスクに対する素早い応答 +- **duo-chat-sonnet-4-5** - ほとんどのワークフローでバランスの取れたパフォーマンス +- **duo-chat-opus-4-5** - 複雑な分析に最も適した能力 + +:::note +必要がない場合は、「GITLAB_TOKEN」環境変数を指定することもできます。 +トークンを OpenCode 認証ストレージに保存します。 +::: + +##### 自己ホスト型 GitLab + +:::note[コンプライアンスメモ] +OpenCode は、セッションタイトルの生成などの一部の AI タスクに小規模なモデルを使用します。 +デフォルトでは、Zen によってホストされる gpt-5-nano を使用するように構成されています。 OpenCode をロックするには +自分の GitLab でホストされているインスタンスのみを使用するには、次の行を +`opencode.json` ファイル。セッション共有を無効にすることもお勧めします。 + +```json +{ + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +セルフホスト型 GitLab インスタンスの場合: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +インスタンスがカスタム AI ゲートウェイを実行している場合: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +または、bash プロファイルに追加します。 + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +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` + ::: + +##### セルフホスト型インスタンスの OAuth + +自己ホスト型インスタンスで Oauth を機能させるには、以下を作成する必要があります。 +新しいアプリケーション ([設定] → [アプリケーション]) で、 +コールバック URL `http://127.0.0.1:8080/callback` と次のスコープ: + +- api (あなたの代わりに API にアクセスします) +- read_user (個人情報の読み取り) +- read_repository (リポジトリへの読み取り専用アクセスを許可します) + +次に、アプリケーション ID を環境変数として公開します。 + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +詳細については、[opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth) ホームページ。 + +##### 設定 + +`opencode.json` を通じてカスタマイズします。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### GitLab API ツール (オプションですが強く推奨) + +GitLab ツール (マージリクエスト、問題、パイプライン、CI/CD など) にアクセスするには: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +このプラグインは、MR レビュー、問題追跡、パイプライン監視などを含む、包括的な GitLab リポジトリ管理機能を提供します。 + +--- + +### GitHub Copilot + +GitHub Copilot サブスクリプションを OpenCode で使用するには: + +:::note +一部のモデルでは [Pro+] が必要になる場合があります。 +subscription](https://github.com/features/copilot/plans) を使用します。 + +一部のモデルは、[GitHub Copilot settings](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use) で構成する必要があります。 +::: + +1. `/connect` コマンドを実行し、GitHub Copilot を検索します。 + + ```txt + /connect + ``` + +2. [github.com/login/device](https://github.com/login/device) に移動し、コードを入力します。 + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + │ + └ Waiting for authorization... + ``` + +3. 次に、`/models` コマンドを実行して、必要なモデルを選択します。 + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +OpenCode で Google Vertex AI を使用するには: + +1. Google Cloud Console の **Model Garden** に移動し、 + お住まいの地域で利用可能なモデル。 + +:::note +Vertex AI API が有効になっている Google Cloud プロジェクトが必要です。 +::: + +2. 必要な環境変数を設定します。 + - `GOOGLE_CLOUD_PROJECT`: Google Cloud プロジェクト ID + - `VERTEX_LOCATION` (オプション): Vertex AI の領域 (デフォルトは `global`) + - 認証 (1 つ選択): + - `GOOGLE_APPLICATION_CREDENTIALS`: サービスアカウントの JSON キーファイルへのパス + - gcloud CLI を使用して認証する: `gcloud auth application-default login` + +opencode の実行中に設定します。 + +```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode +``` + +または、それらを bash プロファイルに追加します。 + +```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` 領域は、追加コストなしで可用性を向上させ、エラーを削減します。データ常駐要件には、リージョンエンドポイント (`us-central1` など) を使用します。 [詳細はこちら](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. `/models` コマンドを実行して、必要なモデルを選択します。 + + ```txt + /models + ``` + +--- + +### Groq + +1. [Groq console](https://console.groq.com/) に移動し、[**API キーの作成**] をクリックして、キーをコピーします。 + +2. `/connect` コマンドを実行し、Groq を検索します。 + + ```txt + /connect + ``` + +3. プロバイダーの API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行して、必要なものを選択します。 + + ```txt + /models + ``` + +--- + +### Hugging Face + +[Hugging Face Inference Provider](https://huggingface.co/docs/inference-providers) は、17 を超えるプロバイダーがサポートするオープンモデルへのアクセスを提供します。 + +1. [Hugging Face settings](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained) に移動して、推論プロバイダーを呼び出す権限を持つトークンを作成します。 + +2. `/connect` コマンドを実行し、**Hugging Face** を検索します。 + + ```txt + /connect + ``` + +3. Hugging Face トークンを入力してください。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行して、_Kimi-K2-Instruct_ や _GLM-4.6_ などのモデルを選択します。 + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) は、AI アプリケーションのロギング、監視、分析を提供する LLM 可観測性プラットフォームです。 Helicone AI ゲートウェイは、モデルに基づいてリクエストを適切なプロバイダーに自動的にルーティングします。 + +1. [Helicone](https://helicone.ai) に移動し、アカウントを作成し、ダッシュボードから API キーを生成します。 + +2. `/connect` コマンドを実行し、**Helicone** を検索します。 + + ```txt + /connect + ``` + +3. Helicone API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行してモデルを選択します。 + + ```txt + /models + ``` + +その他のプロバイダーや、キャッシュやレート制限などの高度な機能については、[Helicone ドキュメント](https://docs.helicone.ai). + +#### オプションの設定 + +OpenCode を通じて自動的に構成されていない Helicone の機能またはモデルを見つけた場合は、いつでも自分で構成できます。 + +これは [Helicone のモデルディレクトリ](https://helicone.ai/models) です。追加するモデルの ID を取得するためにこれが必要になります。 + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250929": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### カスタムヘッダー + +Helicone は、キャッシュ、ユーザー追跡、セッション管理などの機能のカスタムヘッダーをサポートしています。 `options.headers` を使用してプロバイダー設定に追加します。 + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### セッション追跡 + +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 +``` + +それを設定に追加します。 + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +プラグインは、リクエストに `Helicone-Session-Id` ヘッダーと `Helicone-Session-Name` ヘッダーを挿入します。 Helicone のセッションページでは、OpenCode の各会話が個別のセッションとしてリストされています。 + +##### 一般的なヘリコーンヘッダー + +| ヘッダー | 説明 | +| -------------------------- | ---------------------------------------------------------------------- | +| `Helicone-Cache-Enabled` | 応答キャッシュを有効にする (`true`/`false`) | +| `Helicone-User-Id` | ユーザーごとにメトリクスを追跡する | +| `Helicone-Property-[Name]` | カスタムプロパティを追加します (例: `Helicone-Property-Environment`)。 | +| `Helicone-Prompt-Id` | リクエストをプロンプトバージョンに関連付ける | + +利用可能なすべてのヘッダーについては、[Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory) を参照してください。 + +--- + +### llama.cpp + +[llama.cpp の s](https://github.com/ggml-org/llama.cpp) llama-server ユーティリティ] を通じて、ローカルモデルを使用するように opencode を構成できます。 + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +この例では: + +- `llama.cpp` はカスタムプロバイダー ID です。これには任意の文字列を指定できます。 +- `npm` は、このプロバイダーに使用するパッケージを指定します。ここで、`@ai-sdk/openai-compatible` は OpenAI 互換 API に使用されます。 +- `name` は、UI でのプロバイダーの表示名です。 +- `options.baseURL` はローカルサーバーのエンドポイントです。 +- `models` は、モデル ID とその設定のマップです。機種選択リストに機種名が表示されます。 + +--- + +### IO.NET + +IO.NET は、さまざまなユースケースに最適化された 17 のモデルを提供します。 + +1. [IO.NET console](https://ai.io.net/) に移動し、アカウントを作成し、API キーを生成します。 + +2. `/connect` コマンドを実行し、**IO.NET** を検索します。 + + ```txt + /connect + ``` + +3. IO.NET API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行してモデルを選択します。 + + ```txt + /models + ``` + +--- + +### LM Studio + +LM Studio を通じてローカルモデルを使用するように opencode を構成できます。 + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +この例では: + +- `lmstudio` はカスタムプロバイダー ID です。これには任意の文字列を指定できます。 +- `npm` は、このプロバイダーに使用するパッケージを指定します。ここで、`@ai-sdk/openai-compatible` は OpenAI 互換 API に使用されます。 +- `name` は、UI でのプロバイダーの表示名です。 +- `options.baseURL` はローカルサーバーのエンドポイントです。 +- `models` は、モデル ID とその設定のマップです。機種選択リストに機種名が表示されます。 + +--- + +### Moonshot AI + +Moonshot AI の Kim K2 を使用するには: + +1. [Moonshot AI console](https://platform.moonshot.ai/console) に移動し、アカウントを作成し、[**API キーの作成**] をクリックします。 + +2. `/connect` コマンドを実行し、**Moonshot AI** を検索します。 + + ```txt + /connect + ``` + +3. Moonshot API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行して、_Kimi K2_ を選択します。 + + ```txt + /models + ``` + +--- + +### MiniMax + +1. [MiniMax API Console](https://platform.minimax.io/login) に移動し、アカウントを作成し、API キーを生成します。 + +2. `/connect` コマンドを実行し、**MiniMax** を検索します。 + + ```txt + /connect + ``` + +3. MiniMax API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行して、_M2.1_ のようなモデルを選択します。 + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. [Nebius Token Factory console](https://tokenfactory.nebius.com/) に移動し、アカウントを作成し、[**キーの追加**] をクリックします。 + +2. `/connect` コマンドを実行し、**Nebius Token Factory** を検索します。 + + ```txt + /connect + ``` + +3. Nebius Token Factory API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行して、_Kimi K2 Instruct_ のようなモデルを選択します。 + + ```txt + /models + ``` + +--- + +### Ollama + +Ollama を通じてローカルモデルを使用するように opencode を構成できます。 + +:::tip +Ollama は OpenCode 用に自動的に構成できます。詳細については、[Ollama 統合 docs](https://docs.ollama.com/integrations/opencode)」を参照してください。 +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +この例では: + +- `ollama` はカスタムプロバイダー ID です。これには任意の文字列を指定できます。 +- `npm` は、このプロバイダーに使用するパッケージを指定します。ここで、`@ai-sdk/openai-compatible` は OpenAI 互換 API に使用されます。 +- `name` は、UI でのプロバイダーの表示名です。 +- `options.baseURL` はローカルサーバーのエンドポイントです。 +- `models` は、モデル ID とその設定のマップです。機種選択リストに機種名が表示されます。 + +:::tip +ツール呼び出しが機能しない場合は、Ollama の `num_ctx` を増やしてみてください。 16k〜32kあたりから始めてください。 +::: + +--- + +### Ollama Cloud + +OpenCode で Ollama Cloud を使用するには: + +1. [https://ollama.com/](https://ollama.com/) にアクセスしてサインインするか、アカウントを作成します。 + +2. [**設定**] > [キー**] に移動し、[**API キーの追加**] をクリックして新しい API キーを生成します。 + +3. OpenCode で使用するために API キーをコピーします。 + +4. `/connect` コマンドを実行し、**Ollama Cloud** を検索します。 + + ```txt + /connect + ``` + +5. Ollama Cloud API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **重要**: OpenCode でクラウドモデルを使用する前に、モデル情報をローカルに取得する必要があります。 + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. `/models` コマンドを実行して、Ollama Cloud モデルを選択します。 + + ```txt + /models + ``` + +--- + +### OpenAI + +[ChatGPT Plus または Pro](https://chatgpt.com/pricing) にサインアップすることをお勧めします。 + +1. サインアップしたら、`/connect` コマンドを実行し、OpenAI を選択します。 + + ```txt + /connect + ``` + +2. ここで **ChatGPT Plus/Pro** オプションを選択すると、ブラウザが開きます。 + そして認証を求められます。 + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. これで、`/models` コマンドを使用すると、すべての OpenAI モデルが利用できるようになります。 + + ```txt + /models + ``` + +##### APIキーの使用 + +すでに API キーをお持ちの場合は、**API キーを手動で入力** を選択し、ターミナルに貼り付けることができます。 + +--- + +### OpenCode Zen + +OpenCode Zen は、OpenCode チームによって提供される、テストおよび検証されたモデルのリストです。 [詳細はこちら](/docs/zen)。 + +1. **OpenCode Zen** にサインインし、**API キーの作成** をクリックします。 + +2. `/connect` コマンドを実行し、**OpenCode Zen** を検索します。 + + ```txt + /connect + ``` + +3. OpenCode API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行して、_Qwen 3 Coder 480B_ のようなモデルを選択します。 + + ```txt + /models + ``` + +--- + +### OpenRouter + +1. [OpenRouter ダッシュボード](https://openrouter.ai/settings/keys) に移動し、[**API キーの作成**] をクリックして、キーをコピーします。 + +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 コアは、統合プラットフォームを通じて、OpenAI、Anthropic、Google、Amazon、Meta、Mistral、AI21 の 40 以上のモデルへのアクセスを提供します。 + +1. [SAP BTP Cockpit](https://account.hana.ondemand.com/) に移動し、SAP AI コアサービスインスタンスに移動して、サービスキーを作成します。 + +:::tip +サービスキーは、`clientid`、`clientsecret`、`url`、および `serviceurls.AI_API_URL` を含む JSON オブジェクトです。 AI コアインスタンスは、BTP コックピットの **サービス** > **インスタンスとサブスクリプション** で見つかります。 +::: + +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 プロファイルに追加します。 + +```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' +``` + +4. 必要に応じて、デプロイメント ID とリソースグループを設定します。 + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + +:::note +これらの設定はオプションであり、SAP AI コアのセットアップに従って構成する必要があります。 +::: + +5. `/models` コマンドを実行して、40 以上の利用可能なモデルから選択します。 + + ```txt + /models + ``` + +--- + +### OVHcloud AI Endpoints + +1. [OVHcloud パネル](https://ovh.com/manager) に移動します。 `Public Cloud` セクション、`AI & Machine Learning` > `AI Endpoints` に移動し、`API Keys` タブで **新しい API キーの作成** をクリックします。 + +2. `/connect` コマンドを実行し、**OVHcloud AI エンドポイント**を検索します。 + + ```txt + /connect + ``` + +3. OVHcloud AI エンドポイント API キーを入力します。 + + ```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) に移動し、アカウントを作成し、[**キーの追加**] をクリックします。 + +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 ダッシュボード ](https://vercel.com/) に移動し、**AI ゲートウェイ** タブに移動し、**API キー** をクリックして新しい 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 コンソール ](https://z.ai/manage-apikey/apikey-list) に移動し、アカウントを作成し、**新しい API キーの作成** をクリックします。 + +2. `/connect` コマンドを実行し、**Z.AI** を検索します。 + + ```txt + /connect + ``` + +**GLM コーディングプラン**に加入している場合は、**Z.AI コーディングプラン**を選択します。 + +3. Z.AI API キーを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行して、_GLM-4.7_ のようなモデルを選択します。 + + ```txt + /models + ``` + +--- + +### ZenMux + +1. [ZenMux ダッシュボード](https://zenmux.ai/settings/keys) に移動し、[**API キーの作成**] をクリックして、キーをコピーします。 + +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": {} + } + } + } +} +``` + +--- + +## カスタムプロバイダー + +`/connect` コマンドにリストされていない **OpenAI 互換**プロバイダーを追加するには: + +:::tip +OpenAI と互換性のある任意のプロバイダーを OpenCode で使用できます。最新の AI プロバイダーのほとんどは、OpenAI 互換の API を提供しています。 +::: + +1. `/connect` コマンドを実行し、**その他**まで下にスクロールします。 + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. プロバイダーの一意の ID を入力します。 + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + +:::note +覚えやすい 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 パッケージ、OpenAI 互換プロバイダーの場合は `@ai-sdk/openai-compatible` +- **name**: UI での表示名。 +- **models**: 利用可能なモデル。 +- **options.baseURL**: API エンドポイント URL。 +- **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 設定を確認し、次のことを行います。 + - `/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/ja/rules.mdx b/packages/web/src/content/docs/ja/rules.mdx new file mode 100644 index 00000000000..0333850c085 --- /dev/null +++ b/packages/web/src/content/docs/ja/rules.mdx @@ -0,0 +1,179 @@ +--- +title: ルール +description: OpenCode のカスタム命令を設定します。 +--- + +`AGENTS.md` ファイルを作成することで、OpenCode にカスタム命令を提供できます。これは Cursor のルールと似ています。これには、特定のプロジェクトに合わせて LLM の動作をカスタマイズするために LLM のコンテキストに含まれる命令が含まれています。 + +--- + +## 初期化 + +新しい `AGENTS.md` ファイルを作成するには、OpenCode で `/init` コマンドを実行します。 + +:::tip +プロジェクトの `AGENTS.md` ファイルを Git にコミットする必要があります。 +::: +`AGENTS.md` ファイルが生成されます。これは、OpenCode がプロジェクトをより適切にナビゲートするのに役立ちます。 + +既存の `AGENTS.md` ファイルがある場合、これはそれに追加しようとします。 + +--- + +## 例 + +このファイルを手動で作成することもできます。以下は、`AGENTS.md` ファイルに含めることができるいくつかの例です。 + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +ここにプロジェクト固有の手順を追加します。これはチーム全体で共有されます。 + +--- + +## 種類 + +OpenCode は、複数の場所からの `AGENTS.md` ファイルの読み取りもサポートしています。そして、これはさまざまな目的に役立ちます。 + +### プロジェクト + +プロジェクト固有のルールのために、プロジェクトルートに `AGENTS.md` を配置します。これらは、このディレクトリまたはそのサブディレクトリで作業している場合にのみ適用されます。 + +### グローバル + +`~/.config/opencode/AGENTS.md` ファイルにグローバルルールを含めることもできます。これは、すべての OpenCode セッションに適用されます。 + +これは Git にコミットされておらず、チームと共有されていないため、LLM が従うべき個人ルールを指定するためにこれを使用することをお勧めします。 + +### Claude Code 互換性 + +Claude Code から移行するユーザーのために、OpenCode はフォールバックとして Claude Code のファイル規則をサポートしています。 + +- **プロジェクトルール**: プロジェクトディレクトリ内の `CLAUDE.md` (`AGENTS.md` が存在しない場合に使用されます) +- **グローバルルール**: `~/.claude/CLAUDE.md` (`~/.config/opencode/AGENTS.md` が存在しない場合に使用) +- **スキル**: `~/.claude/skills/` — 詳細については、[エージェントスキル](/docs/skills/) を参照してください。 + +Claude Code の互換性を無効にするには、次の環境変数のいずれかを設定します。 + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## 優先順位 + +OpenCode が開始されると、次の順序でルールファイルが検索されます。 + +1. **ローカルファイル** (現在のディレクトリから上に移動) (`AGENTS.md`、`CLAUDE.md`) +2. **グローバルファイル** (`~/.config/opencode/AGENTS.md`) +3. **Claude Code ファイル** (`~/.claude/CLAUDE.md` にあります) (無効になっていない限り) + +最初に一致したファイルが各カテゴリで優先されます。たとえば、`AGENTS.md` と `CLAUDE.md` の両方がある場合、`AGENTS.md` のみが使用されます。同様に、`~/.config/opencode/AGENTS.md` は `~/.claude/CLAUDE.md` よりも優先されます。 + +--- + +## カスタム指示 + +`opencode.json` またはグローバル `~/.config/opencode/opencode.json` でカスタム命令ファイルを指定できます。これにより、あなたとあなたのチームは、既存のルールを AGENTS.md に複製するのではなく、再利用することができます。 + +例: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +リモート URL を使用して Web から命令をロードすることもできます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +リモート命令は 5 秒のタイムアウトでフェッチされます。 + +すべての命令ファイルは `AGENTS.md` ファイルと結合されます。 + +--- + +## 外部ファイル参照 + +OpenCode は `AGENTS.md` のファイル参照を自動的に解析しませんが、次の 2 つの方法で同様の機能を実現できます。 + +### `opencode.json` の使用 + +推奨されるアプローチは、`instructions` の `opencode.json` フィールドを使用することです。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### AGENTS.md の手動指示 + +`AGENTS.md` で明示的な命令を指定することで、OpenCode に外部ファイルを読み取るように教えることができます。実際の例を次に示します。 + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +このアプローチにより、次のことが可能になります。 + +- モジュール式の再利用可能なルールファイルを作成する +- シンボリックリンクまたは git サブモジュールを介してプロジェクト間でルールを共有する +- 詳細なガイドラインを参照しながら、AGENTS.md を簡潔に保ちます +- OpenCode が特定のタスクに必要な場合にのみファイルをロードするようにする + +:::tip +モノリポジトリまたは共有標準を使用するプロジェクトの場合、グロブパターン (`opencode.json` など) で `packages/*/AGENTS.md` を使用する方が、手動で指示するよりも保守しやすくなります。 +::: diff --git a/packages/web/src/content/docs/ja/sdk.mdx b/packages/web/src/content/docs/ja/sdk.mdx new file mode 100644 index 00000000000..ee5fd3645ac --- /dev/null +++ b/packages/web/src/content/docs/ja/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: OpenCode サーバー用の型安全な JS クライアント。 +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +OpenCode JS/TS SDK は、サーバーと対話するための型安全なクライアントを提供します。 +これを使用して、統合を構築し、OpenCode をプログラムで制御します。 + +[サーバーの仕組みについての詳細](/docs/server) をご覧ください。たとえば、コミュニティによって構築された [projects](/docs/ecosystem#projects) をチェックしてください。 + +--- + +## インストール + +npm から SDK をインストールします。 + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## クライアントの作成 + +OpenCode のインスタンスを作成します。 + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +これにより、サーバーとクライアントの両方が起動します + +#### オプション + +| オプション | タイプ | 説明 | デフォルト | +| ---------- | ------------- | ----------------------------------- | ----------- | +| `hostname` | `string` | サーバーのホスト名 | `127.0.0.1` | +| `port` | `number` | サーバーポート | `4096` | +| `signal` | `AbortSignal` | キャンセルのためのアボート信号 | `undefined` | +| `timeout` | `number` | サーバー起動のタイムアウト (ミリ秒) | `5000` | +| `config` | `Config` | 設定オブジェクト | `{}` | + +--- + +## 設定 + +設定オブジェクトを渡して動作をカスタマイズできます。インスタンスは引き続き `opencode.json` を取得しますが、設定をインラインでオーバーライドまたは追加することができます。 + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## クライアントのみ + +すでに実行中の OpenCode のインスタンスがある場合は、それに接続するためのクライアントインスタンスを作成できます。 + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### オプション + +| オプション | タイプ | 説明 | デフォルト | +| --------------- | ---------- | ---------------------------------------- | ----------------------- | +| `baseUrl` | `string` | サーバーの URL | `http://localhost:4096` | +| `fetch` | `function` | カスタムフェッチの実装 | `globalThis.fetch` | +| `parseAs` | `string` | 応答解析方法 | `auto` | +| `responseStyle` | `string` | 戻り値のスタイル: `data` または `fields` | `fields` | +| `throwOnError` | `boolean` | 返す代わりにエラーをスローする | `false` | + +--- + +## 型定義 + +SDK には、すべての API タイプの TypeScript 定義が含まれています。それらを直接インポートします。 + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +すべてのタイプはサーバーの OpenAPI 仕様から生成され、タイプファイル で使用できます。 + +--- + +## エラー + +SDK は、キャッチして処理できるエラーをスローできます。 + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## API + +SDK は、型安全なクライアントを通じてすべてのサーバー API を公開します。 + +--- + +### Global + +| メソッド | 説明 | 戻り値 | +| ----------------- | -------------------------------------- | ------------------------------------ | +| `global.health()` | サーバーの健全性とバージョンを確認する | `{ healthy: true, version: string }` | + +--- + +#### 例 + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### App + +| メソッド | 説明 | 戻り値 | +| -------------- | ------------------------------------------ | ------------------------------------------- | +| `app.log()` | ログエントリを書き込む | `boolean` | +| `app.agents()` | 利用可能なすべてのエージェントをリストする | Agent[] | + +--- + +#### 例 + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### Project + +| メソッド | 説明 | 戻り値 | +| ------------------- | -------------------------------- | --------------------------------------------- | +| `project.list()` | すべてのプロジェクトをリストする | Project[] | +| `project.current()` | 現在のプロジェクトを取得 | Project | + +--- + +#### 例 + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### Path + +| メソッド | 説明 | 戻り値 | +| ------------ | ---------------- | ---------------------------------------- | +| `path.get()` | 現在のパスを取得 | Path | + +--- + +#### 例 + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### Config + +| メソッド | 説明 | 戻り値 | +| -------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | 設定情報を取得する | Config | +| `config.providers()` | プロバイダーとデフォルトのモデルをリストする | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### 例 + +```javascript +const config = await client.config.get() + +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` | + +--- + +#### 例 + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### Files + +| メソッド | 説明 | 戻り値 | +| ------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------- | +| `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[] | + +`find.files` は、いくつかのオプションのクエリフィールドをサポートしています。 + +- `type`: `"file"` または `"directory"` +- `directory`: 検索用のプロジェクトルートをオーバーライドします。 +- `limit`: 最大結果 (1 ~ 200) + +--- + +#### 例 + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| メソッド | 説明 | 戻り値 | +| ------------------------------ | -------------------------------- | --------- | +| `tui.appendPrompt({ body })` | プロンプトにテキストを追加します | `boolean` | +| `tui.openHelp()` | ヘルプダイアログを開く | `boolean` | +| `tui.openSessions()` | セッションセレクターを開く | `boolean` | +| `tui.openThemes()` | テーマセレクターを開く | `boolean` | +| `tui.openModels()` | モデルセレクターを開く | `boolean` | +| `tui.submitPrompt()` | 現在のプロンプトを送信します | `boolean` | +| `tui.clearPrompt()` | プロンプトをクリア | `boolean` | +| `tui.executeCommand({ body })` | コマンドを実行する | `boolean` | +| `tui.showToast({ body })` | トースト通知を表示 | `boolean` | + +--- + +#### 例 + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### Auth + +| メソッド | 説明 | 戻り値 | +| ------------------- | ---------------------- | --------- | +| `auth.set({ ... })` | 認証資格情報を設定する | `boolean` | + +--- + +#### 例 + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### Events + +| メソッド | 説明 | 戻り値 | +| ------------------- | ------------------------------ | ------------------------------ | +| `event.subscribe()` | サーバー送信イベントストリーム | サーバー送信イベントストリーム | + +--- + +#### 例 + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/ja/server.mdx b/packages/web/src/content/docs/ja/server.mdx new file mode 100644 index 00000000000..cbea87083ee --- /dev/null +++ b/packages/web/src/content/docs/ja/server.mdx @@ -0,0 +1,282 @@ +--- +title: サーバー +description: HTTP 経由で OpenCode サーバーと通信します。 +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +`opencode serve` コマンドは、OpenCode クライアントが使用できる OpenAPI エンドポイントを公開するヘッドレス HTTP サーバーを実行します。 + +--- + +### 使用法 + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### オプション + +| フラグ | 説明 | デフォルト | +| --------------- | --------------------------------- | ---------------- | +| `--port` | リッスンするポート | `4096` | +| `--hostname` | リッスンするホスト名 | `127.0.0.1` | +| `--mdns` | mDNS 検出を有効にする | `false` | +| `--mdns-domain` | mDNS サービスのカスタムドメイン名 | `opencode.local` | +| `--cors` | 許可する追加のブラウザーオリジン | `[]` | + +`--cors` は複数回渡すことができます。 + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### 認証 + +HTTP 基本認証でサーバーを保護するには、`OPENCODE_SERVER_PASSWORD` を設定します。ユーザー名はデフォルトで `opencode` になるか、`OPENCODE_SERVER_USERNAME` を設定してオーバーライドします。これは、`opencode serve` と `opencode web` の両方に当てはまります。 + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### 仕組み + +`opencode` を実行すると、TUI とサーバーが起動します。 TUI はサーバーと通信するクライアントです。サーバーは OpenAPI 3.1 仕様のエンドポイントを公開します。このエンドポイントは、[SDK](/docs/sdk) を使用してアクセスできます。 + +:::tip +OpenCode サーバーを使用して、プログラムで OpenCode と対話します。 +::: + +`opencode serve` を実行してスタンドアロンサーバーを起動できます。すでに OpenCode TUI を実行している場合でも、`opencode serve` は新しいサーバーを起動します。 + +--- + +#### 既存のサーバーに接続する + +TUI を起動すると、ポートとホスト名がランダムに割り当てられます。代わりに、`--hostname` と `--port` [フラグ](/docs/cli) を使用して固定できます。次に、これを使用してサーバーに接続します。 + +[`/tui`](#tui) エンドポイントは、サーバー経由で TUI を駆動するために使用できます。たとえば、プロンプトを事前入力したり、実行したりできます。この設定は、OpenCode [IDE](/docs/ide) プラグインによって使用されます。 + +--- + +## 仕様 + +サーバーは、次の場所で閲覧できる OpenAPI 3.1 仕様を公開しています。 + +``` +http://:/doc +``` + +たとえば、`http://localhost:4096/doc`。この仕様を使用して、クライアントを生成したり、要求と応答のタイプを検査したりできます。または、Swagger エクスプローラーで表示します。 + +--- + +## API + +OpenCode サーバーは次の API を公開します。 + +--- + +### Global + +| メソッド | パス | 説明 | レスポンス | +| -------- | ---------------- | ----------------------------------------- | ------------------------------------ | +| `GET` | `/global/health` | サーバーの健全性とバージョンを取得する | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | グローバルイベントの取得 (SSE ストリーム) | イベントストリーム | + +--- + +### Project + +| メソッド | パス | 説明 | レスポンス | +| -------- | ------------------ | -------------------------------- | --------------------------------------------- | +| `GET` | `/project` | すべてのプロジェクトをリストする | Project[] | +| `GET` | `/project/current` | 現在のプロジェクトを取得 | Project | + +--- + +### Path and VCS + +| メソッド | パス | 説明 | レスポンス | +| -------- | ------- | --------------------------------------- | ------------------------------------------- | +| `GET` | `/path` | 現在のパスを取得する | Path | +| `GET` | `/vcs` | 現在のプロジェクトの VCS 情報を取得する | VcsInfo | + +--- + +### Instance + +| メソッド | パス | 説明 | レスポンス | +| -------- | ------------------- | ---------------------------- | ---------- | +| `POST` | `/instance/dispose` | 現在のインスタンスを破棄する | void | + +--- + +### Config + +| メソッド | パス | 説明 | レスポンス | +| -------- | ------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `GET` | `/config` | 設定情報を取得する | Config | +| `PATCH` | `/config` | 設定を更新する | Config | +| `GET` | `/config/providers` | プロバイダーとデフォルトのモデルをリストする | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +### プロバイダー + +| メソッド | パス | 説明 | レスポンス | +| -------- | -------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------ | +| `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` | プロバイダーの OAuth コールバックを処理する | void | + +--- + +### Session + +| メソッド | パス | 説明 | 詳細 | +| -------- | ---------------------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------- | +| `GET` | `/session` | すべてのセッションをリストする | 戻り値 Session[] | +| `POST` | `/session` | 新しいセッションを作成する | 本文: `{ parentID?, title? }`、Session を返します。 | +| `GET` | `/session/status` | すべてのセッションのセッションステータスを取得する | 戻り値 `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | セッションの詳細を取得する | 戻り値 Session | +| `DELETE` | `/session/:id` | セッションとそのすべてのデータを削除する | 戻り値 `boolean` | +| `PATCH` | `/session/:id` | セッションのプロパティを更新する | 本文: `{ title? }`、Session を返します。 | +| `GET` | `/session/:id/children` | セッションの子セッションを取得する | 戻り値 Session[] | +| `GET` | `/session/:id/todo` | セッションの ToDo リストを取得する | 戻り値 Todo[] | +| `POST` | `/session/:id/init` | アプリを分析して `AGENTS.md` を作成する | 本文: `{ messageID, providerID, modelID }`、`boolean` を返します。 | +| `POST` | `/session/:id/fork` | メッセージで既存のセッションをフォークする | 本文: `{ messageID? }`、Session を返します。 | +| `POST` | `/session/:id/abort` | 実行中のセッションを中止する | 戻り値 `boolean` | +| `POST` | `/session/:id/share` | セッションを共有する | 戻り値 Session | +| `DELETE` | `/session/:id/share` | セッションの共有を解除する | 戻り値 Session | +| `GET` | `/session/:id/diff` | このセッションの差分を取得する | クエリ: `messageID?`、FileDiff[] を返します。 | +| `POST` | `/session/:id/summarize` | セッションを要約する | 本文: `{ providerID, modelID }`、`boolean` を返します。 | +| `POST` | `/session/:id/revert` | メッセージを元に戻す | 本文: `{ messageID, partID? }`、`boolean` を返します。 | +| `POST` | `/session/:id/unrevert` | 元に戻したすべてのメッセージを復元する | 戻り値 `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | 許可リクエストに応答する | 本文: `{ response, remember? }`、`boolean` を返します。 | + +--- + +### Message + +| メソッド | パス | 説明 | 詳細 | +| -------- | --------------------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `GET` | `/session/:id/message` | セッション内のメッセージをリストする | クエリ: `limit?`、`{ info: `Message`, parts: `Part[]`}[]` を返します。 | +| `POST` | `/session/:id/message` | メッセージを送信して応答を待ちます | 本文: `{ 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` | スラッシュコマンドを実行します | 本文: `{ messageID?, agent?, model?, command, arguments }`、`{ info: `Message`, parts: `Part[]`}` を返します | +| `POST` | `/session/:id/shell` | シェルコマンドを実行する | 本文: `{ agent, model?, command }`、`{ info: `Message`, parts: `Part[]`}` を返します | + +--- + +### Command + +| メソッド | パス | 説明 | レスポンス | +| -------- | ---------- | ---------------------------- | --------------------------------------------- | +| `GET` | `/command` | すべてのコマンドをリストする | Command[] | + +--- + +### 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` クエリパラメータ + +- `query` (必須) — 検索文字列 (あいまい一致) +- `type` (オプション) — 結果を `"file"` または `"directory"` に制限します +- `directory` (オプション) — 検索用のプロジェクトルートをオーバーライドします。 +- `limit` (オプション) — 最大結果 (1 ~ 200) +- `dirs` (オプション) — 従来のフラグ (`"false"` はファイルのみを返します) + +--- + +### Tool (Experimental) + +| メソッド | パス | 説明 | レスポンス | +| -------- | ------------------------------------------- | ---------------------------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | すべてのツール ID をリストする | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | モデルの JSON スキーマを含むツールをリストする | ToolList | + +--- + +### LSP, Formatter, MCP + +| メソッド | パス | 説明 | レスポンス | +| -------- | ------------ | ---------------------------------- | --------------------------------------------------------------------- | +| `GET` | `/lsp` | LSP サーバーのステータスを取得 | LSPStatus[] | +| `GET` | `/formatter` | フォーマッタのステータスを取得する | FormatterStatus[] | +| `GET` | `/mcp` | MCP サーバーのステータスを取得する | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | MCP サーバーを動的に追加する | 本文: `{ name, config }`、MCP ステータスオブジェクトを返します。 | + +--- + +### Agent + +| メソッド | パス | 説明 | レスポンス | +| -------- | -------- | ------------------------------------------ | ------------------------------------------- | +| `GET` | `/agent` | 利用可能なすべてのエージェントをリストする | Agent[] | + +--- + +### Logging + +| メソッド | パス | 説明 | レスポンス | +| -------- | ------ | ---------------------------------------------------------------------- | ---------- | +| `POST` | `/log` | ログエントリを書き込みます。本体:`{ service, level, message, extra? }` | void | + +--- + +### TUI + +| メソッド | パス | 説明 | レスポンス | +| -------- | ----------------------- | ----------------------------------------------- | -------------------------- | +| `POST` | `/tui/append-prompt` | プロンプトにテキストを追加します | void | +| `POST` | `/tui/open-help` | ヘルプダイアログを開く | void | +| `POST` | `/tui/open-sessions` | セッションセレクターを開く | void | +| `POST` | `/tui/open-themes` | テーマセレクターを開く | void | +| `POST` | `/tui/open-models` | モデルセレクターを開く | void | +| `POST` | `/tui/submit-prompt` | 現在のプロンプトを送信します | void | +| `POST` | `/tui/clear-prompt` | プロンプトをクリア | void | +| `POST` | `/tui/execute-command` | コマンドを実行する (`{ command }`) | void | +| `POST` | `/tui/show-toast` | トーストを表示 (`{ title?, message, variant }`) | void | +| `GET` | `/tui/control/next` | 次の制御リクエストを待ちます | 制御リクエストオブジェクト | +| `POST` | `/tui/control/response` | 制御リクエストに応答する (`{ body }`) | void | + +--- + +### Auth + +| メソッド | パス | 説明 | レスポンス | +| -------- | ----------- | ------------------------------------------------------------------------------ | ---------- | +| `PUT` | `/auth/:id` | 認証資格情報を設定します。本文はプロバイダーのスキーマと一致する必要があります | void | + +--- + +### Event + +| メソッド | パス | 説明 | レスポンス | +| -------- | -------- | ------------------------------------------------------------------------------------- | ------------------------------ | +| `GET` | `/event` | サーバー送信イベントストリーム。最初のイベントは `server.connected`、次にバスイベント | サーバー送信イベントストリーム | + +--- + +### Documentation + +| メソッド | パス | 説明 | レスポンス | +| -------- | ------ | ---------------- | -------------------------------- | +| `GET` | `/doc` | OpenAPI 3.1 仕様 | OpenAPI 仕様を備えた HTML ページ | diff --git a/packages/web/src/content/docs/ja/share.mdx b/packages/web/src/content/docs/ja/share.mdx new file mode 100644 index 00000000000..7995ba9a075 --- /dev/null +++ b/packages/web/src/content/docs/ja/share.mdx @@ -0,0 +1,128 @@ +--- +title: 共有 +description: OpenCode での会話を共有します。 +--- + +OpenCode の共有機能を使用すると、OpenCode の会話への公開リンクを作成できるため、チームメイトと共同作業したり、他の人から助けを得ることができます。 + +:::note +共有された会話は、リンクを知っている人なら誰でも公開してアクセスできます。 +::: + +--- + +## 仕組み + +会話を共有するとき、OpenCode は次のことを行います。 + +1. セッション用の一意のパブリック URL を作成します +2. 会話履歴をサーバーに同期します +3. 共有可能なリンク — `opncd.ai/s/` を介して会話にアクセスできるようにします + +--- + +## 共有 + +OpenCode は、会話の共有方法を制御する 3 つの共有モードをサポートしています。 + +--- + +### 手動(デフォルト) + +デフォルトでは、OpenCode は手動共有モードを使用します。セッションは自動的には共有されませんが、`/share` コマンドを使用して手動で共有できます。 + +``` +/share +``` + +これにより、クリップボードにコピーされる一意の URL が生成されます。 + +[設定ファイル](/docs/config): で手動モードを明示的に設定するには: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### 自動共有 + +[設定ファイル](/docs/config): で `share` オプションを `"auto"` に設定することで、すべての新しい会話の自動共有を有効にできます。 + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +自動共有を有効にすると、すべての新しい会話が自動的に共有され、リンクが生成されます。 + +--- + +### 無効 + +[設定ファイル](/docs/config): で `share` オプションを `"disabled"` に設定することで、共有を完全に無効にすることができます。 + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +これを特定のプロジェクトのチーム全体に強制するには、それをプロジェクトの `opencode.json` に追加し、Git にチェックインします。 + +--- + +## 共有の解除 + +会話の共有を停止し、パブリックアクセスから削除するには: + +``` +/unshare +``` + +これにより、共有リンクが削除され、会話に関連するデータが削除されます。 + +--- + +## プライバシー + +会話を共有する際には、留意すべき点がいくつかあります。 + +--- + +### データの保持 + +共有された会話は、明示的に共有を解除するまでアクセス可能なままになります。これ +以下が含まれます: + +- 完全な会話履歴 +- すべてのメッセージと応答 +- セッションメタデータ + +--- + +### 推奨事項 + +- 機密情報を含まない会話のみを共有してください。 +- 共有する前に会話の内容を確認してください。 +- コラボレーションが完了したら、会話の共有を解除します。 +- 独自のコードや機密データを含む会話を共有することは避けてください。 +- 機密性の高いプロジェクトの場合は、共有を完全に無効にします。 + +--- + +## 企業向け + +エンタープライズ展開の場合、共有機能は次のようになります。 + +- **セキュリティコンプライアンスのため完全に無効** +- **SSO を通じて認証されたユーザーのみに制限** +- 独自のインフラストラクチャで **セルフホスト** + +[組織内での OpenCode の使用について詳しくは、](/docs/enterprise) をご覧ください。 diff --git a/packages/web/src/content/docs/ja/skills.mdx b/packages/web/src/content/docs/ja/skills.mdx new file mode 100644 index 00000000000..6e5bae6c758 --- /dev/null +++ b/packages/web/src/content/docs/ja/skills.mdx @@ -0,0 +1,222 @@ +--- +title: エージェントスキル +description: SKILL.md 定義による再利用可能な動作の定義 +--- + +エージェントスキルにより、OpenCode はリポジトリまたはホームディレクトリから再利用可能な命令を検出できます。 +スキルはネイティブの `skill` ツールを介してオンデマンドでロードされます。エージェントは利用可能なスキルを確認し、必要に応じて完全なコンテンツをロードできます。 + +--- + +## ファイルの配置 + +スキル名ごとにフォルダーを 1 つ作成し、その中に `SKILL.md` を置きます。 +OpenCode は次の場所を検索します。 + +- プロジェクト設定: `.opencode/skills//SKILL.md` +- グローバル設定: `~/.config/opencode/skills//SKILL.md` +- プロジェクト Claude 互換: `.claude/skills//SKILL.md` +- グローバル Claude 互換: `~/.claude/skills//SKILL.md` +- プロジェクトエージェント互換: `.agents/skills//SKILL.md` +- グローバルエージェント互換: `~/.agents/skills//SKILL.md` + +--- + +## 検出の仕組み + +プロジェクトのローカルパスの場合、OpenCode は現在の作業ディレクトリから git ワークツリーに到達するまで進みます。 +途中で、一致する `skills/*/SKILL.md` を `.opencode/` に読み込み、一致する `.claude/skills/*/SKILL.md` または `.agents/skills/*/SKILL.md` を読み込みます。 + +グローバル定義は、`~/.config/opencode/skills/*/SKILL.md`、`~/.claude/skills/*/SKILL.md`、および `~/.agents/skills/*/SKILL.md` からもロードされます。 + +--- + +## フロントマターの記述 + +各 `SKILL.md` は YAML フロントマターで始まる必要があります。 +次のフィールドのみが認識されます。 + +- `name` (必須) +- `description` (必須) +- `license` (オプション) +- `compatibility` (オプション) +- `metadata` (オプション、文字列間のマップ) + +不明なフロントマターフィールドは無視されます。 + +--- + +## 名前の検証 + +`name` は次のことを行う必要があります。 + +- 1 ~ 64 文字であること +- 単一のハイフンで区切られた小文字の英数字であること +- `-` で開始または終了しない +- 連続した `--` を含まない +- `SKILL.md` を含むディレクトリ名と一致する + +同等の正規表現: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## 長さのルール + +`description` は 1 ~ 1024 文字である必要があります。 +エージェントが正しく選択できるように、十分具体的な内容にしてください。 + +--- + +## 使用例 + +次のように `.opencode/skills/git-release/SKILL.md` を作成します。 + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## ツールの説明認識 + +OpenCode では、`skill` ツールの説明に利用可能なスキルがリストされています。 +各エントリにはスキル名と説明が含まれます。 + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +エージェントはツールを呼び出してスキルをロードします。 + +``` +skill({ name: "git-release" }) +``` + +--- + +## 権限の設定 + +`opencode.json` のパターンベースの権限を使用して、エージェントがアクセスできるスキルを制御します。 + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| 許可 | アクション | +| ------- | ---------------------------------------------------------- | +| `allow` | スキルはすぐにロードされます | +| `deny` | スキルはエージェントから隠蔽され、アクセスは拒否されました | +| `ask` | ロードする前にユーザーに承認を求めるメッセージが表示される | + +パターンはワイルドカードをサポートしています: `internal-*` は `internal-docs`、`internal-tools` などに一致します。 + +--- + +## エージェントごとの上書き + +特定のエージェントにグローバルのデフォルトとは異なる権限を与えます。 + +**カスタムエージェントの場合** (エージェントフロントマター内): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**組み込みエージェントの場合** (`opencode.json` 内): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## スキルツールの無効化 + +スキルを使用すべきではないエージェントのスキルを完全に無効にします。 + +**カスタムエージェントの場合**: + +```yaml +--- +tools: + skill: false +--- +``` + +**組み込みエージェントの場合**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +無効にすると、`` セクションが完全に省略されます。 + +--- + +## 読み込みのトラブルシューティング + +スキルが表示されない場合: + +1. `SKILL.md` のスペルがすべて大文字であることを確認してください +2. フロントマターに `name` と `description` が含まれていることを確認します +3. スキル名がすべての場所で一意であることを確認する +4. 権限を確認してください - `deny` のスキルはエージェントから非表示になります diff --git a/packages/web/src/content/docs/ja/themes.mdx b/packages/web/src/content/docs/ja/themes.mdx new file mode 100644 index 00000000000..dd76651d6a5 --- /dev/null +++ b/packages/web/src/content/docs/ja/themes.mdx @@ -0,0 +1,667 @@ +--- +title: テーマ +description: 組み込みのテーマを選択するか、独自のテーマを定義します。 +--- + +OpenCode を使用すると、いくつかの組み込みテーマから 1 つを選択したり、ターミナルのテーマに適合するテーマを使用したり、独自のカスタムテーマを定義したりできます。 + +デフォルトでは、OpenCode は独自の `opencode` テーマを使用します。 + +--- + +## ターミナル要件 + +テーマをフルカラーパレットで正しく表示するには、ターミナルが **Truecolor** (24 ビットカラー) をサポートしている必要があります。最新のターミナルのほとんどはデフォルトでこれをサポートしていますが、有効にする必要がある場合があります。 + +- **サポートを確認してください**: `echo $COLORTERM` を実行します - `truecolor` または `24bit` が出力されるはずです +- **Truecolor を有効にする**: シェルプロファイルで環境変数 `COLORTERM=truecolor` を設定します。 +- **ターミナルの互換性**: ターミナルエミュレータが 24 ビットカラーをサポートしていることを確認してください (iTerm2、Alacritty、Kitty、Windows Terminal、および GNOME Terminal の最新バージョンなどのほとんどの最新のターミナルはサポートしています)。 + +Truecolor のサポートがないと、テーマの色の精度が低下したり、最も近い 256 色の近似値に戻ったりする可能性があります。 + +--- + +## 組み込みのテーマ + +OpenCode にはいくつかの組み込みテーマが付属しています。 + +| Name | Description | +| ---------------------- | ---------------------------------------------------------------------------- | +| `system` | Adapts to your terminal’s background color | +| `tokyonight` | Based on the [Tokyonight](https://github.com/folke/tokyonight.nvim) theme | +| `everforest` | Based on the [Everforest](https://github.com/sainnhe/everforest) theme | +| `ayu` | Based on the [Ayu](https://github.com/ayu-theme) dark theme | +| `catppuccin` | Based on the [Catppuccin](https://github.com/catppuccin) theme | +| `catppuccin-macchiato` | Based on the [Catppuccin](https://github.com/catppuccin) theme | +| `gruvbox` | Based on the [Gruvbox](https://github.com/morhetz/gruvbox) theme | +| `kanagawa` | Based on the [Kanagawa](https://github.com/rebelot/kanagawa.nvim) theme | +| `nord` | Based on the [Nord](https://github.com/nordtheme/nord) theme | +| `matrix` | Hacker-style green on black theme | +| `one-dark` | Based on the [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark theme | + +さらに、新しいテーマも常に追加されています。 + +--- + +## システムテーマ + +`system` テーマは、ターミナルのカラースキームに自動的に適応するように設計されています。固定色を使用する従来のテーマとは異なり、_system_ テーマは次のようになります。 + +- **グレースケールを生成**: ターミナルの背景色に基づいてカスタムグレースケールを作成し、最適なコントラストを確保します。 +- **ANSI カラーを使用**: 構文の強調表示と UI 要素に標準の ANSI カラー (0 ~ 15) を利用し、ターミナルのカラーパレットを尊重します。 +- **ターミナルのデフォルトを維持**: テキストと背景の色に `none` を使用して、ターミナルのネイティブの外観を維持します。 + +システムテーマは、次のようなユーザーを対象としています。 + +- OpenCode をターミナルの外観と一致させたい +- カスタムターミナルのカラースキームを使用する +- すべてのターミナルアプリケーションにわたって一貫した外観を好む + +--- + +## テーマの使用 + +テーマを選択するには、`/theme` コマンドでテーマ選択を表示します。または、[config](/docs/config) で設定します。 + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## カスタムテーマ + +OpenCode は、ユーザーがテーマを簡単に作成およびカスタマイズできる柔軟な JSON ベースのテーマシステムをサポートしています。 + +--- + +### 優先順位 + +テーマは複数のディレクトリから次の順序でロードされ、後のディレクトリが前のディレクトリをオーバーライドします。 + +1. **組み込みテーマ** - これらはバイナリに埋め込まれています +2. **ユーザー設定ディレクトリ** - `~/.config/opencode/themes/*.json` または `$XDG_CONFIG_HOME/opencode/themes/*.json` で定義されます +3. **プロジェクトのルートディレクトリ** - `/.opencode/themes/*.json` で定義されます。 +4. **現在の作業ディレクトリ** - `./.opencode/themes/*.json` で定義 + +複数のディレクトリに同じ名前のテーマが含まれている場合は、優先度の高いディレクトリのテーマが使用されます。 + +--- + +### テーマの作成 + +カスタムテーマを作成するには、テーマディレクトリの 1 つに JSON ファイルを作成します。 + +ユーザー全体のテーマの場合: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +そしてプロジェクト固有のテーマについても。 + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### JSON 形式 + +テーマは、以下をサポートする柔軟な JSON 形式を使用します。 + +- **16 進数の色**: `"#ffffff"` +- **ANSI カラー**: `3` (0-255) +- **色の参照**: `"primary"` またはカスタム定義 +- **ダーク/ライトのバリエーション**: `{"dark": "#000", "light": "#fff"}` +- **色なし**: `"none"` - ターミナルのデフォルトの色または透明を使用します。 + +--- + +### 色の定義 + +`defs` セクションはオプションであり、テーマ内で参照できる再利用可能な色を定義できます。 + +--- + +### ターミナルのデフォルト + +特別な値 `"none"` を任意の色に使用して、ターミナルのデフォルトの色を継承できます。これは、ターミナルの配色とシームレスに融合するテーマを作成する場合に特に便利です。 + +- `"text": "none"` - ターミナルのデフォルトの前景色を使用します +- `"background": "none"` - ターミナルのデフォルトの背景色を使用します + +--- + +### 例 + +カスタムテーマの例を次に示します。 + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` + +--- + +## カスタムテーマ + +OpenCode は、ユーザーがテーマを簡単に作成およびカスタマイズできる柔軟な JSON ベースのテーマ システムをサポートしています。 + +--- + +### 階層 + +テーマは複数のディレクトリから次の順序でロードされ、後のディレクトリが前のディレクトリをオーバーライドします。 + +1. **組み込みテーマ** - これらはバイナリに埋め込まれています +2. **ユーザー設定ディレクトリ** - `~/.config/opencode/themes/*.json` または `$XDG_CONFIG_HOME/opencode/themes/*.json` で定義されます +3. **プロジェクトのルート ディレクトリ** - `/.opencode/themes/*.json` で定義されます。 +4. **現在の作業ディレクトリ** - `./.opencode/themes/*.json` で定義 + +複数のディレクトリに同じ名前のテーマが含まれている場合は、優先度の高いディレクトリのテーマが使用されます。 + +--- + +### テーマの作成 + +カスタム テーマを作成するには、テーマ ディレクトリの 1 つに JSON ファイルを作成します。 + +ユーザー全体のテーマの場合: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +そしてプロジェクト固有のテーマについても。 + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### JSON形式 + +テーマは、以下をサポートする柔軟な JSON 形式を使用します。 + +- **16 進数の色**: `"#ffffff"` +- **ANSI カラー**: `3` (0-255) +- **色の参照**: `"primary"` またはカスタム定義 +- **ダーク/ライトのバリエーション**: `{"dark": "#000", "light": "#fff"}` +- **色なし**: `"none"` - terminal のデフォルトの色または透明を使用します。 + +--- + +### 色の定義 + +`defs` セクションはオプションであり、テーマ内で参照できる再利用可能な色を定義できます。 + +--- + +### ターミナルのデフォルト + +特別な値 `"none"` を任意の色に使用して、terminal のデフォルトの色を継承できます。これは、terminal の配色とシームレスに融合するテーマを作成する場合に特に便利です。 + +- `"text": "none"` - terminal のデフォルトの前景色を使用します +- `"background": "none"` - terminal のデフォルトの背景色を使用します + +--- + +### 例 + +カスタム テーマの例を次に示します。 + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/ja/tools.mdx b/packages/web/src/content/docs/ja/tools.mdx new file mode 100644 index 00000000000..6aa7e956f35 --- /dev/null +++ b/packages/web/src/content/docs/ja/tools.mdx @@ -0,0 +1,379 @@ +--- +title: ツール +description: LLM が使用できるツールを管理します。 +--- + +ツールを使用すると、LLM がコードベースでアクションを実行できるようになります。 OpenCode には一連の組み込みツールが付属していますが、[カスタムツール](/docs/custom-tools) または [MCP サーバー](/docs/mcp-servers) を使用して拡張できます。 + +デフォルトでは、すべてのツールは**有効**になっており、実行するための権限は必要ありません。 [権限](/docs/permissions). + +--- + +## 設定 + +`permission` フィールドを使用してツールの動作を制御します。各ツールを許可、拒否、または承認を要求することができます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +ワイルドカードを使用して複数のツールを一度に制御することもできます。たとえば、MCP サーバーからのすべてのツールの承認を要求するには、次のようにします。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[アクセス許可の構成について詳しくは、](/docs/permissions) をご覧ください。 + +--- + +## 組み込み + +OpenCode で利用可能なすべての組み込みツールを次に示します。 + +--- + +### bash + +プロジェクト環境でシェルコマンドを実行します。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +このツールを使用すると、LLM は `npm install`、`git status`、またはその他のシェルコマンドなどのターミナルコマンドを実行できます。 + +--- + +### edit + +正確な文字列置換を使用して既存のファイルを変更します。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +このツールは、完全に一致するテキストを置き換えることにより、ファイルを正確に編集します。これは、LLM がコードを変更する主な方法です。 + +--- + +### write + +新しいファイルを作成するか、既存のファイルを上書きします。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +これを使用して、LLM が新しいファイルを作成できるようにします。既存のファイルがすでに存在する場合は上書きされます。 + +:::note +`write` ツールは、すべてのファイル変更 (`edit`、`edit`、`write`、`patch`) をカバーする `multiedit` 権限によって制御されます。 +::: + +--- + +### read + +コードベースからファイルの内容を読み取ります。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +このツールはファイルを読み取り、その内容を返します。大きなファイルの特定の行範囲の読み取りをサポートします。 + +--- + +### grep + +正規表現を使用してファイルの内容を検索します。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +コードベース全体での高速コンテンツ検索。完全な正規表現構文とファイルパターンフィルタリングをサポートします。 + +--- + +### glob + +パターンマッチングによりファイルを検索します。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +`**/*.js` や `src/**/*.ts` などの glob パターンを使用してファイルを検索します。一致するファイルパスを変更時間順に並べて返します。 + +--- + +### list + +指定されたパス内のファイルとディレクトリを一覧表示します。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +このツールはディレクトリの内容を一覧表示します。結果をフィルタリングするための glob パターンを受け入れます。 + +--- + +### lsp (実験的) + +構成された LSP サーバーと対話して、定義、参照、ホバー情報、呼び出し階層などのコードインテリジェンス機能を取得します。 + +:::note +このツールは、`OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (または `OPENCODE_EXPERIMENTAL=true`) の場合にのみ使用できます。 +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +サポートされている操作には、`goToDefinition`、`findReferences`、`hover`、`documentSymbol`、`workspaceSymbol`、`goToImplementation`、`prepareCallHierarchy`、`incomingCalls`、および `outgoingCalls` が含まれます。 + +プロジェクトで使用できる LSP サーバーを構成するには、「LSP Servers](/docs/lsp). + +--- + +### patch + +ファイルにパッチを適用します。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +このツールは、コードベースにパッチファイルを適用します。さまざまなソースからの差分やパッチを適用するのに役立ちます。 + +:::note +`patch` ツールは、すべてのファイル変更 (`edit`、`edit`、`write`、`patch`) をカバーする `multiedit` 権限によって制御されます。 +::: + +--- + +### skill + +[skill](/docs/skills) (`SKILL.md` ファイル) をロードし、会話でその内容を返します。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +コーディングセッション中に ToDo リストを管理します。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +タスクリストを作成および更新して、複雑な操作中の進行状況を追跡します。 LLM はこれを使用して、複数ステップのタスクを整理します。 + +:::note +このツールはデフォルトではサブエージェントに対して無効になっていますが、手動で有効にすることができます。 [詳細はこちら](/docs/agents/#permissions) +::: + +--- + +### todoread + +既存の ToDo リストを読み取ります。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +現在の Todo リストの状態を読み取ります。どのタスクが保留中または完了しているかを追跡するために LLM によって使用されます。 + +:::note +このツールはデフォルトではサブエージェントに対して無効になっていますが、手動で有効にすることができます。 [詳細はこちら](/docs/agents/#permissions) +::: + +--- + +### webfetch + +Web コンテンツを取得します。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +LLM が Web ページをフェッチして読み取ることを許可します。ドキュメントの検索やオンラインリソースの調査に役立ちます。 + +--- + +### websearch + +ウェブで情報を検索してください。 + +:::note +このツールは、OpenCode プロバイダーを使用している場合、または `OPENCODE_ENABLE_EXA` 環境変数が真実の値 (`true` または `1` など) に設定されている場合にのみ使用できます。 + +OpenCode の起動時に有効にするには: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +Exa AI を使用して Web 検索を実行し、オンラインで関連情報を見つけます。トピックの調査、最新のイベントの検索、またはトレーニングデータのカットオフを超えた情報の収集に役立ちます。 + +API キーは必要ありません。ツールは認証なしで Exa AI のホストされた MCP サービスに直接接続します。 + +:::tip +情報を見つける必要がある場合 (検出)、`websearch` を使用し、特定の URL からコンテンツを取得する必要がある場合 (取得) は `webfetch` を使用します。 +::: + +--- + +### question + +実行中にユーザーに質問します。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +このツールを使用すると、LLM はタスク中にユーザーに質問できるようになります。これは次の場合に役立ちます。 + +- ユーザーの好みや要件を収集する +- 曖昧な指示を明確にする +- 実装の選択肢について決定を下す +- どの方向に進むべきかについての選択肢を提供する + +各質問には、ヘッダー、質問テキスト、およびオプションのリストが含まれます。ユーザーは、提供されたオプションから選択するか、カスタムの回答を入力できます。複数の質問がある場合、ユーザーはすべての回答を送信する前に質問間を移動できます。 + +--- + +## カスタムツール + +カスタムツールを使用すると、LLM が呼び出すことができる独自の関数を定義できます。これらは設定ファイルで定義されており、任意のコードを実行できます。 + +[カスタムツールの作成について詳しくは、](/docs/custom-tools) をご覧ください。 + +--- + +## MCPサーバー + +MCP (Model Context Protocol) サーバーを使用すると、外部ツールとサービスを統合できます。これには、データベースアクセス、API 統合、サードパーティサービスが含まれます。 + +[MCP サーバーの設定について詳しくは、](/docs/mcp-servers) をご覧ください。 + +--- + +## 内部動作 + +内部的には、`grep`、`glob`、`list` などのツールは内部で [ripgrep](https://github.com/BurntSushi/ripgrep) を使用します。デフォルトでは、ripgrep は `.gitignore` パターンを尊重します。つまり、`.gitignore` にリストされているファイルとディレクトリは検索とリストから除外されます。 + +--- + +### パターンを無視する + +通常は無視されるファイルを含めるには、プロジェクトのルートに `.ignore` ファイルを作成します。このファイルでは、特定のパスを明示的に許可できます。 + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +たとえば、この `.ignore` ファイルを使用すると、ripgrep は、`node_modules/` にリストされている場合でも、`dist/`、`build/`、および `.gitignore` ディレクトリ内を検索できます。 diff --git a/packages/web/src/content/docs/ja/troubleshooting.mdx b/packages/web/src/content/docs/ja/troubleshooting.mdx new file mode 100644 index 00000000000..e58818da6fc --- /dev/null +++ b/packages/web/src/content/docs/ja/troubleshooting.mdx @@ -0,0 +1,300 @@ +--- +title: トラブルシューティング +description: よくある問題とその解決方法。 +--- + +OpenCode の問題をデバッグするには、まず、ディスク上に保存されているログとローカルデータを確認します。 + +--- + +## ログ + +ログファイルは次の場所に書き込まれます。 + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: `WIN+R` を押して `%USERPROFILE%\.local\share\opencode\log` を貼り付けます + +ログファイルにはタイムスタンプ付きの名前が付けられ (例: `2025-01-09T123456.log`)、最新の 10 個のログファイルが保存されます。 + +`--log-level` コマンドラインオプションを使用してログレベルを設定すると、より詳細なデバッグ情報を取得できます。たとえば、`opencode --log-level DEBUG`。 + +--- + +## ストレージ + +OpenCode は、セッションデータとその他のアプリケーションデータをディスク上の次の場所に保存します。 + +- **macOS/Linux**: `~/.local/share/opencode/` +- **Windows**: `WIN+R` を押して `%USERPROFILE%\.local\share\opencode` を貼り付けます + +このディレクトリには次のものが含まれます。 + +- `auth.json` - API キー、OAuth トークンなどの認証データ +- `log/` - アプリケーションログ +- `project/` - セッションデータやメッセージデータなどのプロジェクト固有のデータ + - プロジェクトが Git リポジトリ内にある場合は、`.//storage/` に保存されます + - Git リポジトリではない場合は、`./global/storage/` に保存されます + +--- + +## デスクトップアプリ + +OpenCode Desktop は、ローカル OpenCode サーバー (`opencode-cli` サイドカー) をバックグラウンドで実行します。ほとんどの問題は、誤動作しているプラグイン、破損したキャッシュ、または不正なサーバー設定によって発生します。 + +### クイックチェック + +- アプリを完全に終了して再起動します。 +- アプリにエラー画面が表示された場合は、**再起動** をクリックしてエラーの詳細をコピーします。 +- macOS のみ: `OpenCode` メニュー -> **Webview をリロード** (UI が空白またはフリーズしている場合に役立ちます)。 + +--- + +### プラグインを無効にする + +デスクトップアプリが起動時にクラッシュしたり、ハングしたり、異常な動作をしたりする場合は、まずプラグインを無効にしてください。 + +#### グローバル設定の確認 + +グローバル設定ファイルを開き、`plugin` キーを探します。 + +- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (または `~/.config/opencode/opencode.json`) +- **macOS/Linux** (古いインストール): `~/.local/share/opencode/opencode.jsonc` +- **Windows**: `WIN+R` を押して `%USERPROFILE%\.config\opencode\opencode.jsonc` を貼り付けます + +プラグインを構成している場合は、キーを削除するか空の配列に設定して、プラグインを一時的に無効にします。 + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### プラグインディレクトリの確認 + +OpenCode はディスクからローカルプラグインをロードすることもできます。これらを一時的に邪魔にならない場所に移動し (またはフォルダーの名前を変更し)、デスクトップアプリを再起動します。 + +- **グローバルプラグイン** + - **macOS/Linux**: `~/.config/opencode/plugins/` + - **Windows**: `WIN+R` を押して `%USERPROFILE%\.config\opencode\plugins` を貼り付けます +- **プロジェクトプラグイン** (プロジェクトごとの構成を使用する場合のみ) + - `/.opencode/plugins/` + +アプリが再び動作し始めた場合は、プラグインを 1 つずつ再度有効にして、問題の原因となっているプラ​​グインを特定します。 + +--- + +### キャッシュをクリアする + +プラグインを無効にしても解決しない場合 (またはプラグインのインストールが停止した場合)、OpenCode がキャッシュを再構築できるようにキャッシュをクリアします。 + +1. OpenCode Desktop を完全に終了します。 +2. キャッシュディレクトリを削除します。 + +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/.cache/opencode` を貼り付け +- **Linux**: `~/.cache/opencode` を削除します (または `rm -rf ~/.cache/opencode` を実行します)。 +- **Windows**: `WIN+R` を押して `%USERPROFILE%\.cache\opencode` を貼り付けます + +3. OpenCode デスクトップを再起動します。 + +--- + +### サーバー接続の問題の修正 + +OpenCode Desktop は、独自のローカルサーバー (デフォルト) を起動することも、構成したサーバー URL に接続することもできます。 + +**「接続に失敗しました」** ダイアログが表示された場合 (またはアプリがスプラッシュ画面を通過できない場合)、カスタムサーバー URL を確認してください。 + +#### デスクトップのデフォルトのサーバー URL をクリアします + +ホーム画面でサーバー名 (ステータスドット付き) をクリックしてサーバーピッカーを開きます。 [**デフォルトサーバー**] セクションで、[**クリア**] をクリックします。 + +#### 設定から `server.port` / `server.hostname` を削除します + +`opencode.json(c)` に `server` セクションが含まれている場合は、それを一時的に削除し、デスクトップアプリを再起動します。 + +#### 環境変数を確認する + +環境に `OPENCODE_PORT` が設定されている場合、デスクトップアプリはローカルサーバーにそのポートを使用しようとします。 + +- `OPENCODE_PORT` の設定を解除して (または空きポートを選択して)、再起動します。 + +--- + +### Linux: Wayland / X11 の問題 + +Linux では、一部の Wayland セットアップにより、空白のウィンドウやコンポジターエラーが発生する可能性があります。 + +- Wayland を使用していて、アプリが空白またはクラッシュしている場合は、`OC_ALLOW_WAYLAND=1` で起動してみてください。 +- これにより状況が悪化する場合は、それを削除し、代わりに X11 セッションで起動してみてください。 + +--- + +### Windows: WebView2 ランタイム + +Windows では、OpenCode Desktop には Microsoft Edge **WebView2 ランタイム**が必要です。アプリが空白のウィンドウで開くか、起動しない場合は、WebView2 をインストールまたは更新して、もう一度試してください。 + +--- + +### Windows: 一般的なパフォーマンスの問題 + +Windows でパフォーマンスの低下、ファイルアクセスの問題、またはターミナルの問題が発生している場合は、[WSL (Windows Subsystem for Linux)](/docs/windows-wsl) を使用してみてください。 WSL は、OpenCode の機能とよりシームレスに連携する Linux 環境を提供します。 + +--- + +### 通知が表示されない + +OpenCode Desktop では、次の場合にのみシステム通知が表示されます。 + +- OS 設定で OpenCode の通知が有効になっており、 +- アプリウィンドウにフォーカスがありません。 + +--- + +### デスクトップアプリのストレージのリセット (最後の手段) + +アプリが起動せず、UI 内から設定をクリアできない場合は、デスクトップアプリの保存された状態をリセットします。 + +1. OpenCode デスクトップを終了します。 +2. これらのファイルを見つけて削除します (これらのファイルは OpenCode デスクトップアプリのデータディレクトリにあります)。 + +- `opencode.settings.dat` (デスクトップのデフォルトサーバー URL) +- `opencode.global.dat` および `opencode.workspace.*.dat` (最近のサーバー/プロジェクトなどの UI 状態) + +ディレクトリをすばやく見つけるには: + +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (その後、上記のファイル名を検索します) +- **Linux**: 上記のファイル名を `~/.local/share` で検索します。 +- **Windows**: `WIN+R` -> `%APPDATA%` を押します (その後、上記のファイル名を検索します)。 + +--- + +## ヘルプを求める + +OpenCode で問題が発生している場合: + +1. **GitHub で問題を報告してください** + +バグを報告したり、機能をリクエストしたりする最良の方法は、GitHub リポジトリを使用することです。 + +[**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + +新しい問題を作成する前に、既存の問題を検索して、問題がすでに報告されているかどうかを確認してください。 + +2. **Discord への参加** + +リアルタイムのヘルプやコミュニティのディスカッションについては、Discord サーバーに参加してください。 + +[**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## よくある問題 + +ここでは、いくつかの一般的な問題とその解決方法を示します。 + +--- + +### OpenCode が起動しない + +1. ログでエラーメッセージを確認する +2. `--print-logs` で実行して、ターミナルに出力を確認してください。 +3. `opencode upgrade` を含む最新バージョンを使用していることを確認してください + +--- + +### 認証の問題 + +1. TUI で `/connect` コマンドを使用して再認証を試みます +2. API キーが有効であることを確認してください +3. ネットワークでプロバイダーの API への接続が許可されていることを確認してください + +--- + +### モデルが見つからない + +1. プロバイダーで認証されていることを確認してください +2. 構成内のモデル名が正しいことを確認してください +3. 一部のモデルでは、特定のアクセスまたはサブスクリプションが必要な場合があります + +`ProviderModelNotFoundError` が表示された場合は、間違いがある可能性が高くなります。 +どこかのモデルを参照しています。 +モデルは次のように参照する必要があります: `/` + +例: + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +どのモデルにアクセスできるかを確認するには、`opencode models` を実行します。 + +--- + +### ProviderInitError + +ProviderInitError が発生した場合は、構成が無効または破損している可能性があります。 + +これを解決するには: + +1. まず、[プロバイダーガイド](/docs/providers) に従って、プロバイダーが正しく設定されていることを確認します。 +2. 問題が解決しない場合は、保存されている構成をクリアしてみてください。 + + ```bash + rm -rf ~/.local/share/opencode + ``` + + Windows では、`WIN+R` を押して、`%USERPROFILE%\.local\share\opencode` を削除します。 + +3. TUI の `/connect` コマンドを使用して、プロバイダーで再認証します。 + +--- + +### AI_APICallError とプロバイダーパッケージの問題 + +API 呼び出しエラーが発生した場合は、プロバイダーパッケージが古いことが原因である可能性があります。 OpenCode は、必要に応じてプロバイダーパッケージ (OpenAI、Anthropic、Google など) を動的にインストールし、ローカルにキャッシュします。 + +プロバイダーパッケージの問題を解決するには: + +1. プロバイダーパッケージのキャッシュをクリアします。 + + ```bash + rm -rf ~/.cache/opencode + ``` + + Windows では、`WIN+R` を押して、`%USERPROFILE%\.cache\opencode` を削除します。 + +2. OpenCode を再起動して最新のプロバイダーパッケージを再インストールします + +これにより、OpenCode はプロバイダーパッケージの最新バージョンを強制的にダウンロードすることになり、多くの場合、モデルパラメーターや API の変更に関する互換性の問題が解決されます。 + +--- + +### Linux ではコピー/ペーストが機能しない + +Linux ユーザーがコピー/ペースト機能を動作させるには、次のクリップボードユーティリティのいずれかがインストールされている必要があります。 + +**X11 システムの場合:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**Wayland システムの場合:** + +```bash +apt install -y wl-clipboard +``` + +**ヘッドレス環境の場合:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +OpenCode は、Wayland を使用していて `wl-clipboard` を優先しているかどうかを検出します。そうでない場合は、`xclip` および `xsel` の順序でクリップボードツールを検索しようとします。 diff --git a/packages/web/src/content/docs/ja/tui.mdx b/packages/web/src/content/docs/ja/tui.mdx new file mode 100644 index 00000000000..36c94fffcf7 --- /dev/null +++ b/packages/web/src/content/docs/ja/tui.mdx @@ -0,0 +1,384 @@ +--- +title: TUI +description: OpenCode ターミナルユーザーインターフェイスの使用。 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode は、LLM を使用してプロジェクトを作業するための対話型ターミナルインターフェイスまたは TUI を提供します。 + +OpenCode を実行すると、現在のディレクトリの TUI が開始されます。 + +```bash +opencode +``` + +または、特定の作業ディレクトリに対して起動することもできます。 + +```bash +opencode /path/to/project +``` + +TUI に入ったら、メッセージを表示することができます。 + +```text +Give me a quick summary of the codebase. +``` + +--- + +## ファイル参照 + +`@` を使用してメッセージ内のファイルを参照できます。これにより、現在の作業ディレクトリ内であいまいなファイル検索が行われます。 + +:::tip +`@` を使用してメッセージ内のファイルを参照することもできます。 +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +ファイルの内容は会話に自動的に追加されます。 + +--- + +## Bash コマンド + +メッセージを `!` で開始して、シェルコマンドを実行します。 + +```bash frame="none" +!ls -la +``` + +コマンドの出力は、ツールの結果として会話に追加されます。 + +--- + +## コマンド + +OpenCode TUI を使用する場合、「`/`」に続いてコマンド名を入力すると、アクションをすばやく実行できます。例えば: + +```bash frame="none" +/help +``` + +ほとんどのコマンドには、`ctrl+x` をリーダーキーとして使用するキーバインドもあります。`ctrl+x` がデフォルトのリーダーキーです。 [詳細はこちら](/docs/keybinds)。 + +利用可能なすべてのスラッシュコマンドは次のとおりです。 + +--- + +### 接続 + +OpenCode にプロバイダーを追加します。利用可能なプロバイダーから選択し、その API キーを追加できます。 + +```bash frame="none" +/connect +``` + +--- + +### コンパクト + +現在のセッションを圧縮します。 _別名_: `/summarize` + +```bash frame="none" +/compact +``` + +**キーバインド:** `ctrl+x c` + +--- + +### 詳細 + +ツール実行の詳細を切り替えます。 + +```bash frame="none" +/details +``` + +**キーバインド:** `ctrl+x d` + +--- + +### エディタ + +メッセージを作成するために外部エディタを開きます。 `EDITOR` 環境変数に設定されたエディタを使用します。 [詳細はこちら](#editor-setup)。 + +```bash frame="none" +/editor +``` + +**キーバインド:** `ctrl+x e` + +--- + +### 終了 + +OpenCode を終了します。 _エイリアス_: `/quit`、`/q` + +```bash frame="none" +/exit +``` + +**キーバインド:** `ctrl+x q` + +--- + +### エクスポート + +現在の会話を Markdown にエクスポートし、デフォルトのエディターで開きます。 `EDITOR` 環境変数に設定されたエディタを使用します。 [詳細はこちら](#editor-setup)。 + +```bash frame="none" +/export +``` + +**キーバインド:** `ctrl+x x` + +--- + +### ヘルプ + +ヘルプダイアログを表示します。 + +```bash frame="none" +/help +``` + +**キーバインド:** `ctrl+x h` + +--- + +### 初期化 + +`AGENTS.md` ファイルを作成または更新します。 [詳細はこちら](/docs/rules)。 + +```bash frame="none" +/init +``` + +**キーバインド:** `ctrl+x i` + +--- + +### モデル + +利用可能なモデルをリストします。 + +```bash frame="none" +/models +``` + +**キーバインド:** `ctrl+x m` + +--- + +### 新規セッション + +新しいセッションを開始します。 _別名_: `/clear` + +```bash frame="none" +/new +``` + +**キーバインド:** `ctrl+x n` + +--- + +### やり直し + +以前に取り消したメッセージをやり直します。 `/undo` を使用した後にのみ使用できます。 + +:::tip +ファイルの変更も復元されます。 +::: +内部的には、`undo` を使用してファイルの変更を管理します。したがって、あなたのプロジェクトは **Git リポジトリ** である必要があります。 + +```bash frame="none" +/redo +``` + +**キーバインド:** `ctrl+x r` + +--- + +### セッション + +セッションを一覧表示して切り替えます。 _エイリアス_: `/resume`、`/continue` + +```bash frame="none" +/sessions +``` + +**キーバインド:** `ctrl+x l` + +--- + +### 共有 + +現在のセッションを共有します。 [詳細はこちら](/docs/share)。 + +```bash frame="none" +/share +``` + +**キーバインド:** `ctrl+x s` + +--- + +### テーマ + +利用可能なテーマをリストします。 + +```bash frame="none" +/theme +``` + +**キーバインド:** `ctrl+x t` + +--- + +### 思考 + +会話内の思考/推論ブロックの表示を切り替えます。有効にすると、拡張思考をサポートするモデルの推論プロセスを確認できます。 + +:::note +このコマンドは、思考ブロックを**表示**するかどうかのみを制御します。モデルの推論機能を有効または無効にすることはありません。実際の推論機能を切り替えるには、`ctrl+t` を使用してモデルバリアントを循環させます。 +::: + +```bash frame="none" +/thinking +``` + +--- + +### 元に戻す + +会話の最後のメッセージを元に戻します。最新のユーザーメッセージ、その後のすべての応答、およびファイルの変更を削除します。 + +:::tip +加えられたファイルの変更も元に戻されます。 +::: +内部的には、`undo` を使用してファイルの変更を管理します。したがって、あなたのプロジェクトは **Git リポジトリ** である必要があります。 + +```bash frame="none" +/undo +``` + +**キーバインド:** `ctrl+x u` + +--- + +### 共有の解除 + +現在のセッションの共有を解除します。 [詳細はこちら](/docs/share#un-sharing)。 + +```bash frame="none" +/unshare +``` + +--- + +## エディタのセットアップ + +`/editor` および `/export` コマンドはどちらも、`EDITOR` 環境変数で指定されたエディターを使用します。 + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + +これを永続的にするには、これをシェルプロファイルに追加します。 +`~/.bashrc`、`~/.zshrc`など + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + +これを永続的にするには、**システムプロパティ** > **環境変数**を使用します。 + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + +これを永続的にするには、これを PowerShell プロファイルに追加します。 + + + + +一般的なエディターオプションには次のものがあります。 + +- `code` - VS Code +- `cursor` - Cursor +- `windsurf` - Windsurf +- `nvim` - Neovim エディター +- `vim` - Vim エディター +- `nano` - ナノエディター +- `notepad` - Windows メモ帳 +- `subl` - Sublime Text + +:::note +VS Code などの一部のエディターは、`--wait` フラグを使用して起動する必要があります。 +::: +一部のモードでは実行にコマンドライン引数が必要です。`--wait` フラグを使うと、エディターが閉じるまでプロセスが待機します。 + +--- + +## 設定 + +OpenCode 設定ファイルを通じて TUI の動作をカスタマイズできます。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### オプション + +- `scroll_acceleration` - macOS スタイルのスクロールアクセラレーションを有効にして、スムーズで自然なスクロールを実現します。有効にすると、高速スクロールジェスチャではスクロール速度が向上し、ゆっくりとした動きでは正確なままになります。 **この設定は `scroll_speed` よりも優先され、有効になっている場合は上書きされます。** +- `scroll_speed` - スクロールコマンドを使用するときに TUI がスクロールする速度を制御します (最小: `1`)。デフォルトは `3` です。 **注: `scroll_acceleration.enabled` が `true` に設定されている場合、これは無視されます。** + +--- + +## カスタマイズ + +コマンドパレット (`ctrl+x h` または `/help`) を使用して、TUI ビューのさまざまな側面をカスタマイズできます。これらの設定は再起動後も維持されます。 + +--- + +#### ユーザー名の表示 + +チャットメッセージにユーザー名を表示するかどうかを切り替えます。これには次の方法でアクセスします。 + +- コマンドパレット:「ユーザー名」または「ユーザー名を隠す」を検索します。 +- 設定は自動的に保持され、TUI セッション全体で記憶されます。 diff --git a/packages/web/src/content/docs/ja/web.mdx b/packages/web/src/content/docs/ja/web.mdx new file mode 100644 index 00000000000..77095dac75b --- /dev/null +++ b/packages/web/src/content/docs/ja/web.mdx @@ -0,0 +1,143 @@ +--- +title: ウェブ +description: ブラウザで OpenCode を使用する。 +--- + +OpenCode はブラウザで Web アプリケーションとして実行でき、ターミナルを必要とせずに同じ強力な AI コーディングエクスペリエンスを提供します。 + +![OpenCode Web - 新しいセッション](../../../assets/web/web-homepage-new-session.png) + +--- + +## はじめる + +以下を実行して Web インターフェースを開始します。 + +```bash +opencode web +``` + +これにより、利用可能なランダムなポートを使用して `127.0.0.1` でローカルサーバーが起動され、デフォルトのブラウザで OpenCode が自動的に開きます。 + +:::caution +`OPENCODE_SERVER_PASSWORD` が設定されていない場合、サーバーは保護されません。これはローカルで使用する場合には問題ありませんが、ネットワークアクセス用に設定する必要があります。 +::: +:::tip[Windows ユーザー] +最高のエクスペリエンスを得るには、PowerShell ではなく [WSL](/docs/windows-wsl) から `opencode web` を実行します。これにより、ファイルシステムへの適切なアクセスとターミナルの統合が保証されます。 +::: + +--- + +## 設定 + +コマンドラインフラグを使用するか、[設定ファイル](/docs/config)で Web サーバーを設定できます。 + +### ポート + +デフォルトでは、OpenCode は使用可能なポートを選択します。ポートを指定できます。 + +```bash +opencode web --port 4096 +``` + +### ホスト名 + +デフォルトでは、サーバーは `127.0.0.1` (localhost のみ) にバインドされます。ネットワーク上で OpenCode にアクセスできるようにするには: + +```bash +opencode web --hostname 0.0.0.0 +``` + +`0.0.0.0` を使用すると、OpenCode はローカルアドレスとネットワークアドレスの両方を表示します。 + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### mDNS 検出 + +mDNS を有効にして、ローカルネットワーク上でサーバーを検出できるようにします。 + +```bash +opencode web --mdns +``` + +これにより、ホスト名が自動的に `0.0.0.0` に設定され、サーバーが `opencode.local` としてアドバタイズされます。 + +mDNS ドメイン名をカスタマイズして、同じネットワーク上で複数のインスタンスを実行できます。 + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +CORS の追加ドメインを許可するには (カスタムフロントエンドに便利): + +```bash +opencode web --cors https://example.com +``` + +### 認証 + +アクセスを保護するには、`OPENCODE_SERVER_PASSWORD` 環境変数を使用してパスワードを設定します。 + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +ユーザー名のデフォルトは `opencode` ですが、`OPENCODE_SERVER_USERNAME` で変更できます。 + +--- + +## Web インターフェースの使用 + +開始すると、Web インターフェイスから OpenCode セッションにアクセスできるようになります。 + +### セッション + +ホームページからセッションを表示および管理します。アクティブなセッションを確認したり、新しいセッションを開始したりできます。 + +![OpenCode Web - アクティブなセッション](../../../assets/web/web-homepage-active-session.png) + +### サーバーステータス + +「サーバーを表示」をクリックすると、接続されているサーバーとそのステータスが表示されます。 + +![OpenCode Web - サーバー](../../../assets/web/web-homepage-see-servers.png) + +--- + +## ターミナルの接続 + +実行中の Web サーバーにターミナル TUI を接続できます。 + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +これにより、Web インターフェイスとターミナルの両方を同時に使用し、同じセッションと状態を共有できるようになります。 + +--- + +## 設定ファイル + +`opencode.json` 設定ファイルでサーバー設定を構成することもできます。 + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +コマンドラインフラグは、設定ファイルの設定よりも優先されます。 diff --git a/packages/web/src/content/docs/ja/windows-wsl.mdx b/packages/web/src/content/docs/ja/windows-wsl.mdx new file mode 100644 index 00000000000..f5a09f2708d --- /dev/null +++ b/packages/web/src/content/docs/ja/windows-wsl.mdx @@ -0,0 +1,116 @@ +--- +title: Windows (WSL) +description: WSL を使って Windows で OpenCode を使う。 +--- + +import { Steps } from "@astrojs/starlight/components" + +OpenCode は Windows で直接実行できますが、より快適に使うには [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) の利用をおすすめします。WSL は OpenCode の機能とスムーズに連携する Linux 環境を提供します。 + +:::tip[WSL を使う理由] +WSL を使うと、ファイルシステム性能、ターミナルサポート、OpenCode が依存する開発ツールとの互換性が向上します。 +::: + +--- + +## セットアップ + + + +1. **WSL をインストールする** + + まだの場合は、Microsoft 公式ガイドを使って [WSL をインストール](https://learn.microsoft.com/en-us/windows/wsl/install) します。 + +2. **WSL で OpenCode をインストールする** + + WSL の準備ができたら WSL のターミナルを開き、[インストール方法](/docs/) のいずれかで OpenCode をインストールします。 + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **WSL から OpenCode を使う** + + プロジェクトディレクトリに移動し(Windows ファイルは `/mnt/c/` や `/mnt/d/` などからアクセス)、OpenCode を実行します。 + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## デスクトップアプリ + WSL サーバー + +OpenCode デスクトップアプリを使いつつ、サーバーは WSL で動かしたい場合は次の手順です。 + +1. **WSL でサーバーを起動する** + + 外部接続を許可するため、`--hostname 0.0.0.0` を付けて起動します。 + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **デスクトップアプリを接続する** + + `http://localhost:4096` に接続します。 + +:::note +環境によって `localhost` が使えない場合は、WSL 側で `hostname -I` を実行して IP アドレスを確認し、`http://:4096` に接続してください。 +::: +:::caution +`--hostname 0.0.0.0` を使う場合は、`OPENCODE_SERVER_PASSWORD` を設定してサーバーを保護してください。 + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +## Web クライアント + WSL + +Windows で Web 利用を快適にするには: + +1. **PowerShell ではなく WSL ターミナルで `opencode web` を実行する** + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Windows のブラウザからアクセスする** + + `http://localhost:` にアクセスします(URL は OpenCode が表示します)。 + +WSL から `opencode web` を実行すると、適切なファイルシステムアクセスとターミナル統合を維持したまま、Windows ブラウザから利用できます。 + +--- + +## Windows ファイルへのアクセス + +WSL からは `/mnt/` ディレクトリ経由で Windows ファイルにアクセスできます。 + +- `C:` drive → `/mnt/c/` +- `D:` drive → `/mnt/d/` +- そのほかのドライブも同様です + +例: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +よりスムーズに使うには、リポジトリを WSL のファイルシステム(例: `~/code/`)にクローンまたはコピーして、そこで OpenCode を実行することをおすすめします。 +::: + +--- + +## ヒント + +- Windows ドライブ上のプロジェクトでも、OpenCode は WSL で実行するとファイルアクセスがスムーズです +- OpenCode と一緒に VS Code の [WSL 拡張機能](https://code.visualstudio.com/docs/remote/wsl) を使うと統合的な開発フローを構築できます +- OpenCode の設定とセッションは WSL 環境内の `~/.local/share/opencode/` に保存されます diff --git a/packages/web/src/content/docs/ja/zen.mdx b/packages/web/src/content/docs/ja/zen.mdx new file mode 100644 index 00000000000..751ca45e45d --- /dev/null +++ b/packages/web/src/content/docs/ja/zen.mdx @@ -0,0 +1,245 @@ +--- +title: OpenCode Zen +description: OpenCode によって提供されるモデルの厳選されたリスト。 +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen は、OpenCode チームによって提供される、テストおよび検証されたモデルのリストです。 + +:::note +OpenCode Zen は現在ベータ版です。 +::: +Zen は OpenCode の他のプロバイダーと同様に機能します。 OpenCode Zen にログインすると、API キーを取得できます。これは **完全にオプション** であり、OpenCode を使用するために使用する必要はありません。 + +--- + +## 背景 + +モデルはたくさんありますが、そのうちのほんの一部です +これらのモデルはコーディングエージェントとしてうまく機能します。さらに、ほとんどのプロバイダーは、 +構成が大きく異なります。したがって、まったく異なるパフォーマンスと品質が得られます。 + +:::tip +私たちは、OpenCode で適切に動作するモデルとプロバイダーの選択されたグループをテストしました。 +::: +OpenRouter などを通じてモデルを使用している場合は、決してそうすることはできません。 +必要なモデルの最高のバージョンを入手しているかどうかを確認してください。 + +これを修正するために、いくつかのことを行いました。 + +1. 私たちは選択したモデルのグループをテストし、その方法についてチームと話し合いました。 + それらを実行するのが最善です。 +2. その後、いくつかのプロバイダーと協力して、これらが確実に提供されるようにしました。 +3. 最後に、モデルとプロバイダーの組み合わせをベンチマークし、次の結果を導き出しました。 + 私たちが自信を持ってお勧めするリストをご紹介します。 + +OpenCode Zen は、これらのモデルへのアクセスを可能にする AI ゲートウェイです。 + +--- + +## 仕組み + +OpenCode Zen は、OpenCode の他のプロバイダーと同様に機能します。 + +1. **OpenCode Zen** にログインし、請求内容を追加します + 詳細を確認し、API キーをコピーします。 +2. TUI で `/connect` コマンドを実行し、OpenCode Zen を選択して API キーを貼り付けます。 +3. TUI で `/models` を実行すると、推奨されるモデルのリストが表示されます。 + +リクエストごとに料金が請求され、アカウントにクレジットを追加できます。 + +--- + +## エンドポイント + +次の API エンドポイントを通じてモデルにアクセスすることもできます。 + +| Model | Model ID | Endpoint | AI SDK Package | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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 設定の [model id](/docs/config/#models) +`opencode/` 形式を使用します。たとえば、GPT 5.2 Codex の場合は、 +設定で `opencode/gpt-5.2-codex` を使用してください。 + +--- + +### モデル + +利用可能なモデルとそのメタデータの完全なリストは、次から取得できます。 + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## 価格 + +当社は従量課金制モデルをサポートしています。以下は **100 万トークンあたりの価格**です。 + +| Model | Input | Output | Cached Read | Cached Write | +| --------------------------------- | ------ | ------ | ----------- | ------------ | +| Big Pickle | Free | Free | Free | - | +| MiniMax M2.1 Free | Free | Free | Free | - | +| MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | +| GLM 4.7 Free | Free | Free | Free | - | +| 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 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 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.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 | Free | Free | Free | - | + +使用履歴に _Claude Haiku 3.5_ が表示されるかもしれません。これは [セッションのタイトルを生成するために使用される低コストモデル](/docs/config/#models) です。 + +:::note +クレジットカード手数料は実費で引き継がれます (4.4% + 取引ごとに 0.30 ドル)。それ以上の料金はかかりません。 +::: + +- GLM 4.7 Free は期間限定で OpenCode で入手できます。チームはこの時間を利用してフィードバックを収集し、モデルを改善します。 +- Kim K2.5 Free は OpenCode で期間限定で利用可能です。チームはこの時間を利用してフィードバックを収集し、モデルを改善します。 +- MiniMax M2.1 Free は期間限定で OpenCode で入手できます。チームはこの時間を利用してフィードバックを収集し、モデルを改善します。 +- Big Pickle は、期間限定で OpenCode で無料で利用できるステルスモデルです。チームはこの時間を利用してフィードバックを収集し、モデルを改善します。 + +ご質問がございましたら、お問い合わせください。 + +--- + +### 自動リロード + +残高が 5 ドルを下回ると、Zen は自動的に 20 ドルをリロードします。 + +自動リロード量を変更できます。自動リロードを完全に無効にすることもできます。 + +--- + +### 月ごとの制限 + +ワークスペース全体およびワークスペースごとに月ごとの使用制限を設定することもできます。 +あなたのチームのメンバー。 + +たとえば、毎月の使用制限を 20 ドルに設定したとします。Zen は使用しません。 +月に20ドル以上。ただし、自動リロードを有効にしている場合、Zen が終了する可能性があります。 +残高が 5 ドルを下回ると、20 ドル以上の請求が行われます。 + +--- + +## プライバシー + +すべてのモデルは米国でホストされています。当社のプロバイダーはゼロ保持ポリシーに従い、次の例外を除いて、モデルのトレーニングにデータを使用しません。 + +- 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)に従います。 + +--- + +## チーム向け + +Zen はチームにも効果的です。チームメイトを招待し、役割を割り当て、キュレートすることができます +チームが使用するモデルなど。 + +:::note +ワークスペースは現在、ベータ版の一部としてチームに無料で提供されています。 +::: +価格の詳細については近日中にお知らせします。 + +--- + +### ロール + +チームメイトをワークスペースに招待し、役割を割り当てることができます。 + +- **管理者**: モデル、メンバー、API キー、請求を管理します。 +- **メンバー**: 自分の API キーのみを管理します + +管理者は、コストを管理するために各メンバーの毎月の支出制限を設定することもできます。 + +--- + +### モデルアクセス + +管理者は、ワークスペースの特定のモデルを有効または無効にすることができます。無効なモデルに対してリクエストを行うと、エラーが返されます。 + +これは、モデルの使用を無効にしたい場合に便利です。 +データを収集します。 + +--- + +### 自分のキーを持ち込む + +Zen の他のモデルにアクセスしながら、独自の OpenAI または Anthropic API キーを使用できます。 + +独自のキーを使用する場合、トークンは Zen ではなくプロバイダーによって直接請求されます。 + +たとえば、組織はすでに OpenAI または Anthropic のキーを持っている可能性があります。 +Zen が提供するものの代わりにそれを使用したいとします。 + +--- + +## 目標 + +私たちは次の目的で OpenCode Zen を作成しました。 + +1. **ベンチマーク** コーディングエージェントに最適なモデル/プロバイダー。 +2. **最高品質**のオプションにアクセスでき、パフォーマンスをダウングレードしたり、より安価なプロバイダーにルートしたりする必要はありません。 +3. 原価で販売することで**価格下落**を転嫁します。したがって、唯一のマークアップは処理手数料をカバーすることです。 +4. 他のコーディングエージェントとの併用を許可することで、**ロックイン**がなくなります。また、常に OpenCode で他のプロバイダーも使用できるようにします。 diff --git a/packages/web/src/content/docs/ko/acp.mdx b/packages/web/src/content/docs/ko/acp.mdx new file mode 100644 index 00000000000..2fbd58013f8 --- /dev/null +++ b/packages/web/src/content/docs/ko/acp.mdx @@ -0,0 +1,156 @@ +--- +title: ACP 지원 +description: ACP 호환 편집기에서 opencode를 사용하세요. +--- + +opencode는 [Agent Client Protocol](https://agentclientprotocol.com) 또는 (ACP)을 지원하며, 호환 편집기 및 IDE에서 직접 사용할 수 있습니다. + +:::tip +ACP를 지원하는 편집기 및 도구 목록의 경우 [ACP 진행 보고서](https://zed.dev/blog/acp-progress-report#available-now)를 확인하십시오. +::: + +ACP는 코드 편집기와 AI 코딩 에이전트 간의 통신을 표준화하는 개방형 프로토콜입니다. + +--- + +## 구성 + +ACP를 통해 opencode를 사용하려면 `opencode acp` 명령을 실행하려면 편집기를 구성하십시오. + +명령은 opencode를 실행하여 JSON-RPC를 통해 편집기와 통신하는 ACP 호환 하위 프로세스로 시작합니다. + +아래는 ACP를 지원하는 인기있는 편집기의 예입니다. + +--- + +##### Zed + +[Zed](https://zed.dev) 구성 (`~/.config/zed/settings.json`)에 추가 : + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +그것을 열려면 **Command Palette **에서 `agent: new thread` 동작을 사용하십시오. + +`keymap.json`를 편집하여 키보드 단축키도 결합할 수 있습니다. + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +#### JetBrains IDEs + +[JetBrains IDE]에 추가하십시오 (https://www.jetbrains.com/) [documentation]에 따라 acp.json (https://www.jetbrains.com/help/ai-assistant/acp.html): + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +그것을 열려면 AI Chat Agent selector의 새로운 'opencode' 에이전트를 사용하십시오. + +--- + +#### Avante.nvim + +[Avante.nvim](https://github.com/yetone/avante.nvim) 구성에 추가하십시오: + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +환경 변수를 전달해야 하는 경우: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +#### CodeCompanion.nvim + +opencode를 [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim)에서 ACP 에이전트로 사용하려면 Neovim config에 다음을 추가하십시오. + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +이 구성은 CodeCompanion을 설정하여 채팅을 위한 ACP 에이전트로 opencode를 사용합니다. + +환경 변수 (`OPENCODE_API_KEY`와 같은)를 전달해야하는 경우, CodeCompanion.nvim 문서에서 [Configuring Adapters: Environment variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key)를 참조하십시오. + +## 지원 기능 + +opencode는 터미널과 동일하게 ACP를 통해 작동합니다. 모든 기능은 지원됩니다: + +:::note +`/undo` 및 `/redo`와 같은 일부 내장 슬래시 명령은 현재 지원되지 않습니다. +::: + +- 내장 도구 (파일 작업, terminal 명령 등) +- 사용자 정의 도구 및 슬래시 명령 +- opencode config에서 설정된 MCP 서버 +- `AGENTS.md`의 프로젝트 별 규칙 +- 사용자 정의 포맷 및 라이터 +- 에이전트 및 권한 시스템 diff --git a/packages/web/src/content/docs/ko/agents.mdx b/packages/web/src/content/docs/ko/agents.mdx new file mode 100644 index 00000000000..5b37122435f --- /dev/null +++ b/packages/web/src/content/docs/ko/agents.mdx @@ -0,0 +1,746 @@ +--- +title: 에이전트 +description: 전문 에이전트를 구성하고 사용하세요. +--- + +에이전트는 특정 작업과 워크플로우를 전문으로 하는 구성 가능한 AI 보조자입니다. 사용자 정의 프롬프트, 모델, 도구 액세스로 집중된 도구를 만들 수 있습니다. + +:::tip +코드 변경 없이 제안을 검토할 때는 Plan 에이전트를 사용하세요. +::: + +세션 중에 에이전트를 전환하거나 `@` 멘션으로 호출할 수 있습니다. + +--- + +## 유형 + +OpenCode에는 두 가지 유형의 에이전트가 있습니다: 기본 에이전트(Primary Agent)와 서브 에이전트(Subagent). + +--- + +### 기본 에이전트 + +기본 에이전트는 사용자가 직접 상호 작용하는 주요 보조자입니다. **Tab** 키 또는 설정된 `switch_agent` 키바인드를 사용하여 순환할 수 있습니다. 이 에이전트는 주요 대화를 처리합니다. 도구 액세스는 권한을 통해 구성됩니다 — 예를 들어, Build는 모든 도구를 사용할 수 있지만 Plan은 제한됩니다. + +:::tip +세션 중에 **Tab** 키를 사용하여 기본 에이전트를 전환할 수 있습니다. +::: + +OpenCode는 두 가지 내장 기본 에이전트, **Build** 및 **Plan**을 제공합니다. 아래에서 자세히 살펴봅니다. + +--- + +### 서브 에이전트 + +서브 에이전트는 기본 에이전트가 특정 작업을 위해 호출할 수 있는 전문 보조자입니다. 또한 메시지에서 **@멘션**을 통해 수동으로 호출할 수도 있습니다. + +OpenCode는 두 가지 내장 서브 에이전트, **General** 및 **Explore**를 제공합니다. 아래에서 자세히 살펴봅니다. + +--- + +## 기본 제공 + +OpenCode는 기본 에이전트와 두 개의 내장 서브 에이전트를 제공합니다. + +--- + +### Build + +_모드_: `primary` + +Build는 모든 도구가 활성화된 **기본** 에이전트입니다. 파일 조작 및 시스템 명령에 대한 전체 액세스가 필요한 개발 작업을 위한 표준 에이전트입니다. + +--- + +### Plan + +_모드_: `primary` + +계획 및 분석을 위해 설계된 제한된 에이전트입니다. 더 많은 제어권을 부여하고 의도하지 않은 변경을 방지하기 위해 권한 시스템을 사용합니다. +기본적으로 다음은 모두 `ask`로 설정됩니다: + +- `file edits`: 모든 쓰기, 패치 및 편집 +- `bash`: 모든 bash 명령 + +이 에이전트는 코드를 분석하거나 변경을 제안받고 싶지만, 코드베이스에 실제 수정 없이 계획만 만들고 싶을 때 유용합니다. + +--- + +### General + +_모드_: `subagent` + +복잡한 질문을 연구하고 다단계 작업을 실행하기 위한 범용 에이전트입니다. 전체 도구 액세스(todo 제외)를 가지므로 필요할 때 파일 변경을 수행할 수 있습니다. 여러 단위의 작업을 병렬로 실행할 때 사용하세요. + +--- + +### Explore + +_모드_: `subagent` + +코드베이스를 탐색하는 빠르고 읽기 전용인 에이전트입니다. 파일을 수정할 수 없습니다. 패턴, 키워드로 코드를 검색하거나 코드베이스에 대한 질문에 답하기 위해 파일을 빠르게 찾아야 할 때 사용하세요. + +--- + +### Compaction + +_모드_: `primary` + +긴 컨텍스트를 작은 요약으로 압축하는 숨겨진 시스템 에이전트입니다. 필요한 경우 자동으로 실행되며 UI에서 선택할 수 없습니다. + +--- + +### Title + +_모드_: `primary` + +짧은 세션 제목을 생성하는 숨겨진 시스템 에이전트입니다. 자동으로 실행되며 UI에서 선택할 수 없습니다. + +--- + +### Summary + +_모드_: `primary` + +세션 요약을 만드는 숨겨진 시스템 에이전트입니다. 자동으로 실행되며 UI에서 선택할 수 없습니다. + +--- + +## 사용법 + +1. 기본 에이전트의 경우, 세션 중에 **Tab** 키를 사용하여 순환합니다. 구성된 `switch_agent` 키바인드도 사용할 수 있습니다. + +2. 서브 에이전트는 다음과 같이 호출할 수 있습니다: + - 설명에 근거하여 전문적인 작업을 위해 기본 에이전트에 의해 **자동으로** 호출됨. + - 메시지에서 서브 에이전트를 **@멘션**. 예를 들어: + + ```txt frame="none" + @general help me search for this function + ``` + +3. **세션 간 이동**: 서브 에이전트가 자체 자식 세션을 만들 때, 부모 세션과 자식 세션 간을 탐색할 수 있습니다. + - **\+Right** (또는 부모 → 자식1 → 자식2 순으로 이동하기 위해 설정된 `session_child_cycle` 키바인드) + - **\+Left** (또는 `session_child_cycle_reverse` 키바인드) 부모 방향으로 되돌아가기: 자식2 → 자식1 → 부모 + + 이를 통해 주요 대화와 전문적인 서브 에이전트 작업 간을 원활하게 전환할 수 있습니다. + +--- + +## 구성 + +내장 에이전트를 사용자 정의하거나 구성을 통해 자신만의 에이전트를 만들 수 있습니다. 에이전트는 두 가지 방법으로 구성될 수 있습니다: + +--- + +### JSON + +`opencode.json` config 파일에 에이전트 구성: + +```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 + +Markdown 파일을 사용하여 에이전트를 정의 할 수 있습니다. 그들에 게: + +- 글로벌: `~/.config/opencode/agents/` +- 프로젝트: `.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 파일 이름은 에이전트 이름입니다. 예를 들어, `review.md`는 `review` 에이전트을 만듭니다. + +--- + +## 옵션 + +이 구성 옵션들을 자세히 살펴봅시다. + +--- + +### 설명 + +`description` 옵션을 사용하여 에이전트가 무엇을 하고 언제 사용해야 하는지에 대한 간단한 설명을 제공합니다. + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +\*\* 필수 구성 옵션입니다. + +--- + +### 온도 + +`temperature` 구성으로 LLM 응답의 무작위성과 창의성을 제어합니다. + +값이 낮을수록 더 집중되고 결정적인 응답을 생성하며, 값이 높을수록 창의성과 가변성이 증가합니다. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +온도 값은 일반적으로 0.0에서 1.0 사이입니다: + +- **0.0-0.2**: 매우 집중되고 신중한 응답, 코드 분석 및 계획에 이상적 +- **0.3-0.5**: 창의성과 정확성의 균형, 일반 개발 작업에 좋음 +- **0.6-1.0**: 더 창의적이고 다양한 응답, 브레인스토밍 및 탐색에 유용함 + +```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}" + } + } +} +``` + +온도가 지정되지 않은 경우, OpenCode는 모델별 기본값을 사용합니다. 일반적으로 대부분의 모델은 0, Qwen 모델의 경우 0.55입니다. + +--- + +## 최대 단계 + +에이전트가 중지하고 사용자와 다시 상호 작용하기 전에 실행할 수 있는 최대 단계 수를 제어합니다. 이를 통해 에이전트의 행동과 비용을 제어할 수 있습니다. + +설정되지 않은 경우, 에이전트는 모델이 중지하거나 사용자가 세션을 중단할 때까지 계속됩니다. + +```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 + } + } +} +``` + +제한에 도달하면, 에이전트는 작업 요약과 권장되는 남은 작업을 신속하게 응답하도록 지시받습니다. + +:::caution +레거시 `maxSteps` 필드는 더 이상 사용되지 않습니다. 대신 `steps`를 사용하십시오. +::: + +--- + +#### 비활성화 + +`true`로 설정하여 에이전트를 비활성화합니다. + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +#### 프롬프트 + +`prompt` 구성으로 이 에이전트를 위한 사용자 정의 시스템 프롬프트 파일을 지정하십시오. 프롬프트 파일은 에이전트의 목적에 따른 지시를 포함해야 합니다. + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +이 경로는 구성 파일이 있는 위치를 기준으로 합니다. 따라서 글로벌 OpenCode 구성과 프로젝트별 구성 모두에서 작동합니다. + +--- + +### 모델 + +`model` 구성을 사용하여 이 에이전트에 대한 모델을 재정의합니다. 다른 작업에 최적화된 다른 모델을 사용하는 데 유용합니다. 예를 들어, 계획을 위한 빠른 모델, 구현을 위한 더 강력한 모델 등입니다. + +:::tip +모델을 지정하지 않는 경우, 기본 에이전트는 [전역 구성 모델](/docs/config#models)을 사용하며, 서브 에이전트는 자신을 호출한 기본 에이전트의 모델을 사용합니다. +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +OpenCode 구성의 모델 ID는 `provider/model-id` 형식을 사용합니다. 예를 들어, [OpenCode Zen](/docs/zen)을 사용한다면, GPT 5.1 Codex에 `opencode/gpt-5.1-codex`를 사용할 수 있습니다. + +--- + +## 도구 + +`tools` 구성으로 이 에이전트가 사용할 수 있는 도구를 제어합니다. `true` 또는 `false`로 설정하여 특정 도구를 활성화하거나 비활성화할 수 있습니다. + +```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 +에이전트별 구성은 글로벌 구성을 덮어씁니다. +::: + +한 번에 여러 도구를 제어하기 위해 와일드카드를 사용할 수 있습니다. 예를 들어, MCP 서버에서 모든 도구를 비활성화하려면: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[도구에 대해 더 알아보기](/docs/tools). + +--- + +## 권한 + +에이전트가 수행할 수 있는 작업을 관리할 수 있는 권한을 구성할 수 있습니다. 현재 `edit`, `bash` 및 `webfetch` 도구에 대한 권한은 다음과 같습니다. + +- `"ask"` - 도구를 실행하기 전에 승인 요청 +- `"allow"` - 승인 없이 모든 작업 허용 +- `"deny"` - 도구 비활성화 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +에이전트별로 이 권한을 재정의(override)할 수 있습니다. + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +Markdown 에이전트에서도 권한을 설정할 수 있습니다. + +```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. +``` + +특정 bash 명령에 대한 권한을 설정할 수 있습니다. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +이것은 glob 패턴을 사용할 수 있습니다. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +또한 `*` 와일드카드를 사용하여 모든 명령에 대한 권한을 관리할 수 있습니다. +마지막 일치 규칙이 우선하므로, `*` 와일드카드를 먼저 두고 특정 규칙을 나중에 두십시오. + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[권한에 대해 더 알아보기](/docs/permissions). + +--- + +### 모드 + +`mode` 구성으로 에이전트 모드를 제어합니다. `mode` 옵션은 에이전트가 어떻게 사용될 수 있는지 결정하는 데 사용됩니다. + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +`mode` 옵션은 `primary`, `subagent`, 또는 `all`로 설정할 수 있습니다. `mode`가 지정되지 않은 경우 `all`이 기본값입니다. + +--- + +## 숨김 + +`hidden: true`를 사용하여 `@` 자동 완성 메뉴에서 에이전트를 숨깁니다. 작업 도구를 통해 다른 에이전트에 의해 프로그래밍 방식으로 호출되어야 하는 내부 에이전트에 유용합니다. + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +자동 완성 메뉴의 사용자 가시성에만 영향을 미칩니다. 숨겨진 에이전트는 권한이 허용된다면 여전히 작업 도구를 통해 모델에 의해 호출될 수 있습니다. + +:::note +`mode: subagent` 에이전트에만 적용됩니다. +::: + +--- + +## 작업 권한 + +`permission.task`와 작업 도구를 통해 에이전트가 호출할 수 있는 서브 에이전트를 제어합니다. 유연한 일치를 위한 glob 패턴을 사용합니다. + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +`deny`로 설정할 때, 서브 에이전트는 작업 도구 설명에서 완전히 제거됩니다. 따라서 모델은 그것을 호출하려고 시도하지 않습니다. + +:::tip +규칙은 순서대로 평가되며, **마지막 일치 규칙**이 우선합니다. 위의 예에서 `orchestrator-planner`는 `*` (deny)와 `orchestrator-*` (allow) 모두 일치하지만 `orchestrator-*`가 `*` 뒤에 오므로 결과는 `allow`입니다. +::: + +:::tip +사용자는 에이전트의 작업 권한이 거부되더라도 `@` 자동 완성 메뉴를 통해 직접 어떤 서브 에이전트든 호출할 수 있습니다. +::: + +--- + +### 색상 + +`color` 옵션으로 UI에서 에이전트의 시각적 모양을 사용자 정의합니다. + +유효한 hex 색상(예: `#FF5733`) 또는 테마 색상을 사용하십시오: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +`top_p` 옵션으로 응답의 다양성을 제어합니다. 무작위성 제어를 위한 온도의 대안입니다. + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +값은 0.0에서 1.0 사이입니다. 낮은 값은 더 집중되고, 높은 값은 더 다양합니다. + +--- + +### 추가 옵션 + +에이전트 구성에 지정하는 다른 옵션은 모델 옵션으로 공급자에게 **직접 전달**됩니다. 이를 통해 공급자별 기능 및 매개변수를 사용할 수 있습니다. + +예를 들어, OpenAI의 추론 모델과 함께, 추론 노력을 제어할 수 있습니다: + +```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" + } + } +} +``` + +이 추가 옵션은 모델과 공급자별로 다릅니다. 사용 가능한 매개변수는 공급자의 문서를 확인하십시오. + +:::tip +`opencode models`를 실행하여 사용 가능한 모델 목록을 볼 수 있습니다. +::: + +--- + +## 에이전트 만들기 + +다음 명령을 사용하여 새로운 에이전트를 만들 수 있습니다: + +```bash +opencode agent create +``` + +이 대화형 명령은: + +1. 에이전트를 저장할 위치를 묻습니다 (전역 또는 프로젝트별). +2. 에이전트가 해야 할 일에 대한 설명을 묻습니다. +3. 적절한 시스템 프롬프트 및 식별자를 생성합니다. +4. 에이전트가 접근할 수 있는 도구를 선택하게 합니다. +5. 마지막으로, 에이전트 구성을 가진 markdown 파일을 생성합니다. + +--- + +## 사용 사례 + +다른 에이전트를 위한 몇 가지 일반적인 사용 사례는 다음과 같습니다. + +- **Build Agent**: 모든 도구와 함께 전체 개발 작업 +- **Plan Agent**: 변경 없이 분석 및 계획 +- **Review Agent**: 읽기 전용 액세스 및 문서 도구와 함께 코드 리뷰 +- **Debug Agent**: bash 및 읽기 도구와 함께 조사에 집중 +- **Docs Agent**: 파일 작업과 문서 작성을 하지만 시스템 명령 없음 + +--- + +## 예제 + +여기에 유용 할 수있는 몇 가지 예 에이전트가 있습니다. + +:::tip +공유하고 싶은 에이전트가 있습니까? [PR](https://github.com/anomalyco/opencode). +::: + +--- + +### 문서 에이전트 + +```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 +``` + +--- + +## 보안 감사 + +```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/ko/cli.mdx b/packages/web/src/content/docs/ko/cli.mdx new file mode 100644 index 00000000000..a78ac96f39d --- /dev/null +++ b/packages/web/src/content/docs/ko/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: opencode CLI 옵션과 명령어. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +opencode CLI는 인수 없이 실행하면 기본적으로 [TUI](/docs/tui)를 시작합니다. + +```bash +opencode +``` + +이 페이지에 나온 것처럼 명령을 함께 전달할 수도 있습니다. 이를 통해 opencode를 프로그래밍 방식으로 사용할 수 있습니다. + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +OpenCode 터미널 사용자 인터페이스를 시작합니다. + +```bash +opencode [project] +``` + +#### 플래그 + +| 플래그 | 축약 | 설명 | +| ------------ | ---- | ---------------------------------------------------------------------- | +| `--continue` | `-c` | 마지막 세션 이어서 실행 | +| `--session` | `-s` | 이어서 실행할 세션 ID | +| `--fork` | | 세션을 이어갈 때 포크 생성 (`--continue` 또는 `--session`과 함께 사용) | +| `--prompt` | | 사용할 프롬프트 | +| `--model` | `-m` | 사용할 모델 (`provider/model` 형식) | +| `--agent` | | 사용할 에이전트 | +| `--port` | | 수신 포트 | +| `--hostname` | | 수신 호스트명 | + +--- + +## 명령어 + +opencode CLI는 아래 명령들도 제공합니다. + +--- + +### agent + +opencode용 에이전트를 관리합니다. + +```bash +opencode agent [command] +``` + +--- + +### attach + +`serve` 또는 `web` 명령으로 이미 실행 중인 opencode 백엔드 서버에 터미널을 연결합니다. + +```bash +opencode attach [url] +``` + +원격 opencode 백엔드와 TUI를 연결해 사용할 수 있습니다. 예: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### 플래그 + +| 플래그 | 축약 | 설명 | +| ----------- | ---- | -------------------------- | +| `--dir` | | TUI를 시작할 작업 디렉터리 | +| `--session` | `-s` | 이어서 실행할 세션 ID | + +--- + +#### create + +커스텀 설정으로 새 에이전트를 만듭니다. + +```bash +opencode agent create +``` + +이 명령은 커스텀 시스템 프롬프트와 도구 설정을 사용해 새 에이전트를 만드는 과정을 안내합니다. + +--- + +#### list + +사용 가능한 모든 에이전트를 표시합니다. + +```bash +opencode agent list +``` + +--- + +### auth + +provider 인증 정보와 로그인을 관리합니다. + +```bash +opencode auth [command] +``` + +--- + +#### login + +OpenCode는 [Models.dev](https://models.dev)의 provider 목록을 기반으로 동작하므로, `opencode auth login`으로 원하는 provider의 API 키를 설정할 수 있습니다. 인증 정보는 `~/.local/share/opencode/auth.json`에 저장됩니다. + +```bash +opencode auth login +``` + +OpenCode 시작 시 인증 파일에서 provider 정보를 불러오며, 시스템 환경 변수나 프로젝트의 `.env`에 정의된 키도 함께 로드합니다. + +--- + +#### list + +인증 파일에 저장된 provider 목록을 표시합니다. + +```bash +opencode auth list +``` + +축약형도 사용할 수 있습니다. + +```bash +opencode auth ls +``` + +--- + +#### logout + +인증 파일에서 provider 정보를 제거해 로그아웃합니다. + +```bash +opencode auth logout +``` + +--- + +### github + +저장소 자동화를 위한 GitHub 에이전트를 관리합니다. + +```bash +opencode github [command] +``` + +--- + +#### install + +저장소에 GitHub 에이전트를 설치합니다. + +```bash +opencode github install +``` + +필요한 GitHub Actions 워크플로를 설정하고 구성 과정을 안내합니다. [더 알아보기](/docs/github). + +--- + +#### run + +GitHub 에이전트를 실행합니다. 보통 GitHub Actions에서 사용합니다. + +```bash +opencode github run +``` + +##### 플래그 + +| 플래그 | 설명 | +| --------- | ------------------------- | +| `--event` | 실행할 GitHub 모의 이벤트 | +| `--token` | GitHub 개인 액세스 토큰 | + +--- + +### mcp + +Model Context Protocol 서버를 관리합니다. + +```bash +opencode mcp [command] +``` + +--- + +#### add + +구성에 MCP 서버를 추가합니다. + +```bash +opencode mcp add +``` + +이 명령은 로컬 또는 원격 MCP 서버를 추가하는 과정을 안내합니다. + +--- + +#### list + +구성된 MCP 서버와 연결 상태를 표시합니다. + +```bash +opencode mcp list +``` + +축약형도 사용할 수 있습니다. + +```bash +opencode mcp ls +``` + +--- + +#### auth + +OAuth를 지원하는 MCP 서버를 인증합니다. + +```bash +opencode mcp auth [name] +``` + +서버 이름을 입력하지 않으면 OAuth 지원 서버 목록에서 선택하라는 안내가 표시됩니다. + +OAuth 지원 서버와 인증 상태를 목록으로 볼 수도 있습니다. + +```bash +opencode mcp auth list +``` + +축약형도 사용할 수 있습니다. + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +MCP 서버의 OAuth 인증 정보를 제거합니다. + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +MCP 서버의 OAuth 연결 문제를 디버그합니다. + +```bash +opencode mcp debug +``` + +--- + +### models + +구성된 provider에서 사용 가능한 모델 목록을 표시합니다. + +```bash +opencode models [provider] +``` + +이 명령은 구성된 provider 전체에서 사용 가능한 모델을 `provider/model` 형식으로 출력합니다. + +[config](/docs/config/)에 지정할 정확한 모델명을 확인할 때 유용합니다. + +특정 provider ID를 넘겨 해당 provider의 모델만 필터링할 수도 있습니다. + +```bash +opencode models anthropic +``` + +#### 플래그 + +| 플래그 | 설명 | +| ----------- | ------------------------------------------------- | +| `--refresh` | models.dev에서 모델 캐시 새로고침 | +| `--verbose` | 더 자세한 모델 출력 사용(비용 등 메타데이터 포함) | + +`--refresh` 플래그를 사용하면 캐시된 모델 목록을 갱신할 수 있습니다. provider에 새 모델이 추가된 뒤 OpenCode에서 바로 확인하고 싶을 때 유용합니다. + +```bash +opencode models --refresh +``` + +--- + +### run + +프롬프트를 직접 전달해 비대화형 모드로 opencode를 실행합니다. + +```bash +opencode run [message..] +``` + +스크립트, 자동화, 또는 전체 TUI를 띄우지 않고 빠른 응답이 필요할 때 유용합니다. 예: + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +매번 MCP 서버 콜드 부트가 발생하지 않도록, 실행 중인 `opencode serve` 인스턴스에 붙어서 실행할 수도 있습니다. + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### 플래그 + +| 플래그 | 축약 | 설명 | +| ------------ | ---- | ---------------------------------------------------------------------- | +| `--command` | | 실행할 명령(인수는 message로 전달) | +| `--continue` | `-c` | 마지막 세션 이어서 실행 | +| `--session` | `-s` | 이어서 실행할 세션 ID | +| `--fork` | | 세션을 이어갈 때 포크 생성 (`--continue` 또는 `--session`과 함께 사용) | +| `--share` | | 세션 공유 | +| `--model` | `-m` | 사용할 모델 (`provider/model` 형식) | +| `--agent` | | 사용할 에이전트 | +| `--file` | `-f` | 메시지에 첨부할 파일 | +| `--format` | | 출력 형식: default(포맷됨) 또는 json(원시 JSON 이벤트) | +| `--title` | | 세션 제목(값이 없으면 프롬프트를 잘라 자동 생성) | +| `--attach` | | 실행 중인 opencode 서버에 연결(예: http://localhost:4096) | +| `--port` | | 로컬 서버 포트(기본값: 랜덤 포트) | + +--- + +### serve + +API 접근용 headless OpenCode 서버를 시작합니다. 전체 HTTP 인터페이스는 [server docs](/docs/server)를 참고하세요. + +```bash +opencode serve +``` + +이 명령은 TUI 없이 opencode 기능에 접근할 수 있는 HTTP 서버를 시작합니다. `OPENCODE_SERVER_PASSWORD`를 설정하면 HTTP basic auth가 활성화됩니다(기본 사용자명: `opencode`). + +#### 플래그 + +| 플래그 | 설명 | +| ------------ | --------------------------------- | +| `--port` | 수신 포트 | +| `--hostname` | 수신 호스트명 | +| `--mdns` | mDNS 검색 활성화 | +| `--cors` | 허용할 추가 브라우저 origin(CORS) | + +--- + +### session + +OpenCode 세션을 관리합니다. + +```bash +opencode session [command] +``` + +--- + +#### list + +OpenCode 세션 목록을 표시합니다. + +```bash +opencode session list +``` + +##### 플래그 + +| 플래그 | 축약 | 설명 | +| ------------- | ---- | -------------------------------------- | +| `--max-count` | `-n` | 최근 N개 세션만 표시 | +| `--format` | | 출력 형식: table 또는 json(기본 table) | + +--- + +### stats + +OpenCode 세션의 토큰 사용량과 비용 통계를 표시합니다. + +```bash +opencode stats +``` + +#### 플래그 + +| 플래그 | 설명 | +| ----------- | ------------------------------------------------------------ | +| `--days` | 최근 N일 통계 표시(기본값: 전체 기간) | +| `--tools` | 표시할 도구 개수(기본값: 전체) | +| `--models` | 모델 사용량 상세 표시(기본 숨김). 숫자를 주면 상위 N개 표시 | +| `--project` | 프로젝트 필터(기본: 전체 프로젝트, 빈 문자열: 현재 프로젝트) | + +--- + +### export + +세션 데이터를 JSON으로 내보냅니다. + +```bash +opencode export [sessionID] +``` + +세션 ID를 지정하지 않으면 사용 가능한 세션에서 선택하라는 안내가 표시됩니다. + +--- + +### import + +JSON 파일 또는 OpenCode 공유 URL에서 세션 데이터를 가져옵니다. + +```bash +opencode import +``` + +로컬 파일이나 OpenCode 공유 URL에서 가져올 수 있습니다. + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +웹 인터페이스를 포함한 headless OpenCode 서버를 시작합니다. + +```bash +opencode web +``` + +이 명령은 HTTP 서버를 시작하고 웹 브라우저를 열어 웹 인터페이스로 OpenCode에 접속합니다. `OPENCODE_SERVER_PASSWORD`를 설정하면 HTTP basic auth가 활성화됩니다(기본 사용자명: `opencode`). + +#### 플래그 + +| 플래그 | 설명 | +| ------------ | --------------------------------- | +| `--port` | 수신 포트 | +| `--hostname` | 수신 호스트명 | +| `--mdns` | mDNS 검색 활성화 | +| `--cors` | 허용할 추가 브라우저 origin(CORS) | + +--- + +### acp + +ACP(Agent Client Protocol) 서버를 시작합니다. + +```bash +opencode acp +``` + +이 명령은 nd-JSON 형식으로 stdin/stdout을 통해 통신하는 ACP 서버를 시작합니다. + +#### 플래그 + +| 플래그 | 설명 | +| ------------ | ------------- | +| `--cwd` | 작업 디렉터리 | +| `--port` | 수신 포트 | +| `--hostname` | 수신 호스트명 | + +--- + +### uninstall + +OpenCode를 제거하고 관련 파일을 삭제합니다. + +```bash +opencode uninstall +``` + +#### 플래그 + +| 플래그 | 축약 | 설명 | +| --------------- | ---- | ------------------------------- | +| `--keep-config` | `-c` | 설정 파일 유지 | +| `--keep-data` | `-d` | 세션 데이터와 스냅샷 유지 | +| `--dry-run` | | 실제 삭제 없이 삭제 대상만 표시 | +| `--force` | `-f` | 확인 프롬프트 건너뛰기 | + +--- + +### upgrade + +opencode를 최신 버전 또는 특정 버전으로 업데이트합니다. + +```bash +opencode upgrade [target] +``` + +최신 버전으로 업그레이드: + +```bash +opencode upgrade +``` + +특정 버전으로 업그레이드: + +```bash +opencode upgrade v0.1.48 +``` + +#### 플래그 + +| 플래그 | 축약 | 설명 | +| ---------- | ---- | ------------------------------------------ | +| `--method` | `-m` | 설치 방식 지정: curl, npm, pnpm, bun, brew | + +--- + +## 전역 플래그 + +opencode CLI는 아래 전역 플래그를 지원합니다. + +| 플래그 | 축약 | 설명 | +| -------------- | ---- | ----------------------------------- | +| `--help` | `-h` | 도움말 표시 | +| `--version` | `-v` | 버전 출력 | +| `--print-logs` | | 로그를 stderr로 출력 | +| `--log-level` | | 로그 레벨(DEBUG, INFO, WARN, ERROR) | + +--- + +## 환경 변수 + +OpenCode는 환경 변수로도 구성할 수 있습니다. + +| 변수 | 타입 | 설명 | +| ------------------------------------- | ------- | ---------------------------------------------- | +| `OPENCODE_AUTO_SHARE` | boolean | 세션 자동 공유 | +| `OPENCODE_GIT_BASH_PATH` | string | Windows에서 Git Bash 실행 파일 경로 | +| `OPENCODE_CONFIG` | string | 설정 파일 경로 | +| `OPENCODE_CONFIG_DIR` | string | 설정 디렉터리 경로 | +| `OPENCODE_CONFIG_CONTENT` | string | 인라인 JSON 설정 내용 | +| `OPENCODE_DISABLE_AUTOUPDATE` | boolean | 자동 업데이트 확인 비활성화 | +| `OPENCODE_DISABLE_PRUNE` | boolean | 오래된 데이터 정리(prune) 비활성화 | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | 터미널 제목 자동 업데이트 비활성화 | +| `OPENCODE_PERMISSION` | string | 인라인 JSON 권한 설정 | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | 기본 플러그인 비활성화 | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | LSP 서버 자동 다운로드 비활성화 | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | 실험적 모델 활성화 | +| `OPENCODE_DISABLE_AUTOCOMPACT` | boolean | 자동 컨텍스트 컴팩션 비활성화 | +| `OPENCODE_DISABLE_CLAUDE_CODE` | boolean | `.claude`(프롬프트 + 스킬) 읽기 비활성화 | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | `~/.claude/CLAUDE.md` 읽기 비활성화 | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | `.claude/skills` 로드 비활성화 | +| `OPENCODE_DISABLE_MODELS_FETCH` | boolean | 원격 소스에서 모델 목록 가져오기 비활성화 | +| `OPENCODE_FAKE_VCS` | string | 테스트용 가짜 VCS provider | +| `OPENCODE_DISABLE_FILETIME_CHECK` | boolean | 최적화를 위한 파일 시간 검사 비활성화 | +| `OPENCODE_CLIENT` | string | 클라이언트 식별자(기본값: `cli`) | +| `OPENCODE_ENABLE_EXA` | boolean | Exa 웹 검색 도구 활성화 | +| `OPENCODE_SERVER_PASSWORD` | string | `serve`/`web` 기본 인증 활성화 | +| `OPENCODE_SERVER_USERNAME` | string | 기본 인증 사용자명 오버라이드(기본 `opencode`) | +| `OPENCODE_MODELS_URL` | string | 모델 설정을 가져올 사용자 지정 URL | + +--- + +### 실험적 기능 + +아래 환경 변수는 변경되거나 제거될 수 있는 실험 기능을 활성화합니다. + +| 변수 | 타입 | 설명 | +| ----------------------------------------------- | ------- | ------------------------------ | +| `OPENCODE_EXPERIMENTAL` | boolean | 모든 실험 기능 활성화 | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | 아이콘 탐색 활성화 | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | TUI에서 선택 시 복사 비활성화 | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number | bash 명령 기본 타임아웃(ms) | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | number | LLM 응답 최대 출력 토큰 수 | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolean | 전체 디렉터리 파일 감시 활성화 | +| `OPENCODE_EXPERIMENTAL_OXFMT` | boolean | oxfmt 포매터 활성화 | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolean | 실험적 LSP 도구 활성화 | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | 파일 감시 비활성화 | +| `OPENCODE_EXPERIMENTAL_EXA` | boolean | 실험적 Exa 기능 활성화 | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolean | 실험적 LSP 타입 검사 활성화 | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolean | 실험적 Markdown 기능 활성화 | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolean | Plan mode 활성화 | diff --git a/packages/web/src/content/docs/ko/commands.mdx b/packages/web/src/content/docs/ko/commands.mdx new file mode 100644 index 00000000000..c477cb12fbd --- /dev/null +++ b/packages/web/src/content/docs/ko/commands.mdx @@ -0,0 +1,323 @@ +--- +title: 명령어 +description: 반복적인 작업을 위한 커스텀 명령을 만드세요. +--- + +커스텀 명령을 사용하면 TUI에서 해당 명령이 실행될 때 사용할 프롬프트를 미리 정의할 수 있습니다. + +```bash frame="none" +/my-command +``` + +--- + +커스텀 명령은 `/init`, `/undo`, `/redo`, `/share`, `/help` 같은 내장 명령과 별도로 추가됩니다. [더 알아보기](/docs/tui#commands). + +--- + +## 명령 파일 만들기 + +커스텀 명령은 `commands/` 디렉터리에 Markdown 파일을 만들어 정의합니다. + +예: `.opencode/commands/test.md` + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +프런트매터(frontmatter)에는 명령 속성을 정의하고, 본문은 템플릿 프롬프트가 됩니다. + +명령 이름 앞에 `/`를 붙여 실행합니다. + +```bash frame="none" +"/test" +``` + +--- + +## 구성 + +커스텀 명령은 OpenCode 설정으로 추가하거나, `commands/` 디렉터리에 Markdown 파일을 만들어 추가할 수 있습니다. + +--- + +### JSON + +OpenCode [config](/docs/config)의 `command` 옵션을 사용합니다. + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +이제 TUI에서 다음처럼 실행할 수 있습니다. + +```bash frame="none" +/test +``` + +--- + +### Markdown + +Markdown 파일로도 명령을 정의할 수 있습니다. 아래 경로 중 하나에 두면 됩니다. + +- 전역: `~/.config/opencode/commands/` +- 프로젝트별: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Markdown 파일명이 명령 이름이 됩니다. 예를 들어 `test.md`라면 아래처럼 실행합니다. + +```bash frame="none" +/test +``` + +--- + +## 프롬프트 구성 + +커스텀 명령 프롬프트는 몇 가지 특수 플레이스홀더(placeholder)와 문법을 지원합니다. + +--- + +### 인수 + +`$ARGUMENTS` 플레이스홀더로 명령 인수를 전달할 수 있습니다. + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +인수를 넣어 실행하면: + +```bash frame="none" +/component Button +``` + +`$ARGUMENTS`가 `Button`으로 치환됩니다. + +위치 인수도 사용할 수 있습니다. + +- `$1` - 첫 번째 인수 +- `$2` - 두 번째 인수 +- `$3` - 세 번째 인수 +- 이후 동일 + +예시: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +실행: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +치환 결과: + +- `$1` -> `config.json` +- `$2` -> `src` +- `$3` -> `{ "key": "value" }` + +--- + +### 셸 출력 + +_!`command`_ 문법으로 [bash 명령](/docs/tui#bash-commands)의 출력 결과를 프롬프트에 주입할 수 있습니다. + +예를 들어 테스트 커버리지 분석 명령을 만들면: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +최근 변경 리뷰용으로는: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +명령은 프로젝트 루트 디렉터리에서 실행되며, 출력 결과는 프롬프트 본문에 포함됩니다. + +--- + +### 파일 참조 + +`@` 뒤에 파일명을 붙여 명령에 파일을 포함할 수 있습니다. + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +파일 내용은 자동으로 프롬프트에 포함됩니다. + +--- + +## 옵션 + +구성 옵션을 자세히 살펴봅니다. + +--- + +### 템플릿 + +`template` 옵션은 명령 실행 시 LLM에 전달할 프롬프트를 정의합니다. + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +이 옵션은 **필수**입니다. + +--- + +### 설명 + +`description` 옵션으로 명령의 짧은 설명을 추가할 수 있습니다. + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +이 설명은 TUI에서 명령을 입력할 때 표시됩니다. + +--- + +### 에이전트 + +`agent` 설정으로 이 명령을 실행할 [agent](/docs/agents)를 지정할 수 있습니다. +지정한 값이 [subagent](/docs/agents/#subagents)면 기본적으로 subagent 호출이 실행됩니다. +이 동작을 끄려면 `subtask`를 `false`로 설정하세요. + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +이 옵션은 **선택**입니다. 지정하지 않으면 현재 에이전트가 기본값으로 사용됩니다. + +--- + +### 서브태스크 + +`subtask` 불리언(boolean)을 사용하면 명령이 [subagent](/docs/agents/#subagents) 호출을 강제로 트리거합니다. +주 컨텍스트를 오염시키고 싶지 않을 때 유용하며, [agent](/docs/agents) 설정의 `mode`가 `primary`여도 subagent로 실행합니다. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +이 옵션은 **선택**입니다. + +--- + +### 모델 + +`model` 설정으로 이 명령의 기본 모델을 오버라이드할 수 있습니다. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +이 옵션은 **선택**입니다. + +--- + +## 내장 명령 + +OpenCode는 `/init`, `/undo`, `/redo`, `/share`, `/help` 등 여러 내장 명령을 제공합니다. [더 알아보기](/docs/tui#commands). + +:::note +커스텀 명령은 내장 명령을 덮어쓸 수 있습니다. +::: + +같은 이름으로 커스텀 명령을 정의하면 내장 명령보다 커스텀 명령이 우선합니다. diff --git a/packages/web/src/content/docs/ko/config.mdx b/packages/web/src/content/docs/ko/config.mdx new file mode 100644 index 00000000000..0357ded7857 --- /dev/null +++ b/packages/web/src/content/docs/ko/config.mdx @@ -0,0 +1,682 @@ +--- +title: 구성 +description: OpenCode JSON 구성을 사용합니다. +--- + +JSON 구성 파일을 사용하여 OpenCode를 구성할 수 있습니다. + +--- + +## 형식 + +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, +} +``` + +--- + +## 위치 + +구성을 여러 위치에 배치할 수 있으며, 이들은 서로 다른 우선 순위(precedence)를 가집니다. + +:::note +구성 파일은 **병합**되며, 대체되지 않습니다. +::: + +구성 파일은 함께 병합되며 대체되지 않습니다. 다음 구성 위치의 설정이 결합됩니다. 나중의 구성은 충돌하는 키에 대해 이전 구성을 덮어씁니다. 모든 구성의 설정이 보존됩니다. + +예를 들어, 전역 구성이 `theme: "opencode"` 및 `autoupdate: true`를 설정하고 프로젝트 구성이 `model: "anthropic/claude-sonnet-4-5"`를 설정하면 최종 구성에는 세 가지 설정이 모두 포함됩니다. + +--- + +### 우선 순위 + +구성 소스는 다음 순서로 로드됩니다 (나중 소스가 이전 소스를 덮어씀): + +1. **원격 구성** (`.well-known/opencode`에서) - 조직 기본값 +2. **전역 구성** (`~/.config/opencode/opencode.json`) - 사용자 환경설정 +3. **사용자 정의 구성** (`OPENCODE_CONFIG` 환경 변수) - 사용자 정의 재정의 +4. **프로젝트별 구성** (`opencode.json`) - 프로젝트별 설정 +5. **`.opencode` 디렉토리** - 에이전트, 명령, 플러그인 +6. **인라인 구성** (`OPENCODE_CONFIG_CONTENT` 환경 변수) - 런타임 재정의 + +이것은 프로젝트 구성이 전역 기본값을 덮어쓸 수 있고, 전역 구성이 원격 조직 기본값을 덮어쓸 수 있음을 의미합니다. + +:::note +`.opencode`와 `~/.config/opencode` 디렉토리는 하위 디렉토리에 대해 **복수형 이름**을 사용합니다: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/`, 그리고 `themes/`. 단수형 이름(예: `agent/`)도 하위 호환성을 위해 지원됩니다. +::: + +--- + +### 원격 + +조직은 `.well-known/opencode` 엔드포인트를 통해 기본 구성을 제공할 수 있습니다. 이를 지원하는 공급자로 인증할 때 자동으로 가져옵니다. + +원격 구성은 기본 레이어로 가장 먼저 로드됩니다. 다른 구성 소스(전역, 프로젝트)는 이러한 기본값을 무시(override)할 수 있습니다. + +예를 들어, 조직이 기본적으로 비활성화된 MCP 서버를 제공하는 경우: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +로컬 설정에서 특정 서버를 활성화할 수 있습니다: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +## 전역 + +`~/.config/opencode/opencode.json`에 전역 OpenCode 구성을 배치합니다. 테마, 공급자, 키바인드와 같은 사용자 전체 기본 설정에 전역 구성을 사용하십시오. + +전역 구성은 원격 조직 기본값을 덮어씁니다. + +--- + +## 프로젝트별 + +프로젝트 루트에 `opencode.json`을 추가합니다. 프로젝트 구성은 표준 구성 파일 중 가장 높은 우선순위를 가집니다. 이는 전역 및 원격 구성을 모두 덮어씁니다. + +:::tip +프로젝트의 루트에 특정 설정을 둡니다. +::: + +OpenCode가 시작될 때, 현재 디렉토리의 설정 파일이나 가장 가까운 Git 디렉토리를 찾습니다. + +이것은 Git으로 관리되며 전역 구성과 동일한 스키마를 사용합니다. + +--- + +### 사용자 정의 경로 + +`OPENCODE_CONFIG` 환경 변수를 사용하여 사용자 정의 구성 파일 경로를 지정합니다. + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +사용자 정의 구성은 우선 순위에서 전역 구성과 프로젝트 구성 사이에 로드됩니다. + +--- + +## 사용자 정의 디렉토리 + +`OPENCODE_CONFIG_DIR` 환경 변수를 사용하여 사용자 정의 구성 디렉토리를 지정할 수 있습니다. 이 디렉토리는 표준 `.opencode` 디렉토리와 마찬가지로 에이전트, 명령, 모드 및 플러그인을 검색하며 동일한 구조를 따라야 합니다. + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +사용자 정의 디렉토리는 전역 구성 이후 및 `.opencode` 디렉토리 이전에 로드됩니다. + +--- + +## 스키마 + +구성 파일에는 [**`opencode.ai/config.json`**](https://opencode.ai/config.json)에 정의된 스키마가 있습니다. + +편집기는 스키마에 따라 유효성 검사 및 자동 완성을 제공해야 합니다. + +--- + +#### TUI + +`tui` 옵션을 통해 TUI 관련 설정을 구성할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +유효한 옵션: + +- `scroll_acceleration.enabled` - macOS 스타일 스크롤 가속을 활성화합니다. **`scroll_speed`보다 우선합니다.** +- `scroll_speed` - 사용자 정의 스크롤 속도 배수 (기본값: `3`, 최소값: `1`). `scroll_acceleration.enabled`가 `true`이면 무시됩니다. +- `diff_style` - diff 렌더링을 제어합니다. `"auto"`는 터미널 너비에 맞추고, `"stacked"`는 항상 단일 열을 보여줍니다. + +[TUI 사용법에 대해 더 알아보기](/docs/tui). + +--- + +## 서버 + +`opencode serve` 및 `opencode web` 명령에 대한 서버 설정을 구성할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +유효한 옵션: + +- `port` - 리스닝 포트. +- `hostname` - 리스닝 호스트 이름. `mdns`가 활성화되고 hostname이 설정되지 않으면 `0.0.0.0`이 기본값이 됩니다. +- `mdns` - mDNS 서비스 발견 활성화. 로컬 네트워크의 다른 장치가 OpenCode 서버를 찾을 수 있습니다. +- `mdnsDomain` - mDNS 서비스를 위한 사용자 정의 도메인 이름. 기본값은 `opencode.local`입니다. 동일한 네트워크에서 여러 인스턴스를 실행할 때 유용합니다. +- `cors` - 브라우저 기반 클라이언트에서 HTTP 서버를 사용할 때 CORS를 허용할 추가 출처(Origin). 값은 전체 출처(스킴 + 호스트 + 선택적 포트)여야 합니다. 예: `https://app.example.com`. + +[서버에 대해 더 알아보기](/docs/server). + +--- + +## 도구 + +`tools` 옵션을 통해 LLM이 사용할 수 있는 도구를 구성할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[도구에 대해 더 알아보기](/docs/tools). + +--- + +## 모델 + +`provider`, `model`, `small_model` 옵션을 통해 OpenCode 구성에서 사용할 공급자와 모델을 구성할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +`small_model` 옵션은 제목 생성과 같은 가벼운 작업을 위한 별도의 모델을 구성합니다. 기본적으로, OpenCode는 공급자에게서 사용 가능한 더 저렴한 모델이 있다면 그것을 사용하고, 그렇지 않으면 주 모델로 돌아갑니다. + +공급자 옵션은 `timeout`과 `setCacheKey`를 포함할 수 있습니다: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` - 요청 타임아웃(밀리초) (기본값: 300000). `false`로 설정하여 비활성화할 수 있습니다. +- `setCacheKey` - 지정된 공급자에 대해 캐시 키가 항상 설정되도록 강제합니다. + +[로컬 모델](/docs/models#local)을 구성할 수도 있습니다. [더 알아보기](/docs/models). + +--- + +### 공급자별 옵션 + +일반적인 `timeout` 및 `apiKey` 외에도 일부 공급자는 추가 구성 옵션을 지원합니다. + +##### Amazon Bedrock + +Amazon Bedrock는 AWS 관련 구성을 지원합니다: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` - Bedrock를 위한 AWS 리전 (`AWS_REGION` 환경 변수 또는 `us-east-1`이 기본값) +- `profile` - `~/.aws/credentials`의 AWS 프로필 이름 (`AWS_PROFILE` 환경 변수가 기본값) +- `endpoint` - VPC 엔드포인트 등을 위한 사용자 정의 엔드포인트 URL. 이는 AWS 관련 용어를 사용한 일반적인 `baseURL` 옵션의 별칭입니다. 둘 다 지정된 경우 `endpoint`가 우선합니다. + +:::note +Bearer 토큰(`AWS_BEARER_TOKEN_BEDROCK` 또는 `/connect`)은 프로필 기반 인증보다 우선합니다. 자세한 내용은 [인증 우선 순위](/docs/providers#authentication-precedence)를 참조하십시오. +::: + +[Amazon Bedrock에 대해 더 알아보기](/docs/providers#amazon-bedrock). + +--- + +## 테마 + +`theme` 옵션을 통해 OpenCode 구성에서 사용할 테마를 설정할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[더 알아보기](/docs/themes). + +--- + +## 에이전트 + +`agent` 옵션을 통해 특정 작업을 전문으로 하는 에이전트를 구성할 수 있습니다. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +`~/.config/opencode/agents/` 또는 `.opencode/agents/`에서 Markdown 파일을 사용하여 에이전트를 정의할 수도 있습니다. [더 알아보기](/docs/agents). + +--- + +### 기본 에이전트 + +`default_agent` 옵션을 사용하여 기본 에이전트를 설정할 수 있습니다. 명시적으로 지정되지 않았을 때 어떤 에이전트가 사용될지 결정합니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +기본 에이전트는 기본(primary) 에이전트여야 합니다(서브 에이전트 불가). `"build"` 또는 `"plan"`과 같은 내장 에이전트이거나 정의된 [사용자 정의 에이전트](./agents)일 수 있습니다. 지정된 에이전트가 존재하지 않는 경우, OpenCode는 경고와 함께 `"build"`로 돌아갑니다. + +이 설정은 모든 인터페이스에 적용됩니다: TUI, CLI (`opencode run`), 데스크톱 앱 및 GitHub Action. + +--- + +## 공유 + +`share` 옵션을 통해 [공유](/docs/share) 기능을 구성할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +값은 다음과 같습니다: + +- `"manual"` - 명령을 통한 수동 공유 허용 (기본값) +- `"auto"` - 새로운 대화를 자동으로 공유 +- `"disabled"` - 공유 기능 완전히 비활성화 + +기본적으로 `/share` 명령을 사용하여 대화를 명시적으로 공유해야 하는 수동 모드로 설정됩니다. + +--- + +## 명령 + +`command` 옵션을 통해 반복 작업을 위한 사용자 정의 명령을 구성할 수 있습니다. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +`~/.config/opencode/commands/` 또는 `.opencode/commands/`에서 Markdown 파일을 사용하여 명령을 정의할 수도 있습니다. [더 알아보기](/docs/commands). + +--- + +## 키바인드 + +`keybinds` 옵션을 통해 키바인드를 사용자 정의할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[더 알아보기](/docs/keybinds). + +--- + +## 자동 업데이트 + +OpenCode는 시작될 때 자동으로 새로운 업데이트를 다운로드합니다. `autoupdate` 옵션으로 이를 비활성화할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +업데이트를 원하지 않지만 새 버전을 알림받고 싶다면 `autoupdate`를 `"notify"`로 설정하십시오. +Homebrew와 같은 패키지 관리자를 사용하여 설치되지 않은 경우에만 작동합니다. + +--- + +## 포매터 + +`formatter` 옵션을 통해 코드 포매터를 구성할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[포매터에 대해 더 알아보기](/docs/formatters). + +--- + +## 권한 + +기본적으로, OpenCode는 **명시적 승인 없이 모든 작업을 허용**합니다. `permission` 옵션을 사용하여 이를 변경할 수 있습니다. + +예를 들어, `edit` 및 `bash` 도구가 사용자 승인을 요구하도록 설정하려면: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[권한에 대해 더 알아보기](/docs/permissions). + +--- + +### 압축 + +`compaction` 옵션을 통해 컨텍스트 압축 동작을 제어할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto` - 컨텍스트가 꽉 차면 자동으로 세션을 압축합니다 (기본값: `true`). +- `prune` - 토큰을 절약하기 위해 오래된 도구 출력을 제거합니다 (기본값: `true`). + +--- + +### 파일 감시자 + +`watcher` 옵션을 통해 파일 감시자가 무시할 패턴을 설정할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +패턴은 glob 구문을 따릅니다. 잡음이 많은 디렉토리를 제외하는 데 사용하십시오. + +--- + +### MCP 서버 + +`mcp` 옵션을 통해 사용하려는 MCP 서버를 구성할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[더 알아보기](/docs/mcp-servers). + +--- + +### 플러그인 + +[플러그인](/docs/plugins)은 사용자 정의 도구, 훅(hook), 통합으로 OpenCode를 확장합니다. + +`.opencode/plugins/` 또는 `~/.config/opencode/plugins/`에 플러그인 파일을 배치하십시오. `plugin` 옵션을 통해 npm에서 플러그인을 로드할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[더 알아보기](/docs/plugins). + +--- + +### 지침 + +`instructions` 옵션을 통해 모델에 대한 지침(Rules)을 구성할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +지침 파일에 대한 경로와 glob 패턴의 배열을 사용합니다. [규칙에 대해 더 알아보기](/docs/rules). + +--- + +## 비활성화된 공급자 + +`disabled_providers` 옵션을 통해 자동으로 로드되는 공급자를 비활성화할 수 있습니다. 자격 증명이 유효하더라도 특정 공급자가 로드되는 것을 방지할 때 유용합니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +`disabled_providers`는 `enabled_providers`보다 우선합니다. +::: + +`disabled_providers` 옵션은 공급자 ID의 배열을 허용합니다. 공급자가 비활성화되면: + +- 환경 변수가 설정된 경우에도 로드되지 않습니다. +- API 키가 `/connect` 명령을 통해 구성되는 경우에도 로드되지 않습니다. +- 공급자의 모델은 모델 선택 목록에 표시되지 않습니다. + +--- + +### 활성화된 공급자 + +`enabled_providers` 옵션을 통해 허용할 공급자를 지정할 수 있습니다. 설정하면 지정된 공급자만 활성화되고 다른 모든 공급자는 무시됩니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +OpenCode를 제한하여 특정 공급자만 사용하도록 할 때 유용합니다. + +:::note +`disabled_providers`는 `enabled_providers`보다 우선합니다. +::: + +공급자가 `enabled_providers`와 `disabled_providers` 둘 다에 나타나면, 하위 호환성을 위해 `disabled_providers`가 우선합니다. + +--- + +### 실험적 기능 + +`experimental` 키는 활발히 개발 중인 옵션을 포함합니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +실험적 옵션은 안정적이지 않습니다. 예고 없이 변경되거나 제거될 수 있습니다. +::: + +--- + +## 변수 + +구성 파일에서 환경 변수를 참조하고 파일 내용에 대한 변수 대체를 사용할 수 있습니다. + +--- + +##### 환경 변수 + +`{env:VARIABLE_NAME}`을 사용하여 환경 변수를 대체합니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +환경 변수가 설정되지 않으면 빈 문자열로 대체됩니다. + +--- + +## 파일 + +`{file:path/to/file}`를 사용하여 파일의 내용을 대체합니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +파일 경로는: + +- 구성 파일 디렉토리에 상대적이거나 +- `/` 또는 `~`로 시작하는 절대 경로여야 합니다. + +이것은 다음에 유용합니다: + +- API 키와 같은 민감한 데이터를 별도의 파일에 유지할 때. +- 구성을 어지럽히지 않고 큰 지침 파일을 포함할 때. +- 여러 구성 파일에서 공통 구성 스니펫을 공유할 때. diff --git a/packages/web/src/content/docs/ko/custom-tools.mdx b/packages/web/src/content/docs/ko/custom-tools.mdx new file mode 100644 index 00000000000..5da050f49bd --- /dev/null +++ b/packages/web/src/content/docs/ko/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: 사용자 정의 도구 +description: OpenCode에서 LLM이 호출할 수 있는 도구를 만듭니다. +--- + +사용자 정의 도구는 LLM이 대화 중에 호출 할 수있는 기능을 만듭니다. 그들은 `read`, `write` 및 `bash`와 같은 opencode의 [붙박이 도구](./tools)와 함께 작동합니다. + +--- + +## 도구 만들기 + +도구는 **TypeScript** 또는 **JavaScript** 파일로 정의됩니다. 그러나 도구 정의는 ** 어떤 언어로 작성된 스크립트를 호출 할 수 있습니다 ** - TypeScript 또는 JavaScript는 도구 정의 자체에서만 사용됩니다. + +--- + +## 위치 + +그들은 정의 할 수 있습니다: + +- 프로젝트의 `.opencode/tools/` 디렉토리에 배치하여 로컬. +- 또는 전 세계적으로 `~/.config/opencode/tools/`에 배치하여. + +--- + +## 구조 + +도구를 만드는 가장 쉬운 방법은 `tool()` helper를 사용하여 유형 안전 및 검증을 제공합니다. + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +**파일 이름**는 **tool name**가 됩니다. 위는 `database` 공구를 만듭니다. + +--- + +### 파일당 여러 도구 + +단일 파일에서 여러 도구를 수출할 수 있습니다. 각 수출은 ** 별도의 도구 ** 이름 ** `_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +이것은 2개의 공구를 만듭니다: `math_add`와 `math_multiply`. + +--- + +#### 스키마 + +`tool.schema`를 사용할 수 있습니다, 그냥 [Zod](https://zod.dev), 인수 유형을 정의합니다. + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +[Zod](https://zod.dev)를 직접 가져오고 일반 객체를 반환할 수 있습니다. + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### 컨텍스트 + +도구는 현재 세션에 대한 컨텍스트를받습니다. + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +세션 작업 디렉토리에 `context.directory`를 사용합니다. +git worktree 루트에 `context.worktree`를 사용합니다. + +--- + +## 예제 + +### Python 도구 작성 + +원하는 모든 언어로 도구를 쓸 수 있습니다. 여기에 Python을 사용하여 두 개의 숫자를 추가하는 예입니다. + +먼저 Python 스크립트로 도구를 만듭니다. + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +그런 다음 도구 정의를 만듭니다. + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +여기에 우리는 [`Bun.$`](https://bun.com/docs/runtime/shell) 유틸리티를 사용하여 Python 스크립트를 실행합니다. diff --git a/packages/web/src/content/docs/ko/ecosystem.mdx b/packages/web/src/content/docs/ko/ecosystem.mdx new file mode 100644 index 00000000000..afb741c3d3a --- /dev/null +++ b/packages/web/src/content/docs/ko/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: 생태계 +description: OpenCode로 구축된 프로젝트 및 통합. +--- + +opencode에 내장 된 커뮤니티 프로젝트의 컬렉션. + +:::note +이 목록에 opencode 관련 프로젝트를 추가하시겠습니까? PR 제출 +::: + +[awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) 및 [opencode.cafe](https://opencode.cafe), 생태계와 커뮤니티를 통합하는 커뮤니티도 확인할 수 있습니다. + +--- + +## 플러그인 + +| 이름 | 설명 | +| --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | git sync와 live preview를 가진 고립된 Daytona 샌드박스의 opencode 세션을 자동으로 실행 | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | 자주 사용되는 Helicone session headers for request grouping | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | Auto-inject TypeScript/Svelte 타입의 파일 검색 도구 | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | API 크레딧 대신 ChatGPT Plus/Pro 구독 사용 | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | API 결제 대신 기존 Gemini 플랜 사용 | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | API 결제 대신 Antigravity의 무료 모델 사용 | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | 얕은 clones와 자동 할당된 포트가 있는 Multi-branch devcontainer 고립 | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Google Antigravity OAuth Plugin, 구글 검색 지원, 더 강력한 API 처리 | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | 펀딩이 없는 툴 출력으로 토큰 사용 최적화 | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | 한국어 지원 제공 업체에 대한 기본 웹 연구 지원 추가 Google 접지 스타일 | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | PTY에서 배경 프로세스를 실행하기 위한 AI Agent를 사용해서 대화형 입력을 보냅니다. · | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | 비동기 포탄 명령에 대한 지침 - TTY 의존 작업에서 걸림 방지 | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Wakatime의 opencode 사용 추적 | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | LLMs에서 생산한 Markdown 테이블 정리 | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | 10x 빠른 코드 편집 및 Morph Fast Apply API 및 게으른 편집 마커 | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | 배경 에이전트, 사전 제작된 LSP/AST/MCP 도구, 큐레이터 에이전트, 클로드 코드 호환 | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | opencode 세션을 위한 데스크탑 알림 및 사운드 알림 | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | 허가, 완료 및 오류 이벤트용 데스크탑 알림 및 사운드 알림 | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | opencode 컨텍스트를 기반으로 하는 AI-powered automatic Zellij session naming | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | 기술검출 및 주사를 요구하는 opencode Agent를 게으른 로드 프롬프트 허용 | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Supermemory를 사용하여 세션 전반에 걸쳐 지속되는 메모리 | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | (영어) 상호 작용하는 계획은 시각적인 주석 및 개인/오프라인 공유를 검토합니다 | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | granular flow control과 강력한 오케스트라 시스템 확장 | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | cron 구문을 가진 발사된 (Mac) 또는 체계화된 (Linux)를 사용하여 작업 재발견 | +| [micode](https://github.com/vtemian/micode) | Structured Brainstorm → Plan → 세션 연속성으로 워크플로우 구현 | +| [octto](https://github.com/vtemian/octto) | 멀티 퀘스트 양식으로 AI Brainstorming을 위한 인터랙티브 브라우저 UI | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agent) | 동기화 위임 및 컨텍스트의 코드 스타일 배경 에이전트 | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | opencode의 Native OS 알림 – 작업이 완료되면 알 수 있습니다 | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | 멀티 시약 오케스트라 묶음 하네스 – 16개 부품, 하나 설치 | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | opencode를 위한 Zero-friction git worktree | + +--- + +## 프로젝트 + +| 이름 | 설명 | +| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- | +| [kimaki](https://github.com/remorses/kimaki) | SDK 내장 opencode 세션을 제어하는 Discord bot | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | API에 내장된 편집기웨어 프롬프롬프 플러그인 | +| [portal](https://github.com/hosenur/portal) | Tailscale/VPN에 opencode를 위한 모바일 최초의 웹 UI | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | opencode 플러그인 구축 템플릿 | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | opencode를 위한 Neovim frontend - terminal 기반 AI 코딩 에이전트 | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | @opencode-ai/sdk를 통해 opencode를 사용하는 Vercel AI SDK 제공 | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | 웹 / 데스크탑 앱 및 VS Code Extension for opencode | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Obsidian 플러그인 Obsidian의 UI에서 opencode를 포함 | +| [OpenWork](https://github.com/different-ai/openwork) | opencode에 의해 구동 Claude Cowork에 대한 오픈 소스 대안 | +| [ocx](https://github.com/kdcokenny/ocx) | 휴대용, 절연 프로파일을 갖춘 opencode 확장 관리자. | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | opencode를 위한 데스크탑, 웹, 모바일 및 원격 클라이언트 앱 | + +--- + +## 에이전트 + +| 이름 | 설명 | +| ----------------------------------------------------------------- | --------------------------------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | 구조 개발용 모듈형 AI 에이전트 및 명령 | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | 향상된 워크플로우를 위한 컨피그, 프롬프트, 에이전트 및 플러그인 | diff --git a/packages/web/src/content/docs/ko/enterprise.mdx b/packages/web/src/content/docs/ko/enterprise.mdx new file mode 100644 index 00000000000..9055b592b3d --- /dev/null +++ b/packages/web/src/content/docs/ko/enterprise.mdx @@ -0,0 +1,170 @@ +--- +title: 엔터프라이즈 +description: 조직에서 OpenCode를 안전하게 사용하세요. +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +opencode Enterprise는 코드와 데이터가 인프라를 결코 나타낸다는 것을 보증하는 단체입니다. SSO 및 내부 AI 게이트웨이와 통합하는 중앙화 된 구성을 사용하여 이것을 할 수 있습니다. + +:::note +opencode는 코드 또는 컨텍스트 데이터를 저장하지 않습니다. +::: + +opencode Enterprise로 시작하려면: + +1. 시험은 당신의 팀과 내부적으로 합니다. +2. ** 연락처** 가격 및 구현 옵션을 논의합니다. + +--- + +## 시험 + +opencode는 오픈 소스이며 코드를 저장하지 않거나 컨텍스트 데이터, 그래서 개발자는 단순히 [get start](/docs/) 그리고 재판을 수행 할 수 있습니다. + +--- + +## 데이터 처리 + +**opencode는 코드 또는 컨텍스트 데이터를 저장하지 않습니다. ** 모든 처리는 로컬 또는 직접 API 호출을 통해 AI 공급자. + +이것은 당신이 신뢰하는 공급자, 또는 내부를 사용하고 있는 경우에 +AI 게이트웨이, opencode를 안전하게 사용할 수 있습니다. + +여기에서 유일한 caveat는 선택적인 `/share` 특징입니다. + +--- + +### 공유 대화 + +사용자가 `/share` 기능을 활성화하면 대화와 관련된 데이터가 opencode.ai에서 이러한 공유 페이지를 호스팅하는 데 사용됩니다. + +데이터는 현재 CDN의 가장자리 네트워크를 통해 제공되며 사용자가 가까운 가장자리에 캐시됩니다. + +우리는 당신이 당신의 재판을 위해 이것을 비활성화하는 것을 추천합니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[공유에 대해 더 알아보기](/docs/share). + +--- + +### 코드 소유권 + +**opencode에 의해 생성 된 모든 코드를 소유합니다. ** 제한 또는 소유권 주장이 없습니다. + +--- + +## 가격 + +opencode Enterprise의 per-seat 모델을 사용합니다. LLM 게이트웨이를 가지고 있다면 토큰을 사용할 수 없습니다. 가격 및 구현 옵션에 대한 자세한 내용은 **contact us**. + +--- + +## 배포 + +시험이 완료되면 opencode를 사용해야합니다. +조직, 당신은 할 수 있습니다 **contact us** 토론하기 +가격 및 구현 옵션. + +--- + +### 중앙 구성 + +opencode를 설정하여 전체 조직의 단일 중앙 구성을 사용할 수 있습니다. + +이 중앙 집중식 구성은 SSO 공급자와 통합할 수 있으며 내부 AI 게이트웨이 만 모든 사용자 액세스를 보장합니다. + +--- + +### SSO 통합 + +중앙 구성을 통해 opencode는 인증 기관의 SSO 공급자와 통합 할 수 있습니다. + +opencode는 기존 ID 관리 시스템을 통해 내부 AI 게이트웨이에 대한 자격 증명을 얻을 수 있습니다. + +--- + +## 내부 AI 게이트웨이 + +중앙 설정으로, opencode는 내부 AI 게이트웨이만 사용할 수 있습니다. + +또한 다른 모든 AI 제공 업체를 비활성화 할 수 있습니다, 모든 요청은 조직의 승인 된 인프라를 통해 이동합니다. + +--- + +## 셀프 호스팅 + +공유 페이지를 비활성화하는 것이 좋습니다. +당신의 조직, 우리는 또한 당신의 인프라에 자기 호스팅을 도울 수 있습니다. + +이것은 현재 우리의 로드맵에 있습니다. 관심이 있다면, ****를 알려줍니다. + +--- + +## 자주 묻는 질문 + +

+opencode Enterprise란 무엇입니까? + +opencode Enterprise는 코드와 데이터가 인프라를 결코 나타낸다는 것을 보증하는 단체입니다. SSO 및 내부 AI 게이트웨이와 통합하는 중앙화 된 구성을 사용하여 이것을 할 수 있습니다. + +
+ +
+opencode Enterprise를 어떻게 시작하나요? + +단순히 팀과 내부 평가판을 시작합니다. 기본값으로 opencode는 코드를 저장하지 않거나 context data, 시작하기 쉬운 만들기. + +그런 다음 **contact us**는 가격과 구현 옵션을 논의합니다. + +
+ +
+엔터프라이즈 가격 정책은 어떻게 되나요? + +우리는 per-seat 기업 가격을 제안합니다. LLM 게이트웨이를 가지고 있다면 토큰을 사용할 수 없습니다. 더 자세한 내용은 **contact us** 를 통해 조직의 요구에 따라 맞춤형 견적을 제공합니다. + +
+ +
+opencode Enterprise에서 내 데이터는 안전한가요? + +예. opencode는 코드 또는 컨텍스트 데이터를 저장하지 않습니다. 모든 처리는 로컬 또는 직접 API 호출을 통해 AI 공급자. 중앙 설정 및 SSO 통합으로 데이터는 조직의 인프라 내에서 안전하게 유지됩니다. + +
+ +
+자체 비공개 npm 레지스트리를 사용할 수 있나요? + +opencode는 Bun's native `.npmrc` 파일 지원을 통해 개인 npm 등록을 지원합니다. 조직이 JFrog Artifactory, Nexus 또는 이와 같은 개인 레지스트리를 사용한다면, 개발자가 opencode를 실행하기 전에 인증됩니다. + +개인 레지스트리로 인증을 설정하려면: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +`~/.npmrc`를 인증 세부 사항으로 만듭니다. opencode는 자동으로 +지금 구매하세요. + +:::caution +opencode를 실행하기 전에 개인 레지스트리에 로그인해야합니다. +::: + +또는 `.npmrc` 파일을 수동으로 구성할 수 있습니다. + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +개발자는 opencode를 실행하기 전에 개인 레지스트리에 로그인해야하며 패키지를 설치할 수 있습니다. + +
diff --git a/packages/web/src/content/docs/ko/formatters.mdx b/packages/web/src/content/docs/ko/formatters.mdx new file mode 100644 index 00000000000..c2e539be6f4 --- /dev/null +++ b/packages/web/src/content/docs/ko/formatters.mdx @@ -0,0 +1,129 @@ +--- +title: 포매터 +description: opencode는 언어별 포매터를 사용합니다. +--- + +opencode는 언어 별 형식을 사용하여 작성 또는 편집 한 후 자동으로 파일을 포맷합니다. 이 생성 된 코드는 프로젝트의 코드 스타일을 따릅니다. + +--- + +## 내장 + +opencode는 인기있는 언어 및 프레임 워크에 대한 몇 가지 내장 형식자와 함께 제공됩니다. 아래는 formatters, 지원된 파일 확장 및 명령 또는 구성 옵션의 목록입니다. + +| 포매터 | 확장자 | 요구 사항 | +| -------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| gofmt | .go | `gofmt` 명령 사용 가능 | +| Mix | .ex, .ex, .eex, .heex, .leex, .neex, .sface | `mix` 명령 사용 가능 | +| Biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, [기타](https://biomejs.dev/) | `biome.json(c)` 구성 파일 | +| Zig | .zig, .zon | `zig` 명령 사용 가능 | +| clang-format | .c, .cpp, .h, .hpp, .ino, [기타](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` 구성 파일 | +| ktlint | .kt, .kts | `ktlint` 명령 사용 가능 | +| ruff | .py, .pyi | 구성 가능한 `ruff` 명령 | +| rustfmt | .rs | `rustfmt` 명령 사용 가능 | +| cargo fmt | .rs | `cargo fmt` 명령 사용 가능 | +| uv | .py, .pyi | `uv` 명령 사용 가능 | +| rubocop | .rb, .rake, .gemspec, .ru | `rubocop` 명령 사용 가능 | +| StandardRB | .rb, .rake, .gemspec, .ru | `standardrb` 명령 사용 가능 | +| htmlbeautifier | .erb, .html.erb | `htmlbeautifier` 명령 사용 가능 | +| Air | .R | `air` 명령 사용 가능 | +| Dart | 다트 | `dart` 명령 | +| ocamlformat | .ml, .mli | `ocamlformat` 명령 사용 가능·`.ocamlformat` 설정 파일 | +| Terraform | .tf, .tfvars | `terraform` 명령 사용 가능 | +| gleam | .gleam | `gleam` 명령 사용 가능 | +| nixfmt | .nix | `nixfmt` 명령 사용 가능 | +| shfmt | .sh, .bash | `shfmt` 명령 사용 가능 | +| Pint | .php | `laravel/pint` 의존도 `composer.json` | +| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | `oxfmt` Dependency in `package.json`, [experimental env 변수 플래그](/docs/cli/#experimental) | +| ormolu | .hs | `ormolu` 명령 사용 가능 | + +그래서 프로젝트가 `prettier`를 `package.json`에 가지고 있다면, opencode는 자동으로 그것을 사용합니다. + +--- + +## 작동 방식 + +opencode가 파일을 작성하거나 편집할 때: + +1. 모든 활성화된 formatters에 대한 파일 확장을 확인합니다. +2. 파일에 적절한 형식의 명령을 실행합니다. +3. 형식 변경을 자동으로 적용합니다. + +이 과정은 배경에서 발생합니다. 코드 스타일은 수동 단계없이 유지됩니다. + +--- + +## 구성 + +opencode config의 `formatter` 섹션을 통해 형식기를 사용자 정의 할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +각 formatter 구성은 다음을 지원합니다: + +| 속성 | 타입 | 설명 | +| ------------- | -------- | --------------------------------- | +| `disabled` | boolean | `true`로 설정하여 포매터 비활성화 | +| `command` | 문자열[] | 형식을 실행하는 명령 | +| `environment` | 객체 | 형식의 실행시 설정하는 환경 변수 | +| `extensions` | string[] | 이 형식의 파일 확장자 취급 | + +몇 가지 예제를 살펴 보자. + +--- + +## 포매터 비활성화 + +모든 포매터를 비활성화하려면 `formatter`를 `false`로 설정하십시오: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +**특정** 포매터의 경우, `disabled`를 `true`로 설정하십시오: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### 사용자 정의 포매터 + +내장 형식자를 무시하거나 명령, 환경 변수 및 파일 확장을 지정하여 새로운 것을 추가 할 수 있습니다. + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +명령의 **`$FILE` placeholder**는 형식의 파일 경로로 대체됩니다. diff --git a/packages/web/src/content/docs/ko/github.mdx b/packages/web/src/content/docs/ko/github.mdx new file mode 100644 index 00000000000..777b8cb6db2 --- /dev/null +++ b/packages/web/src/content/docs/ko/github.mdx @@ -0,0 +1,322 @@ +--- +title: GitHub +description: GitHub 이슈 및 풀 리퀘스트에서 opencode를 사용하세요. +--- + +opencode는 GitHub 워크플로우와 통합됩니다. Mention `/opencode` 또는 `/oc` 당신의 의견에, 그리고 opencode는 당신의 GitHub 활동 주자 안에 작업을 실행할 것입니다. + +--- + +## 기능 + +- **이슈**: opencode가 이슈를 보고 설명해 줍니다. +- **수정 및 구현**: 이슈를 수정하거나 기능을 구현하도록 opencode에 요청하세요. 새로운 브랜치에서 작업하고 변경 사항으로 PR을 제출합니다. +- **보안**: opencode는 GitHub 러너 내부에서 실행됩니다. + +--- + +## 설치 + +GitHub 저장소에서 다음과 같은 명령을 실행: + +```bash +opencode github install +``` + +GitHub 앱을 설치하고 워크플로를 만들고 비밀을 설정할 수 있습니다. + +--- + +## 수동 설정 + +또는 수동으로 설정할 수 있습니다. + +1. **GitHub 앱 설치** + +[**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent)로 이동합니다. 대상 저장소에 설치되어 있는지 확인하십시오. + +2. **워크플로우 추가** + +저장소에 `.github/workflows/opencode.yml`에 다음 작업 흐름 파일을 추가합니다. 적절한 `model`를 설정하고 `env`의 API 키가 필요합니다. + +```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx +``` + +3. **API 키를 Secret으로 저장** + +조직 또는 프로젝트 **Settings**에서, 왼쪽의 **Secrets and variables**를 확장하고 **Actions**를 선택합니다. 그리고 필요한 API 키를 추가합니다. + +--- + +## 구성 + +- `model`: opencode를 사용하는 모형. `provider/model`의 형식을 가져 가라. **필수**입니다. +- `agent`: 사용을 위한 에이전트. 주요 에이전트이어야 합니다. `default_agent`로 돌아와서 config 또는 `"build"`에서 찾을 수 없습니다. +- `share`: opencode 세션을 공유하는 것. Defaults to **true** for public 저장소. +- `prompt` : 기본 동작을 무시하기 위해 옵션 사용자 정의 프롬프트. opencode 프로세스 요청을 사용자 정의하기 위해 이것을 사용합니다. +- `token`: 코멘트를 생성, 커밋 변경 및 오프닝 풀 요청과 같은 작업을 수행하기위한 옵션 GitHub 액세스 토큰. 기본적으로 opencode는 opencode GitHub App에서 설치 액세스 토큰을 사용하므로 커밋, 코멘트 및 풀 요청은 앱에서 오는 것과 같이 나타납니다. + +대안으로, GitHub Action runner의 [붙박이 `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github token)을 사용하여 opencode GitHub 앱을 설치하지 않고 사용할 수 있습니다. 워크플로우에서 필요한 권한을 부여하는 것을 확인하십시오. + +```yaml +permissions: + id-token: write + contents: write + pull-requests: write + issues: write +``` + +또한 [개인 액세스 토큰](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT)를 사용할 수 있습니다. + +--- + +## 지원되는 이벤트 + +opencode는 다음 GitHub 이벤트에 의해 트리거 될 수 있습니다: + +| 이벤트 타입 | Triggered by | 상세 | +| ----------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| `issue_comment` | 이슈 또는 PR 댓글 | 멘션 `/opencode` 또는 `/oc` 당신의 의견. opencode는 컨텍스트를 읽고, 지점을 만들 수 있습니다, 열린 PR, 또는 대답. · | +| `pull_request_review_comment` | PR의 특정 코드 라인 댓글 | Mention `/opencode` 또는 `/oc` 코드 검토 중. opencode는 파일 경로, 줄 번호 및 diff 컨텍스트를 수신합니다. · | +| `issues` | 이슈가 열리거나 편집됨 | 이슈가 생성되거나 수정될 때 자동으로 opencode를 트리거합니다. `prompt` 입력이 필요합니다. | +| `pull_request` | PR 오픈 또는 업데이트 | PR이 열릴 때 자동 트리거 opencode 자동 리뷰에 대한 유용한 정보 | +| `schedule` | 크론 기반 일정 | 일정에 opencode를 실행합니다. `prompt` 입력을 요구합니다. 출력 로그 및 PR에 간다 (댓글이 없습니다). | +| `workflow_dispatch` | GitHub UI에서 수동 트리거 | 액션 탭을 통해 까다로운 Trigger opencode. `prompt` 입력을 요구합니다. 출력 로그 및 PR에 간다. | + +### 일정 예제 + +자동화된 작업을 수행하는 일정에 opencode를 실행: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +스케줄된 이벤트의 경우, `prompt` 입력은 **필요 ** 이후의 지시를 추출할 수 없습니다. 사용자 컨텍스트 없이 실행되는 워크플로우는 권한 확인을 위해, 워크플로우는 `contents: write`와 `pull-requests: write`를 부여해야 하며, opencode가 지점이나 PR을 만들게 됩니다. + +--- + +## Pull Request 예제 + +자동 검토 PR 때 그들은 열려있거나 업데이트 : + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +`pull_request` 이벤트의 경우 `prompt`가 제공되지 않은 경우, 풀 요청을 검토하는 opencode 기본값. + +--- + +### 이슈 분류 예제 + +자동으로 새로운 문제를 삼는다. 이 예제는 스팸을 줄이기 위해 30 일 이상 계정 필터 : + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +`issues` 사건을 위해, `prompt` 입력은 ** 필요 ** 거기에서 지시를 추출하는 코멘트가 없습니다. + +--- + +## 사용자 정의 프롬프트 + +opencode의 작업 흐름을 사용자 정의하는 기본 프롬프트를 부여합니다. + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +이것은 특정한 검토 기준, 기호화 기준, 또는 당신의 프로젝트에 관련된 초점 지역을 enforcing를 위해 유용합니다. + +--- + +## 예제 + +GitHub에서 opencode를 사용할 수있는 몇 가지 예입니다. + +- **이슈 설명** + +GitHub 문제에서 이 의견 추가. + +``` + /opencode explain this issue +``` + +opencode는 모든 코멘트를 포함하여 전체 스레드를 읽고, 명확한 설명과 대답. + +- **이슈 해결** + +GitHub 문제에서: + +``` + /opencode fix this +``` + +opencode는 새로운 지점을 만들 것이며 변경 사항을 실행하고 PR을 변경합니다. + +- **PR 및 변경 사항 검토** + +GitHub PR에 다음 댓글을 남겨주세요. + +``` + Delete the attachment from S3 when the note is removed /oc +``` + +opencode는 요청한 변경을 구현하고 동일한 PR에 커밋합니다. + +- **특정 코드 라인** + +PR의 "Files" 탭의 코드 라인에 직접 댓글을 남겨주세요. opencode는 파일, 줄 번호 및 diff 컨텍스트를 자동으로 감지하여 정확한 응답을 제공합니다. + +``` + [Comment on specific lines in Files tab] + /oc add error handling here +``` + +특정 라인에 대한 의견이 있을 때, opencode는 다음과 같습니다. + +- 검토되는 정확한 파일 +- 코드의 특정 라인 +- 주변 diff 컨텍스트 +- 라인 번호 정보 + +파일 경로 또는 라인 번호를 수동으로 지정하지 않고 더 많은 대상 요청을 허용합니다. diff --git a/packages/web/src/content/docs/ko/gitlab.mdx b/packages/web/src/content/docs/ko/gitlab.mdx new file mode 100644 index 00000000000..7b6468c7406 --- /dev/null +++ b/packages/web/src/content/docs/ko/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: GitLab 이슈 및 머지 리퀘스트에서 opencode를 사용하세요. +--- + +opencode는 GitLab CI/CD 파이프라인 또는 GitLab Duo를 통해 GitLab 워크플로우와 통합됩니다. + +두 경우, opencode는 GitLab runners에서 실행됩니다. + +--- + +# GitLab CI 소개 + +opencode는 일반 GitLab 파이프라인에서 작동합니다. [CI 컴포넌트](https://docs.gitlab.com/ee/ci/components/)로 파이프라인에 구축할 수 있습니다. + +여기에서 우리는 opencode에 대한 커뮤니티 생성 CI / CD 구성품을 사용하고 있습니다. [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### 기능 + +- **실행별 사용자 지정 구성 사용**: 사용자 정의 구성 디렉토리와 opencode 구성, 예를 들어 `./config/#custom-directory`는 opencode 실행마다 활성화하거나 비활성화 할 수 있습니다. +- ** 최소 설정**: CI 구성 요소는 opencode를 배경으로 설정하면 opencode 구성과 초기 프롬프트를 만들 필요가 있습니다. +- **Flexible**: CI 구성 요소는 여러 입력을 지원합니다. + +--- + +## 설정 + +1. opencode 인증 JSON을 **Settings** > **CI/CD** > **Variables**에서 파일 유형 CI 환경 변수로 저장하십시오. "Masked and hidden"로 표시하십시오. +2. `.gitlab-ci.yml` 파일에 뒤에 추가하십시오. + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +더 많은 입력 및 사용 사례 [docs를 체크 아웃](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) 이 구성 요소에 대한. + +--- + +## GitLab Duo + +opencode는 GitLab 워크플로우와 통합됩니다. +코멘트에 Mention `@opencode`, opencode는 GitLab CI 파이프라인 내에서 작업을 실행합니다. + +--- + +### 기능 + +- **이슈**: opencode가 문제점을 보고 당신을 설명합니다. +- **수정 및 구현**: 이슈를 수정하거나 기능을 구현하려면 opencode에 문의하십시오. + 새로운 지점을 만들고 변화를 병합 요청을 제기합니다. +- **보안**: opencode는 GitLab runners에서 실행됩니다. + +--- + +## 설정 + +opencode는 GitLab CI/CD 파이프라인에서 실행되며, 여기서 설정해야 할 일은 다음과 같습니다. + +:::tip +[**GitLab docs**](https://docs.gitlab.com/user/duo agent platform/agent assistant/) 를 체크 아웃하십시오. +::: + +1. GitLab 환경 설정 +2. CI/CD 설치 +3. AI 모형 공급자 API 열쇠를 얻으십시오 +4. 서비스 계정 만들기 +5. CI/CD 변수 구성 +6. Flow config 파일을 만들려면 다음과 같습니다. + +
+ + Flow configuration + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +자세한 지침에 대한 [GitLab CLI Agent docs](https://docs.gitlab.com/user/duo agent platform/agent assistant/)를 참조할 수 있습니다. + +--- + +### 예제 + +다음은 GitLab에서 opencode를 사용할 수있는 몇 가지 예입니다. + +:::tip +`@opencode`보다 다른 트리거 구문을 사용할 수 있습니다. +::: + +- **이슈 설명** + +GitLab 문제에서이 코멘트를 추가하십시오. + +``` + @opencode explain this issue +``` + +opencode는 문제와 대답을 명확하게 설명합니다. + +- **이슈 해결** + +GitLab 문제에서, 말한다: + +``` + @opencode fix this +``` + +opencode는 새로운 지점을 만들 것이며 변경 사항을 구현하고 변경 사항을 병합 요청을 엽니다. + +- **머지 리퀘스트 검토** + +GitLab 병합 요청에 대한 다음 의견을 남겨주세요. + +``` + @opencode review this merge request +``` + +opencode는 병합 요청을 검토하고 피드백을 제공합니다. diff --git a/packages/web/src/content/docs/ko/ide.mdx b/packages/web/src/content/docs/ko/ide.mdx new file mode 100644 index 00000000000..2df782a9e72 --- /dev/null +++ b/packages/web/src/content/docs/ko/ide.mdx @@ -0,0 +1,47 @@ +--- +title: IDE +description: VS Code, Cursor 및 기타 IDE용 opencode 확장 프로그램. +--- + +opencode는 VS Code, Cursor, 또는 터미널을 지원하는 IDE와 통합됩니다. 시작하려면 terminal에서 `opencode`를 실행하십시오. + +--- + +## 사용법 + +-**Quick Launch**: `Cmd+Esc` (Mac) 또는 `Ctrl+Esc` (Windows/Linux)를 사용하여 통합 터미널 뷰에 opencode를 열거나 기존 terminal 세션을 이미 실행하면 됩니다. -**New Session**: `Cmd+Shift+Esc` (Mac) 또는 `Ctrl+Shift+Esc` (Windows/Linux)를 사용하여 새로운 opencode terminal 세션을 시작하려면 이미 열리면 됩니다. UI에서 opencode 버튼을 클릭합니다. -**Context Awareness**: opencode로 현재 선택 또는 탭을 자동으로 공유합니다. + +- **파일 참조 단축키** : 파일 참조를 삽입하려면 `Cmd+Option+K` (Mac) 또는 `Alt+Ctrl+K` (Linux / Windows)를 사용하십시오. 예를 들어, `@File#L37-42`. + +--- + +## 설치 + +VS Code에 opencode를 설치하고 Cursor, Windsurf, VSCodium과 같은 인기있는 포크 : + +1. VS Code 열기 +2. 통합 terminal을 여십시오 +3. 실행 `opencode` - 확장 자동으로 설치 + +반면에 TUI에서 `/editor` 또는 `/export`를 실행할 때, 당신은 `export EDITOR="code --wait"`를 설정할 필요가 있을 것입니다. [Learn more](/docs/tui/#editor-setup). + +--- + +## 수동 설치 + +확장 마켓 플레이스에서 **opencode**를 검색하고 **Install**를 클릭합니다. + +--- + +### 문제 해결 + +확장이 자동으로 설치되지 않는 경우: + +- 통합 terminal에서 `opencode`를 실행하는 것을 보장합니다. +- IDE용 CLI가 설치됩니다. +- VS Code : `code` 명령 +- 커서: `cursor` 명령 +- 윈드 서핑을 위해: `windsurf` 명령 +- VSCodium의 경우: `codium` 명령 +- 만약 `Cmd+Shift+P` (Mac) 또는 `Ctrl+Shift+P` (Windows/Linux)를 실행하고 "Shell Command: PATH"에서 'code' 명령을 설치하십시오 (또는 IDE에 해당) +- Ensure VS Code는 확장을 설치하는 권한이 있습니다. diff --git a/packages/web/src/content/docs/ko/index.mdx b/packages/web/src/content/docs/ko/index.mdx new file mode 100644 index 00000000000..d5bd6a979cd --- /dev/null +++ b/packages/web/src/content/docs/ko/index.mdx @@ -0,0 +1,343 @@ +--- +title: 소개 +description: OpenCode를 시작해 보세요. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**OpenCode**](/)는 터미널 기반 인터페이스, 데스크톱 앱, IDE 확장 형태로 사용할 수 있는 오픈 소스 AI 코딩 에이전트입니다. + +![opencode TUI with the opencode theme](../../../assets/lander/screenshot.png) + +바로 시작해 봅시다. + +--- + +## 사전 준비 + +터미널에서 OpenCode를 사용하려면 다음이 필요합니다. + +1. 최신 터미널 에뮬레이터 (예:) + - [WezTerm](https://wezterm.org), 크로스 플랫폼 + - [Alacritty](https://alacritty.org), 크로스 플랫폼 + - [Ghostty](https://ghostty.org), Linux 및 macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux 및 macOS + +2. 사용할 LLM 제공자의 API 키 + +--- + +## 설치 + +가장 쉬운 설치 방법은 설치 스크립트를 사용하는 것입니다. + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +아래 명령으로도 설치할 수 있습니다. + +- **Node.js 사용** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **macOS/Linux에서 Homebrew 사용** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > 최신 릴리스는 OpenCode tap 사용을 권장합니다. 공식 `brew install opencode` 포뮬러는 Homebrew 팀이 관리하므로 업데이트 주기가 더 긴 편입니다. + +- **Arch Linux에서 Paru 사용** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[권장: WSL 사용] +Windows에서는 [Windows Subsystem for Linux (WSL)](/docs/windows-wsl)을 사용하는 것이 가장 좋습니다. OpenCode 기능과의 호환성이 높고 성능도 더 좋습니다. +::: + +- **Chocolatey 사용** + + ```bash + choco install opencode + ``` + +- **Scoop 사용** + + ```bash + scoop install opencode + ``` + +- **NPM 사용** + + ```bash + npm install -g opencode-ai + ``` + +- **Mise 사용** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **Docker 사용** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +Windows에서 Bun을 통한 OpenCode 설치는 아직 지원되지 않으며, 현재 지원을 준비 중입니다. + +[Releases](https://github.com/anomalyco/opencode/releases)에서 바이너리를 직접 받아 설치할 수도 있습니다. + +--- + +## 구성 + +OpenCode는 API 키를 설정하면 원하는 LLM 제공자를 사용할 수 있습니다. + +LLM 제공자(LLM Provider)를 처음 사용한다면 [OpenCode Zen](/docs/zen)을 추천합니다. +OpenCode 팀이 테스트하고 검증한 모델 목록입니다. + +1. TUI에서 `/connect` 명령을 실행한 뒤 `opencode`를 선택하고 [opencode.ai/auth](https://opencode.ai/auth)로 이동합니다. + + ```txt + /connect + ``` + +2. 로그인 후 결제 정보를 입력하고 API 키를 복사합니다. + +3. API 키를 붙여 넣습니다. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +다른 제공자를 선택해도 됩니다. [더 알아보기](/docs/providers#directory). + +--- + +## 초기화 + +이제 제공자 구성이 끝났으니, 작업할 프로젝트 디렉터리로 이동합니다. + +```bash +cd /path/to/project +``` + +그리고 OpenCode를 실행합니다. + +```bash +opencode +``` + +다음 명령으로 프로젝트용 OpenCode 초기화를 진행합니다. + +```bash frame="none" +/init +``` + +이 명령은 프로젝트를 분석하고 루트에 `AGENTS.md` 파일을 생성합니다. + +:::tip +프로젝트의 `AGENTS.md`는 Git에 커밋해 두는 것을 권장합니다. +::: + +그러면 OpenCode가 프로젝트 구조와 코딩 패턴을 더 잘 이해할 수 있습니다. + +--- + +## 사용법 + +이제 OpenCode로 프로젝트 작업을 시작할 준비가 되었습니다. 무엇이든 물어보세요. + +AI 코딩 에이전트를 처음 쓰는 경우 도움이 되는 예시를 소개합니다. + +--- + +### 질문하기 + +OpenCode에 코드베이스 설명을 요청할 수 있습니다. + +:::tip +프로젝트 파일은 `@` 키로 퍼지 검색할 수 있습니다. +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +직접 작업하지 않은 코드 영역을 이해할 때 특히 유용합니다. + +--- + +### 기능 추가 + +프로젝트에 새 기능을 추가해 달라고 요청할 수 있습니다. 다만 먼저 계획을 만들게 하는 것을 권장합니다. + +1. **계획 만들기** + + OpenCode에는 변경 작업을 비활성화하고 구현 방법을 제안만 하는 *Plan mode*가 있습니다. + + **Tab** 키로 전환하면 오른쪽 아래에 모드 표시가 나타납니다. + + ```bash frame="none" title="Switch to Plan mode" + + ``` + + 이제 원하는 작업을 구체적으로 설명합니다. + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + OpenCode가 정확히 이해할 만큼 충분한 맥락을 주는 것이 중요합니다. 팀의 주니어 개발자에게 설명하듯 요청하면 도움이 됩니다. + + :::tip + 맥락과 예시를 충분히 제공하면 원하는 결과를 얻기 쉽습니다. + ::: + +2. **계획 다듬기** + + 계획이 나오면 피드백을 주거나 추가 요구사항을 붙일 수 있습니다. + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + + :::tip + 이미지를 터미널에 드래그 앤 드롭하면 프롬프트에 첨부할 수 있습니다. + ::: + + OpenCode는 첨부한 이미지를 분석해 프롬프트에 포함합니다. + +3. **기능 구현** + + 계획이 충분히 만족스러우면 **Tab** 키를 다시 눌러 *Build mode*로 돌아갑니다. + + ```bash frame="none" + + ``` + + 그리고 실제 변경을 요청합니다. + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### 바로 변경하기 + +비교적 단순한 변경은 계획 검토 없이 바로 구현하도록 요청해도 됩니다. + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +원하는 변경이 정확히 반영되도록, 필요한 맥락을 충분히 제공하세요. + +--- + +### 변경 되돌리기 + +예를 들어 OpenCode에 변경을 요청했다고 가정해 보겠습니다. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +결과가 기대와 다르면 `/undo` 명령으로 **되돌릴 수** 있습니다. + +```bash frame="none" +/undo +``` + +OpenCode는 방금 적용한 변경을 되돌리고 원래 메시지를 다시 보여줍니다. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +이 상태에서 프롬프트를 다듬어 다시 시도하면 됩니다. + +:::tip +`/undo`는 여러 번 연속으로 실행할 수 있습니다. +::: + +반대로 `/redo` 명령으로 **다시 적용**할 수도 있습니다. + +```bash frame="none" +/redo +``` + +--- + +## 공유 + +OpenCode와의 대화는 [팀과 공유](/docs/share)할 수 있습니다. + +```bash frame="none" +/share +``` + +현재 대화 링크를 생성하고 클립보드에 복사합니다. + +:::note +대화는 기본값으로 공유되지 않습니다. +::: + +아래는 OpenCode [대화 예시](https://opencode.ai/s/4XP1fce5)입니다. + +--- + +## 사용자 지정 + +이제 OpenCode 사용의 기본은 끝났습니다. + +자신의 워크플로우에 맞추려면 [테마 선택](/docs/themes), [키바인드 사용자 지정](/docs/keybinds), [코드 포매터 설정](/docs/formatters), [커스텀 명령 작성](/docs/commands), [OpenCode 구성 조정](/docs/config)을 추천합니다. diff --git a/packages/web/src/content/docs/ko/keybinds.mdx b/packages/web/src/content/docs/ko/keybinds.mdx new file mode 100644 index 00000000000..d41fb8cef5e --- /dev/null +++ b/packages/web/src/content/docs/ko/keybinds.mdx @@ -0,0 +1,192 @@ +--- +title: 키바인드 +description: 키바인드를 사용자 지정하세요. +--- + +opencode는 opencode config를 통해 사용자 정의 할 수있는 keybinds 목록을 가지고 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## 리더 키 + +opencode는 대부분의 keybinds에 대한 `leader` 키를 사용합니다. 이것은 당신의 terminal에 있는 충돌을 피합니다. + +기본적으로 `ctrl+x`는 리더 키이며 대부분의 작업은 리더 키를 먼저 누르고 단축키를 누릅니다. 예를 들어, 새 세션을 시작하려면 먼저 `ctrl+x`를 누르고 `n`를 누릅니다. + +키바인드에 리더 키를 사용할 필요는 없지만, 사용하는 것을 권장합니다. + +--- + +## 키바인드 비활성화 + +"none"의 값으로 구성에 키를 추가하여 keybind를 비활성화 할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## 데스크탑 프롬프트 단축키 + +opencode 데스크톱 앱 프롬프트 입력은 텍스트 편집을 위한 일반적인 Readline/Emacs-style 단축키를 지원합니다. 이들은 내장되어 있으며 현재 `opencode.json`를 통해 구성할 수 없습니다. + +| 단축키 | 동작 | +| -------- | -------------------------- | +| `ctrl+a` | 현재 행 시작으로 이동 | +| `ctrl+e` | 현재선 끝으로 이동 | +| `ctrl+b` | 커서를 다시 한 문자로 이동 | +| `ctrl+f` | 한자 앞의 커서 | +| `alt+b` | 한 단어로 커서 이동 | +| `alt+f` | 한 단어를 넘겨 주세요 | +| `ctrl+d` | 커서의 캐릭터 삭제 | +| `ctrl+k` | 노선의 종료 | +| `ctrl+u` | 노선 시작 | +| `ctrl+w` | 이전 단어 | +| `alt+d` | 다음 단어를 죽이기 | +| `ctrl+t` | 자가용 캐릭터 | +| `ctrl+g` | 팝오버를 취소 / 응답 취소 | + +--- + +## Shift+Enter + +몇몇 terminal은 기본적으로 입력한 보조 키를 보내지 않습니다. `Shift+Enter`를 이스케이프 시퀀스로 보낼 terminal을 구성해야 할 수 있습니다. + +### Windows Terminal + +`settings.json`를 엽니다: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +루트 레벨 `actions` 배열에 이것을 추가하십시오: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +루트 레벨 `keybindings` 배열에 이것을 추가하십시오: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +파일을 저장하고 Windows Terminal을 다시 시작하거나 새 탭을 엽니 다. diff --git a/packages/web/src/content/docs/ko/lsp.mdx b/packages/web/src/content/docs/ko/lsp.mdx new file mode 100644 index 00000000000..31d3dda26d3 --- /dev/null +++ b/packages/web/src/content/docs/ko/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: LSP 서버 +description: OpenCode는 LSP 서버와 통합되어 작동합니다. +--- + +OpenCode는 언어 서버 프로토콜(LSP)과 통합되어 LLM이 코드베이스와 상호 작용할 수 있게 돕습니다. 이를 통해 진단 정보를 사용하여 LLM에 피드백을 제공합니다. + +--- + +## 기본 제공 (Built-in) + +OpenCode는 인기 있는 언어들에 대해 여러 내장 LSP 서버를 제공합니다. + +| 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+)` 설치 | +| 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, .ct, .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` 설치 (macOS의 `xcode`) | +| svelte | .svelte | Svelte 프로젝트 자동 설치 | +| terraform | .tf, .tfvars | GitHub 릴리스에서 자동 설치 | +| typst | .typ, .typc | GitHub 릴리스에서 자동 설치 | +| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | 프로젝트의 `typescript` 의존성 | +| vue | .vue | Vue 프로젝트 자동 설치 | +| yaml-ls | .yaml, .yml | Red Hat yaml-language-server 자동 설치 | +| zls | .zig, .zon | `zig` 명령 사용 가능 | + +LSP 서버는 위 파일 확장자 중 하나가 감지되고 요구 사항이 충족되면 자동으로 활성화됩니다. + +:::note +`OPENCODE_DISABLE_LSP_DOWNLOAD` 환경 변수를 `true`로 설정하여 자동 LSP 서버 다운로드를 비활성화 할 수 있습니다. +::: + +--- + +## 작동 방식 + +OpenCode가 파일을 열 때, 다음과 같이 작동합니다: + +1. 활성화된 모든 LSP 서버에 대해 파일 확장자를 확인합니다. +2. 적절한 LSP 서버가 아직 실행 중이지 않다면 시작합니다. + +--- + +## 구성 + +OpenCode 설정의 `lsp` 섹션을 통해 LSP 서버를 사용자 정의할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +각 LSP 서버는 다음을 지원합니다: + +| 속성 | 유형 | 설명 | +| ---------------- | -------- | --------------------------------------- | +| `disabled` | boolean | LSP 서버를 비활성화하려면 `true`로 설정 | +| `command` | string[] | LSP 서버를 시작하는 명령 | +| `extensions` | string[] | 이 LSP 서버의 확장자 | +| `env` | object | 서버 시작 시 설정할 환경 변수 | +| `initialization` | object | LSP 서버에 보내는 초기화 옵션 | + +몇 가지 예제를 살펴봅시다. + +--- + +## 환경 변수 + +`env` 속성을 사용하여 LSP 서버를 시작할 때 환경 변수를 설정합니다. + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### 초기화 옵션 + +`initialization` 속성을 사용하여 초기화 옵션을 LSP 서버에 전달합니다. 이들은 LSP `initialize` 요청에 보내진 서버 별 설정입니다. + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +초기화 옵션은 LSP 서버가 다릅니다. LSP 서버의 사용 가능한 옵션을 확인하세요. +::: + +--- + +### LSP 서버 비활성화 + +전역적으로 **모든** LSP 서버를 비활성화하려면 `lsp`를 `false`로 설정하십시오. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +**특정** LSP 서버를 비활성화하려면 `disabled`를 `true`로 설정하십시오. + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +## 사용자 정의 LSP 서버 + +명령어와 파일 확장자를 지정하여 사용자 정의 LSP 서버를 추가할 수 있습니다. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## 추가 정보 + +### PHP Intelephense + +PHP Intelephense는 라이선스 키를 통해 프리미엄 기능을 제공합니다. 텍스트 파일에 키(만)를 저장하여 라이선스 키를 제공할 수 있습니다. + +- macOS/Linux: `$HOME/intelephense/license.txt` +- Windows: `%USERPROFILE%/intelephense/license.txt` + +파일에는 다른 내용이 없어야 합니다. diff --git a/packages/web/src/content/docs/ko/mcp-servers.mdx b/packages/web/src/content/docs/ko/mcp-servers.mdx new file mode 100644 index 00000000000..2d5a8e025e0 --- /dev/null +++ b/packages/web/src/content/docs/ko/mcp-servers.mdx @@ -0,0 +1,511 @@ +--- +title: MCP 서버 +description: 로컬 및 원격 MCP 도구를 추가하세요. +--- + +Model Context Protocol , 또는 MCP를 사용하여 opencode에 외부 도구를 추가할 수 있습니다. opencode는 로컬 및 원격 서버를 모두 지원합니다. + +추가되면 MCP 도구는 내장 도구와 함께 LLM에 자동으로 사용할 수 있습니다. + +--- + +#### 주의사항 + +MCP 서버를 사용할 때 컨텍스트에 추가됩니다. 도구가 많으면 컨텍스트가 빠르게 채워질 수 있습니다. 그래서 우리는 당신이 사용하는 MCP 서버와 주의를 기울여야 합니다. + +:::tip +MCP 서버는 귀하의 컨텍스트에 추가하므로, 활성화할 수 있는 것을 주의해야 합니다. +::: + +GitHub MCP 서버와 같은 특정 MCP 서버는 많은 토큰을 추가하고 컨텍스트 제한을 쉽게 초과 할 수 있습니다. + +--- + +## 구성 + +`mcp`에서 MCP 서버를 정의할 수 있습니다. 각 MCP를 고유 이름으로 추가합니다. LLM을 프롬프트할 때 MCP를 참조할 수 있습니다. + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +`enabled`를 `false`로 설정하여 서버를 비활성화 할 수 있습니다. config에서 제거하지 않고 서버를 일시적으로 비활성화하려는 경우 유용합니다. + +--- + +### 원격 기본값 재정의 + +조직은 `.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` | Array | Y | MCP 서버를 실행하는 명령과 인수. | +| `environment` | 개체 | | 서버 실행시 설정하는 환경 변수 | +| `enabled` | boolean | | 시동에서 MCP 서버 사용 가능 | +| `timeout` | number | | 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` | boolean | | 시동에서 MCP 서버 사용 가능 | +| `headers` | 개체 | | 헤드러는 요청으로 보내드립니다. | +| `oauth` | 개체 | | OAuth 인증 구성 [OAuth](#oauth) 아래의 섹션을 참조하십시오. | +| `timeout` | number | | MCP 서버에서 태핑툴을 위한 타임아웃 기본 5000 (5 초). | + +--- + +## OAuth + +opencode는 원격 MCP 서버에 대한 OAuth 인증을 자동으로 처리합니다. 서버가 인증이 필요할 때, opencode는: + +1. 401 응답을 검출하고 OAuth 흐름을 시작 +2. **Dynamic Client 등록 (RFC 7591) ** 서버에서 지원되는 경우 +3. 미래의 요청에 대해 안전하게 보관 토큰 + +--- + +## 자동 설정 + +대부분의 OAuth-enabled 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 `를 사용하여 [수동으로 트리거](#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 서버를 나열하고 auth 상태: + +```bash +opencode mcp list +``` + +저장된 자격 제거: + +```bash +opencode mcp logout my-oauth-server +``` + +`mcp auth` 명령은 사용자의 브라우저를 엽니다. `~/.local/share/opencode/mcp-auth.json`에서 토큰을 안전하게 저장합니다. + +--- + +#### OAuth 비활성화 + +서버의 자동 OAuth를 비활성화하려는 경우 (예를 들어, 대신 API 키를 사용하는 서버), `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` | 개체 \| false | OAuth config object, 또는 `false`를 비활성화하는 OAuth 자동검출. · | +| `clientId` | 문자열 | OAuth 클라이언트 ID. 제공되지 않은 경우, 동적 클라이언트 등록 시도됩니다. · | +| `clientSecret` | String | OAuth 클라이언트 비밀, 허가서 서버가 필요한 경우. | +| `scope` | String | OAuth 범위는 인증 중입니다. | + +###### 디버깅 + +원격 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` 명령은 현재 auth 상태를 보여 주며 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 + } +} +``` + +또한 glob 패턴을 사용하여 일치하는 모든 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 + } +} +``` + +여기에 우리는 모든 MCP를 비활성화하는 glob 패턴 `my-mcp*`를 사용합니다. + +--- + +## 에이전트별 + +많은 MCP 서버가 있다면 전역적으로는 비활성화하고 에이전트별로만 활성화할 수 있습니다. 이 작업을 수행: + +1. 글로벌 도구로 사용 가능. +2. [agent 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 + } + } + } +} +``` + +--- + +### Glob 패턴 + +glob 패턴은 간단한 regex globbing 패턴을 사용합니다 : + +- `*`는 어떤 특성 (예를들면, `"my-mcp*"` 경기 `my-mcp_search`, `my-mcp_list`, 등)의 0개 이상 일치합니다. +- `?`는 정확히 하나의 문자 일치 +- 다른 모든 문자 일치 말 그대로 + +:::note +MCP 서버 도구는 서버 이름으로 prefix로 등록되므로 서버의 모든 도구를 간단하게 사용할 수 있습니다. + +``` +"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 계정에 연결하십시오. + +일단 인증되면, 당신은 쿼리 문제, 프로젝트, 오류 데이터에 대한 프린트 도구를 사용할 수 있습니다. + +```txt "use sentry" +Show me the latest unresolved issues in my project. use sentry +``` + +--- + +### Context7 + +[Context7 MCP 서버](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` 환경 변수 세트가 있다는 것을 assuming입니다. + +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 + +[Grep by Vercel](https://grep.app) MCP 서버를 추가하여 GitHub에서 코드 스니펫을 검색합니다. + +```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/ko/models.mdx b/packages/web/src/content/docs/ko/models.mdx new file mode 100644 index 00000000000..2eeaa1ef59e --- /dev/null +++ b/packages/web/src/content/docs/ko/models.mdx @@ -0,0 +1,223 @@ +--- +title: 모델 +description: LLM 공급자 및 모델 구성. +--- + +opencode는 [AI SDK](https://ai-sdk.dev/) 및 [Models.dev](https://models.dev)를 사용하여 **75+ LLM 제공 업체**를 지원하며 로컬 모델을 실행합니다. + +--- + +## 공급자 + +가장 인기 있는 공급자는 기본적으로 미리 로드되어 있습니다. `/connect` 명령을 통해 공급자를위한 자격 증명을 추가하면 opencode를 시작할 때 사용할 수 있습니다. + +자세히 알아보기 [providers](/docs/providers). + +--- + +## 모델 선택 + +공급자를 구성하면 입력하여 원하는 모델을 선택할 수 있습니다. + +```bash frame="none" +/models +``` + +--- + +## 추천 모델 + +수많은 모델이 있으며, 매주 새로운 모델이 출시됩니다. + +:::tip +우리가 추천하는 모델 중 하나를 사용하여 고려하십시오. +::: + +하지만 코드 작성과 도구 호출 모두에서 뛰어난 성능을 보이는 모델들이 있습니다. + +특별한 순서는 없습니다. (이 목록은 전체 목록이 아니며 최신 상태가 아닐 수 있습니다): + +- GPT 5.2 +- GPT 5.1 Codex +- Claude Opus 4.5 +- Claude Sonnet 4.5 +- M2.1 +- Gemini 3 Pro + +--- + +## 기본값 설정 + +기본 모델로 설정하려면 `model` 키를 설정할 수 있습니다. +opencode 설정. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +전체 ID는 `provider_id/model_id`입니다. 예를 들어, [OpenCode Zen](/docs/zen)을 사용한다면, GPT 5.1 Codex에 `opencode/gpt-5.1-codex`를 사용할 수 있습니다. + +[custom Provider](/docs/providers#custom)를 구성하면 `provider_id`는 구성의 `provider` 부분에서 키이며 `model_id`는 `provider.models`에서 키입니다. + +--- + +## 모델 구성 + +config를 통해 모델의 옵션을 구성할 수 있습니다. + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +여기서는 두 개의 내장 모델에 대한 전역 설정을 구성합니다: `gpt-5`를 통해 액세스 할 때 `openai` 공급자 및 `claude-sonnet-4-20250514`는 `anthropic` 공급자를 통해 액세스 할 때. +내장 공급자 및 모델 이름은 [Models.dev](https://models.dev)에서 찾을 수 있습니다. + +사용중인 에이전트에 이러한 옵션을 구성할 수 있습니다. 에이전트 구성은 여기에 모든 글로벌 옵션을 overrides. [더 알아보기](/docs/agents/#additional). + +내장 된 것을 확장하는 사용자 정의 변형을 정의 할 수 있습니다. Variants는 중복 항목 생성 없이 동일한 모델을 위한 다른 설정을 구성할 수 있습니다: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## 변형 + +많은 모델이 다양한 구성의 변형(variant)을 지원합니다. opencode는 인기있는 공급자를위한 기본 변형으로 배송됩니다. + +## 내장 변형 + +opencode는 많은 공급자를 위한 기본 변종으로 발송합니다: + +**Anthropic**: + +- `high` - 높은 생각(Thinking) 예산 (기본) +- `max` - 최대 생각 예산 + +** OpenAI **: + +모델에 따라 다릅니다. + +- `none` - 추론(Reasoning) 없음 +- `minimal` - 최소 추론 노력 +- `low` - 낮은 이유 노력 +- `medium` - 중간 이유 노력 +- `high` - 높은 이유 노력 +- `xhigh` - 추가 높은 이유 노력 + +** 구글 **: + +- `low` - 더 낮은 노력/토큰 예산 +- `high` - 더 높은 노력 / 토큰 예산 + +:::tip +이 목록은 포괄적이지 않습니다. 다른 많은 공급자는 기본적으로 내장되어 있습니다. +::: + +### 사용자 정의 변형 + +기존의 변형을 과도하게 할 수 있거나 자신에게 추가 할 수 있습니다. + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +## 변형 순환 + +keybind `variant_cycle`를 사용하여 변형 사이 신속하게 전환합니다. [더 알아보기](/docs/keybinds). + +--- + +## 모델 로딩 순서 + +opencode가 시작될 때, 다음의 우선순위 순서에 있는 모형을 검사합니다: + +1. `--model` 또는 `-m` 명령 선 깃발. 형식은 구성 파일과 동일합니다. `provider_id/model_id`. + +2. opencode config의 모델 목록. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + +여기에 형식은 `provider/model`입니다. + +3. 마지막 사용된 모형. + +4. 내부 우선 순위를 사용하는 첫 번째 모델. diff --git a/packages/web/src/content/docs/ko/modes.mdx b/packages/web/src/content/docs/ko/modes.mdx new file mode 100644 index 00000000000..4daa4100019 --- /dev/null +++ b/packages/web/src/content/docs/ko/modes.mdx @@ -0,0 +1,329 @@ +--- +title: 모드 +description: 다양한 사용 사례를 위한 다양한 모드. +--- + +:::caution +모드는 opencode 설정에서 `agent` 옵션을 통해 구성되어 있습니다. 더 보기 +`mode` 옵션이 이제 비활성화되었습니다. [더 알아보기](/docs/agents). +::: + +opencode의 모드는 다른 사용 사례에 대한 행동, 도구 및 프롬프트를 사용자 정의 할 수 있습니다. + +그것은 두 개의 내장 모드와 함께 제공됩니다 : ** 빌드 ** 및 ** 계획 **. 사용자 정의 할 수 있습니다. +opencode config를 통해 자체를 구성합니다. + +세션 중에 모드를 전환하거나 구성 파일에서 구성할 수 있습니다. + +--- + +## 내장 + +opencode는 2개의 붙박이 형태로 옵니다. + +--- + +### 빌드 + +빌드는 **default** 모드로 모든 도구가 활성화됩니다. 이것은 파일 운영 및 시스템 명령에 대한 전체 액세스가 필요한 개발 작업을위한 표준 모드입니다. + +--- + +## 계획 + +계획 및 분석을 위해 설계된 제한 모드. 계획 모드에서 다음 도구는 기본적으로 비활성화됩니다: + +- `write` - 새로운 파일을 만들 수 없습니다 +- `edit` - `.opencode/plans/*.md`에 위치한 파일을 제외하고 기존 파일을 수정할 수 없습니다. +- `patch` - 패치 적용 +- `bash` - shell 명령을 실행할 수 없습니다 + +이 모드는 코드를 분석하기 위해 AI를 원할 때 유용합니다. 변경 사항을 제안하거나 코드베이스에 실제 수정없이 계획을 만들 수 있습니다. + +--- + +## 전환 + +Tab 키를 사용하여 세션 중에 모드를 전환할 수 있습니다. 또는 당신의 형성된 `switch_mode` keybind. + +참조 : [Formatters](/docs/formatters) 코드 형식 설정에 대한 정보. + +--- + +## 구성 + +내장 모드를 사용자 정의하거나 구성을 통해 자신의 만들 수 있습니다. 형태는 2가지 방법으로 형성될 수 있습니다: + +### JSON 구성 + +`opencode.json` 설정 파일에서 모드 구성: + +```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 구성 + +Markdown 파일을 사용하여 모드를 정의할 수 있습니다. 그들에 게: + +- 글로벌: `~/.config/opencode/modes/` +- 프로젝트: `.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. +``` + +Markdown 파일 이름은 모드 이름 (예 : `review.md`는 `review` 모드를 만듭니다)이됩니다. + +이 구성 옵션을 자세히 살펴봅시다. + +--- + +### 모델 + +`model` config를 사용하여 이 모드의 기본 모델을 무시합니다. 다른 작업에 최적화 된 다른 모델을 사용하는 데 유용합니다. 예를 들어, 계획을위한 빠른 모델, 구현을위한 더 많은 모델. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### 온도 + +`temperature` config와 AI의 응답의 임의성과 창의성을 제어합니다. 더 낮은 값은 더 집중하고 세심한 응답을 만듭니다. 더 높은 값은 창의력과 가변성을 증가하면서. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +온도 값은 일반적으로 0.0에서 1.0에 배열합니다: + +- **0.0-0.2**: 매우 집중하고 신중한 응답, 코드 분석 및 계획에 이상 -**0.3-0.5**: 일부 창의력과 균형 잡힌 응답, 일반 개발 작업에 좋은 +- **0.6-1.0**: 더 창조적이고 다양한 응답, 브레인스토밍 및 탐험에 유용한 + +```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}" + } + } +} +``` + +온도가 지정되지 않은 경우, opencode는 모델별 기본 (일반적으로 0 대부분의 모델에 대한, 0.55 Qwen 모델)을 사용합니다. + +--- + +#### 프롬프트 + +`prompt` config를 가진 이 형태를 위한 주문 체계 prompt 파일을 지정하십시오. prompt 파일은 모드의 목적에 특정한 지시를 포함해야 합니다. + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +이 경로는 config 파일이 있는 곳에 관계됩니다. 그래서이 작품 +글로벌 opencode config 및 프로젝트 특정 구성 모두. + +--- + +## 도구 + +이 모드에서는 `tools` config를 사용할 수 있습니다. `true` 또는 `false`로 설정하여 특정 도구를 활성화하거나 비활성화 할 수 있습니다. + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +도구가 지정되지 않은 경우, 모든 도구는 기본적으로 활성화됩니다. + +--- + +### 유효한 도구 + +여기에 모든 도구는 모드 구성을 통해 제어 할 수 있습니다. + +| 도구 | 설명 | +| ----------- | --------------------- | +| `bash` | shell 명령 실행 | +| `edit` | 기존 파일 수정 | +| `write` | 새 파일 만들기 | +| `read` | 읽는 파일 내용 | +| `grep` | 파일 검색 | +| `glob` | 패턴으로 찾기 | +| `list` | 디렉토리 내용 보기 | +| `patch` | 파일에 패치 적용 | +| `todowrite` | 할 일(Todo) 목록 관리 | +| `todoread` | 할 일(Todo) 목록 읽기 | +| `webfetch` | 웹사이트 가져오기 | + +--- + +## 사용자 정의 모드 + +구성에 추가하여 사용자 정의 모드를 만들 수 있습니다. 여기에는 두 가지 접근법이 있습니다. + +### JSON 구성 사용 + +```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 + } + } + } +} +``` + +### markdown 파일 사용 + +프로젝트 별 모드 또는 `~/.config/opencode/modes/`의 모드 파일을 만들 수 있습니다. + +```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 +``` + +--- + +### 사용 사례 + +다음은 다른 모드에 대한 일반적인 사용 사례입니다. + +- **Build 모드**: 모든 도구와 함께 전체 개발 작업 +- **Plan 모드**: 변화없이 분석 및 계획 -**Review 모드**: Code review with read-only access plus 문서 도구 +- **Debug 모드**: bash 및 읽기 도구와 함께 조사에 집중 +- **Docs 모드**: 파일 작업과 문서 작성하지만 시스템 명령 없음 + +다른 모델을 찾을 수 있습니다 다른 사용 케이스에 대 한 좋은. diff --git a/packages/web/src/content/docs/ko/network.mdx b/packages/web/src/content/docs/ko/network.mdx new file mode 100644 index 00000000000..ee3cbfa2550 --- /dev/null +++ b/packages/web/src/content/docs/ko/network.mdx @@ -0,0 +1,57 @@ +--- +title: 네트워크 +description: 프록시 및 사용자 정의 인증서 구성. +--- + +opencode는 엔터프라이즈 네트워크 환경을 위한 표준 프록시 환경 변수 및 사용자 지정 인증서를 지원합니다. + +--- + +## 프록시 + +opencode는 표준 프록시 환경 변수를 존중합니다. + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +TUI는 로컬 HTTP 서버와 통신합니다. routing 루프를 방지하기 위해이 연결에 대한 프록시를 우회해야합니다. +::: + +[CLI 플래그](/docs/cli#run)을 사용하여 서버 포트와 호스트명을 구성할 수 있습니다. + +--- + +### 인증 + +프록시가 기본 인증을 필요로 하는 경우 URL에서 자격 증명이 포함되어 있습니다. + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +암호를 해독하지 마십시오. 환경 변수를 사용하거나 자격 증명 스토리지를 확보하십시오. +::: + +NTLM 또는 Kerberos와 같은 고급 인증을 요구하는 프록시는 인증 방법을 지원하는 LLM Gateway를 사용하여 고려합니다. + +--- + +## 사용자 정의 인증서 + +엔터프라이즈가 HTTPS 연결을 위해 사용자 정의 CA를 사용한다면, opencode를 사용하여 신뢰합니다. + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +프록시 연결과 직접 API 액세스를 위한 이 작업. diff --git a/packages/web/src/content/docs/ko/permissions.mdx b/packages/web/src/content/docs/ko/permissions.mdx new file mode 100644 index 00000000000..ac698b7cfb3 --- /dev/null +++ b/packages/web/src/content/docs/ko/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: 권한 +description: 실행 승인이 필요한 작업을 제어합니다. +--- + +opencode는 주어진 동작이 자동으로 실행되는지 결정하기 위해 `permission` config를 사용하거나 차단합니다. + +`v1.1.1`의 것과 같이, 유산 `tools` 불린 구성은 deprecated이고 `permission`로 합병되었습니다. 오래된 `tools` config는 여전히 뒤쪽 호환성을 위해 지원됩니다. + +--- + +## 동작 + +각 권한 규칙은 다음과 같습니다: + +- `"allow"` - 승인없이 실행 +- `"ask"` - 승인을위한 prompt +- `"deny"` - 동작 차단 + +--- + +## 구성 + +글로벌 권한(`*` 포함) 및 특정 도구를 부여할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +한 번에 모든 권한을 설정할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## 세부 규칙 (객체 구문) + +대부분의 권한을 위해 도구 입력을 기반으로 다른 작업을 적용 할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +규칙은 패턴 일치에 의해 평가됩니다, ** 마지막 일치 규칙 우승 **. 일반적인 패턴은 catch-all `"*"` 규칙을 먼저 넣는 것입니다, 그리고 그 후에 더 구체적인 규칙. + +## 와일드카드 + +Permission 본 사용 간단한 wildcard 일치: + +- `*`는 어떤 성격든지의 0개 이상 일치합니다 +- `?`는 정확히 하나의 문자 일치 +- 다른 모든 문자 일치 말 그대로 + +## 홈 디렉토리 확장 + +`~` 또는 `$HOME`를 사용할 수 있습니다 패턴의 시작에 홈 디렉토리를 참조. 이것은 특히 유용합니다 [`external_directory`](#external-directories) 규칙. + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +## 외부 디렉터리 + +`external_directory`를 사용하여 도구가 opencode가 시작된 작업 디렉토리 밖에 터치 경로가 호출되도록합니다. 이것은 입력 (예 : `read`, `edit`, `list`, `glob`, `glob`, `grep` 및 많은 `bash` 명령)로 경로를 수행하는 모든 도구에 적용됩니다. + +홈 확장 (`~/...`와 같은) 패턴이 작성된 방법에 영향을 미칩니다. 그것은 현재의 작업 공간의 외부 경로 부분을 만들지 않습니다, 그래서 작업 디렉토리 외부 경로는 여전히 `external_directory`를 통해 허용해야합니다. + +예를 들어, 이것은 `~/projects/personal/`의 모든 것에 액세스 할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +여기에 허용되는 모든 디렉토리는 현재 작업 공간과 동일한 기본값을 상속합니다. [`read` defaults to `allow`](#defaults)는 `external_directory`에서 `external_directory`의 항목에 대해 읽을 수 있습니다. 도구가 이러한 경로에 제한 될 때 명시적 규칙을 추가하십시오. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +신뢰할 수있는 경로에 초점을 맞춘 목록을 유지하고 다른 도구 (예 : `bash`)에 필요한대로 추가 허용하거나 deny 규칙을 층을 설정합니다. + +--- + +## 사용 가능한 권한 + +opencode 권한은 도구 이름에 의해 키 입력되며, 두 개의 안전 가드 : + +- `read` - 파일 읽기 (파일 경로의 매칭) +- `edit` - 모든 파일 수정 (covers `edit`, `write`, `patch`, `multiedit`) +- `glob` - 파일 globbing (glob 패턴 매칭) +- `grep` - 콘텐츠 검색 ( regex 패턴 매칭) +- `list` - 디렉토리의 목록 파일 (폴더 경로 매칭) +- `bash` - shell 명령 실행 (`git status --porcelain`와 같은 팟 명령) +- `task` - 에이전트 실행 (작업 에이전트 유형) +- `skill` - 기술을 로딩 (기술 이름을 매칭) +- `lsp` - LSP 쿼리 실행 (현재 비 과립) +- `todoread`, `todowrite` - 토도 목록의 읽기 / 업데이트 +- `webfetch` - URL을 fetching ( URL을 매칭) +- `websearch`, `codesearch` - 웹 / 코드 검색 (문자 쿼리) +- `external_directory` - 프로젝트 작업 디렉토리 외부의 도구 접촉 경로 때 트리거 +- `doom_loop` - 동일한 도구 호출이 동일한 입력으로 3 번 반복 할 때 트리거 + +--- + +## 기본값 + +아무것도 지정하지 않는 경우, opencode는 permissive 기본값에서 시작합니다. + +- `"allow"`에 기본 권한. +- `doom_loop` 및 `external_directory` 기본적으로 `"ask"`. +- `read`는 `"allow"`이고, 그러나 `.env` 파일은 기본적으로 denied: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## "Ask"란 무엇입니까? + +opencode가 승인되면 UI는 세 가지 결과를 제공합니다. + +- `once` - 이 요청을 승인 +- `always` - 제안 된 패턴과 일치하는 미래 요청 (현재 opencode 세션의 나머지) +- `reject` - 요청을 거부 + +`always`는 도구 (예를 들면, bash 승인 일반적으로 `git status*`와 같은 안전한 명령 접두사)에 의해 approve가 제공 될 패턴의 집합. + +--- + +## 에이전트 + +에이전트 당 권한이 부여 될 수 있습니다. 에이전트 권한은 글로벌 구성과 합병되며, 에이전트 규칙은 우선합니다. [Learn more](/docs/agents#permissions) 약 에이전트 권한. + +:::note +[Granular Rules (Object Syntax)](#granular-rules-object-syntax))에 대한 자세한 패턴 매칭 예제를 참조하십시오. +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +Markdown의 에이전트 권한을 구성할 수 있습니다. + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +인자와 명령에 대한 패턴 매칭을 사용합니다. `"grep *"`는 `grep pattern file.txt`를 허용하고, `"grep"`는 혼자 그것을 막을 것입니다. `git status`와 같은 명령은 기본 동작을 위해 작동하지만, 인수가 전달될 때 명시된 권한 (`"git status *"`와 같은)이 필요합니다. +::: diff --git a/packages/web/src/content/docs/ko/plugins.mdx b/packages/web/src/content/docs/ko/plugins.mdx new file mode 100644 index 00000000000..9a2995df839 --- /dev/null +++ b/packages/web/src/content/docs/ko/plugins.mdx @@ -0,0 +1,385 @@ +--- +title: 플러그인 +description: OpenCode를 확장하기 위해 자신만의 플러그인을 작성하세요. +--- + +플러그인은 다양한 이벤트와 사용자 정의 행동으로 후킹하여 opencode를 확장 할 수 있습니다. 플러그인을 만들 수 있습니다 새로운 기능을 추가, 외부 서비스와 통합, 또는 opencode의 기본 동작을 수정. + +예를 들어, 커뮤니티에 의해 생성 된 [plugins](/docs/ecosystem#plugins)를 확인하십시오. + +--- + +## 플러그인 사용 + +플러그인을로드하는 두 가지 방법이 있습니다. + +--- + +## 로컬 파일에서 + +플러그인 디렉토리에 JavaScript 또는 TypeScript 파일을 배치합니다. + +- `.opencode/plugins/` - 프로젝트 레벨 플러그인 +- `~/.config/opencode/plugins/` - 글로벌 플러그인 + +이 디렉토리의 파일은 자동으로 시작에로드됩니다. + +--- + +### npm에서 + +config 파일에 npm 패키지를 지정합니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +일반 및 범위의 npm 패키지 모두 지원됩니다. + +[ecosystem](/docs/ecosystem#plugins)에서 사용할 수 있는 플러그인을 찾아보세요. + +--- + +## 플러그인이 설치되는 방법 + +**npm 플러그인**은 시작시 Bun을 사용하여 자동으로 설치됩니다. 패키지와 그들의 의존성은 `~/.cache/opencode/node_modules/`에서 캐시됩니다. + +**로컬 플러그인**은 플러그인 디렉토리에서 직접로드됩니다. 외부 패키지를 사용하려면 구성 디렉토리 내 `package.json`를 작성해야 합니다 ([Dependencies](#dependencies)), 또는 플러그인을 npm에 게시하고 [config에 추가](/docs/config#plugins). + +--- + +## 로드 순서 + +플러그인은 모든 소스에서로드되며 모든 후크는 순서대로 실행됩니다. 로드 순서는 다음과 같습니다: + +1. 글로벌 구성 (`~/.config/opencode/opencode.json`) +2. 프로젝트 구성 (`opencode.json`) +3. 글로벌 플러그인 디렉토리 (`~/.config/opencode/plugins/`) +4. 프로젝트 플러그인 디렉토리 (`.opencode/plugins/`) + +중복 npm 패키지는 한 번만 로드됩니다. 하지만, 로컬 플러그인과 같은 이름과 npm 플러그인은 모두 별도로로드됩니다. + +--- + +## 플러그인 만들기 + +플러그인은 **JavaScript/TypeScript 모듈**입니다. +기능. 각 함수는 context 객체를 수신하고 Hooks 객체를 반환합니다. + +--- + +### 의존성 + +로컬 플러그인 및 사용자 정의 도구는 외부 npm 패키지를 사용할 수 있습니다. `package.json`를 config 디렉토리에 추가하면 필요한 의존도가 있습니다. + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +opencode는 `bun install`를 시작합니다. 플러그인 및 도구가 가져올 수 있습니다. + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### 기본 구조 + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +플러그인 기능 수신: + +- `project`: 현재 프로젝트 정보. +- `directory`: 현재 작업 디렉토리. +- `worktree`: git worktree 경로. +- `client`: AI와 상호 작용을 위한 opencode SDK 클라이언트. +- `$`: Bun's [shell API](https://bun.com/docs/runtime/shell) 명령어를 실행합니다. + +--- + +### TypeScript 지원 + +TypeScript 플러그인의 경우 플러그인 패키지에서 유형을 가져올 수 있습니다. + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +## 이벤트 + +플러그인은 예제 섹션에서 아래에서 볼 때 이벤트에 가입 할 수 있습니다. 여기에 다른 이벤트의 목록입니다. + +### 명령어 이벤트 + +- `command.executed` + +### 파일 이벤트 + +- `file.edited` +- `file.watcher.updated` + +### 설치 이벤트 + +- `installation.updated` + +### LSP 이벤트 + +- `lsp.client.diagnostics` +- `lsp.updated` + +### 메시지 이벤트 + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### 권한 이벤트 + +- `permission.asked` +- `permission.replied` + +### 서버 이벤트 + +- `server.connected` + +### 세션 이벤트 + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +### Todo 이벤트 + +- `todo.updated` + +#### 셸 이벤트 + +- `shell.env` + +##### 도구 이벤트 + +- `tool.execute.after` +- `tool.execute.before` + +#### TUI 이벤트 + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## 예제 + +opencode를 확장하기 위해 사용할 수있는 플러그인의 몇 가지 예입니다. + +--- + +## 알림 보내기 + +특정 이벤트가 발생할 때 알림을 전송: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +macOS에서 AppleScript를 실행하려면 `osascript`를 사용하고 있습니다. 여기에 우리는 그것을 사용하여 알림을 보낼 수 있습니다. + +:::note +opencode 데스크톱 앱을 사용하는 경우 응답이 준비되어 있거나 세션 오류가 있을 때 시스템 알림을 자동으로 보낼 수 있습니다. +::: + +--- + +### .env 보호 + +읽기 `.env` 파일에서 opencode를 방지하십시오: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### Inject 환경 변수 + +환경 변수를 모든 shell 실행 (AI 도구 및 사용자 terminal)로 주사하십시오. + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### 사용자 정의 도구 + +플러그인은 opencode에 사용자 정의 도구를 추가 할 수 있습니다 : + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +`tool` helper는 opencode가 호출 할 수있는 사용자 정의 도구를 만듭니다. Zod schema 기능을 가지고 도구 정의를 반환: + +- `description`: 도구는 무엇을 +- `args`: 도구의 인수에 대한 Zod 스키마 +- `execute`: 도구가 호출될 때 실행되는 기능 + +사용자 정의 도구는 내장 도구와 함께 opencode를 사용할 수 있습니다. + +--- + +### 로깅 + +구조화된 로깅을 위한 `client.app.log()` 대신에 `console.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)를 참고하세요. + +--- + +## Compaction 훅 + +세션이 압축 될 때 포함 된 컨텍스트를 사용자 지정: + +```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 +`) + }, + } +} +``` + +LLM이 압축 요약을 생성하기 전에 `experimental.session.compacting` 훅이 실행됩니다. 기본 압축 프롬프트를 대체할 수 있도록 도메인 별 컨텍스트를 주입합니다. + +당신은 또한 `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` 배열은 이 경우에 무시됩니다. diff --git a/packages/web/src/content/docs/ko/providers.mdx b/packages/web/src/content/docs/ko/providers.mdx new file mode 100644 index 00000000000..488c0253718 --- /dev/null +++ b/packages/web/src/content/docs/ko/providers.mdx @@ -0,0 +1,1890 @@ +--- +title: 공급자 +description: OpenCode에서 LLM 공급자를 사용합니다. +--- + +import config from "../../../../config.mjs" +export const console = config.console + +OpenCode는 [AI SDK](https://ai-sdk.dev/) 및 [Models.dev](https://models.dev)를 사용하여 **75개 이상의 LLM 공급자**를 지원하며 로컬 모델도 실행할 수 있습니다. + +필요한 공급자를 추가하려면: + +1. `/connect` 명령을 사용하여 공급자의 API 키를 추가하십시오. +2. OpenCode 구성에서 공급자를 구성하십시오. + +--- + +### 자격 증명 + +`/connect` 명령으로 공급자의 API 키를 추가하면 다음 위치에 저장됩니다: +`~/.local/share/opencode/auth.json` + +--- + +#### 구성 + +OpenCode 설정의 `provider` 섹션을 통해 공급자를 사용자 정의할 수 있습니다. + +--- + +### 기본 URL + +`baseURL` 옵션을 설정하여 모든 공급자를 위한 기본 URL을 사용자 정의할 수 있습니다. 프록시 서비스 또는 사용자 정의 엔드포인트를 사용할 때 유용합니다. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen은 OpenCode 팀이 OpenCode와 잘 작동하도록 테스트하고 검증한 모델 목록입니다. [더 알아보기](/docs/zen). + +:::tip +처음이라면 OpenCode Zen으로 시작하는 것이 좋습니다. +::: + +1. TUI에서 `/connect` 명령을 실행하고 `opencode`를 선택한 뒤, [opencode.ai/auth](https://opencode.ai/auth)로 이동합니다. + + ```txt + /connect + ``` + +2. 로그인하고 결제 정보를 입력한 후 API 키를 복사하십시오. + +3. API 키를 붙여넣습니다. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. TUI에서 `/models`를 실행하여 추천 모델 목록을 볼 수 있습니다. + + ```txt + /models + ``` + +OpenCode의 다른 공급자처럼 작동하며 사용은 완전히 선택 사항입니다. + +--- + +## 디렉토리 + +공급자 세부 정보를 확인하세요. 목록에 공급자를 추가하려면 PR을 열어주세요. + +:::note +원하는 공급자가 없나요? PR을 제출해 주세요. +::: + +--- + +### 302.AI + +1. [302.AI 콘솔](https://302.ai/)로 이동하여 계정을 만들고 API 키를 생성합니다. + +2. `/connect` 명령을 실행하고 **302.AI**를 검색하십시오. + + ```txt + /connect + ``` + +3. 302.AI API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 모델을 선택하려면 `/models` 명령을 실행하십시오. + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +OpenCode로 Amazon Bedrock을 사용하려면: + +1. Amazon Bedrock 콘솔의 **Model catalog**로 이동하여 원하는 모델에 대한 액세스를 요청합니다. + + :::tip + Amazon Bedrock에서 원하는 모델에 대한 액세스 권한이 있어야 합니다. + ::: + +2. 다음 방법 중 하나를 사용하여 **설정**합니다: + +### 환경 변수 (빠른 시작) + +OpenCode를 실행하는 동안 다음 환경 변수 중 하나를 설정합니다: + +```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode +``` + +또는 bash 프로필에 추가합니다: + +```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" + } + } + } +} +``` + +**유효한 옵션:** + +- `region` - AWS 리전 (예: `us-east-1`, `eu-west-1`) +- `profile` - `~/.aws/credentials`의 AWS 프로필 이름 +- `endpoint` - VPC 엔드포인트 등을 위한 사용자 정의 엔드포인트 URL (일반 `baseURL` 옵션의 별칭) + + :::tip + 구성 파일 옵션은 환경 변수보다 우선 순위가 높습니다. + ::: + +#### 고급: 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" + } + } + } +} +``` + +:::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에 의해 자동으로 주입됩니다. + +#### 인증 우선 순위 + +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 자격 증명 방법보다 우선 순위가 높습니다. + ::: + +3. `/models` 명령을 실행하여 원하는 모델을 선택하십시오. + + ```txt + /models + ``` + +:::note +사용자 정의 추론 프로필(custom inference profiles)의 경우, 키에 모델과 공급자 이름을 사용하고 `id` 속성에 ARN을 설정하십시오. 이렇게 하면 올바른 캐싱이 보장됩니다: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +#### Anthropic + +1. 가입 후 `/connect` 명령을 실행하고 **Anthropic**을 선택합니다. + + ```txt + /connect + ``` + +2. **Claude Pro/Max** 옵션을 선택하면 브라우저가 열립니다. + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. 이제 `/models` 명령을 사용할 때 모든 Anthropic 모델을 사용할 수 있습니다. + + ```txt + /models + ``` + +:::info +OpenCode에서 Claude Pro/Max 구독을 사용하는 것은 [Anthropic](https://anthropic.com)에서 공식적으로 지원하지 않습니다. +::: + +##### API 키 사용 + +Pro/Max 구독이 없는 경우 **Create an API Key**를 선택할 수 있습니다. 브라우저가 열리고 Anthropic에 로그인한 후 터미널에 붙여넣을 수 있는 코드를 제공합니다. + +또는 이미 API 키가 있다면, **Manually enter API Key**를 선택하고 터미널에 붙여넣을 수 있습니다. + +--- + +### Azure OpenAI + +:::note +"I'm sorry, but I can't support that request" 오류가 발생하면, Azure 리소스의 콘텐츠 필터를 **DefaultV2**에서 **Default**로 변경해 보세요. +::: + +1. [Azure 포털](https://portal.azure.com/)로 이동하여 **Azure OpenAI** 리소스를 만듭니다. 다음이 필요합니다: + - **리소스 이름**: API 엔드포인트의 일부가 됩니다 (`https://RESOURCE_NAME.openai.azure.com/`) + - **API 키**: 리소스의 `KEY 1` 또는 `KEY 2` + +2. [Azure AI Foundry](https://ai.azure.com/)로 이동하여 모델을 배포합니다. + + :::note + 배포 이름은 제대로 작동하려면 OpenCode의 모델 이름과 일치해야 합니다. + ::: + +3. `/connect` 명령을 실행하고 **Azure**를 검색하십시오. + + ```txt + /connect + ``` + +4. API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. 리소스 이름을 환경 변수로 설정: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + 또는 bash 프로필에 추가: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. `/models` 명령을 실행하여 배포된 모델을 선택하십시오. + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. [Azure 포털](https://portal.azure.com/)로 이동하여 **Azure OpenAI** 리소스를 만듭니다. 다음이 필요합니다: + - **리소스 이름**: API 엔드포인트의 일부가 됩니다 (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) + - **API 키**: 리소스의 `KEY 1` 또는 `KEY 2` + +2. [Azure AI Foundry](https://ai.azure.com/)로 이동하여 모델을 배포합니다. + + :::note + 배포 이름은 제대로 작동하려면 OpenCode의 모델 이름과 일치해야 합니다. + ::: + +3. `/connect` 명령을 실행하고 **Azure Cognitive Services**를 검색하십시오. + + ```txt + /connect + ``` + +4. API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. 리소스 이름을 환경 변수로 설정: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + 또는 bash 프로필에 추가: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. `/models` 명령을 실행하여 배포된 모델을 선택하십시오. + + ```txt + /models + ``` + +--- + +#### Baseten + +1. [Baseten](https://app.baseten.co/)으로 이동하여 계정을 만들고 API 키를 생성합니다. + +2. `/connect` 명령을 실행하고 **Baseten**을 검색하십시오. + + ```txt + /connect + ``` + +3. Baseten API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 모델을 선택하려면 `/models` 명령을 실행하십시오. + + ```txt + /models + ``` + +--- + +#### Cerebras + +1. [Cerebras 콘솔](https://inference.cerebras.ai/)로 이동하여 계정을 만들고 API 키를 생성합니다. + +2. `/connect` 명령을 실행하고 **Cerebras**를 검색하십시오. + + ```txt + /connect + ``` + +3. Cerebras API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 모델(예: Qwen 3 Coder 480B)을 선택하십시오. + + ```txt + /models + ``` + +--- + +## Cloudflare AI Gateway + +Cloudflare AI Gateway는 OpenAI, Anthropic, Workers AI 등의 모델에 액세스할 수 있으며, 통합된 엔드포인트를 통해 더 많은 기능을 제공합니다. [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/)을 사용하면 각 공급자의 별도 API 키가 필요하지 않습니다. + +1. [Cloudflare 대시보드](https://dash.cloudflare.com/)로 이동하여, **AI** > **AI Gateway**로 가서 새로운 게이트웨이를 만듭니다. + +2. 계정 ID 및 Gateway ID를 환경 변수로 설정하십시오. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. `/connect` 명령을 실행하고 **Cloudflare AI Gateway**를 검색하십시오. + + ```txt + /connect + ``` + +4. Cloudflare API 토큰을 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + 또는 환경 변수로 설정합니다. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. 모델을 선택하려면 `/models` 명령을 실행하십시오. + + ```txt + /models + ``` + + OpenCode 구성을 통해 모델을 추가할 수 있습니다. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +#### Cortecs + +1. [Cortecs 콘솔](https://cortecs.ai/)로 이동하여 계정을 만들고 API 키를 생성합니다. + +2. `/connect` 명령을 실행하고 **Cortecs**를 검색하십시오. + + ```txt + /connect + ``` + +3. Cortecs API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 모델(예: Kimi K2 Instruct)을 선택하십시오. + + ```txt + /models + ``` + +--- + +## DeepSeek + +1. [DeepSeek 콘솔](https://platform.deepseek.com/)로 이동하여 계정을 만들고 **API Keys**를 클릭하여 키를 생성합니다. + +2. `/connect` 명령을 실행하고 **DeepSeek**를 검색하십시오. + + ```txt + /connect + ``` + +3. DeepSeek API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 DeepSeek 모델(예: DeepSeek Reasoner)을 선택하십시오. + + ```txt + /models + ``` + +--- + +## Deep Infra + +1. [Deep Infra 대시보드](https://deepinfra.com/dash)로 이동하여 계정을 만들고 API 키를 생성합니다. + +2. `/connect` 명령을 실행하고 **Deep Infra**를 검색하십시오. + + ```txt + /connect + ``` + +3. Deep Infra API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 모델을 선택하려면 `/models` 명령을 실행하십시오. + + ```txt + /models + ``` + +--- + +## Firmware + +1. [Firmware 대시보드](https://app.firmware.ai/signup)로 이동하여 계정을 만들고 API 키를 생성합니다. + +2. `/connect` 명령을 실행하고 **Firmware**를 검색하십시오. + + ```txt + /connect + ``` + +3. Firmware API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 모델을 선택하려면 `/models` 명령을 실행하십시오. + + ```txt + /models + ``` + +--- + +## Fireworks AI + +1. [Fireworks AI 콘솔](https://app.fireworks.ai/)로 이동하여 계정을 만들고 **API Keys**를 클릭합니다. + +2. `/connect` 명령을 실행하고 **Fireworks AI**를 검색하십시오. + + ```txt + /connect + ``` + +3. Fireworks AI API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 모델(예: Kimi K2 Instruct)을 선택하십시오. + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo는 GitLab의 Anthropic 프록시를 통해 기본 도구 호출 기능을 갖춘 AI 기반 에이전트 채팅을 제공합니다. + +1. `/connect` 명령을 실행하고 GitLab을 선택합니다. + + ```txt + /connect + ``` + +2. 인증 방법을 선택하십시오: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ + ``` + +#### OAuth 사용 (권장) + +**OAuth**를 선택하면 브라우저에서 권한 부여를 요청합니다. + +### 개인 액세스 토큰 사용 + +1. [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens)로 이동 +2. 새 토큰 추가 +3. 이름: `OpenCode`, 범위: `api` +4. 토큰 복사 (`glpat-`로 시작) +5. 터미널에 입력하십시오. + +6. 사용 가능한 모델을 보려면 `/models` 명령을 실행하십시오. + + ```txt + /models + ``` + +세 가지 Claude 기반 모델을 사용할 수 있습니다: + +- **duo-chat-haiku-4-5** (기본값) - 빠른 작업을 위한 빠른 응답 +- **duo-chat-sonnet-4-5** - 대부분의 워크플로우에 균형 잡힌 성능 +- **duo-chat-opus-4-5** - 복잡한 분석 가능 + +:::note +`GITLAB_TOKEN` 환경 변수를 지정할 수도 있습니다. +OpenCode는 인증 저장소에 토큰을 저장합니다. +::: + +#### 셀프 호스팅 GitLab (Self-Hosted) + +:::note[규정 준수 참고 사항] +OpenCode는 세션 제목 생성과 같은 일부 AI 작업을 위해 작은 모델을 사용합니다. +기본적으로 Zen에서 호스팅되는 gpt-5-nano를 사용하도록 구성됩니다. +OpenCode를 자체 호스팅 GitLab 인스턴스만 사용하도록 제한하려면 `opencode.json` 파일에 다음을 추가하십시오. +세션 공유를 비활성화하는 것도 권장합니다. + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +자체 호스팅 GitLab 인스턴스: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +인스턴스가 사용자 정의 AI Gateway를 실행하는 경우: + +```bash +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +또는 bash 프로필에 추가: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +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` + ::: + +#### 셀프 호스팅 인스턴스용 OAuth + +자체 호스팅 인스턴스에 대해 OAuth를 작동시키려면 새로운 애플리케이션(Settings → Applications)을 만들어야 합니다. +콜백 URL `http://127.0.0.1:8080/callback` 및 다음 범위가 필요합니다: + +- `api` (사용자 대신 API 액세스) +- `read_user` (개인 정보 읽기) +- `read_repository` (리포지토리 읽기 전용 액세스) + +그런 다음 애플리케이션 ID를 환경 변수로 노출하십시오: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +[opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth) 홈페이지에 추가 문서가 있습니다. + +##### 구성 + +`opencode.json`을 통해 사용자 정의: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### GitLab API 도구 (선택 사항이지만 강력 권장) + +GitLab 도구(병합 요청, 이슈, 파이프라인, CI/CD 등)에 액세스하려면: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +이 플러그인은 MR 리뷰, 이슈 추적, 파이프라인 모니터링 등을 포함한 포괄적인 GitLab 리포지토리 관리 기능을 제공합니다. + +--- + +### GitHub Copilot + +GitHub Copilot 구독을 사용하여 opencode: + +:::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). +::: + +1. `/connect` 명령을 실행하고 GitHub Copilot을 검색하십시오. + + ```txt + /connect + ``` + +2. [github.com/login/device](https://github.com/login/device)로 이동하여 코드를 입력합니다. + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + └ Waiting for authorization... + ``` + +3. 이제 원하는 모델을 선택하기 위해 `/models` 명령을 실행합니다. + + ```txt + /models + ``` + +--- + +### 구글 Vertex AI + +opencode로 Google Vertex AI를 사용하려면: + +1. Google Cloud Console에서 ** Model Garden**을 통해 헤드를 확인하고 확인하십시오. + 당신의 지역에서 유효한 모형. + + :::note + 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` + +opencode를 실행하면서 설정한다. + +```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode +``` + +또는 bash 프로파일에 추가하십시오. + +```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) +::: + +3. 당신이 원하는 모형을 선정하기 위하여 `/models` 명령을 실행하십시오. + + ```txt + /models + ``` + +--- + +##### Groq + +1. [Groq 콘솔](https://console.groq.com/)에 머리, click **Create API Key**, 키 복사. + +2. `/connect` 명령을 실행하고 Groq에 대한 검색. + + ```txt + /connect + ``` + +3. 공급자를 위한 API 열쇠를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 원하는 것을 선택합니다. + + ```txt + /models + ``` + +--- + +### Hugging Face + +[Hugging Face Inference Provider](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에게 호출할 권한을 부여합니다. + +2. `/connect` 명령을 실행하고 **Hugging Face**를 검색하십시오. + + ```txt + /connect + ``` + +3. Hugging Face 토큰을 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 Kimi-K2-Instruct 또는 GLM-4.6 . + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai)는 AI 애플리케이션에 대한 로깅, 모니터링 및 분석 기능을 제공하는 LLM Observability 플랫폼입니다. Helicone AI Gateway는 모델을 기반으로 적절한 공급자에게 요청을 자동으로 전달합니다. + +1. [Helicone](https://helicone.ai)에 머리, 계정을 만들고, 대시보드에서 API 키를 생성합니다. + +2. `/connect` 명령을 실행하고 ** Helicone**를 검색하십시오. + + ```txt + /connect + ``` + +3. Helicone API 열쇠를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 모델을 선택하려면 `/models` 명령을 실행하십시오. + + ```txt + /models + ``` + +캐싱 및 속도 제한과 같은 더 많은 공급자와 고급 기능을 위해 [Helicone 문서](https://docs.helicone.ai)를 확인하십시오. + +#### 선택 사항 + +이벤트에서 opencode를 통해 자동으로 구성되지 않는 Helicone의 기능 또는 모델을 볼 수 있습니다. + +여기에 [Helicone의 모델 디렉토리](https://helicone.ai/models), 당신은 당신이 추가 할 모델의 ID를 잡아이 필요. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +##### 사용자 정의 헤더 + +Helicone는 캐싱, 사용자 추적 및 세션 관리와 같은 기능을 위한 사용자 정의 헤더를 지원합니다. `options.headers`를 사용하여 공급자 구성에 추가하십시오: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### 세션 추적 + +Helicone's [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 +``` + +설정에 추가하십시오. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +플러그인은 `Helicone-Session-Id` 및 `Helicone-Session-Name` 헤더를 귀하의 요청에 주사합니다. Helicone의 세션 페이지에서는 별도의 세션으로 나열된 각 opencode 대화를 볼 수 있습니다. + +###### 공통 Helicone 헤더 + +| 헤드러 | Description | +| -------------------------- | ---------------------------------------------------------- | +| `Helicone-Cache-Enabled` | 대응 캐싱 (`true`/`false`) | +| `Helicone-User-Id` | 사용자별 추적 가능 | +| `Helicone-Property-[Name]` | 사용자 정의 속성 추가(예: `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | prompt 대응 | + +모든 사용 가능한 헤더에 대한 [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory)를 참조하십시오. + +--- + +#### llama.cpp + +[llama.cpp's](https://github.com/ggml-org/llama.cpp) llama-server 유틸리티를 통해 로컬 모델을 사용할 수 있습니다. + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +이 예제에서: + +- `llama.cpp`는 주문 공급자 ID입니다. 원하는 문자열이 될 수 있습니다. +- `npm`는 이 공급자를 위해 사용할 포장을 지정합니다. 여기, `@ai-sdk/openai-compatible`는 OpenAI 호환 API에 사용됩니다. +- `name`는 UI에 있는 공급자를 위한 전시 이름입니다. +- `options.baseURL`는 로컬 서버의 엔드포인트입니다. +- `models`는 모델 ID를 구성하는 맵입니다. 모델 이름은 모델 선택 목록에 표시됩니다. + +--- + +###### IO.NET + +IO.NET은 다양한 사용 사례에 최적화된 17개의 모델을 제공합니다: + +1. [IO.NET 콘솔](https://ai.io.net/)에 머리, 계정을 만들고 API 키를 생성합니다. + +2. `/connect` 명령을 실행하고 **IO.NET**를 검색하십시오. + + ```txt + /connect + ``` + +3. IO.NET API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 모델을 선택하려면 `/models` 명령을 실행하십시오. + + ```txt + /models + ``` + +--- + +### LM Studio + +LM Studio를 통해 로컬 모델을 사용할 수 있습니다. + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +이 예제에서: + +- `lmstudio`는 주문 공급자 ID입니다. 원하는 문자열이 될 수 있습니다. +- `npm`는 이 공급자를 위해 사용할 포장을 지정합니다. 여기, `@ai-sdk/openai-compatible`는 OpenAI 호환 API에 사용됩니다. +- `name`는 UI에 있는 공급자를 위한 전시 이름입니다. +- `options.baseURL`는 로컬 서버의 엔드포인트입니다. +- `models`는 모델 ID를 구성하는 맵입니다. 모델 이름은 모델 선택 목록에 표시됩니다. + +--- + +## Moonshot AI + +Moonshot AI에서 Kimi K2 사용 : + +1. [Moonshot AI 콘솔](https://platform.moonshot.ai/console)에 머리, 계정을 만들고, ** API 키**를 클릭합니다. + +2. `/connect` 명령을 실행하고 **Moonshot AI**를 검색하십시오. + + ```txt + /connect + ``` + +3. Moonshot API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 Kimi K2 . + + ```txt + /models + ``` + +--- + +## MiniMax + +1. [MiniMax API 콘솔](https://platform.minimax.io/login)에 머리, 계정을 만들고 API 키를 생성합니다. + +2. `/connect` 명령을 실행하고 **MiniMax**를 검색하십시오. + + ```txt + /connect + ``` + +3. MiniMax API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 M2.1 . + + ```txt + /models + ``` + +--- + +## Nebius Token Factory + +1. [Nebius Token Factory 콘솔](https://tokenfactory.nebius.com/)에 머리, 계정을 만들고, ** 키 추가 **. + +2. `/connect` 명령을 실행하고 **Nebius Token Factory**를 검색하십시오. + + ```txt + /connect + ``` + +3. Nebius 토큰 공장 API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 Kimi K2 Instruct . + + ```txt + /models + ``` + +--- + +#### Ollama + +Ollama를 통해 로컬 모델을 사용할 수 있습니다. + +:::tip +Ollama는 opencode를 자동으로 구성할 수 있습니다. 자세한 내용은 [Ollama 통합 문서](https://docs.ollama.com/integrations/opencode)를 참조하십시오. +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +이 예제에서: + +- `ollama`는 주문 공급자 ID입니다. 원하는 문자열이 될 수 있습니다. +- `npm`는 이 공급자를 위해 사용할 포장을 지정합니다. 여기, `@ai-sdk/openai-compatible`는 OpenAI 호환 API에 사용됩니다. +- `name`는 UI에 있는 공급자를 위한 전시 이름입니다. +- `options.baseURL`는 로컬 서버의 엔드포인트입니다. +- `models`는 모델 ID를 구성하는 맵입니다. 모델 이름은 모델 선택 목록에 표시됩니다. + +:::tip +도구 호출이 작동하지 않는 경우, Ollama에서 `num_ctx` 증가. 주위 시작 16k - 32k. +::: + +--- + +## Ollama Cloud + +opencode로 Ollama Cloud를 사용하려면: + +1. [https://ollama.com/](https://ollama.com/) 이상 머리와 로그인하거나 계정을 만들 수 있습니다. + +2. Navigate to**Settings** > **Keys** 및 click **API Key**를 추가하여 새로운 API 키 생성. + +3. opencode에서 사용을 위한 API 열쇠를 복사하십시오. + +4. `/connect` 명령을 실행하고 ** Ollama Cloud**를 검색하십시오. + + ```txt + /connect + ``` + +5. Ollama Cloud API 키 입력. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. ** 중요 **: opencode의 클라우드 모델을 사용하기 전에, 로컬 모델 정보를 끌어야 합니다: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. `/models` 명령을 실행하여 Ollama Cloud 모델을 선택하십시오. + + ```txt + /models + ``` + +--- + +### OpenAI + +[ChatGPT Plus 또는 Pro](https://chatgpt.com/pricing)에 가입하는 것이 좋습니다. + +1. 가입하면 `/connect` 명령을 실행하고 OpenAI를 선택하십시오. + + ```txt + /connect + ``` + +2. **ChatGPT Plus/Pro** 옵션을 선택하고 브라우저를 열 수 있습니다. + 자주 묻는 질문 + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. 이제 모든 OpenAI 모델은 `/models` 명령을 사용할 때 사용할 수 있어야합니다. + + ```txt + /models + ``` + +##### API 키 사용 + +API 키가 이미 있다면 ** 수동으로 API 키**를 입력하고 terminal에서 붙여넣을 수 있습니다. + +--- + +## OpenCode Zen + +OpenCode Zen은 opencode 팀에서 제공하는 테스트 및 검증된 모델 목록입니다. [더 알아보기](/docs/zen). + +1. 로그인 **OpenCode Zen** and click**Create API Key**. + +2. `/connect` 명령을 실행하고 **OpenCode Zen**를 검색하십시오. + + ```txt + /connect + ``` + +3. opencode API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 Qwen 3 Coder 480B . + + ```txt + /models + ``` + +--- + +## OpenRouter + +1. [OpenRouter 대시보드](https://openrouter.ai/settings/keys)에 머리, click ** API Key**를 클릭하고 키를 복사합니다. + +2. `/connect` 명령을 실행하고 OpenRouter를 검색하십시오. + + ```txt + /connect + ``` + +3. 공급자를 위한 API 열쇠를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 많은 OpenRouter 모델은 기본적으로 `/models` 명령을 실행하여 원하는 것을 선택합니다. + + ```txt + /models + ``` + +opencode config를 통해 추가 모델을 추가할 수 있습니다. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "somecoolnewmodel": {} + } + } + } +} +``` + +5. 당신은 또한 당신의 opencode config를 통해 그들을 주문을 받아서 만들 수 있습니다. 공급자 지정의 예입니다. + + ```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는 OpenAI, Anthropic, Google, Amazon, Meta, Mistral 및 AI21의 40+ 모델에 대한 액세스를 제공합니다. + +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 인스턴스를 찾을 수 있습니다. + ::: + +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 프로파일에 추가: + +```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' +``` + +4. 선택적으로 배치 ID 및 자원 그룹: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + 이 설정은 선택 사항이며 SAP AI Core 설정에 따라 구성해야합니다. + ::: + +5. `/models` 명령을 실행하여 40+ 유효한 모형에서 선택하십시오. + + ```txt + /models + ``` + +--- + +### OVHcloud AI 엔드포인트 + +1. [OVHcloud 패널](https://ovh.com/manager)에 머리. `Public Cloud` 섹션으로 이동, `AI & Machine Learning` > `AI Endpoints` 및 `API Keys` 탭에서, ** 새로운 API 키 활성화 **. + +2. `/connect` 명령을 실행하고 ** OVHcloud AI Endpoints**를 검색하십시오. + + ```txt + /connect + ``` + +3. OVHcloud AI Endpoints API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 gpt-oss-120b . + + ```txt + /models + ``` + +--- + +### Scaleway + +opencode를 사용하여 [Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/)를 사용하려면: + +1. [Scaleway 콘솔 IAM 설정](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 콘솔](https://api.together.ai)에 머리, 계정을 만들고 ** 키 추가 **를 클릭합니다. + +2. `/connect` 명령을 실행하고 **Together AI**를 검색하십시오. + + ```txt + /connect + ``` + +3. 함께 AI API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 Kimi K2 Instruct . + + ```txt + /models + ``` + +--- + +## Venice AI + +1. [Venice AI 콘솔](https://venice.ai)에 머리, 계정을 만들고 API 키를 생성합니다. + +2. `/connect` 명령을 실행하고 **Venice AI **를 검색하십시오. + + ```txt + /connect + ``` + +3. 베니스 AI API 열쇠를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 Llama 3.3 70B . + + ```txt + /models + ``` + +--- + +## Vercel AI 게이트웨이 + +Vercel AI를 게이트웨이는 OpenAI, Anthropic, Google, xAI 등에서 모델에 액세스할 수 있습니다. 모델은 Markup없이 목록 가격에서 제공됩니다. + +1. [Vercel 대시보드](https://vercel.com/)에 머리, **AI Gateway** 탭으로 이동하고, **API 키**를 클릭하여 새로운 API 키 생성. + +2. `/connect` 명령을 실행하고 **Vercel AI Gateway**를 검색하십시오. + + ```txt + /connect + ``` + +3. Vercel AI Gateway API 키 입력. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 모델을 선택하려면 `/models` 명령을 실행하십시오. + + ```txt + /models + ``` + +opencode config를 통해 모델을 사용자 정의 할 수 있습니다. 공급자 routing 순서를 지정하는 예입니다. + +```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 콘솔](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 콘솔](https://z.ai/manage-apikey/apikey-list)에 머리, 계정을 만들고, **새로운 API 키**를 클릭합니다. + +2. `/connect` 명령을 실행하고 ** Z.AI**를 검색하십시오. + + ```txt + /connect + ``` + +**GLM 코딩 플랜**에 가입하면 **Z.AI 코딩 플랜**을 선택하십시오. + +3. Z.AI API 키를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 GLM-4.7 . + + ```txt + /models + ``` + +--- + +## ZenMux + +1. [ZenMux 대쉬보드](https://zenmux.ai/settings/keys)에 머리, click **Create API Key**, 키 복사. + +2. `/connect` 명령을 실행하고 ZenMux를 검색하십시오. + + ```txt + /connect + ``` + +3. 공급자를 위한 API 열쇠를 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 많은 ZenMux 모델은 기본적으로 사전 로드되며 `/models` 명령을 실행하여 원하는 것을 선택합니다. + + ```txt + /models + ``` + +opencode config를 통해 추가 모델을 추가할 수 있습니다. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "zenmux": { + "models": { + "somecoolnewmodel": {} + } + } + } +} +``` + +--- + +## 사용자 정의 공급자 + +`/connect` 명령에 나열되지 않은 **OpenAI-compatible** 공급자를 추가하려면: + +:::tip +opencode를 사용하여 OpenAI 호환 공급자를 사용할 수 있습니다. 가장 현대적인 AI 제공 업체는 OpenAI 호환 API를 제공합니다. +::: + +1. `/connect` 명령을 실행하고 ** 다른**로 스크롤하십시오. + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. 공급자를 위한 유일한 ID를 입력하십시오. + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::note + 기억에 남는 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 패키지, OpenAI 호환 공급자 `@ai-sdk/openai-compatible` -**name**: UI의 표시 이름. +- ** 모델**: 유효한 모델. +- **options.baseURL**: API 엔드포인트 URL. +- **options.apiKey**: 선택적으로 auth를 사용하지 않는 경우 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` 변수 구문을 사용하여 설정, [learn more](/docs/config#env-vars). -**headers**: 각 요청으로 전송된 사용자 정의 헤더. +- **limit.context**: 모델이 허용하는 최대 Input Tokens. +- **limit.output**: 모델이 생성할 수 있는 최대 Output Tokens. + +`limit` 필드를 사용하면 opencode가 얼마나 많은 컨텍스트를 이해 할 수 있습니다. 표준 공급자는 model.dev에서 자동적으로 당깁니다. + +--- + +## 문제 해결 + +공급자 구성에 문제가 있는 경우 다음을 확인하십시오. + +1. **주의 설정 확인 **: `opencode auth list`를 실행하여 자격 증명을 볼 수 있습니다. + 공급자는 config에 추가됩니다. + +이것은 Amazon Bedrock과 같은 공급자에 적용되지 않습니다. 환경 변수에 의존합니다. + +2. 주문 공급자를 위해, opencode config를 검사하고: + +- `/connect` 명령에 사용되는 공급자 ID가 opencode config에서 ID를 일치시킵니다. +- 오른쪽 npm 패키지는 공급자에 사용됩니다. 예를 들어 Cerebras의 `@ai-sdk/cerebras`를 사용합니다. 그리고 다른 모든 OpenAI 호환 공급자를 위해, 사용 `@ai-sdk/openai-compatible`. +- 올바른 API 엔드포인트는 `options.baseURL` 필드에 사용됩니다. diff --git a/packages/web/src/content/docs/ko/rules.mdx b/packages/web/src/content/docs/ko/rules.mdx new file mode 100644 index 00000000000..940ad6237aa --- /dev/null +++ b/packages/web/src/content/docs/ko/rules.mdx @@ -0,0 +1,179 @@ +--- +title: 규칙 +description: OpenCode에 대한 사용자 정의 지침 설정. +--- + +`AGENTS.md` 파일을 만들 수 있도록 opencode에 사용자 정의 지침을 제공 할 수 있습니다. Cursor의 규칙과 유사합니다. LLM의 컨텍스트에 포함된 지침을 통해 특정 프로젝트에 대한 행동을 사용자 정의합니다. + +--- + +## 초기화 + +새로운 `AGENTS.md` 파일을 만들려면 `/init` 명령을 opencode에서 실행할 수 있습니다. + +:::tip +프로젝트의 `AGENTS.md` 파일을 Git에 투입해야 합니다. +::: + +프로젝트가 무엇인지 이해하고 `AGENTS.md` 파일을 생성합니다. 이 도움말 opencode는 프로젝트를 더 잘 탐색합니다. + +기존 `AGENTS.md` 파일이있는 경우이 추가하려고합니다. + +--- + +## 예 + +이 파일을 수동으로 만들 수도 있습니다. 다음은 `AGENTS.md` 파일에 넣을 수있는 것들의 예입니다. + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +우리는 여기에 프로젝트 별 지침을 추가하고 이것은 팀을 통해 공유됩니다. + +--- + +## 유형 + +opencode는 또한 다수 위치에서 `AGENTS.md` 파일을 읽습니다. 그리고 이것은 다른 목적을 봉사합니다. + +## 프로젝트 + +프로젝트 별 규칙에 대한 프로젝트 루트에 `AGENTS.md`를 배치합니다. 이 디렉토리 또는 하위 디렉토리에서 작업 할 때만 적용됩니다. + +## 전역 + +또한 `~/.config/opencode/AGENTS.md` 파일에서 글로벌 규칙을 가질 수 있습니다. 이 모든 opencode 세션에서 적용됩니다. + +이것은 Git에 전념하지 않거나 팀과 공유하지 않기 때문에 LLM이 따르는 모든 개인 규칙을 지정하는 것이 좋습니다. + +### Claude 코드 호환성 + +Claude Code에서 마이그레이션하는 경우, opencode는 Claude Code의 파일 컨벤션을 fallbacks로 지원합니다. + +- ** 규칙 ** : 프로젝트 디렉토리에 `CLAUDE.md` (`AGENTS.md`가 존재하지 않는 경우 사용) +- ** 글로벌 규칙**: `~/.claude/CLAUDE.md` (`~/.config/opencode/AGENTS.md`가 존재하지 않는 경우 사용) -**Skills**: `~/.claude/skills/` — [Agent Skills](/docs/skills/)를 참조하십시오. + +Claude Code 호환성을 비활성화하려면 이러한 환경 변수 중 하나를 설정하십시오. + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## 우선순위 + +opencode가 시작될 때, 이 순서에 있는 규칙 파일을 찾습니다: + +1. **Local 파일 ** 현재 디렉토리에서 추적 (`AGENTS.md`, `CLAUDE.md`) +2. ** 글로벌 파일 ** `~/.config/opencode/AGENTS.md` +3. **Claude 코드 파일 ** `~/.claude/CLAUDE.md`에서 (무효한) + +첫 번째 일치 파일은 각 범주에서 승리합니다. 예를 들어, `AGENTS.md`와 `CLAUDE.md` 모두가있는 경우 `AGENTS.md` 만 사용됩니다. 유사하게, `~/.config/opencode/AGENTS.md`는 `~/.claude/CLAUDE.md`에 전진합니다. + +--- + +## 사용자 정의 지침 + +`opencode.json` 또는 글로벌 `~/.config/opencode/opencode.json`에서 사용자 지정 명령 파일을 지정할 수 있습니다. AGENTS.md에 복제하지 않고 기존 규칙을 재사용 할 수 있습니다. + +예: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +웹에서 지침을로드하는 원격 URL도 사용할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +원격 지침은 5 초 타임 아웃으로 fetched. + +모든 명령 파일은 `AGENTS.md` 파일과 결합됩니다. + +--- + +## 외부 파일 참조 + +opencode가 `AGENTS.md`에 있는 자동적으로 파스 파일 참조를 하지 않는 동안, 당신은 두 가지 방법으로 유사한 기능을 달성할 수 있습니다: + +## opencode.json 사용 + +`instructions`의 `opencode.json` 필드를 사용하는 것이 좋습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### AGENTS.md의 수동 지침 + +`AGENTS.md`에 명시된 지침을 제공함으로써 외부 파일을 읽을 수 있습니다. 여기에 실용적인 예: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +이 접근법은 다음과 같습니다: + +- 모듈, 재사용 가능한 규칙 파일 생성 +- symlinks 또는 git submodules를 통해 프로젝트 전반에 걸쳐 규칙 공유 +- 상세한 가이드를 참조하면서 AGENTS.md concise 유지 +- 특정 작업에 필요한 경우에만 opencode 로드 파일 유지 + +:::tip +공유 표준을 가진 monorepos 또는 프로젝트를 위해, glob 본을 가진 `opencode.json`를 사용하여 (`packages/*/AGENTS.md` 같이)는 수동 지시 보다는 더 유지가능합니다. +::: diff --git a/packages/web/src/content/docs/ko/sdk.mdx b/packages/web/src/content/docs/ko/sdk.mdx new file mode 100644 index 00000000000..f6d43c136d6 --- /dev/null +++ b/packages/web/src/content/docs/ko/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: opencode 서버를 위한 타입 안전한 JS 클라이언트. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +opencode JS/TS SDK는 서버와 상호 작용을 위한 유형 안전한 클라이언트를 제공합니다. +통합 및 제어 opencode programmatically를 구축하는 데 사용됩니다. + +[Learn more](/docs/server) 서버가 어떻게 작동하나요? 예를 들어, 커뮤니티에 의해 구축 된 [projects](/docs/ecosystem#projects)를 확인하십시오. + +--- + +## 설치 + +npm에서 SDK 설치: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## 클라이언트 만들기 + +opencode의 인스턴스 만들기: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +서버와 클라이언트 모두 시작 + +#### 옵션 + +| 옵션 | 유형 | 설명 | 기본 | +| ---------- | ------------- | ----------------------- | ----------- | +| `hostname` | `string` | 서버 호스트명 | `127.0.0.1` | +| `port` | `number` | 서버포트 | `4096` | +| `signal` | `AbortSignal` | 취소 신호 | `undefined` | +| `timeout` | `number` | 서버 시작시의 시간 아웃 | `5000` | +| `config` | `Config` | 구성 객체 | `{}` | + +--- + +## 구성 + +구성 객체를 전달할 수 있습니다. 인스턴스는 여전히 `opencode.json`를 선택하지만 구성 인라인을 추가 할 수 있습니다. + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## 클라이언트만 + +opencode의 실행 인스턴스가 이미 있다면 클라이언트 인스턴스를 만들 수 있습니다. + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### 옵션 + +| 옵션 | 유형 | 설명 | 기본 | +| --------------- | ---------- | --------------------------------- | ----------------------- | +| `baseUrl` | `string` | 서버의 URL | `http://localhost:4096` | +| `fetch` | `function` | 사용자 정의 fetch 구현 | `globalThis.fetch` | +| `parseAs` | `string` | 응답 파싱 방법 | `auto` | +| `responseStyle` | `string` | 반품 스타일: `data` 또는 `fields` | `fields` | +| `throwOnError` | `boolean` | 반품 시 오류 | `false` | + +--- + +## 타입 + +SDK에는 모든 API 유형의 TypeScript 정의가 포함되어 있습니다. 직접 가져 오기 : + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +모든 유형은 서버의 OpenAPI 사양에서 생성되며 types 파일에서 사용할 수 있습니다. + +--- + +## 오류 + +SDK는 잡을 수 있는 오류를 던질 수 있습니다: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## API + +SDK는 type-safe 클라이언트를 통해 모든 서버 API를 노출합니다. + +--- + +## 글로벌 + +| 메서드 | 설명 | 응답 | +| ----------------- | ---------------------- | ------------------------------------ | +| `global.health()` | 서버 건강 및 버전 확인 | `{ healthy: true, version: string }` | + +--- + +#### 예제 + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### 앱 + +| 방법 | 설명 | 응답 | +| -------------- | ------------------------- | ----------------------------------------------- | +| `app.log()` | 로그 항목 작성 | `boolean` | +| `app.agents()` | 이용 가능한 모든 에이전트 | 에이전트[] | + +--- + +#### 예제 + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +## 프로젝트 + +| 방법 | 설명 | 응답 | +| ------------------- | ----------------------- | --------------------------------------------- | +| `project.list()` | 모든 프로젝트 보기 | Project[] | +| `project.current()` | 현재 프로젝트 가져 오기 | Project | + +--- + +#### 예제 + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### 경로 + +| 방법 | 설명 | 응답 | +| ------------ | ------------------- | ---------------------------------------- | +| `path.get()` | 현재 경로 가져 오기 | Path | + +--- + +#### 예제 + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +#### 구성 + +| 방법 | 설명 | 응답 | +| -------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | 구성 정보 | Config | +| `config.providers()` | 목록 제공업체 및 기본 모델 | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### 예제 + +```javascript +const config = await client.config.get() + +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` | + +--- + +#### 예제 + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +## 파일 + +| 방법 | 설명 | 응답 | +| ------------------------- | ---------------------------- | -------------------------------------------------------------------------------------- | +| `find.text({ query })` | 파일에서 텍스트 검색 | `path`, `lines`, `line_number`, `absolute_offset`, `submatches`와 일치하는 개체의 배열 | +| `find.files({ query })` | 이름의 파일 및 디렉토리 찾기 | `string[]` (경로) | +| `find.symbols({ query })` | 작업 공간 심볼 찾기 | Symbol[] | +| `file.read({ query })` | 파일 보기 | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | 트랙 된 파일 상태를 확인 | File[] | + +`find.files`는 몇몇 선택적인 조회 분야를 지원합니다: + +- `type`: `"file"` 또는 `"directory"` +- `directory`: 검색에 대한 프로젝트 루트를 override +- `limit`: 최대 결과 (1-200) + +--- + +#### 예제 + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +#### TUI + +| 방법 | 설명 | 응답 | +| ------------------------------ | ------------------------ | --------- | +| `tui.appendPrompt({ body })` | 프롬프트에 텍스트를 부여 | `boolean` | +| `tui.openHelp()` | 도움말 열기 | `boolean` | +| `tui.openSessions()` | 세션 선택 안내 | `boolean` | +| `tui.openThemes()` | 테마 선택 열기 | `boolean` | +| `tui.openModels()` | 모델 선택 안내 | `boolean` | +| `tui.submitPrompt()` | 현재 프롬프트 제출 | `boolean` | +| `tui.clearPrompt()` | 프롬프트 클리어 | `boolean` | +| `tui.executeCommand({ body })` | 명령어 실행 | `boolean` | +| `tui.showToast({ body })` | 토스트 알림 표시 | `boolean` | + +--- + +#### 예제 + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +##### 인증 + +| 방법 | 설명 | 응답 | +| ------------------- | -------------- | --------- | +| `auth.set({ ... })` | 인증 자격 증명 | `boolean` | + +--- + +#### 예제 + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +## 이벤트 + +| 방법 | 설명 | 응답 | +| ------------------- | ----------------------- | ----------------------- | +| `event.subscribe()` | 서버-sent 이벤트 스트림 | 서버-sent 이벤트 스트림 | + +--- + +#### 예제 + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/ko/server.mdx b/packages/web/src/content/docs/ko/server.mdx new file mode 100644 index 00000000000..a6914605a7c --- /dev/null +++ b/packages/web/src/content/docs/ko/server.mdx @@ -0,0 +1,287 @@ +--- +title: 서버 +description: HTTP를 통해 OpenCode 서버와 상호 작용합니다. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +`opencode serve` 명령은 opencode 클라이언트가 사용할 수 있는 OpenAPI 엔드포인트를 노출하는 headless HTTP 서버를 실행합니다. + +--- + +### 사용법 + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### 옵션 + +| 플래그 | 설명 | 기본값 | +| --------------- | ------------------------------------- | ---------------- | +| `--port` | 수신 대기할 포트 | `4096` | +| `--hostname` | 수신 대기할 호스트명 | `127.0.0.1` | +| `--mdns` | mDNS 탐지 활성화 | `false` | +| `--mdns-domain` | mDNS 서비스의 사용자 지정 도메인 이름 | `opencode.local` | +| `--cors` | 허용할 추가 브라우저 origin | `[]` | + +`--cors`는 다수 시간을 통과될 수 있습니다: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### 인증 + +`OPENCODE_SERVER_PASSWORD`를 설정하여 서버를 HTTP Basic auth로 보호합니다. `opencode` 또는 `OPENCODE_SERVER_USERNAME`를 오버라이드로 설정하는 사용자의 기본값. 이것은 `opencode serve`와 `opencode web` 둘 다에 적용합니다. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### 작동 방식 + +`opencode`를 실행하면 TUI와 서버를 시작합니다. TUI는 어디에 있습니까? +서버와 대화하는 클라이언트. 서버는 OpenAPI 3.1 spec을 노출 +끝점. 이 엔드포인트는 [SDK](/docs/sdk)을 생성하는 데도 사용됩니다. + +:::tip +opencode 서버를 사용하여 opencode programmatically와 상호 작용합니다. +::: + +이 아키텍처는 opencode 지원 여러 클라이언트를 허용하고 opencode programmatically와 상호 작용 할 수 있습니다. + +독립 서버를 시작하려면 `opencode serve`를 실행할 수 있습니다. 당신이 있는 경우에 +opencode TUI 실행, `opencode serve` 새로운 서버를 시작합니다. + +--- + +#### 기존 서버에 연결 + +TUI를 시작하면 무작위로 포트와 호스트 이름을 할당합니다. 대신 `--hostname`와 `--port` [flags](/docs/cli)에서 전달할 수 있습니다. 그런 다음 서버에 연결하십시오. + +[`/tui`](#tui) 엔드포인트는 서버를 통해 TUI를 구동하는 데 사용될 수 있습니다. 예를 들어 미리 작성하거나 프롬프트를 실행할 수 있습니다. 이 설정은 opencode [IDE](/docs/ide) 플러그인에 의해 사용됩니다. + +--- + +## 사양 + +서버는 OpenAPI 3.1 spec을 게시합니다. + +``` +http://:/doc +``` + +예를 들어, `http://localhost:4096/doc`. 클라이언트를 생성하거나 요청 및 응답 유형을 검사하는 spec를 사용하십시오. 또는 Swagger 탐험가에서 볼 수 있습니다. + +--- + +## API + +opencode 서버는 다음과 같은 API를 노출합니다. + +--- + +## 글로벌 + +| 방법 | 경로 | 설명 | 응답 | +| ----- | ---------------- | ------------------------- | ------------------------------------ | +| `GET` | `/global/health` | 서버 건강 및 버전 | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | 글로벌 이벤트(SSE 스트림) | 이벤트 스트림 | + +--- + +## 프로젝트 + +| 방법 | 경로 | 설명 | 응답 | +| ----- | ------------------ | ----------------------- | --------------------------------------------- | +| `GET` | `/project` | 모든 프로젝트 보기 | Project[] | +| `GET` | `/project/current` | 현재 프로젝트 가져 오기 | 프로젝트 | + +--- + +### 경로 & VCS + +| 방법 | 경로 | 설명 | 응답 | +| ----- | ------- | ----------------------------- | ------------------------------------------- | +| `GET` | `/path` | 현재 경로 받기 | Path | +| `GET` | `/vcs` | 현재 프로젝트의 VCS 정보 받기 | VcsInfo | + +--- + +### 인스턴스 + +| 방법 | 경로 | 설명 | 응답 | +| ------ | ------------------- | -------------------- | --------- | +| `POST` | `/instance/dispose` | 현재 인스턴스를 해제 | `boolean` | + +--- + +### 구성 + +| 방법 | 경로 | 설명 | 응답 | +| ------- | ------------------- | -------------------------- | ---------------------------------------------------------------------------------------- | +| `GET` | `/config` | 구성정보 | Config | +| `PATCH` | `/config` | 업데이트 구성 | Config | +| `GET` | `/config/providers` | 목록 제공업체 및 기본 모델 | `{ providers: ` 사이트 맵`, default: { [key: string]: string } }` | + +--- + +## 공급자 + +| 방법 | 경로 | 설명 | 응답 | +| ------ | -------------------------------- | --------------------------- | ----------------------------------------------------------------------------------- | +| `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` | 공급자를 위한 OAuth 콜백 | `boolean` | + +--- + +## 세션 + +| 메서드 | 경로 | 설명 | 비고 | +| -------- | ---------------------------------------- | ---------------------------------- | ----------------------------------------------------------------------------- | +| `GET` | `/session` | 모든 세션 일람표 | 반환 Session[] | +| `POST` | `/session` | 새 세션 만들기 | 몸: `{ parentID?, title? }`, 반환 Session | +| `GET` | `/session/status` | 모든 세션의 세션 상태를 가져옵니다 | `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | 세션 상세보기 | 반품 Session | +| `DELETE` | `/session/:id` | 세션 삭제 및 모든 데이터 | `boolean` | +| `PATCH` | `/session/:id` | 업데이트 세션 속성 | 본체: `{ title? }`, 반환 Session | +| `GET` | `/session/:id/children` | 세션의 하위 세션 | 리턴 Session[] | +| `GET` | `/session/:id/todo` | 세션의 할 일(Todo) 목록 받기 | Todo[] | +| `POST` | `/session/:id/init` | 앱 초기화 및 `AGENTS.md` 분석 | 몸: `{ messageID, providerID, modelID }`, 반환 `boolean` | +| `POST` | `/session/:id/fork` | 메시지의 기존 세션 | 몸: `{ messageID? }`, 반환 Session | +| `POST` | `/session/:id/abort` | 운영 중인 세션 | 반품 `boolean` | +| `POST` | `/session/:id/share` | 세션 공유 | Session | +| `DELETE` | `/session/:id/share` | 세션 공유 | Session | +| `GET` | `/session/:id/diff` | `/session/:id/diff` | `messageID?`, 반환 FileDiff[] | +| `POST` | `/session/:id/summarize` | 세션을 요약 | 본체: `{ providerID, modelID }`, `boolean` 반환 | +| `POST` | `/session/:id/revert` | 메시지 재생 | 몸: `{ messageID, partID? }`, 반환 `boolean` | +| `POST` | `/session/:id/unrevert` | 메시지 되돌리기 취소 | 반품 `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | 허가 요청 대응 | 본체: `{ response, remember? }`, `boolean` | + +--- + +## 메시지 + +| 방법 | 경로 | 설명 | 주 | +| ------ | --------------------------------- | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `GET` | `/session/:id/message` | 세션의 목록 메시지 | 쿼리: `limit?`, `{ info: `Message`, parts: `Part[]`}[]` | +| `POST` | `/session/:id/message` | 응답을 위해 메시지를 보내고 기다립니다 | 몸: `{ 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` | 비동기적으로 메시지 보내기 | 몸: `/session/:id/message`와 동일, `204 No Content`를 반환 | +| `POST` | `/session/:id/command` | 슬래시 명령어 실행 | 본체: `{ messageID?, agent?, model?, command, arguments }`, 반환 `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/shell` | shell 명령 실행 | 체: `{ agent, model?, command }`, 반환 `{ info: `Message`, parts: `Part[]`}` | + +--- + +## 명령 + +| 방법 | 경로 | 설명 | 응답 | +| ----- | ---------- | --------- | --------------------------------------------- | +| `GET` | `/command` | 모든 명령 | Command[] | + +--- + +## 파일 + +| 방법 | 경로 | 설명 | 응답 | +| ----- | ------------------------ | ---------------------------- | --------------------------------------------------------------------------------------- | +| `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` 쿼리 매개 변수 + +- `query` (required) - 검색 문자열 (fuzzy 일치) +- `type` (선택 사항) - `"file"` 또는 `"directory"`에 제한 결과 +- `directory` (선택 사항) - 검색에 대한 프로젝트 루트를 무시 +- (선택) `limit` - 최대 결과 (1-200) +- `dirs` (옵션) - 레거시 플래그 (`"false"`는 파일만 반환) + +--- + +## 도구 (실험적) + +| 방법 | 경로 | 설명 | 응답 | +| ----- | ------------------------------------------- | ----------------------- | --------------------------------------------- | +| `GET` | `/experimental/tool/ids` | 모든 도구 ID | 도구 | +| `GET` | `/experimental/tool?provider=

&model=` | 모델용 JSON 스키마 목록 | 도구 목록 | + +--- + +### LSP, 포매터 & MCP + +| 방법 | 경로 | 설명 | 응답 | +| ------ | ------------ | ---------------------- | -------------------------------------------------------- | +| `GET` | `/lsp` | LSP 서버 상태 | LSPStatus[] | +| `GET` | `/formatter` | 형식의 상태를 확인 | FormatterStatus[] | +| `GET` | `/mcp` | MCP 서버 상태를 얻는다 | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | MCP 서버가 동적 | 본체: `{ name, config }`, MCP 상태 객체를 반환 | + +--- + +## 에이전트 + +| 방법 | 경로 | 설명 | 응답 | +| ----- | -------- | ------------------------- | ----------------------------------------------- | +| `GET` | `/agent` | 이용 가능한 모든 에이전트 | 에이전트[] | + +--- + +### 로깅 + +| 방법 | 경로 | 설명 | 응답 | +| ------ | ------ | ----------------------------------------------------- | --------- | +| `POST` | `/log` | 로그 입력 바디: `{ service, level, message, extra? }` | `boolean` | + +--- + +### TUI + +| 방법 | 경로 | 설명 | 응답 | +| ------ | ----------------------- | ----------------------------------------- | -------------- | +| `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` | 인증 자격 증명 몸은 공급자 스키마를 일치해야 합니다 | `boolean` | + +--- + +## 이벤트 + +| 방법 | 경로 | 설명 | 응답 | +| ----- | -------- | ------------------------------------------------------------------------------- | ------------------------ | +| `GET` | `/event` | 서버 전송 이벤트 스트림. 첫 번째 이벤트는 `server.connected`, 그 후 버스 이벤트 | Server-sent event stream | + +--- + +### 문서 + +| 방법 | 경로 | 설명 | 응답 | +| ----- | ------ | ---------------- | ------------------------ | +| `GET` | `/doc` | OpenAPI 3.1 사양 | HTML 페이지 OpenAPI 사양 | diff --git a/packages/web/src/content/docs/ko/share.mdx b/packages/web/src/content/docs/ko/share.mdx new file mode 100644 index 00000000000..55cf6a2c3e3 --- /dev/null +++ b/packages/web/src/content/docs/ko/share.mdx @@ -0,0 +1,128 @@ +--- +title: 공유 +description: OpenCode 대화를 공유하세요. +--- + +opencode의 공유 기능은 opencode 대화에 대한 공개 링크를 만들 수 있으므로 Teammates와 협업하거나 다른 곳에서 도움을받을 수 있습니다. + +:::note +공유 대화는 링크를 통해 누구나 쉽게 접근할 수 있습니다. +::: + +--- + +## 작동 방식 + +대화를 공유할 때, opencode: + +1. 세션에 대한 독특한 공개 URL 만들기 +2. 우리의 서버에 대화 기록 동기화 +3. 공유 가능한 링크를 통해 접근 할 수있는 대화 만들기 — `opncd.ai/s/` + +--- + +## 공유 + +opencode는 대화가 공유되는 방법을 제어하는 세 가지 공유 모드를 지원합니다. + +--- + +## 수동 (기본) + +기본적으로 opencode는 수동 공유 모드를 사용합니다. 세션은 자동으로 공유되지 않지만 `/share` 명령을 사용하여 수동으로 공유 할 수 있습니다. + +``` +/share +``` + +클립보드에 복사할 수 있는 독특한 URL을 생성합니다. + +[config 파일](/docs/config)에서 수동 모드를 명시적으로 설정하려면: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +## 자동 공유 + +`share` 옵션을 설정하여 모든 새로운 대화에 대한 자동 공유를 활성화 할 수 있습니다 `"auto"` 당신의 [config 파일](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +자동 공유 활성화로 모든 새로운 대화는 자동으로 공유되고 링크가 생성됩니다. + +--- + +#### 비활성화 + +`share` 옵션을 설정하여 완전히 공유할 수 있습니다. `"disabled"`에 [config file](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +주어진 프로젝트를 위해 팀 전반에 걸쳐 이것을 시행하려면 프로젝트에 `opencode.json`에 추가하고 Git로 확인하십시오. + +--- + +## 공유 취소 + +대화를 중지하고 공공 액세스에서 제거 : + +``` +/unshare +``` + +이 공유 링크를 제거하고 대화와 관련된 데이터를 삭제합니다. + +--- + +## 개인 정보 + +대화를 나누면 마음이 유지되는 몇 가지가 있습니다. + +--- + +## 데이터 보유 + +공유 대화는 명시적으로 그들을 공유 할 때까지 접근 할 수 있습니다. 이름 \* +다음: + +- 전체 대화 기록 +- 모든 메시지 및 응답 +- 세션 메타데이터 + +--- + +### 추천 + +- 민감한 정보를 포함하지 않는 대화 만 공유합니다. +- 공유하기 전에 대화 내용을 검토하십시오. +- 협업이 완료되면 Unshare 대화. +- 독점 코드 또는 기밀 데이터와 대화를 공유하지 마십시오. +- 민감한 프로젝트를 위해, 완전히 공유할 수 있습니다. + +--- + +## 기업용 + +기업 배포를 위해, 공유 기능은: + +- ** 보안 준수를 위해 완전히 비활성화 ** +- **SSO를 통해 인증된 사용자에 대한 제한 ** +- ** 자체 인프라 ** + +[Learn more](/docs/enterprise) 귀하의 조직에서 opencode를 사용하여. diff --git a/packages/web/src/content/docs/ko/skills.mdx b/packages/web/src/content/docs/ko/skills.mdx new file mode 100644 index 00000000000..03ec9c75a4a --- /dev/null +++ b/packages/web/src/content/docs/ko/skills.mdx @@ -0,0 +1,222 @@ +--- +title: "에이전트 스킬" +description: "SKILL.md 정의를 통해 재사용 가능한 동작을 정의합니다." +--- + +Agent Skill let opencode discover reusable instruction from your repo 또는 홈 디렉토리. +Skills are loaded on-demand via native `skill` tool-agents see available skills and can loaded full content when needed. + +--- + +## 파일 위치 + +기술 이름 당 하나의 폴더를 만들고 내부 `SKILL.md`를 넣어. +opencode 이 위치를 검색: + +- 프로젝트 구성: `.opencode/skills//SKILL.md` +- 글로벌 구성: `~/.config/opencode/skills//SKILL.md` +- 프로젝트 클로드 호환 : `.claude/skills//SKILL.md` +- 글로벌 클로드 호환 : `~/.claude/skills//SKILL.md` +- 프로젝트 에이전트 호환 : `.agents/skills//SKILL.md` +- 글로벌 에이전트 호환 : `~/.agents/skills//SKILL.md` + +--- + +## 검색 이해 + +Project-local paths의 경우, opencode는 git worktree에 도달 할 때까지 현재 작업 디렉토리에서 걷습니다. +그것은 `skills/*/SKILL.md`에 있는 어떤 어울리는 `.opencode/` 및 어떤 어울리는 `.claude/skills/*/SKILL.md` 또는 `.agents/skills/*/SKILL.md`를 방법 적재합니다. + +세계적인 정의는 또한 `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md` 및 `~/.agents/skills/*/SKILL.md`에서 적재됩니다. + +--- + +## Frontmatter 작성 + +각 `SKILL.md`는 YAML frontmatter로 시작해야 합니다. +이 필드는 인식됩니다: + +- `name` (필수) +- `description` (필수) +- (선택) `license` +- (선택) `compatibility` +- `metadata` (선택 사항, 문자열에 문자열 맵) + +알려진 frontmatter 필드는 무시됩니다. + +--- + +## 유효한 이름 + +`name`는 해야 합니다: + +- 1–64자 +- 단 하나 hyphen 분리기를 가진 더 낮은 케이스 alphanumeric가 있으십시오 +- `-`로 시작 또는 끝 아닙니다 +- 연속 `--` 포함하지 +- `SKILL.md`를 포함하는 디렉토리 이름을 일치 + +동등한 regex: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## 길이 규칙 준수 + +`description`는 1-1024 특성이어야 합니다. +제대로 선택하기 위해 에이전트에 대해 충분히 유지하십시오. + +--- + +## 사용 예제 + +이처럼 `.opencode/skills/git-release/SKILL.md` 만들기: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## 도구 설명 인식 + +opencode는 `skill` 도구 설명에서 사용할 수있는 기술을 나열합니다. +각 항목에는 기술 이름 및 설명이 포함됩니다. + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +에이전트는 도구를 호출하여 기술을로드 : + +``` +skill({ name: "git-release" }) +``` + +--- + +## 권한 구성 + +기술 에이전트가 `opencode.json`의 패턴 기반 권한을 사용하여 액세스 할 수있는 제어 : + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| 권한 | 동작 | +| ------- | --------------------------------- | +| `allow` | 기술이 즉시 로드됨 | +| `deny` | 에이전트에서 기술 숨김, 접근 거부 | +| `ask` | 로드 전에 사용자에게 승인 요청 | + +패턴 지원 와일드 카드: `internal-*` 경기 `internal-docs`, `internal-tools`, 등. + +--- + +## 에이전트별 재정의 + +글로벌 디폴트보다 특정 에이전트 다른 권한을 부여합니다. + +**사용자 지정 에이전트 ** ( 에이전트 frontmatter): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +** 내장 에이전트 ** (`opencode.json`에서): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## 스킬 도구 비활성화 + +그들을 사용하지 않는 에이전트을위한 완전히 비활성화 된 기술 : + +**사용자 지정 에이전트**: + +```yaml +--- +tools: + skill: false +--- +``` + +** 내장 에이전트 **: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +비활성화 할 때, `` 섹션은 완전히 부유합니다. + +--- + +## 로딩 문제 해결 + +기술이 나타나지 않는 경우: + +1. `SKILL.md`는 모든 모자에서 spelled +2. `name`와 `description`를 포함하는 검사 +3. 기술 이름은 모든 위치에서 독특합니다. +4. `deny`를 가진 허가를 검사하십시오 에이전트에서 숨겨집니다 diff --git a/packages/web/src/content/docs/ko/themes.mdx b/packages/web/src/content/docs/ko/themes.mdx new file mode 100644 index 00000000000..b83b6201702 --- /dev/null +++ b/packages/web/src/content/docs/ko/themes.mdx @@ -0,0 +1,368 @@ +--- +title: 테마 +description: 내장 테마를 선택하거나 자신만의 테마를 정의하세요. +--- + +opencode를 사용하면 여러 내장 테마 중 하나에서 선택할 수 있으며 terminal 테마에 적응하는 테마를 사용하거나 사용자 정의 테마를 정의 할 수 있습니다. + +기본적으로 opencode는 자체 `opencode` 테마를 사용합니다. + +--- + +## 터미널 요구 사항 + +자신의 풀 컬러 팔레트로 올바르게 표시하려면 terminal을 지원해야합니다 ** truecolor** (24 비트 색상). 대부분의 현대 terminal은 기본적으로 이것을 지원합니다, 그러나 당신은 그것을 가능하게 할 필요가 있을지도 모릅니다: + +-**체크 지원**: `echo $COLORTERM` - 그것은 `truecolor` 또는 `24bit`를 출력해야 합니다 + +- ** truecolor 사용 가능**: shell 프로파일에서 환경 변수 `COLORTERM=truecolor`를 설정 +- **Terminal 호환성 **: terminal 에뮬레이터 지원 24 비트 색상 (iTerm2, Alacritty, Kitty, Windows Terminal 및 GNOME Terminal의 최신 버전) + +truecolor 지원 없이, 테마는 감소된 색깔 정확도로 나타날지도 모릅니다 또는 가장 가까운 256 색깔 대류로 뒤떨어질지도 모릅니다. + +--- + +## 내장 테마 + +opencode는 여러 내장 테마와 함께 제공됩니다. + +| 이름 | 설명 | +| ---------------------- | ------------------------------------------------------------------- | +| `system` | terminal 배경 색상에 맞춰 자동으로 조정됨 | +| `tokyonight` | [Tokyonight](https://github.com/folke/tokyonight.nvim) 테마 기반 | +| `everforest` | [Everforest](https://github.com/sainnhe/everforest) 테마 기반 | +| `ayu` | [Ayu](https://github.com/ayu-theme) 다크 테마 기반 | +| `catppuccin` | [Catppuccin](https://github.com/catppuccin) 테마 기반 | +| `catppuccin-macchiato` | [Catppuccin](https://github.com/catppuccin) 테마 기반 | +| `gruvbox` | [Gruvbox](https://github.com/morhetz/gruvbox) 테마 기반 | +| `kanagawa` | [Kanagawa](https://github.com/rebelot/kanagawa.nvim) 테마 기반 | +| `nord` | [Nord](https://github.com/nordtheme/nord) 테마 기반 | +| `matrix` | 검은 배경에 녹색 텍스트의 해커 스타일 테마 | +| `one-dark` | [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark 테마 기반 | + +그리고 더, 우리는 끊임없이 새로운 테마를 추가하고 있습니다. + +--- + +## 시스템 테마 + +`system` 테마는 terminal의 색깔 계획에 자동적으로 적응시키기 위하여 디자인됩니다. 고정 색상을 사용하는 전통적인 테마와 달리, system 테마: + +- **그레이스케일**: terminal의 배경 색상을 기반으로 사용자 정의 회색 가늠자를 만들고 최적의 대조를 보장합니다. +- ** ANSI 색상 사용 ** : terminal의 색상 팔레트를 존중하는 구문 강조 및 UI 요소에 대한 표준 ANSI 색상 (0-15). +- ** terminal 기본 사항**: `none` 텍스트 및 배경 색상을 사용하여 terminal의 네이티브 외관을 유지합니다. + +시스템 테마는 사용자를위한 것입니다 : + +- opencode가 terminal의 외관과 일치해야 합니다. +- 사용자 정의 terminal 색상 구성 +- 모든 terminal 응용 분야의 일관된 모습 + +--- + +## 테마 사용 + +테마를 `/theme` 명령어로 선택하여 테마를 선택할 수 있습니다. 또는 [config](/docs/config)에서 지정할 수 있습니다. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## 사용자 정의 테마 + +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`에서 정의 + +여러 디렉토리가 같은 이름을 가진 테마를 포함한다면, 더 높은 우선 순위를 가진 디렉토리의 테마가 사용됩니다. + +--- + +### 테마 만들기 + +사용자 정의 테마를 만들려면 테마 디렉토리 중 하나에서 JSON 파일을 만듭니다. + +사용자 넓은 테마: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +프로젝트 별 테마. + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### JSON 형식 + +테마는 유연한 JSON 형식을 사용하여 지원: + +-**Hex 색상**: `"#ffffff"` + +- ** ANSI 색상**: `3` (0-255) +- ** 색상 참조 ** : `"primary"` 또는 사용자 정의 정의 +- ** 어두운 / 조명 변형 ** : `{"dark": "#000", "light": "#fff"}` +- ** 색상 없음 ** : `"none"` - terminal의 기본 색상 또는 투명 사용 + +--- + +### 색상 정의 + +`defs` 단면도는 선택적이고 당신은 주제에서 참조될 수 있는 재사용할 수 있는 색깔을 정의할 수 있습니다. + +--- + +## 터미널 기본값 + +특별한 가치 `"none"`는 terminal의 기본 색깔을 상속하기 위하여 어떤 색깔든지를 위해 사용될 수 있습니다. 이것은 특히 당신의 terminal의 색깔 계획과 이음새가 없는 혼합 테마 창조를 위해 유용합니다: + +- `"text": "none"` - terminal의 기본 전경 색상 사용 +- `"background": "none"` - terminal의 기본 배경 색상 사용 + +--- + +### 예제 + +사용자 정의 테마의 예입니다 : + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/ko/tools.mdx b/packages/web/src/content/docs/ko/tools.mdx new file mode 100644 index 00000000000..c9f4fdaf635 --- /dev/null +++ b/packages/web/src/content/docs/ko/tools.mdx @@ -0,0 +1,379 @@ +--- +title: 도구 +description: LLM이 사용할 수 있는 도구를 관리합니다. +--- + +도구는 LLM을 사용하여 코드베이스에서 작업을 수행 할 수 있습니다. opencode는 내장 도구 세트로 제공되지만, [custom tools](/docs/custom-tools) 또는 [MCP 서버](/docs/mcp-servers)로 확장할 수 있습니다. + +기본적으로 모든 도구는**enabled**이며, 실행할 권한이 없습니다. [permissions](/docs/permissions)를 통해 공구 동작을 제어할 수 있습니다. + +--- + +## 구성 + +`permission` 필드를 사용하여 도구 동작을 제어합니다. 각 도구에 대한 승인이 필요할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +한 번에 여러 도구를 제어 할 와일드 카드를 사용할 수 있습니다. 예를 들어, MCP 서버의 모든 도구에 대한 승인을 요구합니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[Learn more](/docs/permissions) configuring 권한에 대해. + +--- + +## 내장 + +다음은 opencode에서 사용할 수있는 모든 내장 도구입니다. + +--- + +###### bash + +프로젝트 환경에서 shell 명령을 실행합니다. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +이 도구는 `npm install`, `git status` 또는 다른 shell 명령과 같은 terminal 명령을 실행하는 LLM을 허용합니다. + +--- + +### edit + +정확한 문자열 교체를 사용하여 기존 파일을 수정합니다. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +이 도구는 정확한 텍스트 일치를 대체하여 파일에 정확한 편집을 수행합니다. LLM은 코드를 modify하는 주요 방법입니다. + +--- + +### write + +새로운 파일을 만들거나 기존의 것을 덮어쓰기. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +LLM을 사용하여 새 파일을 만듭니다. 이미 존재하는 경우 기존 파일을 덮어쓰겠습니다. + +:::note +`write` 공구는 모든 파일 수정 (`edit`, `write`, `patch`, `multiedit`)를 포함하는 `edit` 허가에 의해 통제됩니다. +::: + +--- + +### read + +codebase에서 파일 내용을 읽으십시오. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +이 도구는 파일을 읽고 내용을 반환합니다. 큰 파일에 대한 특정 라인 범위를 읽을 수 있습니다. + +--- + +#### grep + +정규 표현식을 사용하여 파일 내용을 검색합니다. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +Codebase에서 빠른 콘텐츠 검색. 전체 regex 문법 및 파일 패턴 필터링 지원. + +--- + +#### glob + +패턴 매칭으로 파일 찾기. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +`**/*.js` 또는 `src/**/*.ts`와 같은 glob 패턴을 사용하여 파일 검색. 수정 시간에 의해 정렬 된 파일 경로 반환. + +--- + +### list + +주어진 경로의 파일 및 디렉토리 목록. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +이 도구는 디렉토리 내용을 나열합니다. 그것은 glob 패턴을 필터 결과에 받아들입니다. + +--- + +### lsp (실험적) + +정의, 참고, hover info 및 호출 hierarchy와 같은 코드 인텔리전스 기능을 얻기 위해 구성 된 LSP 서버와 인터랙트. + +:::note +이 도구는 `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (또는 `OPENCODE_EXPERIMENTAL=true`) 때만 유효합니다. +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +지원된 가동은 `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls` 및 `outgoingCalls`를 포함합니다. + +LSP 서버가 프로젝트에 사용할 수 있는 구성하려면 [LSP Servers](/docs/lsp)를 참조하십시오. + +--- + +## patch + +파일에 패치를 적용합니다. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +이 도구는 코드베이스에 패치 파일을 적용합니다. 다양한 소스에서 diffs 및 Patch를 적용하는 데 유용합니다. + +:::note +`patch` 공구는 모든 파일 수정 (`edit`, `write`, `patch`, `multiedit`)를 포함하는 `edit` 허가에 의해 통제됩니다. +::: + +--- + +### skill + +[skill](/docs/skills) (`SKILL.md` 파일)을로드하고 대화의 내용을 반환합니다. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +## todowrite + +코딩 세션 중에 todo 목록을 관리합니다. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +복잡한 작업 중에 진행 상황을 추적하기 위해 작업 목록을 만들고 업데이트합니다. LLM은 멀티 단계 작업을 구성하기 위해 이것을 사용합니다. + +:::note +이 도구는 기본으로 시약을 비활성화하지만 수동으로 활성화 할 수 있습니다. [더 알아보기](/docs/agents/#permissions) +::: + +--- + +#### todoread + +기존의 todo 목록 읽기. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +현재 todo 목록 상태를 읽습니다. 작업이 종료되거나 완료되는 것을 추적하기 위해 LLM에 의해 사용됩니다. + +:::note +이 도구는 기본으로 시약을 비활성화하지만 수동으로 활성화 할 수 있습니다. [더 알아보기](/docs/agents/#permissions) +::: + +--- + +#### webfetch + +Fetch 웹 콘텐츠. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +LLM을 fetch 및 웹 페이지를 읽을 수 있습니다. 온라인 리소스를 찾는 데 도움이 되는 문서 또는 연구 + +--- + +#### websearch + +웹 검색 + +:::note +이 도구는 opencode 제공 업체 또는 `OPENCODE_ENABLE_EXA` 환경 변수가 모든 진실 값 (예 : `true` 또는 `1`)로 설정할 때만 사용할 수 있습니다. + +opencode를 실행할 때 활성화: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +Exa AI를 사용하여 웹 검색을 수행하여 관련 정보를 온라인으로 찾으십시오. 연구 주제에 유용한, 현재 이벤트를 찾는, 또는 훈련 데이터 차단을 넘어 정보를 수집. + +API 키가 필요하지 않습니다 - 도구는 인증없이 Exa AI의 호스팅 MCP 서비스에 직접 연결됩니다. + +:::tip +`websearch`를 사용하면 특정 URL (retrieval)에서 콘텐츠를 검색해야합니다. +::: + +--- + +### question + +실행 중에 사용자의 질문 요청. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +이 도구는 작업 중에 LLM을 요청할 수 있습니다. 그것은 유용합니다: + +- 사용자 선호도 또는 요구 사항 변경 +- 주위 지침 +- 구현 선택에 대한 결정 +- 어떤 방향에 대한 선택 제공 + +각 질문에는 헤더, 질문 텍스트 및 옵션 목록이 포함되어 있습니다. 사용자는 제공된 선택권에서 선택하거나 주문 대답을 타자를 수 있습니다. 여러 질문이 있을 때, 사용자는 모든 답변을 제출하기 전에 그들 사이에서 탐색 할 수 있습니다. + +--- + +## 사용자 정의 도구 + +사용자 정의 도구는 LLM이 호출 할 수있는 자신의 기능을 정의 할 수 있습니다. config 파일에 정의되어 arbitrary 코드를 실행할 수 있습니다. + +[Learn more](/docs/custom-tools) 사용자 정의 도구 만들기. + +--- + +## MCP 서버 + +MCP(Model Context Protocol) 서버는 외부 도구와 서비스를 통합할 수 있습니다. 이 데이터베이스 액세스, API 통합 및 타사 서비스가 포함되어 있습니다. + +MCP 서버 구성에 대한 [Learn more](/docs/mcp-servers). + +--- + +## 내부 + +내부, 도구 `grep`, `glob`, 그리고 `list` 사용 [ripgrep](https://github.com/BurntSushi/ripgrep) 후드 아래에. 기본적으로 ripgrep은 `.gitignore` 패턴을 존중하며 `.gitignore`에 나열된 파일 및 디렉토리를 검색 및 목록에서 제외됩니다. + +--- + +#### Ignore 패턴 + +일반적으로 무시되는 파일을 포함하려면 프로젝트 루트에 `.ignore` 파일을 만듭니다. 이 파일은 명시적으로 특정 경로를 허용 할 수 있습니다. + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +예를 들어,이 `.ignore` 파일은 `node_modules/`, `dist/` 및 `build/` 디렉토리 내에서 검색 할 수 있습니다. `.gitignore`. diff --git a/packages/web/src/content/docs/ko/troubleshooting.mdx b/packages/web/src/content/docs/ko/troubleshooting.mdx new file mode 100644 index 00000000000..a7a7ae5e43a --- /dev/null +++ b/packages/web/src/content/docs/ko/troubleshooting.mdx @@ -0,0 +1,303 @@ +--- +title: 문제 해결 +description: 일반적인 문제와 해결 방법. +--- + +opencode와 문제를 디버그하려면 로그와 로컬 데이터를 확인하여 디스크에 저장합니다. + +--- + +## 로깅 + +로그 파일은 다음과 같습니다: + +-**macOS/리눅스**: `~/.local/share/opencode/log/` + +- **Windows**: 압박 `WIN+R`와 풀 `%USERPROFILE%\.local\share\opencode\log` + +로그 파일은 타임스탬프 (예 : `2025-01-09T123456.log`)과 가장 최근 10 로그 파일이 보관됩니다. + +자세한 디버그 정보를 얻기 위해 `--log-level` 명령줄 옵션을 사용하여 로그 레벨을 설정할 수 있습니다. 예를 들면, `opencode --log-level DEBUG`. + +--- + +## 저장소 + +opencode 저장 세션 데이터 및 디스크에 다른 응용 데이터: + +-**macOS/리눅스**: `~/.local/share/opencode/` + +- **Windows**: 압박 `WIN+R`와 풀 `%USERPROFILE%\.local\share\opencode` + +이 디렉토리는 다음과 같습니다: + +- `auth.json` - API 키, OAuth 토큰과 같은 인증 데이터 +- `log/` - 응용 프로그램 로그 +- `project/` - 세션 및 메시지 데이터와 같은 프로젝트별 데이터 +- 프로젝트가 Git repo 안에 있는 경우에, 그것은 `.//storage/`에서 저장됩니다 +- Git repo가 아닌 경우 `./global/storage/`에 저장됩니다. + +--- + +## 데스크톱 앱 + +opencode 데스크톱은 배경에서 로컬 opencode 서버 (`opencode-cli` sidecar)를 실행합니다. 대부분의 문제는 misbehaving 플러그인, 손상된 캐시, 또는 나쁜 서버 설정에 의해 발생합니다. + +## 빠른 확인 + +- 완전히 종료하고 앱을 다시 시작. +- 앱이 오류 화면을 보여 주면 ** Restart**를 클릭하고 오류 세부 정보를 복사합니다. +- macOS만: `OpenCode` 메뉴 -> **웹뷰 **(UI가 공백/frozen인 경우). + +--- + +## 플러그인 비활성화 + +데스크톱 앱이 출시, 거는, 또는 이상한 것에서 충돌하면 플러그인을 비활성화하여 시작합니다. + +### 전역 설정 확인 + +글로벌 설정 파일을 열고 `plugin` 키를 찾습니다. + +-**macOS/리눅스**: `~/.config/opencode/opencode.jsonc` (또는 `~/.config/opencode/opencode.json`) -**macOS/Linux** (외부 설치): `~/.local/share/opencode/opencode.jsonc` + +- **Windows**: 압박 `WIN+R`와 풀 `%USERPROFILE%\.config\opencode\opencode.jsonc` + +구성 된 플러그인이있는 경우, 일시적으로 키를 제거하거나 빈 배열로 설정하여 비활성화하십시오. + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +### 플러그인 디렉터리 확인 + +opencode는 디스크에서 로컬 플러그인을로드 할 수 있습니다. Temporarily 이동 이러한 방법 (또는 폴더 이름을 변경) 및 데스크톱 응용 프로그램을 다시 시작: + +- **글로벌 플러그인** -**macOS/리눅스**: `~/.config/opencode/plugins/` +- **Windows**: 압박 `WIN+R`와 풀 `%USERPROFILE%\.config\opencode\plugins` +- **프로젝트 플러그인** (프로젝트 설정만 사용) +- `/.opencode/plugins/` + +앱이 다시 일하는 경우, 재 활성화 플러그인은 한 번에 문제가 발생할 수 있습니다. + +--- + +#### 캐시 삭제 + +플러그인을 비활성화하는 경우 도움이되지 않습니다 (또는 플러그인 설치가 붙어있다), 캐시를 삭제 그래서 opencode는 그것을 재구성 할 수 있습니다. + +1. Quit opencode 데스크톱 완전히. +2. 캐시 디렉토리 삭제: + +-**macOS**: 찾기 -> `Cmd+Shift+G` -> 붙여넣기 `~/.cache/opencode` + +- **Linux**: `~/.cache/opencode` 삭제 (또는 `rm -rf ~/.cache/opencode` 실행) +- **Windows**: 압박 `WIN+R`와 풀 `%USERPROFILE%\.cache\opencode` + +3. Restart opencode 데스크탑. + +--- + +## 서버 연결 문제 수정 + +opencode 데스크톱은 자체 로컬 서버(기본)를 시작하거나 구성된 서버 URL에 연결할 수 있습니다. + +**"Connection Failed"** 대화 상자 (또는 앱이 스패시 화면을 지나지 않습니다), 사용자 정의 서버 URL을 확인합니다. + +### 데스크톱 기본 서버 URL 삭제 + +Home 화면에서 Server Picker를 열려면 서버 이름(상태 점)을 클릭하십시오. **기본 서버** 섹션에서 **Clear**를 클릭합니다. + +#### 설정에서 server.port/server.hostname 제거 + +`opencode.json(c)`가 `server` 섹션을 포함하면 일시적으로 제거하고 데스크톱 앱을 다시 시작합니다. + +### 환경 변수 확인 + +`OPENCODE_PORT`가 있는 경우, 데스크탑 앱은 로컬 서버의 포트를 사용하려고 합니다. + +- `OPENCODE_PORT` (또는 무료 포트를 선택) 및 재시작. + +--- + +## Linux: Wayland / X11 문제 + +Linux에서 일부 Wayland 설정은 공백 창이나 compositor 오류를 일으킬 수 있습니다. + +- If you're on Wayland and the app is blank/crashing, `OC_ALLOW_WAYLAND=1`로 출시하려고합니다. +- 더 나쁜 것을 만드는 경우, 제거하고 X11 세션에서 실행하려고합니다. + +--- + +## Windows: WebView2 런타임 + +Windows에서 opencode 데스크톱은 Microsoft Edge ** WebView2 실행 시간 **를 요구합니다. 앱이 공백 창에 열거나 시작하지 않을 경우, install/update WebView2를 설치하고 다시 시도하십시오. + +--- + +## Windows: 일반 성능 문제 + +느린 성능, 파일 액세스 문제 또는 Windows의 terminal 문제를 경험하는 경우 [WSL (Windows Subsystem for Linux)](/docs/windows-wsl)를 사용하여 시도하십시오. WSL은 opencode의 기능으로 더 원활하게 작동하는 Linux 환경을 제공합니다. + +--- + +## 알림이 표시되지 않음 + +opencode 데스크톱은 시스템 알림을 보여줍니다 : + +- OS 설정에서 opencode에 대한 알림이 활성화되고, +- 앱 창이 집중되지 않습니다. + +--- + +## 데스크톱 앱 저장소 재설정 (최후의 수단) + +앱이 시작되지 않은 경우 UI 내부에서 설정을 취소할 수 없습니다. 데스크탑 앱의 저장된 상태를 재설정하십시오. + +1. Quit opencode 데스크탑. +2. 이 파일을 찾아 삭제 (opencode 데스크톱 앱 데이터 디렉토리에서 라이브): + +- `opencode.settings.dat` (데스크톱 기본 서버 URL) +- `opencode.global.dat` 및 `opencode.workspace.*.dat` (최근 서버/프로젝트와 같은 UI 국가) + +빠른 디렉토리를 찾을 수: + +-**macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (위의 파일명 검색) + +- **리눅스 **: 위의 파일명에 대한 `~/.local/share`의 밑에 검색 +- **Windows**: `WIN+R` -> `%APPDATA%`를 눌러 (위의 파일 이름을 검색) + +--- + +## 도움 받기 + +opencode와 문제가 발생하면: + +1. ** GitHub의 문제 해결 ** + +버그 또는 요청 기능을보고하는 가장 좋은 방법은 GitHub 저장소를 통해 다음과 같습니다. + +[**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + +새로운 문제를 만들기 전에, 당신의 문제가 이미보고 된 경우 기존 문제를 검색. + +2. ** 우리의 Discord ** + +실시간 도움말 및 커뮤니티 토론을 위해 Discord 서버에 가입하십시오. + +[**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## 일반적인 문제 + +몇 가지 일반적인 문제와 해결 방법. + +--- + +## opencode가 시작되지 않습니다. + +1. 오류 메시지에 대한 로그 확인 +2. terminal에 있는 산출을 보기 위하여 `--print-logs`로 달리기를 시도하십시오 +3. 당신은 `opencode upgrade`를 가진 최신 버전이 있는 것을 지킵니다 + +--- + +### 인증 문제 + +1. TUI에서 `/connect` 명령으로 다시 입력 시도 +2. API 키가 유효하다는 것을 확인 +3. 네트워크가 공급자의 API에 연결을 허용 + +--- + +#### 모델을 사용할 수 없음 + +1. 공급자와 정통한 확인 +2. config의 모델명을 수정한다. +3. 몇몇 모형은 특정한 접근 또는 구독을 요구할지도 모릅니다 + +만약 당신이 `ProviderModelNotFoundError`에 직면 하는 경우 가장 가능성이 잘못 +모델 어딘가를 나타냅니다. +모형은 이렇게 참고되어야 합니다: `/` + +예제: + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +당신이 액세스 할 수있는 모델을 파악하려면, `opencode models`를 실행 + +--- + +## ProviderInitError + +ProviderInitError가 발생하면 잘못된 구성이나 손상된 구성이 있습니다. + +해결하기: + +1. 첫째로, 당신의 공급자는 [providers guide](./providers)를 따르기 위하여 제대로 설치됩니다 +2. 문제가 발생하면 저장된 구성을 삭제하십시오. + + ```bash + rm -rf ~/.local/share/opencode + ``` + +Windows에서, `WIN+R`를 누르고 삭제하십시오: `%USERPROFILE%\.local\share\opencode` + +3. TUI의 `/connect` 명령을 사용하여 공급자와 재해. + +--- + +### AI_APICallError 및 공급자 패키지 문제 + +API 호출 오류가 발생하면, 이 공급 업체 패키지로 인해 발생할 수 있습니다. opencode 동적 설치 공급자 패키지 (OpenAI, Anthropic, Google 등) 필요 하 고 로컬로 캐시. + +공급자 패키지 문제를 해결하려면: + +1. 공급자 포장 캐시를 지우십시오: + + ```bash + rm -rf ~/.cache/opencode + ``` + +Windows에서, `WIN+R`를 누르고 삭제하십시오: `%USERPROFILE%\.cache\opencode` + +2. 최신 공급자 포장을 재설치하는 Restart opencode + +이것은 종종 모델 매개 변수와 API 변경과 호환성 문제를 해결하는 공급자 패키지의 가장 최근 버전을 다운로드하기 위해 opencode를 강제합니다. + +--- + +#### Linux에서 복사/붙여넣기 작동 안 함 + +Linux 사용자는 다음과 같은 클립 보드 유틸리티 중 하나가 복사 / 붙여 넣기 기능에 설치해야합니다. + +** X11 시스템:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**웨이랜드 시스템:** + +```bash +apt install -y wl-clipboard +``` + +** 헤드리스 환경에 대한:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +opencode는 당신이 Wayland를 사용하고 `wl-clipboard`를 선호하는 경우에 검출할 것입니다, 그렇지 않으면의 순서에 있는 클립보드 공구를 찾아낼 것입니다: `xclip`와 `xsel`. diff --git a/packages/web/src/content/docs/ko/tui.mdx b/packages/web/src/content/docs/ko/tui.mdx new file mode 100644 index 00000000000..8717cc785f8 --- /dev/null +++ b/packages/web/src/content/docs/ko/tui.mdx @@ -0,0 +1,390 @@ +--- +title: TUI +description: OpenCode 터미널 사용자 인터페이스 사용. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +opencode는 LLM과 함께 프로젝트를 위해 대화형 terminal 인터페이스 또는 TUI를 제공합니다. + +opencode는 현재 디렉토리에 TUI를 시작합니다. + +```bash +opencode +``` + +또는 특정 작업 디렉토리에 대해 시작할 수 있습니다. + +```bash +opencode /path/to/project +``` + +TUI에 있다면 메시지가 표시됩니다. + +```text +Give me a quick summary of the codebase. +``` + +--- + +## 파일 참조 + +`@`를 사용하여 메시지에 파일을 참조 할 수 있습니다. 이것은 현재 작업 디렉토리에서 fuzzy 파일 검색입니다. + +:::tip +`@`를 사용하여 메시지의 참조 파일을 사용할 수 있습니다. +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +파일의 내용이 자동으로 대화에 추가됩니다. + +--- + +## Bash 명령 + +`!`를 사용하여 shell 명령을 실행합니다. + +```bash frame="none" +!ls -la +``` + +명령의 출력은 도구 결과로 대화에 추가됩니다. + +--- + +## 명령 + +opencode TUI를 사용할 때, `/`를 입력하여 명령 이름을 따라 작업을 신속하게 실행할 수 있습니다. 예를 들면: + +```bash frame="none" +/help +``` + +대부분의 명령은 `ctrl+x`를 `ctrl+x`가 기본 리더 키입니다. [더 알아보기](/docs/keybinds). + +여기에 모든 가능한 슬래시 명령이 있습니다. + +--- + +### /connect + +opencode에 대한 공급자를 추가합니다. 사용 가능한 공급자에서 선택하고 API 키를 추가 할 수 있습니다. + +```bash frame="none" +/connect +``` + +--- + +### /compact + +현재 세션을 압축합니다. 앨리스 : `/summarize` + +```bash frame="none" +/compact +``` + +** Keybind:** `ctrl+x c` + +--- + +### /details + +토글 툴 실행 세부 사항. + +```bash frame="none" +/details +``` + +** Keybind:** `ctrl+x d` + +--- + +### /editor + +메시지를 작성하기 위한 외부 편집기를 엽니다. `EDITOR` 환경에서 설정된 편집기를 사용합니다. [더 알아보기](#editor-setup). + +```bash frame="none" +/editor +``` + +** Keybind:** `ctrl+x e` + +--- + +### /exit + +opencode를 종료합니다. Aliases : `/quit`, `/q` + +```bash frame="none" +/exit +``` + +** Keybind:** `ctrl+x q` + +--- + +### /export + +Markdown에 대한 현재 대화를 내보내고 기본 편집기에서 열립니다. `EDITOR` 환경에서 설정된 편집기를 사용합니다. [더 알아보기](#editor-setup). + +```bash frame="none" +/export +``` + +** Keybind:** `ctrl+x x` + +--- + +### /help + +도움말 대화 상자를 표시합니다. + +```bash frame="none" +/help +``` + +** Keybind:** `ctrl+x h` + +--- + +###### /init + +`AGENTS.md` 파일을 만들거나 업데이트하십시오. [더 알아보기](/docs/rules). + +```bash frame="none" +/init +``` + +** Keybind:** `ctrl+x i` + +--- + +## /models + +사용 가능한 모델 목록. + +```bash frame="none" +/models +``` + +** Keybind:** `ctrl+x m` + +--- + +## /new + +새로운 세션을 시작합니다. 앨리스 : `/clear` + +```bash frame="none" +/new +``` + +** Keybind:** `ctrl+x n` + +--- + +##### /redo + +이전 undone 메시지 Redo. `/undo`를 사용하는 후에만 유효한. + +:::tip +모든 파일 변경도 복원됩니다. +::: + +내부적으로 Git을 사용하여 파일 변경을 관리합니다. 그래서 프로젝트 ** +Git 저장소**입니다. + +```bash frame="none" +/redo +``` + +** Keybind:** `ctrl+x r` + +--- + +## /sessions + +세션 간 목록 및 전환. Aliases : `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +** Keybind:** `ctrl+x l` + +--- + +## 공유 + +현재 세션 공유. [더 알아보기](/docs/share). + +```bash frame="none" +/share +``` + +** Keybind:** `ctrl+x s` + +--- + +## /theme + +사용할 수 있는 테마 목록. + +```bash frame="none" +/theme +``` + +** Keybind:** `ctrl+x t` + +--- + +### /thinking + +대화의 사고/거주 블록의 가시성을 토합니다. 사용할 때, 확장 된 생각을 지원하는 모델의 이유 프로세스를 볼 수 있습니다. + +:::note +이 명령은 생각 블록이 ** 표시되었는지 여부 만 제어 ** - 모델의 소싱 기능을 활성화하거나 비활성화하지 않습니다. toggle 실제적인 reasoning 기능에, 모형 변종을 통해서 주기 위하여 `ctrl+t`를 이용합니다. +::: + +```bash frame="none" +/thinking +``` + +--- + +##### /undo + +대화에서 마지막 메시지. 가장 최근의 사용자 메시지, 모든 후속 응답 및 모든 파일 변경 제거. + +:::tip +어떤 파일 변경도 복제됩니다. +::: + +내부적으로 Git을 사용하여 파일 변경을 관리합니다. 그래서 프로젝트 ** +Git 저장소**입니다. + +```bash frame="none" +/undo +``` + +** Keybind:** `ctrl+x u` + +--- + +#### /unshare + +Unshare 현재 세션. [더 알아보기](/docs/share#un-sharing). + +```bash frame="none" +/unshare +``` + +--- + +## 편집기 설정 + +`/editor`와 `/export` 명령 모두는 `EDITOR` 환경변수에서 지정된 편집기를 사용합니다. + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + +영원한 만들기 위하여, 당신의 shell 프로파일에 이것을 추가하십시오; +`~/.bashrc`, `~/.zshrc`, 등. + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + +영구적으로, use **System Properties** > ** 환경 +변수**. + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + +영구적으로 만들려면 PowerShell 프로파일에 추가하십시오. + + + + +인기있는 편집기 옵션은 다음과 같습니다 : + +- `code` - Visual Studio 코드 +- `cursor` - 커서 +- `windsurf` - 윈드 서핑 +- `nvim` - Neovim 편집기 +- `vim` - Vim 편집기 +- `nano` - 나노 편집기 +- `notepad` - 윈도우 노트패드 +- `subl` - 승화 텍스트 + +:::note +VS Code와 같은 일부 편집기는 `--wait` 플래그와 함께 시작해야합니다. +::: + +일부 편집기는 명령줄 인수가 차단 모드에서 실행되어야 합니다. `--wait` 플래그는 닫힐 때까지 편집기 프로세스 블록을 만듭니다. + +--- + +## 구성 + +opencode config 파일을 통해 TUI 동작을 사용자 정의할 수 있습니다. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### 옵션 + +- `scroll_acceleration` - 부드러운 자연 스크롤을위한 macOS 스타일 스크롤 가속 가능. 사용할 때, 스크롤 속도는 빠른 스크롤 제스처로 증가하고 느린 움직임을 위해 정확한 유지. **이 설정은 `scroll_speed`를 통해 우선 순위를 부여하고 활성화 할 때. ** +- `scroll_speed` - 스크롤 명령 (최소 : `1`)을 사용하여 TUI 스크롤을 빠르게 제어합니다. 기본 `3`. ** 참고: `scroll_acceleration.enabled`가 `true`로 설정되면 무시됩니다.** + +--- + +## 사용자 정의 + +명령 팔레트 (`ctrl+x h` 또는 `/help`)를 사용하여 TUI보기의 다양한 측면을 사용자 정의 할 수 있습니다. 재시작에 따른 설정 persist. + +--- + +#### 사용자 이름 표시 + +사용자 이름이 채팅 메시지에 나타나는지 여부를 수정합니다. 이것을 통해 접근: + +- 명령 팔레트 : "username" 또는 "hide 사용자" 검색 +- 자동 설정은 TUI 세션을 통해 기억됩니다. diff --git a/packages/web/src/content/docs/ko/web.mdx b/packages/web/src/content/docs/ko/web.mdx new file mode 100644 index 00000000000..349ee4d08d6 --- /dev/null +++ b/packages/web/src/content/docs/ko/web.mdx @@ -0,0 +1,142 @@ +--- +title: Web +description: 브라우저에서 OpenCode 사용하기. +--- + +opencode는 브라우저에서 웹 응용 프로그램을 실행할 수 있으며 terminal을 필요로하지 않고 동일한 강력한 AI 코딩 경험을 제공합니다. + +![opencode Web - 새로운 세션](../../../assets/web/web-homepage-new-session.png) + +## 시작하기 + +실행하여 웹 인터페이스를 시작: + +```bash +opencode web +``` + +`127.0.0.1`의 로컬 서버를 랜덤 사용 가능한 포트로 시작하고 기본 브라우저에서 opencode를 자동으로 엽니다. + +:::caution +`OPENCODE_SERVER_PASSWORD`가 설정되지 않은 경우 서버가 중단되지 않습니다. 이것은 로컬 사용을위한 괜찮지만 네트워크 액세스를 설정해야합니다. +::: + +:::tip[Windows 사용자] +최고의 경험을 위해서는 PowerShell보다 `opencode web`를 실행하십시오. 적절한 파일 시스템 액세스 및 terminal 통합을 보장합니다. +::: + +--- + +## 구성 + +명령줄 플래그 또는 [config file](/docs/config)에서 웹 서버를 구성할 수 있습니다. + +## 포트 + +기본적으로 opencode는 사용할 수 있는 포트를 선택합니다. 포트를 지정할 수 있습니다: + +```bash +opencode web --port 4096 +``` + +## 호스트 이름 + +기본적으로 서버는 `127.0.0.1` (localhost only)에 바인딩합니다. 네트워크에서 opencode를 사용할 수 있도록: + +```bash +opencode web --hostname 0.0.0.0 +``` + +`0.0.0.0`를 사용할 때, opencode는 로컬 및 네트워크 주소를 모두 표시합니다. + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### mDNS 발견 + +로컬 네트워크에서 서버를 발견할 수 있는 mDNS: + +```bash +opencode web --mdns +``` + +이 자동으로 `0.0.0.0`에 hostname을 설정하고 `opencode.local`로 서버를 광고합니다. + +동일한 네트워크에서 여러 인스턴스를 실행하려면 mDNS 도메인 이름을 지정할 수 있습니다. + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +###### CORS + +CORS에 대한 추가 도메인을 허용하려면 (사용자 정의 frontends에 적합) : + +```bash +opencode web --cors https://example.com +``` + +### 인증 + +액세스를 보호하려면 `OPENCODE_SERVER_PASSWORD` 환경 변수를 사용하여 암호를 설정하십시오. + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +`opencode`에 대한 사용자의 기본값은 `OPENCODE_SERVER_USERNAME`로 변경할 수 있습니다. + +--- + +## 웹 인터페이스 사용 + +시작되면 웹 인터페이스는 opencode 세션에 액세스 할 수 있습니다. + +## 세션 + +홈페이지에서 세션을 보고 관리합니다. 활성 세션을 볼 수 있으며 새로운 것을 시작합니다. + +![opencode Web - Active Session](../../../assets/web/web-homepage-active-session.png) + +## 서버 상태 + +"See Servers"를 클릭하여 연결된 서버와 상태를 볼 수 있습니다. + +![opencode Web - Servers 참조](../../../assets/web/web-homepage-see-servers.png) + +--- + +## 터미널 연결 + +실행 웹 서버에 terminal TUI를 연결할 수 있습니다. + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +웹 인터페이스와 terminal을 동시에 사용할 수 있도록, 같은 세션과 상태를 공유합니다. + +--- + +## 구성 파일 + +`opencode.json` config 파일에서 서버 설정을 구성할 수 있습니다: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +Command line flags는 config 파일 설정에 대한 precedence를 가져옵니다. diff --git a/packages/web/src/content/docs/ko/windows-wsl.mdx b/packages/web/src/content/docs/ko/windows-wsl.mdx new file mode 100644 index 00000000000..e75ad41f1cd --- /dev/null +++ b/packages/web/src/content/docs/ko/windows-wsl.mdx @@ -0,0 +1,119 @@ +--- +title: Windows (WSL) +description: WSL로 Windows에서 opencode를 더 편하게 사용하세요. +--- + +import { Steps } from "@astrojs/starlight/components" + +opencode는 Windows에서 직접 실행할 수 있지만, 가장 좋은 사용 경험을 위해 [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) 사용을 권장합니다. WSL은 opencode 기능과 자연스럽게 동작하는 Linux 환경을 제공합니다. + +:::tip[왜 WSL인가요?] +WSL은 더 나은 파일 시스템 성능, 완전한 terminal 지원, 그리고 opencode가 의존하는 개발 도구와의 호환성을 제공합니다. +::: + +--- + +## 설정 + + + +1. **WSL 설치하기** + + 아직 설치하지 않았다면 Microsoft 공식 가이드를 따라 [WSL을 설치](https://learn.microsoft.com/en-us/windows/wsl/install)하세요. + +2. **WSL에 opencode 설치하기** + + WSL 설정이 끝나면 WSL terminal을 열고 [설치 방법](/docs/) 중 하나로 opencode를 설치하세요. + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **WSL에서 opencode 실행하기** + + 프로젝트 디렉터리로 이동한 뒤(opencode에서 Windows 파일은 `/mnt/c/`, `/mnt/d/` 등으로 접근) opencode를 실행하세요. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## 데스크톱 앱 + WSL 서버 + +opencode 데스크톱 앱을 쓰면서 서버는 WSL에서 실행하고 싶다면 다음처럼 진행하세요. + +1. **WSL에서 서버 시작하기** + + 외부 연결을 허용하려면 `--hostname 0.0.0.0` 옵션을 사용하세요. + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **데스크톱 앱 연결하기** + + `http://localhost:4096`로 연결하세요. + +:::note +환경에 따라 `localhost`가 동작하지 않으면 WSL의 IP 주소를 사용하세요(WSL에서 `hostname -I` 실행). 이후 `http://:4096`로 접속하면 됩니다. +::: + +:::caution +`--hostname 0.0.0.0`을 사용할 때는 `OPENCODE_SERVER_PASSWORD`를 설정해 서버를 보호하세요. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## 웹 클라이언트 + WSL + +Windows에서 웹 사용 경험을 가장 좋게 하려면: + +1. **PowerShell 대신 WSL terminal에서 `opencode web` 실행하기** + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Windows 브라우저에서 접속하기** + + `http://localhost:`로 접속하세요(opencode가 URL을 출력합니다). + +WSL에서 `opencode web`를 실행하면 올바른 파일 시스템 접근과 terminal 통합을 유지하면서도 Windows 브라우저에서 바로 사용할 수 있습니다. + +--- + +## Windows 파일 접근 + +WSL에서는 `/mnt/` 디렉터리를 통해 Windows 파일 전체에 접근할 수 있습니다. + +- `C:` drive → `/mnt/c/` +- `D:` drive → `/mnt/d/` +- 다른 드라이브도 같은 방식입니다 + +예시: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +가장 매끄러운 경험을 원한다면 저장소를 WSL 파일시스템(예: `~/code/`)으로 복제하거나 복사한 뒤 그 위치에서 opencode를 실행해 보세요. +::: + +--- + +## 팁 + +- Windows 드라이브에 있는 프로젝트라도 opencode는 WSL에서 실행하면 파일 접근이 더 자연스럽습니다 +- 통합된 개발 워크플로를 위해 opencode와 함께 VS Code의 [WSL 확장](https://code.visualstudio.com/docs/remote/wsl)을 사용해 보세요 +- opencode 설정과 세션은 WSL 환경의 `~/.local/share/opencode/`에 저장됩니다 diff --git a/packages/web/src/content/docs/ko/zen.mdx b/packages/web/src/content/docs/ko/zen.mdx new file mode 100644 index 00000000000..bf30ccc655f --- /dev/null +++ b/packages/web/src/content/docs/ko/zen.mdx @@ -0,0 +1,254 @@ +--- +title: Zen +description: OpenCode가 제공하는 엄선된 모델 목록. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen은 opencode 팀에서 제공하는 테스트 및 검증된 모델 목록입니다. + +:::note +OpenCode Zen은 현재 베타입니다. +::: + +Zen은 opencode의 다른 공급자와 같이 작동합니다. OpenCode Zen에 로그인하고 +API 키. 그것은 ** 완전 옵션 ** 당신은 사용할 필요가 없습니다 +opencode입니다. + +--- + +## 배경 + +거기에 모델의 큰 수는 있지만 몇 가지의 +이 모형은 뿐 아니라 기호화 에이전트 작동합니다. 또한, 대부분의 공급자는 +아주 다르게 형성하십시오; 그래서 당신은 아주 다른 성과 및 질을 얻습니다. + +:::tip +opencode와 잘 작동하는 모델 및 공급자의 선택 그룹을 테스트했습니다. +::: + +OpenRouter와 같은 무언가를 통해 모델을 사용하고 있다면 결코 할 수 없습니다. +당신이 원하는 모델의 최고의 버전을 얻는 경우. + +이것을 해결하기 위해, 우리는 몇 가지 일을했다 : + +1. 우리는 모형의 선택 그룹을 시험하고 그들의 팀에 대략 이야기했습니다 + 가장 좋은 것. +2. 우리는 그(것)들이 봉사한 것을 확인하기 위하여 몇몇 공급자와 일했습니다 + 견적 요청 +3. 마지막으로, 우리는 model/provider의 조합을 벤치마크하고 올랐습니다 + 우리가 좋은 권고를 느끼는 목록으로. + +OpenCode Zen은 이 모델에 액세스 할 수있는 AI 게이트웨이입니다. + +--- + +## 어떻게 작동합니까? + +OpenCode Zen은 opencode의 다른 공급자와 같습니다. + +1. 로그인 **OpenCode Zen**, 청구 추가 + 세부 사항 및 API 키 복사. +2. TUI에서 `/connect` 명령을 실행하고 OpenCode Zen을 선택하고 API 키를 붙여 넣으십시오. +3. TUI의 `/models`를 실행하여 우리가 추천하는 모델 목록을 볼 수 있습니다. + +요청에 따라 청구되며 계정에 크레딧을 추가 할 수 있습니다. + +--- + +## 엔드포인트 + +다음 API 엔드포인트를 통해 모델에 액세스할 수 있습니다. + +| 모델 | 모델 ID | 엔드포인트 | AI SDK 패키지 | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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에서 [model id](/docs/config/#models) +형식 `opencode/`를 사용합니다. 예를 들어, GPT 5.2 Codex의 경우, +설정에서 `opencode/gpt-5.2-codex`를 사용합니다. + +--- + +## 모델 + +사용할 수 있는 모델과 메타데이터의 전체 목록은 다음과 같습니다: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## 가격 + +우리는 pay-as-you-go 모델을 지원합니다. 아래는 1M 토큰 \*\* 당 가격입니다. + +| 모델 | 입력 | 출력 | 캐시 읽기 | 캐시 쓰기 | +| --------------------------------- | ------ | ------ | --------- | --------- | +| Big Pickle | Free | Free | Free | - | +| MiniMax M2.1 Free | Free | Free | Free | - | +| MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | +| GLM 4.7 Free | Free | Free | Free | - | +| 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 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 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.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 | Free | Free | Free | - | + +You might notice Claude Haiku 3.5 사용 역사. 이것은 세션의 제목을 생성하는 데 사용되는 [low cost model](/docs/config/#models)입니다. + +:::note +신용 카드 수수료는 비용 (4.4% + 거래 당 $0.30)에 따라 전달됩니다. 우리는 그 이상을 청구하지 않습니다. +::: + +무료 모델: + +- GLM의 4.7 제한된 시간에 opencode에서 무료로 사용할 수 있습니다. 팀은 피드백을 수집하고 모델을 개선하기 위해이 시간을 사용합니다. +- 김이 K2.5 제한된 시간에 opencode에서 무료로 사용할 수 있습니다. 팀은 피드백을 수집하고 모델을 개선하기 위해이 시간을 사용합니다. +- 미니 맥스 M2.1 제한된 시간에 opencode에서 무료로 사용할 수 있습니다. 팀은 피드백을 수집하고 모델을 개선하기 위해이 시간을 사용합니다. +- Big Pickle은 제한된 시간 동안 opencode에서 무료 훔친 모델입니다. 팀은 피드백을 수집하고 모델을 개선하기 위해이 시간을 사용합니다. + +Contact us if you have any questions. + +--- + +### 자동 로드 + +잔액이 $ 5 미만인 경우 Zen은 $ 20를 자동으로 다시로드합니다. + +자동로드 금액을 변경할 수 있습니다. 또한 완전히 자동 부하를 비활성화 할 수 있습니다. + +--- + +## 월간 제한 + +또한 전체 작업 공간에 대한 월간 사용 제한을 설정할 수 있습니다. +당신의 팀의 일원. + +예를 들어, 매달 사용 제한을 $20로 설정하면 Zen은 사용하지 않습니다. +한 달에 $ 20 이상. 그러나 자동 로드가 활성화되면 Zen이 종료 될 수 있습니다. +잔액이 $5 미만인 경우 $20 이상 충전. + +--- + +## 개인 정보 + +우리의 모든 모델은 미국에서 호스팅됩니다. 우리의 공급자는 제로 보유 정책을 따르고 모형 훈련을 위한 당신의 자료를 이용하지 않습니다, 뒤에 오는 예외로: + +- Big Pickle : 무료 기간 동안 수집 된 데이터는 모델을 개선하기 위해 사용될 수있다. +- GLM 4.7 무료 : 무료 기간 동안 수집 된 데이터는 모델을 개선하기 위해 사용될 수있다. +- Kimi K2.5 무료 : 무료 기간 동안 수집 된 데이터는 모델을 개선하기 위해 사용될 수있다. +- MiniMax M2.1 무료 : 무료 기간 동안 수집 된 데이터는 모델을 개선하기 위해 사용될 수있다. +- OpenAI APIs: 요청은 [OpenAI's Data Policies](https://platform.openai.com/docs/guides/your-data)에 따라 30일 동안 유지됩니다. +- Anthropic APIs : 요청은 [Anthropic's Data Policies](https://docs.anthropic.com/en/docs/claude-code/data-usage)에 따라 30 일 동안 유지됩니다. + +--- + +## 팀 + +Zen은 팀을 위해 잘 작동합니다. 팀메이트를 초대 할 수 있습니다, 역할 할당, curate +당신의 팀 용도 및 더 많은 모델을. + +:::note +Workspaces는 현재 베타의 일부로 팀에 무료로 제공됩니다. +::: + +작업 공간 관리는 현재 베타의 일부로 팀에 무료로 제공됩니다. 우리는 +가격을 곧 공유하십시오. + +--- + +## 역할 + +작업 공간에 팀메이트를 초대하고 역할 할당 할 수 있습니다. + +- **Admin**: 모델, 회원, API 키 및 청구 +- **회원**: 자신의 API 키만 관리 + +Admins는 또한 통제의 밑에 비용을 지키는 각 일원을 위한 매달 지출 한계를 놓을 수 있습니다. + +--- + +## 모델 접근 + +관리자는 작업 공간에 특정 모델을 활성화하거나 비활성화 할 수 있습니다. 장애인 모델에 요청은 오류를 반환합니다. + +이것은 당신이 모델의 사용을 비활성화하려는 경우 유용합니다 +데이터 수집 + +--- + +## BYOK (Bring Your Own Key) + +OpenAI 또는 Anthropic API 키를 사용하여 Zen에서 다른 모델에 액세스 할 수 있습니다. + +자신의 키를 사용할 때, 토큰은 Zen에 의해 공급자에 의해 직접 청구됩니다. + +예를 들어, 조직은 이미 OpenAI 또는 Anthropic에 대한 열쇠가있을 수 있습니다. +Zen이 제공하는 것을 대신 사용하고 싶습니다. + +--- + +## 목표 + +OpenCode Zen을 생성했습니다. + +1. **Benchmark ** 코딩 에이전트에 대한 최고의 모델 / 프로바이더. +2. ** 고품질 ** 옵션에 액세스하고 더 싼 공급자에 고급 성능 또는 노선을 내리지 마십시오. +3. 비용에 판매해서 ** 가격 하락 **를 따라 통과하십시오; 그래서 단지 감적은 우리의 가공 비용을 커버하는 것입니다. +4. 잠금 해제 \*\* 다른 코딩 에이전트와 함께 사용할 수 있도록. 그리고 항상 opencode와 다른 모든 공급자를 사용할 수 있습니다. diff --git a/packages/web/src/content/docs/nb/acp.mdx b/packages/web/src/content/docs/nb/acp.mdx new file mode 100644 index 00000000000..23fbd06d22b --- /dev/null +++ b/packages/web/src/content/docs/nb/acp.mdx @@ -0,0 +1,156 @@ +--- +title: ACP-støtte +description: Bruk opencode i en hvilken som helst ACP-kompatibel editor. +--- + +OpenCode støtter [Agent Client Protocol](https://agentclientprotocol.com) eller (ACP), slik at du kan bruke den direkte i kompatible editorer og IDE-er. + +:::tip +For en liste over editorer og verktøy som støtter ACP, sjekk ut [ACP fremdriftsrapport](https://zed.dev/blog/acp-progress-report#available-now). +::: + +ACP er en åpen protokoll som standardiserer kommunikasjon mellom kodeditorer og AI-kodeagenter. + +--- + +## Konfigurasjon + +For å bruke OpenCode via ACP, konfigurer redigeringsprogrammet til å kjøre kommandoen `opencode acp`. + +Kommandoen starter OpenCode som en ACP-kompatibel underprosess som kommuniserer med editoren din over JSON-RPC via stdio. + +Nedenfor er eksempler på populære editorer som støtter ACP. + +--- + +### Zed + +Legg til i [Zed](https://zed.dev)-konfigurasjonen (`~/.config/zed/settings.json`): + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +For å åpne den, bruk handlingen `agent: new thread` i **Kommandopaletten**. + +Du kan også binde en hurtigtast ved å redigere `keymap.json`: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### JetBrains IDE-er + +Legg til [JetBrains IDE](https://www.jetbrains.com/) acp.json i henhold til [dokumentasjonen](https://www.jetbrains.com/help/ai-assistant/acp.html): + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +For å åpne den, bruk den nye 'OpenCode'-agenten i AI Chat-agentvelgeren. + +--- + +### Avante.nvim + +Legg til i [Avante.nvim](https://github.com/yetone/avante.nvim)-konfigurasjonen: + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +Hvis du trenger å sende miljøvariabler: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +For å bruke OpenCode som en ACP-agent i [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim), legg til følgende i Neovim-konfigurasjonen: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +Denne konfigurasjonen setter opp CodeCompanion.nvim til å bruke OpenCode som ACP-agent for chat. + +Hvis du trenger å sende miljøvariabler (som `OPENCODE_API_KEY`), se [Konfigurere adaptere: miljøvariabler](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) i CodeCompanion.nvim-dokumentasjonen for fullstendige detaljer. + +## Støtte + +OpenCode fungerer på samme måte via ACP som i terminalen. Alle funksjoner støttes: + +:::note +Noen innebygde slash-kommandoer som `/undo` og `/redo` støttes for øyeblikket ikke. +::: + +- Innebygde verktøy (filoperasjoner, terminalkommandoer, etc.) +- Egendefinerte verktøy og slash-kommandoer +- MCP servere konfigurert i OpenCode-konfigurasjonen +- Prosjektspesifikke regler fra `AGENTS.md` +- Tilpassede formatere og linters +- Agenter og tillatelsessystem diff --git a/packages/web/src/content/docs/nb/agents.mdx b/packages/web/src/content/docs/nb/agents.mdx new file mode 100644 index 00000000000..d7831e3387d --- /dev/null +++ b/packages/web/src/content/docs/nb/agents.mdx @@ -0,0 +1,746 @@ +--- +title: Agenter +description: Konfigurer og bruk spesialiserte agenter. +--- + +Agenter er spesialiserte AI-assistenter som kan konfigureres for spesifikke oppgaver og arbeidsflyter. De lar deg lage fokuserte verktøy med tilpassede meldinger, modeller og verktøytilgang. + +:::tip +Bruk planagenten til å analysere kode og gjennomgå forslag uten å gjøre noen kodeendringer. +::: + +Du kan bytte mellom agenter under en økt eller påkalle dem med `@`-omtalen. + +--- + +## Typer + +Det er to typer agenter i OpenCode; primære agenter og underagenter. + +--- + +### Primæragenter + +Primæragenter er de viktigste assistentene du samhandler direkte med. Du kan bla gjennom dem ved å bruke **Tab**-tasten, eller din konfigurerte `switch_agent`-tastebinding. Disse agentene håndterer hovedsamtalen din. Verktøytilgang konfigureres via tillatelser - for eksempel har Build alle verktøy aktivert mens Plan er begrenset. + +:::tip +Du kan bruke **Tab**-tasten for å bytte mellom primære agenter under en økt. +::: + +OpenCode kommer med to innebygde primære agenter, **Build** og **Plan**. Vi ser nærmere på disse nedenfor. + +--- + +### Underagenter + +Underagenter er spesialiserte assistenter som primære agenter kan påkalle for spesifikke oppgaver. Du kan også starte dem manuelt ved å **@ nevne** dem i meldingene dine. + +OpenCode kommer med to innebygde underagenter, **General** og **Explore**. Vi skal se på dette nedenfor. + +--- + +## Innebygd + +OpenCode kommer med to innebygde primære agenter og to innebygde underagenter. + +--- + +### Bruk av Build + +_Modus_: `primary` + +Build er **standard** primæragent med alle verktøy aktivert. Dette er standardagenten for utviklingsarbeid der du trenger full tilgang til filoperasjoner og systemkommandoer. + +--- + +### Bruk av Plan + +_Modus_: `primary` + +En begrenset agent designet for planlegging og analyse. Vi bruker et tillatelsessystem for å gi deg mer kontroll og forhindre utilsiktede endringer. +Som standard er alt av følgende satt til `ask`: + +- `file edits`: Alle skrivinger, patcher og redigeringer +- `bash`: Alle bash-kommandoer + +Denne agenten er nyttig når du vil at LLM skal analysere kode, foreslå endringer eller lage planer uten å gjøre noen faktiske endringer i kodebasen. + +--- + +### Bruk av General + +_Modus_: `subagent` + +En generell agent for å undersøke komplekse spørsmål og utføre flertrinnsoppgaver. Har full verktøytilgang (unntatt todo), slik at den kan gjøre filendringer når det er nødvendig. Bruk denne til å kjøre flere arbeidsenheter parallelt. + +--- + +### Bruk av Explore + +_Modus_: `subagent` + +En rask, skrivebeskyttet agent for å utforske kodebaser. Kan ikke endre filer. Bruk dette når du raskt trenger å finne filer etter mønstre, søke i kode etter nøkkelord eller svare på spørsmål om kodebasen. + +--- + +### Bruk av Compaction + +_Modus_: `primary` + +Skjult systemagent som komprimerer lang kontekst til et mindre sammendrag. Den kjører automatisk ved behov og kan ikke velges i UI. + +--- + +### Bruk av Title + +_Modus_: `primary` + +Skjult systemagent som genererer korte økttitler. Den kjører automatisk og kan ikke velges i UI. + +--- + +### Bruk av Summary + +_Modus_: `primary` + +Skjult systemagent som lager øktsammendrag. Den kjører automatisk og kan ikke velges i UI. + +--- + +## Bruk + +1. For primære agenter, bruk **Tab**-tasten for å bla gjennom dem under en økt. Du kan også bruke din konfigurerte `switch_agent` nøkkelbinding. + +2. Underagenter kan påkalles: + - **Automatisk** av primære agenter for spesialiserte oppgaver basert på deres beskrivelser. + - Manuelt ved å **@ nevne** en underagent i meldingen. For eksempel. + + ```txt frame="none" + @general help me search for this function + ``` + +3. **Navigering mellom økter**: Når underagenter oppretter sine egne underordnede økter, kan du navigere mellom overordnede økter og alle underordnede økter ved å bruke: + - **\+Right** (eller din konfigurerte `session_child_cycle`-tastebinding) for å gå videre gjennom forelder → barn1 → barn2 → ... → forelder + - **\+Left** (eller din konfigurerte `session_child_cycle_reverse`-tastebinding) for å gå bakover gjennom forelder ← barn1 ← barn2 ← ... ← forelder + + Dette lar deg sømløst bytte mellom hovedsamtalen og spesialisert underagentarbeid. + +--- + +## Konfigurasjon + +Du kan tilpasse de innebygde agentene eller lage dine egne gjennom konfigurasjon. Agenter kan konfigureres på to måter: + +--- + +### JSON + +Konfigurer agenter i konfigurasjonsfilen `opencode.json`: + +```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 + +Du kan også definere agenter ved å bruke markdown-filer. Plasser dem i: + +- Globalt: `~/.config/opencode/agents/` +- Per prosjekt: `.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-filnavnet blir agentnavnet. For eksempel oppretter `review.md` en `review`-agent. + +--- + +## Alternativer + +La oss se på disse konfigurasjonsalternativene i detalj. + +--- + +### Beskrivelse + +Bruk alternativet `description` for å gi en kort beskrivelse av hva agenten gjør og når den skal brukes. + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +Dette er et **obligatorisk** konfigurasjonsalternativ. + +--- + +### Temperatur + +Kontroller tilfeldigheten og kreativiteten til LLMs svar med `temperature`-konfigurasjonen. + +Lavere verdier gjør svarene mer fokuserte og deterministiske, mens høyere verdier øker kreativiteten og variasjonen. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Temperaturverdier varierer vanligvis fra 0,0 til 1,0: + +- **0.0-0.2**: Veldig fokuserte og deterministiske svar, ideell for kodeanalyse og planlegging +- **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" +{ + "agent": { + "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; typisk 0 for de fleste modeller, 0,55 for Qwen-modeller. + +--- + +### Maks trinn + +Kontroller det maksimale antallet agentiske iterasjoner en agent kan utføre før den blir tvunget til å svare kun med tekst. Dette lar brukere som ønsker å kontrollere kostnadene sette en grense for agenthandlinger. + +Hvis dette ikke er satt, vil agenten fortsette å iterere til modellen velger å stoppe eller brukeren avbryter økten. + +```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 + } + } +} +``` + +Når grensen er nådd, mottar agenten en spesiell systemmelding som instruerer den om å svare med en oppsummering av arbeidet og anbefalte gjenværende oppgaver. + +:::caution +Det gamle `maxSteps`-feltet er avviklet. Bruk `steps` i stedet. +::: + +--- + +### Deaktiver + +Sett til `true` for å deaktivere agenten. + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### Ledetekst + +Spesifiser en tilpasset systemmeldingsfil for denne agenten med `prompt`-konfigurasjonen. Ledetekstfilen skal inneholde instruksjoner som er spesifikke for agentens formål. + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Denne banen er i forhold til hvor konfigurasjonsfilen er plassert. Så dette fungerer for både den globale OpenCode-konfigurasjonen og den prosjektspesifikke konfigurasjonen. + +--- + +### Modell + +Bruk `model`-konfigurasjonen for å overstyre modellen for denne agenten. Nyttig for bruk av ulike modeller optimalisert for ulike oppgaver. For eksempel en raskere modell for planlegging, en mer kapabel modell for implementering. + +:::tip +Hvis du ikke spesifiserer en modell, bruker primæragenter [modell globalt konfigurert](/docs/config#models) mens subagenter vil bruke modellen til primæragenten som påkalte subagenten. +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +Modellen ID i OpenCode-konfigurasjonen din bruker formatet `provider/model-id`. For eksempel, hvis du bruker [OpenCode Zen](/docs/zen), vil du bruke `opencode/gpt-5.1-codex` for GPT 5.1 Codex. + +--- + +### Verktøy + +Kontroller hvilke verktøy som er tilgjengelige i denne agenten med `tools`-konfigurasjonen. Du kan aktivere eller deaktivere spesifikke verktøy ved å sette dem til `true` eller `false`. + +```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 +Den agentspesifikke konfigurasjonen overstyrer den globale konfigurasjonen. +::: + +Du kan også bruke jokertegn for å kontrollere flere verktøy samtidig. For eksempel, for å deaktivere alle verktøy fra en MCP-server: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[Finn ut mer om verktøy](/docs/tools). + +--- + +### Tillatelser + +Du kan konfigurere tillatelser for å administrere hvilke handlinger en agent kan utføre. For øyeblikket kan tillatelsene for verktøyene `edit`, `bash` og `webfetch` konfigureres til: + +- `"ask"` — Be om godkjenning før du kjører verktøyet +- `"allow"` — Tillat alle operasjoner uten godkjenning +- `"deny"` — Deaktiver verktøyet + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +Du kan overstyre disse tillatelsene per agent. + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +Du kan også angi tillatelser i Markdown-agenter. + +```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. +``` + +Du kan angi tillatelser for spesifikke bash-kommandoer. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +Dette kan ta et globmønster. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +Og du kan også bruke jokertegnet `*` for å administrere tillatelser for alle kommandoer. +Siden den siste samsvarsregelen har forrang, setter du jokertegnet `*` først og spesifikke regler etter. + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[Finn ut mer om tillatelser](/docs/permissions). + +--- + +### Modus + +Kontroller agentens modus med `mode`-konfigurasjonen. Alternativet `mode` brukes til å bestemme hvordan agenten kan brukes. + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +Alternativet `mode` kan settes til `primary`, `subagent` eller `all`. Hvis ingen `mode` er spesifisert, er den standard til `all`. + +--- + +### Skjult + +Skjul en underagent fra `@` autofullføringsmenyen med `hidden: true`. Nyttig for interne underagenter som bare skal påkalles programmatisk av andre agenter via oppgaveverktøyet. + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +Dette påvirker kun brukersynlighet i autofullfør-menyen. Skjulte agenter kan fortsatt påkalles av modellen via oppgaveverktøyet hvis tillatelser tillater det. + +:::note +Gjelder kun `mode: subagent`-agenter. +::: + +--- + +### Oppgavetillatelser + +Kontroller hvilke subagenter en agent kan påkalle via oppgaveverktøyet med `permission.task`. Bruker glob-mønstre for fleksibel matching. + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +Når den er satt til `deny`, fjernes subagenten fullstendig fra oppgaveverktøybeskrivelsen, så modellen vil ikke forsøke å starte den. + +:::tip +Reglene evalueres i rekkefølge, og den **siste samsvarsregelen vinner**. I eksemplet ovenfor samsvarer `orchestrator-planner` med både `*` (avslå) og `orchestrator-*` (tillat), men siden `orchestrator-*` kommer etter `*`, er resultatet `allow`. +::: + +:::tip +Brukere kan alltid starte en hvilken som helst underagent direkte via `@` autofullføringsmenyen, selv om agentens oppgavetillatelser ville nekte det. +::: + +--- + +### Farge + +Tilpass agentens visuelle utseende i UI med alternativet `color`. Dette påvirker hvordan agenten vises i grensesnittet. + +Bruk en gyldig sekskantfarge (f.eks. `#FF5733`) eller temafarge: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +Kontroller responsmangfoldet med alternativet `top_p`. Alternativ til temperatur for å kontrollere tilfeldighet. + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +Verdiene varierer fra 0,0 til 1,0. Lavere verdier er mer fokuserte, høyere verdier mer mangfoldige. + +--- + +### Ekstra + +Eventuelle andre alternativer du spesifiserer i agentkonfigurasjonen vil bli **overført direkte** til leverandøren som modellalternativer. Dette lar deg bruke leverandørspesifikke funksjoner og parametere. + +For eksempel, med OpenAIs resonneringsmodeller kan du kontrollere resonnementinnsatsen: + +```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" + } + } +} +``` + +Disse tilleggsalternativene er modell- og leverandørspesifikke. Sjekk leverandørens dokumentasjon for tilgjengelige parametere. + +:::tip +Kjør `opencode models` for å se en liste over tilgjengelige modeller. +::: + +--- + +## Opprette agenter + +Du kan opprette nye agenter ved å bruke følgende kommando: + +```bash +opencode agent create +``` + +Denne interaktive kommandoen vil: + +1. Spør hvor du skal lagre agenten; global eller prosjektspesifikk. +2. Beskrivelse av hva agenten skal gjøre. +3. Generer en passende systemmelding og identifikator. +4. La deg velge hvilke verktøy agenten har tilgang til. +5. Lag til slutt en nedmerkingsfil med agentkonfigurasjonen. + +--- + +## Bruksområder + +Her er noen vanlige bruksområder for forskjellige agenter. + +- **Byggagent**: Fullstendig utviklingsarbeid med alle verktøy aktivert +- **Planagent**: Analyse og planlegging uten å gjøre endringer +- **Kodevurderingsagent**: Kodegjennomgang med skrivebeskyttet tilgang pluss dokumentasjonsverktøy +- **Feilsøkingsagent**: Fokusert på etterforskning med bash og leseverktøy aktivert +- **Dokumentasjonsagent**: Dokumentasjonsskriving med filoperasjoner, men ingen systemkommandoer + +--- + +## Eksempler + +Her er noen eksempler på agenter du kan finne nyttige. + +:::tip +Har du en agent du vil dele? [Send inn en PR](https://github.com/anomalyco/opencode). +::: + +--- + +### Dokumentasjonsagent + +```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 +``` + +--- + +### Sikkerhetsrevisor + +```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/nb/cli.mdx b/packages/web/src/content/docs/nb/cli.mdx new file mode 100644 index 00000000000..2f1b3884ea0 --- /dev/null +++ b/packages/web/src/content/docs/nb/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: OpenCode CLI-alternativer og kommandoer. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode CLI starter som standard [TUI](/docs/tui) når den kjøres uten noen argumenter. + +```bash +opencode +``` + +Men den godtar også kommandoer som dokumentert på denne siden. Dette lar deg samhandle med OpenCode programmatisk. + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +Start OpenCode-terminalbrukergrensesnittet. + +```bash +opencode [project] +``` + +#### Flagg + +| Flagg | Kort | Beskrivelse | +| ------------ | ---- | ------------------------------------------------------------------------ | +| `--continue` | `-c` | Fortsett siste økt | +| `--session` | `-s` | Økt ID for å fortsette | +| `--fork` | | Forgren økten ved fortsettelse (bruk med `--continue` eller `--session`) | +| `--prompt` | | Ledetekst som skal brukes | +| `--model` | `-m` | Modell å bruke i form av leverandør/modell | +| `--agent` | | Agent som skal brukes | +| `--port` | | Port å lytte på | +| `--hostname` | | Vertsnavn å lytte på | + +--- + +## Kommandoer + +OpenCode CLI har også følgende kommandoer. + +--- + +### agent + +Administrer agenter for OpenCode. + +```bash +opencode agent [command] +``` + +--- + +### attach + +Koble en terminal til en allerede kjørende OpenCode-backend-server startet via `serve` eller `web` kommandoer. + +```bash +opencode attach [url] +``` + +Dette gjør det mulig å bruke TUI med en ekstern OpenCode-backend. For eksempel: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### Flagg + +| Flagg | Kort | Beskrivelse | +| ----------- | ---- | --------------------------------- | +| `--dir` | | Arbeidskatalog for å starte TUI i | +| `--session` | `-s` | Økt ID for å fortsette | + +--- + +#### create + +Opprett en ny agent med tilpasset konfigurasjon. + +```bash +opencode agent create +``` + +Denne kommandoen vil veilede deg gjennom å lage en ny agent med en tilpasset systemmelding og verktøykonfigurasjon. + +--- + +#### list + +List opp alle tilgjengelige agenter. + +```bash +opencode agent list +``` + +--- + +### auth + +Kommando for administrasjon av påloggingsinformasjon og innlogging for leverandører. + +```bash +opencode auth [command] +``` + +--- + +#### login + +OpenCode drives av leverandørlisten på [Models.dev](https://models.dev), så du kan bruke `opencode auth login` til å konfigurere API-nøkler for enhver leverandør du vil bruke. Dette er lagret i `~/.local/share/opencode/auth.json`. + +```bash +opencode auth login +``` + +Når OpenCode starter opp, laster den leverandørene fra filen med påloggingsinformasjon. Og hvis det er noen nøkler definert i miljøene dine eller en `.env`-fil i prosjektet ditt. + +--- + +#### list + +Viser alle de autentiserte leverandørene som er lagret i filen med påloggingsinformasjon. + +```bash +opencode auth list +``` + +Eller bruk kortversjonen. + +```bash +opencode auth ls +``` + +--- + +#### logout + +Logger deg ut av en leverandør ved å fjerne den fra filen med påloggingsinformasjon. + +```bash +opencode auth logout +``` + +--- + +### github + +Administrer GitHub-agenten for depotautomatisering. + +```bash +opencode github [command] +``` + +--- + +#### install + +Installer GitHub-agenten i depotet ditt. + +```bash +opencode github install +``` + +Dette setter opp den nødvendige GitHub Actions-arbeidsflyten og veileder deg gjennom konfigurasjonsprosessen. [Finn ut mer](/docs/github). + +--- + +#### run + +Kjør GitHub-agenten. Dette brukes vanligvis i GitHub Actions. + +```bash +opencode github run +``` + +##### Flagg + +| Flagg | Beskrivelse | +| --------- | -------------------------------------------- | +| `--event` | GitHub mock-hendelse agenten skal kjøres for | +| `--token` | GitHub personlig tilgangsnøkkel | + +--- + +### mcp + +Administrer Model Context Protocol-servere. + +```bash +opencode mcp [command] +``` + +--- + +#### add + +Legg til en MCP-server til konfigurasjonen. + +```bash +opencode mcp add +``` + +Denne kommandoen vil veilede deg gjennom å legge til enten en lokal eller ekstern MCP-server. + +--- + +#### list + +Liste alle konfigurerte MCP-servere og deres tilkoblingsstatus. + +```bash +opencode mcp list +``` + +Eller bruk den korte versjonen. + +```bash +opencode mcp ls +``` + +--- + +#### auth + +Autentiser med en OAuth-aktivert MCP-server. + +```bash +opencode mcp auth [name] +``` + +Hvis du ikke oppgir et servernavn, blir du bedt om å velge blant tilgjengelige OAuth-kompatible servere. + +Du kan også liste opp OAuth-kompatible servere og deres autentiseringsstatus. + +```bash +opencode mcp auth list +``` + +Eller bruk den korte versjonen. + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +Fjern OAuth-påloggingsinformasjon for en MCP-server. + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +Feilsøk OAuth-tilkoblingsproblemer for en MCP-server. + +```bash +opencode mcp debug +``` + +--- + +### models + +List opp alle tilgjengelige modeller fra konfigurerte leverandører. + +```bash +opencode models [provider] +``` + +Denne kommandoen viser alle modeller som er tilgjengelige på tvers av dine konfigurerte leverandører i formatet `provider/model`. + +Dette er nyttig for å finne ut det eksakte modellnavnet som skal brukes i [din konfigurasjon](/docs/config/). + +Du kan eventuelt sende en leverandør ID for å filtrere modeller etter den leverandøren. + +```bash +opencode models anthropic +``` + +#### Flagg + +| Flagg | Beskrivelse | +| ----------- | ------------------------------------------------------------------- | +| `--refresh` | Oppdater modellbufferen fra models.dev | +| `--verbose` | Bruk mer detaljert modellutdata (inkluderer metadata som kostnader) | + +Bruk `--refresh`-flagget for å oppdatere den bufrede modelllisten. Dette er nyttig når nye modeller er lagt til en leverandør og du vil se dem i OpenCode. + +```bash +opencode models --refresh +``` + +--- + +### run + +Kjør OpenCode i ikke-interaktiv modus ved å sende en melding direkte. + +```bash +opencode run [message..] +``` + +Dette er nyttig for skripting, automatisering eller når du vil ha et raskt svar uten å starte hele TUI. For eksempel. + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +Du kan også koble til en kjørende `opencode serve`-forekomst for å unngå MCP-serveres kaldstarttid ved hver kjøring: + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### Flagg + +| Flagg | Kort | Beskrivelse | +| ------------ | ---- | ------------------------------------------------------------------------ | +| `--command` | | Kommandoen for å kjøre, bruk melding for args | +| `--continue` | `-c` | Fortsett siste økt | +| `--session` | `-s` | Økt ID for å fortsette | +| `--fork` | | Forgren økten ved fortsettelse (bruk med `--continue` eller `--session`) | +| `--share` | | Del økten | +| `--model` | `-m` | Modell å bruke i form av leverandør/modell | +| `--agent` | | Agent å bruke | +| `--file` | `-f` | Fil(er) som skal legges ved meldingen | +| `--format` | | Format: standard (formatert) eller json (rå JSON hendelser) | +| `--title` | | Tittel for økten (bruker avkortet ledetekst hvis ingen verdi er oppgitt) | +| `--attach` | | Koble til en kjørende OpenCode-server (f.eks. http://localhost:4096) | +| `--port` | | Port for den lokale serveren (standard til tilfeldig port) | + +--- + +### serve + +Start en headless OpenCode-server for API-tilgang. Sjekk ut [server-dokumentene](/docs/server) for hele HTTP-grensesnittet. + +```bash +opencode serve +``` + +Dette starter en HTTP-server som gir API tilgang til OpenCode-funksjonalitet uten TUI-grensesnittet. Sett `OPENCODE_SERVER_PASSWORD` for å aktivere HTTP grunnleggende autentisering (brukernavn er standard til `opencode`). + +#### Flagg + +| Flagg | Beskrivelse | +| ------------ | -------------------------------------------------- | +| `--port` | Port å lytte på | +| `--hostname` | Vertsnavn å lytte på | +| `--mdns` | Aktiver mDNS-oppdagelse | +| `--cors` | Ytterligere nettleseropprinnelse som tillater CORS | + +--- + +### session + +Administrer OpenCode-økter. + +```bash +opencode session [command] +``` + +--- + +#### list + +List opp alle OpenCode-økter. + +```bash +opencode session list +``` + +##### Flagg + +| Flagg | Kort | Beskrivelse | +| ------------- | ---- | ---------------------------------------- | +| `--max-count` | `-n` | Begrens til N siste økter | +| `--format` | | Utdataformat: tabell eller json (tabell) | + +--- + +### stats + +Vis tokenbruk og kostnadsstatistikk for OpenCode-øktene dine. + +```bash +opencode stats +``` + +#### Flagg + +| Flagg | Beskrivelse | +| ----------- | -------------------------------------------------------------------------------- | +| `--days` | Vis statistikk for de siste N dagene (hele tiden) | +| `--tools` | Antall verktøy som skal vises (alle) | +| `--models` | Vis oversikt over modellbruk (skjult som standard). Gi et tall for å vise topp N | +| `--project` | Filtrer etter prosjekt (alle prosjekter, tom streng: gjeldende prosjekt) | + +--- + +### export + +Eksporter øktdata som JSON. + +```bash +opencode export [sessionID] +``` + +Hvis du ikke gir en økt ID, blir du bedt om å velge fra tilgjengelige økter. + +--- + +### import + +Importer øktdata fra en JSON-fil eller en OpenCode share-URL. + +```bash +opencode import +``` + +Du kan importere fra en lokal fil eller en OpenCode share-URL. + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +Start en headless OpenCode-server med et webgrensesnitt. + +```bash +opencode web +``` + +Dette starter en HTTP-server og åpner en nettleser for å få tilgang til OpenCode via et nettgrensesnitt. Sett `OPENCODE_SERVER_PASSWORD` for å aktivere HTTP grunnleggende autentisering (brukernavn er standard til `opencode`). + +#### Flagg + +| Flagg | Beskrivelse | +| ------------ | -------------------------------------------------- | +| `--port` | Port å lytte på | +| `--hostname` | Vertsnavn å lytte på | +| `--mdns` | Aktiver mDNS-oppdagelse | +| `--cors` | Ytterligere nettleseropprinnelse som tillater CORS | + +--- + +### acp + +Start en ACP (Agent Client Protocol) server. + +```bash +opencode acp +``` + +Denne kommandoen starter en ACP-server som kommuniserer via stdin/stdout ved å bruke nd-JSON. + +#### Flagg + +| Flagg | Beskrivelse | +| ------------ | -------------------- | +| `--cwd` | Arbeidskatalog | +| `--port` | Port å lytte på | +| `--hostname` | Vertsnavn å lytte på | + +--- + +### uninstall + +Avinstaller OpenCode og fjern alle relaterte filer. + +```bash +opencode uninstall +``` + +#### Flagg + +| Flagg | Kort | Beskrivelse | +| --------------- | ---- | --------------------------------------------- | +| `--keep-config` | `-c` | Behold konfigurasjonsfiler | +| `--keep-data` | `-d` | Behold øktdata og øyeblikksbilder | +| `--dry-run` | | Vis hva som ville blitt fjernet uten å fjerne | +| `--force` | `-f` | Hopp over bekreftelsesforespørsler | + +--- + +### upgrade + +Oppdaterer OpenCode til siste versjon eller en spesifikk versjon. + +```bash +opencode upgrade [target] +``` + +For å oppgradere til siste versjon. + +```bash +opencode upgrade +``` + +For å oppgradere til en bestemt versjon. + +```bash +opencode upgrade v0.1.48 +``` + +#### Flagg + +| Flagg | Kort | Beskrivelse | +| ---------- | ---- | -------------------------------------------------------------- | +| `--method` | `-m` | Installasjonsmetoden som ble brukt: curl, npm, pnpm, bun, brew | + +--- + +## Globale flagg + +OpenCode CLI bruker følgende globale flagg. + +| Flagg | Kort | Beskrivelse | +| -------------- | ---- | ----------------------------------- | +| `--help` | `-h` | Vis hjelp | +| `--version` | `-v` | Skriv ut versjonsnummer | +| `--print-logs` | | Skriv ut logger til stderr | +| `--log-level` | | Loggnivå (DEBUG, INFO, WARN, ERROR) | + +--- + +## Miljøvariabler + +OpenCode kan konfigureres ved hjelp av miljøvariabler. + +| Variabel | Type | Beskrivelse | +| ------------------------------------- | ------ | --------------------------------------------------------------------- | +| `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_CONFIG_DIR` | streng | Bane til konfigurasjonskatalog | +| `OPENCODE_CONFIG_CONTENT` | streng | Innebygd json-konfigurasjonsinnhold | +| `OPENCODE_DISABLE_AUTOUPDATE` | boolsk | Deaktiver automatiske oppdateringskontroller | +| `OPENCODE_DISABLE_PRUNE` | boolsk | Deaktiver beskjæring av gamle data | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolsk | Deaktiver automatiske terminaltitteloppdateringer | +| `OPENCODE_PERMISSION` | streng | Innebygd json-tillatelseskonfigurasjon | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolsk | Deaktiver standard plugins | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolsk | Deaktiver automatiske LSP servernedlastinger | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolsk | Aktiver eksperimentelle modeller | +| `OPENCODE_DISABLE_AUTOCOMPACT` | boolsk | Deaktiver automatisk kontekstkomprimering | +| `OPENCODE_DISABLE_CLAUDE_CODE` | boolsk | Deaktiver lesing fra `.claude` (spørsmål + ferdigheter) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolsk | Deaktiver lesing `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolsk | Deaktiver innlasting av `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | boolsk | Deaktiver henting av modeller fra eksterne kilder | +| `OPENCODE_FAKE_VCS` | streng | Falsk VCS-leverandør for testformål | +| `OPENCODE_DISABLE_FILETIME_CHECK` | boolsk | Deaktiver filtidskontroll for optimalisering | +| `OPENCODE_CLIENT` | streng | Klientidentifikator (standard til `cli`) | +| `OPENCODE_ENABLE_EXA` | boolsk | Aktiver Exa-nettsøkeverktøy | +| `OPENCODE_SERVER_PASSWORD` | streng | Aktiver grunnleggende autentisering for `serve`/`web` | +| `OPENCODE_SERVER_USERNAME` | streng | Overstyr grunnleggende autentiseringsbrukernavn (standard `opencode`) | +| `OPENCODE_MODELS_URL` | streng | Egendefinert URL for henting av modellkonfigurasjon | + +--- + +### Eksperimentelt + +Disse miljøvariablene muliggjør eksperimentelle funksjoner som kan endres eller fjernes. + +| Variabel | Type | Beskrivelse | +| ----------------------------------------------- | ------ | --------------------------------------------- | +| `OPENCODE_EXPERIMENTAL` | boolsk | Aktiver alle eksperimentelle funksjoner | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolsk | Aktiver ikonoppdagelse | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolsk | Deaktiver kopi ved valg i TUI | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | tall | Standard tidsavbrudd for bash-kommandoer i ms | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | tall | Maks Output Tokens for LLM-svar | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolsk | Aktiver filovervåker for hele dir | +| `OPENCODE_EXPERIMENTAL_OXFMT` | boolsk | Aktiver oxfmt formatter | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolsk | Aktiver eksperimentelt LSP-verktøy | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolsk | Deaktiver filovervåking | +| `OPENCODE_EXPERIMENTAL_EXA` | boolsk | Aktiver eksperimentelle Exa-funksjoner | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolsk | Aktiver eksperimentell LSP-typekontroll | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolsk | Aktiver eksperimentelle Markdown-funksjoner | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolsk | Aktiver planmodus | diff --git a/packages/web/src/content/docs/nb/commands.mdx b/packages/web/src/content/docs/nb/commands.mdx new file mode 100644 index 00000000000..b4bf8f09f37 --- /dev/null +++ b/packages/web/src/content/docs/nb/commands.mdx @@ -0,0 +1,323 @@ +--- +title: Kommandoer +description: Lag egendefinerte kommandoer for repeterende oppgaver. +--- + +Egendefinerte kommandoer lar deg spesifisere en ledetekst du vil kjøre når kommandoen utføres i TUI. + +```bash frame="none" +/my-command +``` + +Egendefinerte kommandoer kommer i tillegg til de innebygde kommandoene som `/init`, `/undo`, `/redo`, `/share`, `/help`. [Finn ut mer](/docs/tui#commands). + +--- + +## Lag kommandofiler + +Lag nedmerkingsfiler i `commands/`-katalogen for å definere egendefinerte kommandoer. + +Opprett `.opencode/commands/test.md`: + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Frontmatter definerer kommandoegenskaper. Innholdet blir malen. + +Bruk kommandoen ved å skrive `/` etterfulgt av kommandonavnet. + +```bash frame="none" +"/test" +``` + +--- + +## Konfigurasjon + +Du kan legge til egendefinerte kommandoer gjennom OpenCode-konfigurasjonen eller ved å lage markdown-filer i katalogen `commands/`. + +--- + +### JSON + +Bruk alternativet `command` i OpenCode [config](/docs/config): + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Nå kan du kjøre denne kommandoen i TUI: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +Du kan også definere kommandoer ved å bruke markdown-filer. Plasser dem i: + +- Globalt: `~/.config/opencode/commands/` +- Per prosjekt: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Markdown-filnavnet blir kommandonavnet. For eksempel lar `test.md` +deg kjøre: + +```bash frame="none" +/test +``` + +--- + +## Ledetekstkonfigurasjon + +Ledetekstene for de egendefinerte kommandoene støtter flere spesielle plassholdere og syntaks. + +--- + +### Argumenter + +Send argumenter til kommandoer ved å bruke plassholderen `$ARGUMENTS`. + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +Kjør kommandoen med argumenter: + +```bash frame="none" +/component Button +``` + +Og `$ARGUMENTS` vil bli erstattet med `Button`. + +Du kan også få tilgang til individuelle argumenter ved å bruke posisjonelle parametere: + +- `$1` - Første argument +- `$2` - Andre argument +- `$3` - Tredje argument +- Og så videre... + +For eksempel: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +Kjør kommandoen: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +Dette erstatter: + +- `$1` med `config.json` +- `$2` med `src` +- `$3` med `{ "key": "value" }` + +--- + +### Shell-utdata + +Bruk _!`command`_ for å injisere [bash-kommando](/docs/tui#bash-commands)-utdata i ledeteksten. + +For eksempel, for å lage en egendefinert kommando som analyserer testdekning: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +Eller for å se gjennom nylige endringer: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +Kommandoer kjøres i prosjektets rotkatalog og utdataene deres blir en del av ledeteksten. + +--- + +### Filreferanser + +Inkluder filer i kommandoen din ved å bruke `@` etterfulgt av filnavnet. + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +Filinnholdet blir automatisk inkludert i ledeteksten. + +--- + +## Alternativer + +La oss se på konfigurasjonsalternativene i detalj. + +--- + +### Mal + +Alternativet `template` definerer ledeteksten som vil bli sendt til LLM når kommandoen utføres. + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +Dette er et **obligatorisk** konfigurasjonsalternativ. + +--- + +### Beskrivelse + +Bruk alternativet `description` for å gi en kort beskrivelse av hva kommandoen gjør. + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +Dette vises som beskrivelsen i TUI når du skriver inn kommandoen. + +--- + +### Agent + +Bruk `agent`-konfigurasjonen for å spesifisere hvilken [agent](/docs/agents) som skal utføre denne kommandoen. +Hvis dette er en [subagent](/docs/agents/#subagents), vil kommandoen utløse en subagent påkalling som standard. +For å deaktivere denne virkemåten, sett `subtask` til `false`. + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +Denne kommandoen vil veilede deg gjennom å lage en ny agent med en tilpasset systemmelding og verktøykonfigurasjon. + +--- + +### Underoppgave + +Bruk `subtask` for å tvinge kommandoen til å utløse en [subagent](/docs/agents/#subagents) påkalling. +Dette er nyttig hvis du vil at kommandoen ikke skal forurense din primære kontekst og vil **tvinge** agenten til å fungere som en underagent, +selv om `mode` er satt til `primary` på [agent](/docs/agents) konfigurasjonen. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +Dette er et **valgfritt** konfigurasjonsalternativ. + +--- + +### Modell + +Bruk `model`-konfigurasjonen for å overstyre standardmodellen for denne kommandoen. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Dette er et **valgfritt** konfigurasjonsalternativ. + +--- + +## Innebygd + +OpenCode inkluderer flere innebygde kommandoer som `/init`, `/undo`, `/redo`, `/share`, `/help`; [finn ut mer](/docs/tui#commands). + +:::note +Egendefinerte kommandoer kan overstyre innebygde kommandoer. +::: + +Hvis du definerer en egendefinert kommando med samme navn, vil den overstyre den innebygde kommandoen. diff --git a/packages/web/src/content/docs/nb/config.mdx b/packages/web/src/content/docs/nb/config.mdx new file mode 100644 index 00000000000..8f54335794c --- /dev/null +++ b/packages/web/src/content/docs/nb/config.mdx @@ -0,0 +1,685 @@ +--- +title: Konfigurasjon +description: Ved å bruke opencode JSON-konfigurasjonen. +--- + +Du kan konfigurere OpenCode ved å bruke en JSON konfigurasjonsfil. + +--- + +## Format + +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, +} +``` + +--- + +## Plasseringer + +Du kan plassere konfigurasjonen på et par forskjellige steder, og de har en +annen rekkefølge. + +:::note +Konfigurasjonsfiler er **slått sammen**, ikke erstattet. +::: + +Konfigurasjonsfiler slås sammen, ikke erstattes. Innstillinger fra følgende konfigurasjonsplasseringer kombineres. Senere konfigurasjoner overstyrer tidligere kun for motstridende nøkler. Ikke-motstridende innstillinger fra alle konfigurasjoner er bevart. + +For eksempel, hvis din globale konfigurasjon setter `theme: "opencode"` og `autoupdate: true`, og prosjektkonfigurasjonen setter `model: "anthropic/claude-sonnet-4-5"`, vil den endelige konfigurasjonen inkludere alle tre innstillingene. + +--- + +### Prioritetsrekkefølge + +Konfigurasjonskilder lastes inn i denne rekkefølgen (senere kilder overstyrer tidligere): + +1. **Ekstern konfigurasjon** (fra `.well-known/opencode`) - organisasjonsstandarder +2. **Global konfigurasjon** (`~/.config/opencode/opencode.json`) - brukerinnstillinger +3. **Egendefinert konfigurasjon** (`OPENCODE_CONFIG` env var) - egendefinerte overstyringer +4. **Prosjektkonfigurasjon** (`opencode.json` i prosjekt) - prosjektspesifikke innstillinger +5. **`.opencode` kataloger** - agenter, kommandoer, plugins +6. **Inline config** (`OPENCODE_CONFIG_CONTENT` env var) - kjøretidsoverstyringer + +Dette betyr at prosjektkonfigurasjoner kan overstyre globale standardinnstillinger, og globale konfigurasjoner kan overstyre eksterne organisasjonsstandarder. + +:::note +`.opencode` og `~/.config/opencode` katalogene bruker **flertallsnavn** på underkataloger: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/` og `themes/`. Enkeltnavn (f.eks. `agent/`) støttes også for bakoverkompatibilitet. +::: + +--- + +### Ekstern konfigurasjon + +Organisasjoner kan tilby standardkonfigurasjon via `.well-known/opencode`-endepunktet. Dette hentes automatisk når du autentiserer med en leverandør som støtter det. + +Ekstern konfigurasjon lastes først, og fungerer som grunnlaget. Alle andre konfigurasjonskilder (global, prosjekt) kan overstyre disse standardinnstillingene. + +For eksempel, hvis organisasjonen din tilbyr MCP servere som er deaktivert som standard: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +Du kan aktivere spesifikke servere i din lokale konfigurasjon: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### Global konfigurasjon + +Plasser din globale OpenCode-konfigurasjon i `~/.config/opencode/opencode.json`. Bruk global konfigurasjon for brukerspesifikke preferanser som temaer, leverandører eller nøkkelbindinger. + +Global konfigurasjon overstyrer eksterne organisasjonsstandarder. + +--- + +### Per prosjekt + +Legg til `opencode.json` i prosjektroten din. Prosjektkonfigurasjon har den høyeste prioritet blant standard config-filer - den overstyrer både globale og eksterne konfigurasjoner. + +:::tip +Plasser prosjektspesifikk konfigurasjon i roten til prosjektet ditt. +::: + +Når OpenCode starter opp, ser den etter en konfigurasjonsfil i gjeldende katalog eller går opp til nærmeste Git-katalog. + +Det er også trygt å sjekke inn dette i Git og bruker samme skjema som det globale. + +--- + +### Egendefinert bane + +Spesifiser en tilpasset konfigurasjonsfilbane ved å bruke miljøvariabelen `OPENCODE_CONFIG`. + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +Egendefinert konfigurasjon lastes inn mellom globale og prosjektkonfigurasjoner i prioritetsrekkefølge. + +--- + +### Egendefinert katalog + +Spesifiser en tilpasset konfigurasjonskatalog ved å bruke `OPENCODE_CONFIG_DIR` +miljøvariabel. Denne katalogen vil bli søkt etter agenter, kommandoer, +moduser og plugins akkurat som standard `.opencode` katalog, og bør +følge samme struktur. + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +Den egendefinerte katalogen lastes inn etter den globale konfigurasjonen og `.opencode`-katalogene, slik at den **kan overstyre** innstillingene deres. + +--- + +## Skjema + +Konfigurasjonsfilen har et skjema som er definert i [**`opencode.ai/config.json`**](https://opencode.ai/config.json). + +Redaktøren din skal kunne validere og autofullføre basert på skjemaet. + +--- + +### TUI + +Du kan konfigurere TUI-spesifikke innstillinger gjennom alternativet `tui`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +Tilgjengelige alternativer: + +- `scroll_acceleration.enabled` - Aktiver rulleakselerasjon i macOS-stil. **Tar forrang over `scroll_speed`.** +- `scroll_speed` - Egendefinert rullehastighetsmultiplikator (standard: `3`, minimum: `1`). Ignorert hvis `scroll_acceleration.enabled` er `true`. +- `diff_style` - Kontroller diff-gjengivelse. `"auto"` tilpasser seg terminalbredden, `"stacked"` viser alltid en kolonne. + +[Les mer om bruk av TUI her](/docs/tui). + +--- + +### Tjener + +Du kan konfigurere serverinnstillinger for kommandoene `opencode serve` og `opencode web` gjennom alternativet `server`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +Tilgjengelige alternativer: + +- `port` - Port å lytte på. +- `hostname` - Vertsnavn å lytte på. Når `mdns` er aktivert og ingen vertsnavn er angitt, er standard `0.0.0.0`. +- `mdns` - Aktiver mDNS-tjenesteoppdagelse. Dette lar andre enheter på nettverket oppdage OpenCode-serveren din. +- `mdnsDomain` - Egendefinert domenenavn for mDNS-tjeneste. Standard er `opencode.local`. Nyttig for å kjøre flere forekomster på samme nettverk. +- `cors` - Ytterligere opprinnelser for å tillate CORS når du bruker HTTP-serveren fra en nettleserbasert klient. Verdiene må være fullstendige opprinnelser (skjema + vert + valgfri port), f.eks. `https://app.example.com`. + +[Les mer om serveren her](/docs/server). + +--- + +### Verktøy + +Du kan administrere verktøyene en LLM kan bruke gjennom alternativet `tools`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[Les mer om verktøy her](/docs/tools). + +--- + +### Modeller + +Du kan konfigurere leverandørene og modellene du vil bruke i OpenCode-konfigurasjonen gjennom alternativene `provider`, `model` og `small_model`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +Alternativet `small_model` konfigurerer en egen modell for lette oppgaver som tittelgenerering. Som standard prøver OpenCode å bruke en rimeligere modell hvis en er tilgjengelig fra leverandøren din, ellers faller den tilbake til hovedmodellen din. + +Leverandøralternativer kan inkludere `timeout` og `setCacheKey`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` - Tidsavbrudd for forespørsler i millisekunder (standard: 300 000). Sett til `false` for å deaktivere. +- `setCacheKey` - Sørg for at en hurtigbuffernøkkel alltid settes for valgt leverandør. + +Du kan også konfigurere [lokale modeller](/docs/models#local). [Finn ut mer](/docs/models). + +--- + +#### Leverandørspesifikke alternativer + +Noen leverandører støtter flere konfigurasjonsalternativer utover de generiske innstillingene `timeout` og `apiKey`. + +##### Amazon Bedrock + +Amazon Bedrock støtter AWS-spesifikk konfigurasjon: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` - AWS-region for Bedrock (standard er `AWS_REGION` env var eller `us-east-1`) +- `profile` - AWS navngitt profil fra `~/.aws/credentials` (standard til `AWS_PROFILE` env var) +- `endpoint` - Egendefinert endepunkt URL for VPC endepunkter. Dette er et alias for det generiske `baseURL`-alternativet som bruker AWS-spesifikk terminologi. Hvis begge er spesifisert, har `endpoint` forrang. + +:::note +Bærer-tokens (`AWS_BEARER_TOKEN_BEDROCK` eller `/connect`) har forrang over profilbasert autentisering. Se [autentiseringsprioritet](/docs/providers#authentication-precedence) for detaljer. +::: + +[Les mer om konfigurasjon av Amazon Bedrock](/docs/providers#amazon-bedrock). + +--- + +### Temaer + +Du kan konfigurere temaet du vil bruke i OpenCode-konfigurasjonen gjennom alternativet `theme`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[Les mer her](/docs/themes). + +--- + +### Agenter + +Du kan konfigurere spesialiserte agenter for spesifikke oppgaver gjennom alternativet `agent`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +Du kan også definere agenter ved å bruke markdown-filer i `~/.config/opencode/agents/` eller `.opencode/agents/`. [Les mer her](/docs/agents). + +--- + +### Standardagent + +Du kan angi standard agent ved å bruke alternativet `default_agent`. Dette bestemmer hvilken agent som brukes når ingen er eksplisitt spesifisert. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +Standardagenten må være en primæragent (ikke en underagent). Dette kan være en innebygd agent som `"build"` eller `"plan"`, eller en [egendefinert agent](/docs/agents) du har definert. Hvis den angitte agenten ikke eksisterer eller er en subagent, vil OpenCode falle tilbake til `"build"` med en advarsel. + +Denne innstillingen gjelder for alle grensesnitt: TUI, CLI (`opencode run`), skrivebordsapp og GitHub Action. + +--- + +### Deling + +Du kan konfigurere [share](/docs/share)-funksjonen gjennom alternativet `share`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +Dette krever: + +- `"manual"` - Tillat manuell deling via kommandoer (standard) +- `"auto"` - Del nye samtaler automatisk +- `"disabled"` - Deaktiver deling helt + +Som standard er deling satt til manuell modus der du eksplisitt må dele samtaler ved å bruke kommandoen `/share`. + +--- + +### Kommandoer + +Du kan konfigurere egendefinerte kommandoer for repeterende oppgaver gjennom alternativet `command`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +Du kan også definere kommandoer ved å bruke markdown-filer i `~/.config/opencode/commands/` eller `.opencode/commands/`. [Les mer her](/docs/commands). + +--- + +### Tastebindinger + +Du kan tilpasse tastebindingene dine gjennom alternativet `keybinds`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[Les mer her](/docs/keybinds). + +--- + +### Autooppdatering + +OpenCode vil automatisk laste ned eventuelle nye oppdateringer når den starter opp. Du kan deaktivere dette med alternativet `autoupdate`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +Hvis du ikke vil ha oppdateringer, men ønsker å bli varslet når en ny versjon er tilgjengelig, sett `autoupdate` til `"notify"`. +Legg merke til at dette bare fungerer hvis det ikke ble installert med en pakkebehandling som Homebrew. + +--- + +### Formatere + +Du kan konfigurere kodeformatere gjennom alternativet `formatter`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[Les mer om formattere her](/docs/formatters). + +--- + +### Tillatelser + +Som standard **tillater OpenCode alle operasjoner** uten å kreve eksplisitt godkjenning. Du kan endre dette ved å bruke alternativet `permission`. + +Slik sikrer du at verktøyene `edit` og `bash` krever brukergodkjenning: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[Les mer om tillatelser her](/docs/permissions). + +--- + +### Komprimering + +Du kan styre kontekstkomprimering gjennom alternativet `compaction`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto` - Komprimer økten automatisk når konteksten er full (standard: `true`). +- `prune` - Fjern gamle verktøyutdata for å spare tokens (standard: `true`). + +--- + +### Filovervåker + +Du kan konfigurere ignoreringsmønstre for filovervåking gjennom alternativet `watcher`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +Mønstre følger glob-syntaks. Bruk dette for å ekskludere støyende kataloger fra filovervåking. + +--- + +### MCP servere + +Du kan konfigurere MCP-servere du vil bruke gjennom alternativet `mcp`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[Les mer her](/docs/mcp-servers). + +--- + +### Utvidelser + +[Plugins](/docs/plugins) utvider OpenCode med tilpassede verktøy, kroker og integrasjoner. + +Plasser plugin-filer i `.opencode/plugins/` eller `~/.config/opencode/plugins/`. Du kan også laste inn plugins fra npm gjennom alternativet `plugin`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[Les mer her](/docs/plugins). + +--- + +### Instruksjoner + +Du kan konfigurere instruksjoner for modellen du bruker gjennom alternativet `instructions`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Dette krever en liste med baner og globmønstre til instruksjonsfiler. [Les mer +om regler her](/docs/rules). + +--- + +### Deaktiverte leverandører + +Du kan deaktivere leverandører som lastes automatisk gjennom alternativet `disabled_providers`. Dette er nyttig når du vil forhindre at enkelte leverandører lastes inn selv om deres legitimasjon er tilgjengelig. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +`disabled_providers` har prioritet over `enabled_providers`. +::: + +Alternativet `disabled_providers` godtar en rekke leverandør-ID-er. Når en leverandør er deaktivert: + +- Den blir ikke lastet selv om miljøvariabler er angitt. +- Den vil ikke bli lastet inn selv om API-nøkler er konfigurert gjennom `/connect`-kommandoen. +- Leverandørens modeller vises ikke i modellvalglisten. + +--- + +### Aktiverte leverandører + +Du kan spesifisere en godkjenningsliste over leverandører gjennom alternativet `enabled_providers`. Når angitt, vil bare de angitte leverandørene være aktivert og alle andre vil bli ignorert. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +Dette er nyttig når du vil begrense OpenCode til kun å bruke spesifikke leverandører i stedet for å deaktivere dem én etter én. + +:::note +`disabled_providers` har prioritet over `enabled_providers`. +::: + +Hvis en leverandør vises i både `enabled_providers` og `disabled_providers`, har `disabled_providers` prioritet for bakoverkompatibilitet. + +--- + +### Eksperimentelt + +`experimental`-nøkkelen inneholder alternativer som er under aktiv utvikling. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +Eksperimentelle alternativer er ikke stabile. De kan endres eller fjernes uten varsel. +::: + +--- + +## Variabler + +Du kan bruke variabelerstatning i konfigurasjonsfilene dine for å referere til miljøvariabler og filinnhold. + +--- + +### Miljøvariabler + +Bruk `{env:VARIABLE_NAME}` for å erstatte miljøvariabler: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +Hvis miljøvariabelen ikke er angitt, vil den bli erstattet med en tom streng. + +--- + +### Filer + +Bruk `{file:path/to/file}` for å erstatte innholdet i en fil: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +Filbaner kan være: + +- I forhold til konfigurasjonsfilkatalogen +- Eller absolutte baner som begynner med `/` eller `~` + +Disse er nyttige for: + +- Oppbevaring av sensitive data som API-nøkler i separate filer. +- Inkludert store instruksjonsfiler uten å rote konfigurasjonen din. +- Deling av vanlige konfigurasjonsbiter på tvers av flere konfigurasjonsfiler. diff --git a/packages/web/src/content/docs/nb/custom-tools.mdx b/packages/web/src/content/docs/nb/custom-tools.mdx new file mode 100644 index 00000000000..0b88f750773 --- /dev/null +++ b/packages/web/src/content/docs/nb/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: Egendefinerte verktøy +description: Lag verktøy som LLM kan kalle inn OpenCode. +--- + +Egendefinerte verktøy er funksjoner du oppretter som LLM kan kalle under samtaler. De fungerer sammen med OpenCode sine [innebygde verktøy](/docs/tools) som `read`, `write` og `bash`. + +--- + +## Opprette et verktøy + +Verktøy er definert som **TypeScript**- eller **JavaScript**-filer. Verktøydefinisjonen kan imidlertid påkalle skript skrevet på **alle språk** - TypeScript eller JavaScript brukes bare for selve verktøydefinisjonen. + +--- + +### Plassering + +De kan defineres: + +- Lokalt ved å plassere dem i `.opencode/tools/`-katalogen til prosjektet ditt. +- Eller globalt, ved å plassere dem i `~/.config/opencode/tools/`. + +--- + +### Struktur + +Den enkleste måten å lage verktøy på er å bruke `tool()`-hjelperen som gir typesikkerhet og validering. + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +**filnavnet** blir **verktøynavnet**. Ovennevnte oppretter et `database`-verktøy. + +--- + +#### Flere verktøy per fil + +Du kan også eksportere flere verktøy fra en enkelt fil. Hver eksport blir **et separat verktøy** med navnet **`_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +Dette lager to verktøy: `math_add` og `math_multiply`. + +--- + +### Argumenter + +Du kan bruke `tool.schema`, som bare er [Zod](https://zod.dev), for å definere argumenttyper. + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +Du kan også importere [Zod](https://zod.dev) direkte og returnere et vanlig objekt: + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### Kontekst + +Verktøy mottar kontekst om gjeldende økt: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +Bruk `context.directory` for øktens arbeidskatalog. +Bruk `context.worktree` for git-arbeidstreet. + +--- + +## Eksempler + +### Skrive et verktøy i Python + +Du kan skrive verktøyene dine på hvilket som helst språk du vil. Her er et eksempel som legger til to tall ved hjelp av Python. + +Først lager du verktøyet som et Python-skript: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +Lag deretter verktøydefinisjonen som påkaller den: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +Her bruker vi [`Bun.$`](https://bun.com/docs/runtime/shell)-verktøyet for å kjøre Python-skriptet. diff --git a/packages/web/src/content/docs/nb/ecosystem.mdx b/packages/web/src/content/docs/nb/ecosystem.mdx new file mode 100644 index 00000000000..714a9ee95e1 --- /dev/null +++ b/packages/web/src/content/docs/nb/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: Økosystem +description: Prosjekter og integrasjoner bygget med OpenCode. +--- + +En samling fellesskapsprosjekter bygget på OpenCode. + +:::note +Vil du legge til ditt OpenCode-relaterte prosjekt til denne listen? Send inn en PR. +::: + +Du kan også sjekke ut [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) og [opencode.cafe](https://opencode.cafe), et fellesskap som samler økosystemet og fellesskapet. + +--- + +## Utvidelser + +| Navn | Beskrivelse | +| --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | Kjør OpenCode-økter automatisk i isolerte Daytona-sandkasser med git-synkronisering og live-forhåndsvisninger | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | Injiser automatisk Helicone-headers for forespørselsgruppering | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | Auto-injiser TypeScript/Svelte-typer i fillesninger med oppslagsverktøy | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | Bruk ChatGPT Plus/Pro-abonnementet ditt i stedet for API kreditter | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | Bruk din eksisterende Gemini-plan i stedet for API-fakturering | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | Bruk Antigravitys gratis modeller i stedet for API-fakturering | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Multi-branch devcontainer-isolasjon med grunne kloner og automatisk tildelte porter | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Google Antigravity OAuth-plugin, med støtte for Google Søk og mer robust API-håndtering | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Optimaliser bruken av token ved å beskjære utdaterte verktøy | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Legg til innebygd støtte for nettsøk for støttede leverandører med Googles kildebaserte stil | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Gjør det mulig for AI-agenter å kjøre bakgrunnsprosesser i en PTY, sende interaktiv inndata til dem. | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Instruksjoner for ikke-interaktive skallkommandoer - forhindrer heng ved TTY-avhengige operasjoner | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Spor OpenCode-bruk med Wakatime | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Rydd opp i markdown-tabeller produsert av LLMs | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | 10 ganger raskere koderedigering med Morph Fast Apply API og lazy-redigeringsmarkører | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Bakgrunnsagenter, forhåndsbygde LSP/AST/MCP verktøy, kurerte agenter, Claude Code-kompatibel | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | Skrivebordsvarsler og lydvarsler for OpenCode-økter | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Skrivebordsvarsler og lydvarsler for tillatelse, fullføring og feilhendelser | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | AI-drevet automatisk Zellij-sesjonsnavn basert på OpenCode-kontekst | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Tillat OpenCode-agenter å lazy-loade meldinger på forespørsel med ferdighetsoppdagelse og injeksjon | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Vedvarende minne på tvers av økter ved hjelp av Supermemory | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Interaktiv plangjennomgang med visuell merknad og privat/offline deling | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Utvid OpenCode /kommandoer til et kraftig orkestreringssystem med granulær flytkontroll | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | Planlegg gjentakende jobber ved hjelp av launchd (Mac) eller systemd (Linux) med cron-syntaks | +| [micode](https://github.com/vtemian/micode) | Strukturert brainstorm → Plan → Implementer arbeidsflyt med øktkontinuitet | +| [octto](https://github.com/vtemian/octto) | Interaktiv nettleser UI for AI idédugnad med flerspørsmålsskjemaer | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | Claude Bakgrunnsagenter i kodestil med asynkrondelegering og kontekstutholdenhet | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | Innfødte OS-varsler for OpenCode – vet når oppgaver fullføres | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | Medfølgende multi-agent orkestreringsrammeverk – 16 komponenter, én installasjon | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | Nullfriksjon git-arbeidstre for OpenCode | + +--- + +## Prosjekter + +| Navn | Beskrivelse | +| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- | +| [kimaki](https://github.com/remorses/kimaki) | Discord-bot for å kontrollere OpenCode-økter, bygget på SDK | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Neovim-plugin for editor-tilpassede meldinger, bygget på API | +| [portal](https://github.com/hosenur/portal) | Mobile-first web UI for OpenCode over Tailscale/VPN | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | Mal for å bygge OpenCode-plugins | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Neovim-grensesnitt for OpenCode - en terminalbasert AI-kodingsagent | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Vercel AI SDK leverandør for bruk av OpenCode via @opencode-ai/sdk | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | Web-/skrivebordsapp og VS Code-utvidelse for OpenCode | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Obsidian-plugin som bygger inn OpenCode i Obsidians UI | +| [OpenWork](https://github.com/different-ai/openwork) | Et åpen kildekode-alternativ til Claude Cowork, drevet av OpenCode | +| [ocx](https://github.com/kdcokenny/ocx) | OpenCode utvidelsesbehandler med bærbare, isolerte profiler. | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | Desktop, Web, Mobile og Remote Client App for OpenCode | + +--- + +## Agenter + +| Navn | Beskrivelse | +| ----------------------------------------------------------------- | --------------------------------------------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | Modulære AI agenter og kommandoer for strukturert utvikling | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | Konfigurasjoner, meldinger, agenter og plugins for forbedrede arbeidsflyter | diff --git a/packages/web/src/content/docs/nb/enterprise.mdx b/packages/web/src/content/docs/nb/enterprise.mdx new file mode 100644 index 00000000000..eef0d7e986a --- /dev/null +++ b/packages/web/src/content/docs/nb/enterprise.mdx @@ -0,0 +1,170 @@ +--- +title: Bedrift +description: Sikker bruk av opencode i din organisasjon. +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +OpenCode Enterprise er for organisasjoner som ønsker å sikre at deres kode og data aldri forlater deres infrastruktur. Den kan gjøre dette ved å bruke en sentralisert konfigurasjon som integreres med din SSO og interne AI gateway. + +:::note +OpenCode lagrer ingen av koden eller kontekstdataene dine. +::: + +For å komme i gang med OpenCode Enterprise: + +1. Gjør en prøveversjon internt med teamet ditt. +2. **Kontakt oss** for å diskutere priser og implementeringsalternativer. + +--- + +## Prøveversjon + +OpenCode er åpen kildekode og lagrer ingen av koden eller kontekstdataene dine, så utviklerne dine kan ganske enkelt [komme i gang](/docs/) og utføre en prøveversjon. + +--- + +### Datahåndtering + +**OpenCode lagrer ikke koden eller kontekstdataene dine.** All behandling skjer lokalt eller gjennom direkte API-anrop til AI-leverandøren din. + +Dette betyr at så lenge du bruker en leverandør du stoler på, eller en intern +AI gateway, kan du bruke OpenCode sikkert. + +Det eneste forbeholdet her er den valgfrie `/share`-funksjonen. + +--- + +#### Deling av samtaler + +Hvis en bruker aktiverer funksjonen `/share`, sendes samtalen og dataene knyttet til den til tjenesten vi bruker til å være vert for disse delesidene på opencode.ai. + +Dataene leveres for øyeblikket gjennom vårt CDNs edge-nettverk, og bufres på kanten nær brukerne dine. + +Vi anbefaler at du deaktiverer dette for prøveversjonen. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[Finn ut mer om deling](/docs/share). + +--- + +### Kodeeierskap + +**Du eier all kode produsert av OpenCode.** Det er ingen lisensieringsbegrensninger eller eierskapskrav. + +--- + +## Priser + +Vi bruker en per-sete-modell for OpenCode Enterprise. Hvis du har din egen LLM-gateway, tar vi ikke betalt for tokens som brukes. For mer informasjon om priser og implementeringsalternativer, **kontakt oss**. + +--- + +## Implementering + +Når du har fullført prøveversjonen og du er klar til å bruke OpenCode på +organisasjonen din, kan du **kontakte oss** for å diskutere +prissetting og implementeringsalternativer. + +--- + +### Sentral konfigurasjon + +Vi kan sette opp OpenCode for å bruke en enkelt sentral konfigurasjon for hele organisasjonen din. + +Denne sentraliserte konfigurasjonen kan integreres med SSO-leverandøren din og sikrer at alle brukere kun får tilgang til din interne AI-gateway. + +--- + +### SSO-integrasjon + +Gjennom den sentrale konfigurasjonen kan OpenCode integreres med organisasjonens SSO-leverandør for autentisering. + +Dette lar OpenCode få legitimasjon for din interne AI-gateway gjennom ditt eksisterende identitetsadministrasjonssystem. + +--- + +### Intern AI-gateway + +Med den sentrale konfigurasjonen kan OpenCode også konfigureres til kun å bruke din interne AI-gateway. + +Du kan også deaktivere alle andre AI-leverandører, og sikre at alle forespørsler går gjennom organisasjonens godkjente infrastruktur. + +--- + +### Egen hosting + +Selv om vi anbefaler å deaktivere delingssidene for å sikre at dataene dine aldri forsvinner +organisasjonen din, kan vi også hjelpe deg med å være vert for dem på din infrastruktur. + +Dette er nå på veikartet vårt. Hvis du er interessert, **gi oss beskjed**. + +--- + +## Ofte stilte spørsmål (FAQ) + +

+Hva er OpenCode Enterprise? + +OpenCode Enterprise er for organisasjoner som ønsker å sikre at deres kode og data aldri forlater deres infrastruktur. Den kan gjøre dette ved å bruke en sentralisert konfigurasjon som integreres med din SSO og interne AI gateway. + +
+ +
+Hvordan kommer jeg i gang med OpenCode Enterprise? + +Bare sett i gang en intern prøveversjon med teamet ditt. OpenCode lagrer som standard ikke koden eller kontekstdataene dine, noe som gjør det enkelt å komme i gang. + +Så **kontakt oss** for å diskutere priser og implementeringsalternativer. + +
+ +
+Hvordan fungerer bedriftsprising? + +Vi tilbyr bedriftspriser per bruker. Hvis du har din egen LLM-gateway, tar vi ikke betalt for tokens som brukes. For ytterligere detaljer, **kontakt oss** for et tilpasset tilbud basert på organisasjonens behov. + +
+ +
+Er dataene mine trygge med OpenCode Enterprise? + +Ja. OpenCode lagrer ikke koden eller kontekstdataene dine. All behandling skjer lokalt eller gjennom direkte API-anrop til AI-leverandøren din. Med sentral konfigurasjon og SSO-integrasjon forblir dataene dine sikre i organisasjonens infrastruktur. + +
+ +
+Kan vi bruke vårt eget private NPM-register? + +OpenCode støtter private npm-registre gjennom Bun sin innebygde støtte for .npmrc-filer. Hvis organisasjonen din bruker et privat register, som JFrog Artifactory, Nexus eller lignende, sørg for at utviklerne er autentisert før du kjører OpenCode. + +Slik setter du opp autentisering med ditt private register: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +Dette oppretter `~/.npmrc` med autentiseringsdetaljer. OpenCode vil automatisk +oppdage dette. + +:::caution +Du må være logget inn i det private registeret før du kjører OpenCode. +::: + +Alternativt kan du konfigurere en `.npmrc`-fil manuelt: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +Utviklere må være logget på det private registeret før de kjører OpenCode for å sikre at pakker kan installeres fra bedriftsregisteret. + +
diff --git a/packages/web/src/content/docs/nb/formatters.mdx b/packages/web/src/content/docs/nb/formatters.mdx new file mode 100644 index 00000000000..b9fe99a4486 --- /dev/null +++ b/packages/web/src/content/docs/nb/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: Formattere +description: OpenCode bruker språkspesifikke formattere. +--- + +OpenCode formaterer automatisk filer etter at de er skrevet eller redigert ved hjelp av språkspesifikke formattere. Dette sikrer at koden som genereres følger kodestilene til prosjektet ditt. + +--- + +## Innebygde formattere + +OpenCode kommer med flere innebygde formattere for populære språk og rammeverk. Nedenfor er en liste over formattere, støttede filendelser og kommandoer eller konfigurasjonsalternativer den krever. + +| Formatter | Filendelser | Krav | +| ---------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | +| gofmt | .go | `gofmt` kommando tilgjengelig | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | `mix` kommando tilgjengelig | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml og [flere](https://prettier.io/docs/en/index.html) | `prettier` avhengighet i `package.json` | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml og [flere](https://biomejs.dev/) | `biome.json(c)` konfigurasjonsfil | +| zig | .zig, .zon | `zig` kommando tilgjengelig | +| clang-format | .c, .cpp, .h, .hpp, .ino og [flere](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` konfigurasjonsfil | +| ktlint | .kt, .kts | `ktlint` kommando tilgjengelig | +| ruff | .py, .pyi | `ruff` kommando tilgjengelig med config | +| rustfmt | .rs | `rustfmt` kommando tilgjengelig | +| cargofmt | .rs | `cargo fmt` kommando tilgjengelig | +| uv | .py, .pyi | `uv` kommando tilgjengelig | +| rubocop | .rb, .rake, .gemspec, .ru | `rubocop` kommando tilgjengelig | +| standardrb | .rb, .rake, .gemspec, .ru | `standardrb` kommando tilgjengelig | +| htmlbeautifier | .erb, .html.erb | `htmlbeautifier` kommando tilgjengelig | +| air | .R | `air` kommando tilgjengelig | +| dart | .dart | `dart` kommando tilgjengelig | +| ocamlformat | .ml, .mli | `ocamlformat` kommando tilgjengelig og `.ocamlformat` konfigurasjonsfil | +| terraform | .tf, .tfvars | `terraform` kommando tilgjengelig | +| gleam | .gleam | `gleam` kommando tilgjengelig | +| nixfmt | .nix | `nixfmt` kommando tilgjengelig | +| shfmt | .sh, .bash | `shfmt` kommando tilgjengelig | +| pint | .php | `laravel/pint` avhengighet i `composer.json` | +| oxfmt (Eksperimentell) | .js, .jsx, .ts, .tsx | `oxfmt` avhengighet i `package.json` og et [eksperimentelt env variabel flagg](/docs/cli/#experimental) | +| ormolu | .hs | `ormolu` kommando tilgjengelig | + +Så hvis prosjektet ditt har `prettier` i `package.json`, vil OpenCode automatisk bruke det. + +--- + +## Slik fungerer det + +Når OpenCode skriver eller redigerer en fil, gjør den: + +1. Kontrollerer filtypen mot alle aktiverte formattere. +2. Kjører riktig formateringskommando på filen. +3. Bruker formateringsendringene automatisk. + +Denne prosessen skjer i bakgrunnen, og sikrer at kodestilene dine opprettholdes uten noen manuelle trinn. + +--- + +## Konfigurasjon + +Du kan tilpasse formattere gjennom `formatter`-delen i OpenCode-konfigurasjonen. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +Hver formateringskonfigurasjon støtter følgende: + +| Egenskap | Type | Beskrivelse | +| ------------- | -------- | --------------------------------------------------------------- | +| `disabled` | boolean | Sett dette til `true` for å deaktivere formatteren | +| `command` | string[] | Kommandoen som skal kjøres for formatering | +| `environment` | object | Miljøvariabler som skal settes når formateringsverktøyet kjøres | +| `extensions` | string[] | Filendelser denne formatteren skal håndtere | + +La oss se på noen eksempler. + +--- + +### Deaktivering av formattere + +For å deaktivere **alle** formattere globalt, sett `formatter` til `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +For å deaktivere en **spesifikk** formatter, sett `disabled` til `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### Egendefinerte formattere + +Du kan overstyre de innebygde formatterne eller legge til nye ved å spesifisere kommandoen, miljøvariablene og filtypene: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +**Plassholderen $FILE** i kommandoen vil bli erstattet med banen til filen som formateres. diff --git a/packages/web/src/content/docs/nb/github.mdx b/packages/web/src/content/docs/nb/github.mdx new file mode 100644 index 00000000000..4a39c8830d0 --- /dev/null +++ b/packages/web/src/content/docs/nb/github.mdx @@ -0,0 +1,325 @@ +--- +title: GitHub +description: Bruk opencode i GitHub-problemer og pull-forespørsler. +--- + +OpenCode integreres med GitHub-arbeidsflyten din. Nevn `/opencode` eller `/oc` i kommentaren din, og OpenCode vil utføre oppgaver i din GitHub Actions-løper. + +--- + +## Funksjoner + +- **Triage saker**: Be OpenCode se på en sak og forklare den for deg. +- **Fiks og implementer**: Be OpenCode om å fikse en sak eller implementere en funksjon. Den vil jobbe i en ny gren og sende inn en PR med alle endringene. +- **Sikkert**: OpenCode kjører i GitHub-runners. + +--- + +## Installasjon + +Kjør følgende kommando i et prosjekt som er et GitHub-repo: + +```bash +opencode github install +``` + +Dette vil lede deg gjennom å installere GitHub-appen, lage arbeidsflyten og sette opp secrets (hemmeligheter). + +--- + +### Manuelt oppsett + +Eller du kan sette den opp manuelt. + +1. **Installer GitHub-appen** + + Gå over til [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). Sørg for at den er installert på mållageret. + +2. **Legg til arbeidsflyten** + + Legg til følgende arbeidsflytfil til `.github/workflows/opencode.yml` i repoen. Sørg for å sette riktig `model` og nødvendige API-nøkler i `env`. + + ```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx + ``` + +3. **Lagre API-nøklene i hemmeligheter** + + Utvid **Hemmeligheter og variabler** til venstre i **innstillingene** for organisasjonen eller prosjektet og velg **Actions**. Og legg til de nødvendige API-nøklene. + +--- + +## Konfigurasjon + +- `model`: Modellen som skal brukes med OpenCode. Tar formatet `provider/model`. Dette er **obligatorisk**. +- `agent`: Agenten som skal brukes. Må være en primær agent. Faller tilbake til `default_agent` fra config eller `"build"` hvis ikke funnet. +- `share`: Om OpenCode-økten skal deles. Standard er **true** for offentlige depoter. +- `prompt`: Valgfri egendefinert melding for å overstyre standard oppførsel. Bruk dette til å tilpasse hvordan OpenCode behandler forespørsler. +- `token`: Valgfritt GitHub-tilgangstoken for å utføre operasjoner som å lage kommentarer, foreta endringer og åpne pull-forespørsler. Som standard bruker OpenCode installasjonstilgangstokenet fra OpenCode GitHub-appen, så commits, kommentarer og pull-forespørsler ser ut til å komme fra appen. + + Alternativt kan du bruke GitHub Action-løperens [innebygde `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) uten å installere OpenCode GitHub-appen. Bare sørg for å gi de nødvendige tillatelsene i arbeidsflyten din: + + ```yaml + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + ``` + + Du kan også bruke en [personlig tilgangstoken](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) hvis foretrukket. + +--- + +## Støttede hendelser + +OpenCode kan utløses av følgende GitHub-hendelser: + +| Hendelsestype | Utløst av | Detaljer | +| ----------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `issue_comment` | Kommentar på sak eller PR | Nevn `/opencode` eller `/oc` i kommentaren din. OpenCode leser kontekst og kan opprette grener, åpne PR-er eller svare. | +| `pull_request_review_comment` | Kommenter spesifikke kodelinjer i en PR | Nevn `/opencode` eller `/oc` mens du ser gjennom koden. OpenCode mottar filbane, linjenummer og diff-kontekst. | +| `issues` | Sak åpnet eller redigert | Utløs OpenCode automatisk når saker opprettes eller endres. Krever `prompt` inngang. | +| `pull_request` | PR åpnet eller oppdatert | Utløs OpenCode automatisk når PR-er åpnes, synkroniseres eller gjenåpnes. Nyttig for automatiserte anmeldelser. | +| `schedule` | Cron-basert tidsplan | Kjør OpenCode etter en tidsplan. Krever `prompt` inngang. Utdata går til logger og PR (ingen sak å kommentere). | +| `workflow_dispatch` | Manuell utløser fra GitHub UI | Utløs OpenCode på forespørsel via fanen Handlinger. Krever `prompt` inngang. Utdata går til logger og PR-er. | + +### Eksempel på tidsplan + +Kjør OpenCode på en tidsplan for å utføre automatiserte oppgaver: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +For planlagte arrangementer er `prompt`-inngangen **påkrevd** siden det ikke er noen kommentarer å trekke ut instruksjoner fra. Planlagte workflows kjører uten brukerkontekst for tillatelsessjekking, så arbeidsflyten må gi `contents: write` og `pull-requests: write` hvis du forventer at OpenCode oppretter grener eller PR-er. + +--- + +### Eksempel på Pull Request + +Gjennomgå PR-er automatisk når de åpnes eller oppdateres: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +For `pull_request`-hendelser, hvis ingen `prompt` er oppgitt, går OpenCode som standard gjennom PR-en. + +--- + +### Eksempel på triage av saker + +Automatisk triage av nye saker. Dette eksemplet filtrerer til kontoer eldre enn 30 dager for å redusere spam: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +For `issues`-hendelser er `prompt`-inngangen **påkrevd** siden det ikke er noen kommentarer å trekke ut instruksjoner fra. + +--- + +## Egendefinerte prompter + +Overstyr standardprompten for å tilpasse oppførselen til OpenCode for arbeidsflyten din. + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Dette er nyttig for å håndheve spesifikke vurderingskriterier, kodestandarder eller fokusområder som er relevante for prosjektet ditt. + +--- + +## Eksempler + +Her er noen eksempler på hvordan du kan bruke OpenCode i GitHub. + +:::tip +Du kan konfigurere til å bruke en annen triggerfrase enn `@opencode`. +::: + +- **Forklar en sak (issue)** + + Legg til denne kommentaren i en GitHub-sak. + + ``` + /opencode explain this issue + ``` + + OpenCode vil lese hele tråden, inkludert alle kommentarer, og svare med en tydelig forklaring. + +- **Fiks en sak** + + I en GitHub-sak, si: + + ``` + /opencode fix this + ``` + + Og OpenCode vil opprette en ny gren, implementere endringene og åpne en PR med endringene. + +- **Se gjennom PR-er og gjør endringer** + + Legg igjen følgende kommentar på en GitHub PR. + + ``` + Delete the attachment from S3 when the note is removed /oc + ``` + + OpenCode vil implementere den forespurte endringen og committe den til samme PR. + +- **Review av spesifikke kodelinjer** + + Legg igjen en kommentar direkte på kodelinjer i PRs "Filer"-fane. OpenCode oppdager automatisk filen, linjenumrene og diff-konteksten for å gi presise svar. + + ``` + [Comment on specific lines in Files tab] + /oc add error handling here + ``` + + Når du kommenterer spesifikke linjer, mottar OpenCode: + - Den nøyaktige filen blir gjennomgått + - De spesifikke kodelinjene + - Den omkringliggende diff-konteksten + - Linjenummerinformasjon + + Dette gir mulighet for mer målrettede forespørsler uten å måtte spesifisere filstier eller linjenumre manuelt. diff --git a/packages/web/src/content/docs/nb/gitlab.mdx b/packages/web/src/content/docs/nb/gitlab.mdx new file mode 100644 index 00000000000..2fc34a3e8f1 --- /dev/null +++ b/packages/web/src/content/docs/nb/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: Bruk opencode i GitLab-problemer og Merge Requests. +--- + +OpenCode integreres med GitLab arbeidsflyten gjennom GitLab CI/CD pipeline eller med GitLab Duo. + +I begge tilfeller vil OpenCode kjøre på GitLab Runners. + +--- + +## GitLab CI + +OpenCode fungerer i en vanlig GitLab-pipeline. Du kan bygge den inn i en pipeline som en [CI-komponent](https://docs.gitlab.com/ee/ci/components/) + +Her bruker vi en fellesskapsskapt CI/CD-komponent for OpenCode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### Funksjoner + +- **Bruk tilpasset konfigurasjon per jobb**: Konfigurer OpenCode med en tilpasset konfigurasjonskatalog, for eksempel `./config/#custom-directory` for å aktivere eller deaktivere funksjonalitet per OpenCode-anrop. +- **Minimalt oppsett**: CI-komponenten setter opp OpenCode i bakgrunnen, du trenger bare å lage OpenCode-konfigurasjonen og den første ledeteksten. +- **Fleksibel**: CI-komponenten støtter flere innganger for å tilpasse virkemåten + +--- + +### Oppsett + +1. Lagre OpenCode sin autentiserings-JSON som en CI-miljøvariabel av typen Fil under **Innstillinger** > **CI/CD** > **Variabler**. Sørg for å merke dem som "Masked and hidden". +2. Legg til følgende i `.gitlab-ci.yml`-filen. + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +For flere inndata og brukstilfeller [sjekk ut dokumentene](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) for denne komponenten. + +--- + +## GitLab Duo + +OpenCode integreres med din GitLab arbeidsflyt. +Nevn `@opencode` i en kommentar, og OpenCode vil utføre oppgaver innenfor din GitLab CI-pipeline. + +--- + +### Funksjoner + +- **Triage av saker**: Be OpenCode se på en sak og forklare den for deg. +- **Fiks og implementer**: Be OpenCode om å fikse en sak eller implementere en funksjon. + Det vil opprette en ny gren og sende en Merge Request med endringene. +- **Sikkert**: OpenCode kjører på GitLab Runners. + +--- + +### Oppsett + +OpenCode kjører i GitLab CI/CD pipeline, her er det du trenger for å sette den opp: + +:::tip +Sjekk ut [**GitLab-dokumentene**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) for oppdaterte instruksjoner. +::: + +1. Konfigurer GitLab-miljøet ditt +2. Sett opp CI/CD +3. Få en AI modellleverandør API nøkkel +4. Opprett en tjenestekonto +5. Konfigurer CI/CD variabler +6. Lag en flytkonfigurasjonsfil, her er et eksempel: + +
+ + Flow configuration + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +Du kan se [GitLab CLI agents docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) for detaljerte instruksjoner. + +--- + +### Eksempler + +Her er noen eksempler på hvordan du kan bruke OpenCode i GitLab. + +:::tip +Du kan konfigurere til å bruke en annen triggerfrase enn `@opencode`. +::: + +- **Forklar en sak** + + Legg til denne kommentaren i en GitLab-sak. + + ``` + @opencode explain this issue + ``` + + OpenCode vil lese saken og svare med en klar forklaring. + +- **Fiks en sak** + + I en GitLab-sak, si: + + ``` + @opencode fix this + ``` + + OpenCode vil opprette en ny gren, implementere endringene og åpne en Merge Request med endringene. + +- **Review av Merge Requests** + + Legg igjen følgende kommentar på en GitLab Merge Request. + + ``` + @opencode review this merge request + ``` + + OpenCode vil gjennomgå Merge Request-en og gi tilbakemelding. diff --git a/packages/web/src/content/docs/nb/ide.mdx b/packages/web/src/content/docs/nb/ide.mdx new file mode 100644 index 00000000000..76b1ce16648 --- /dev/null +++ b/packages/web/src/content/docs/nb/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: OpenCode-utvidelsen for VS Code, Cursor og andre IDE-er +--- + +OpenCode integreres med VS Code, Cursor eller en hvilken som helst IDE som støtter en terminal. Bare kjør `opencode` i terminalen for å komme i gang. + +--- + +## Bruk + +- **Hurtigstart**: Bruk `Cmd+Esc` (Mac) eller `Ctrl+Esc` (Windows/Linux) for å åpne OpenCode i en delt terminalvisning, eller fokuser en eksisterende terminaløkt hvis en allerede kjører. +- **Ny økt**: Bruk `Cmd+Shift+Esc` (Mac) eller `Ctrl+Shift+Esc` (Windows/Linux) for å starte en ny OpenCode-terminaløkt, selv om en allerede er åpen. Du kan også klikke på OpenCode-knappen i UI. +- **Kontekstbevissthet**: Del automatisk ditt nåværende valg eller fane med OpenCode. +- **Snarveier for filreferanser**: Bruk `Cmd+Option+K` (Mac) eller `Alt+Ctrl+K` (Linux/Windows) for å sette inn filreferanser. For eksempel `@File#L37-42`. + +--- + +## Installasjon + +For å installere OpenCode på VS Code og populære varianter som Cursor, Windsurf, VSCodium: + +1. Åpne VS Code +2. Åpne den integrerte terminalen +3. Kjør `opencode` - utvidelsen installeres automatisk + +Hvis du derimot vil bruke din egen IDE når du kjører `/editor` eller `/export` fra TUI, må du angi `export EDITOR="code --wait"`. [Finn ut mer](/docs/tui/#editor-setup). + +--- + +### Manuell installasjon + +Søk etter **OpenCode** i Extension Marketplace og klikk på **Install**. + +--- + +### Feilsøking + +Hvis utvidelsen ikke kan installeres automatisk: + +- Sørg for at du kjører `opencode` i den integrerte terminalen. +- Bekreft at CLI for IDE er installert: + - For VS Code: `code` kommando + - For Cursor: `cursor` kommando + - For Windsurf: `windsurf` kommando + - For VSCodium: `codium` kommando + - Hvis ikke, kjør `Cmd+Shift+P` (Mac) eller `Ctrl+Shift+P` (Windows/Linux) og søk etter "Shell Command: Install 'code' command in PATH" (eller tilsvarende for din IDE) +- Sørg for at VS Code har tillatelse til å installere utvidelser diff --git a/packages/web/src/content/docs/nb/index.mdx b/packages/web/src/content/docs/nb/index.mdx new file mode 100644 index 00000000000..b10662537d5 --- /dev/null +++ b/packages/web/src/content/docs/nb/index.mdx @@ -0,0 +1,358 @@ +--- +title: Introduksjon +description: Kom i gang med OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**OpenCode**](/) er en åpen kildekode AI kodeagent. Den er tilgjengelig som et terminalbasert grensesnitt, skrivebordsapp eller IDE-utvidelse. + +![OpenCode TUI med opencode-temaet](../../../assets/lander/screenshot.png) + +La oss komme i gang. + +--- + +#### Forutsetninger + +For å bruke OpenCode i terminalen din trenger du: + +1. En moderne terminalemulator som: + - [WezTerm](https://wezterm.org), på tvers av plattformer + - [Alacritty](https://alacritty.org), på tvers av plattformer + - [Ghostty](https://ghostty.org), Linux og macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux og macOS + +2. API-nøkler for LLM-leverandørene du vil bruke. + +--- + +## Installasjon + +Den enkleste måten å installere OpenCode på er gjennom installasjonsskriptet. + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +Du kan også installere den med følgende kommandoer: + +- **Bruke Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **Bruke Homebrew på macOS og Linux** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > Vi anbefaler å bruke OpenCode-tappen for de mest oppdaterte utgivelsene. Den offisielle `brew install opencode`-formelen vedlikeholdes av Homebrew-teamet og oppdateres sjeldnere. + +- **Bruke Paru på Arch Linux** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[Anbefalt: Bruk WSL] +For den beste opplevelsen på Windows anbefaler vi å bruke [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Det gir bedre ytelse og full kompatibilitet med funksjonene i OpenCode. +::: + +- **Bruke Chocolatey** + + ```bash + choco install opencode + ``` + +- **Bruke Scoop** + + ```bash + scoop install opencode + ``` + +- **Bruke npm** + + ```bash + npm install -g opencode-ai + ``` + +- **Bruke Mise** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **Bruke Docker** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +Støtte for installasjon av OpenCode på Windows med Bun er under arbeid. + +Du kan også hente binæren fra [Releases](https://github.com/anomalyco/opencode/releases). + +--- + +## Konfigurasjon + +Med OpenCode kan du bruke hvilken som helst LLM-leverandør ved å konfigurere deres API-nøkler. + +Hvis du er ukjent med LLM-leverandører, anbefaler vi å bruke [OpenCode Zen](/docs/zen). +Det er en kuratert liste over modeller som har blitt testet og verifisert av OpenCode-teamet. + +1. Kjør kommandoen `/connect` i TUI, velg OpenCode og gå til [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. Logg på, legg til faktureringsdetaljene dine og kopier API-nøkkelen. + +3. Lim inn API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +Alternativt kan du velge en av de andre leverandørene. [Finn ut mer](/docs/providers#directory). + +--- + +## Initialisering + +Nå som du har konfigurert en leverandør, kan du navigere til et prosjekt som +du vil jobbe med. + +```bash +cd /path/to/project +``` + +Og kjør OpenCode. + +```bash +opencode +``` + +Deretter initialiserer du OpenCode for prosjektet ved å kjøre følgende kommando. + +```bash frame="none" +/init +``` + +Dette vil få OpenCode til å analysere prosjektet ditt og opprette en `AGENTS.md`-fil i +prosjektroten. + +:::tip +Du bør overgi prosjektets `AGENTS.md`-fil til Git. +::: + +Dette hjelper OpenCode med å forstå prosjektstrukturen og kodingsmønstrene +brukt. + +--- + +## Bruk + +Du er nå klar til å bruke OpenCode for å jobbe med prosjektet ditt. Spør det gjerne +noe! + +Hvis du er ukjent med AI-kodeagenter, her er noen eksempler som kan +hjelpe. + +--- + +### Still spørsmål + +Du kan be OpenCode forklare kodebasen for deg. + +:::tip +Bruk `@`-tasten for uklart søk etter filer i prosjektet. +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +Dette er nyttig hvis det er en del av kodebasen du ikke har jobbet med. + +--- + +### Legg til funksjonalitet + +Du kan be OpenCode legge til nye funksjoner i prosjektet ditt. Selv om vi først anbefaler å be den om å lage en plan. + +1. **Lag en plan** + + OpenCode har en _Plan-modus_ som deaktiverer muligheten til å gjøre endringer og + foreslår i stedet _hvordan_ den vil implementere funksjonen. + + Bytt til den ved å bruke **Tab**-tasten. Du vil se en indikator for dette i nedre høyre hjørne. + + ```bash frame="none" title="Switch to Plan mode" + + ``` + + La oss nå beskrive hva vi vil at den skal gjøre. + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + Du bør gi OpenCode nok detaljer til å forstå hva du ønsker. Det hjelper + å snakke med det som om du snakker med en juniorutvikler på laget ditt. + + :::tip + Gi OpenCode mye kontekst og eksempler for å hjelpe den å forstå hva du + ønsker. + ::: + +2. **Iterer på planen** + + Når du får en plan, kan du gi den tilbakemelding eller legge til flere detaljer. + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + + :::tip + Dra og slipp bilder i terminalen for å legge dem til ledeteksten. + ::: + + OpenCode kan skanne alle bilder du gir den og legge dem til i ledeteksten. Du kan + gjør dette ved å dra og slippe et bilde inn i terminalen. + +3. **Bygg funksjonen** + + Når du føler deg komfortabel med planen, bytt tilbake til _Byggemodus_ ved å + trykke på **Tab**-tasten igjen. + + ```bash frame="none" + + ``` + + Og be den om å gjøre endringene. + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### Gjør endringer + +For mer enkle endringer kan du be OpenCode om å bygge det direkte +uten å måtte gjennomgå planen først. + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +Sørg for å gi nok detaljer, slik at OpenCode gjør de rette +endringene. + +--- + +### Angre endringer + +La oss si at du ber OpenCode om å gjøre noen endringer. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Men du skjønner at det ikke er det du ønsket. Du **kan angre** endringene +ved å bruke kommandoen `/undo`. + +```bash frame="none" +/undo +``` + +OpenCode vil nå tilbakestille endringene du har gjort og vise den opprinnelige meldingen +igjen. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Herfra kan du justere ledeteksten og be OpenCode om å prøve igjen. + +:::tip +Du kan kjøre `/undo` flere ganger for å angre flere endringer. +::: + +Eller du **kan gjøre om** endringene ved å bruke `/redo`-kommandoen. + +```bash frame="none" +/redo +``` + +--- + +## Deling + +Samtalene du har med OpenCode kan [deles med din +team](/docs/share). + +```bash frame="none" +/share +``` + +Dette vil opprette en kobling til den gjeldende samtalen og kopiere den til utklippstavlen. + +:::note +Samtaler deles ikke som standard. +::: + +Her er en [eksempelsamtale](https://opencode.ai/s/4XP1fce5) med OpenCode. + +--- + +## Tilpasning + +Og det er det! Du er nå en proff på å bruke OpenCode. + +For å tilpasse det anbefaler vi å [velge et tema](/docs/themes), [tilpasse tastebindingene](/docs/keybinds), [konfigurere kodeformattere](/docs/formatters), [opprette egendefinerte kommandoer](/docs/commands) eller leke med [OpenCode-konfigurasjonen](/docs/config). diff --git a/packages/web/src/content/docs/nb/keybinds.mdx b/packages/web/src/content/docs/nb/keybinds.mdx new file mode 100644 index 00000000000..d762a647f20 --- /dev/null +++ b/packages/web/src/content/docs/nb/keybinds.mdx @@ -0,0 +1,192 @@ +--- +title: Tastebindinger +description: Tilpass tastebindingene dine. +--- + +OpenCode har en liste over tastebindinger som du kan tilpasse gjennom OpenCode-konfigurasjonen. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## Leader-tast + +OpenCode bruker en `leader`-tast for de fleste tastebindinger. Dette unngår konflikter i terminalen din. + +Som standard er `ctrl+x` ledertasten, og de fleste handlinger krever at du først trykker på ledertasten og deretter snarveien. For å starte en ny økt, trykker du for eksempel først `ctrl+x` og deretter `n`. + +Du trenger ikke å bruke en ledertast for tastebindingene dine, men vi anbefaler at du gjør det. + +--- + +## Deaktivering av tastebindinger + +Du kan deaktivere en tastebinding ved å legge til tasten til konfigurasjonen med verdien "none". + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## Snarveier i skrivebordsappen + +Prompt-feltet for OpenCode-skrivebordsappen støtter vanlige snarveier i Readline/Emacs-stil for redigering av tekst. Disse er innebygd og foreløpig ikke konfigurerbare via `opencode.json`. + +| Snarvei | Handling | +| -------- | ---------------------------------------- | +| `ctrl+a` | Flytt til starten av gjeldende linje | +| `ctrl+e` | Flytt til slutten av gjeldende linje | +| `ctrl+b` | Flytt markøren ett tegn tilbake | +| `ctrl+f` | Flytt markøren ett tegn fremover | +| `alt+b` | Flytt markøren ett ord tilbake | +| `alt+f` | Flytt markøren ett ord fremover | +| `ctrl+d` | Slett tegn under markøren | +| `ctrl+k` | Slett til slutten av linjen | +| `ctrl+u` | Slett til starten av linjen | +| `ctrl+w` | Slett forrige ord | +| `alt+d` | Slett neste ord | +| `ctrl+t` | Bytt om tegn | +| `ctrl+g` | Avbryt popovers / avbryt kjøring av svar | + +--- + +## Shift+Enter + +Noen terminaler sender ikke modifikasjonstaster med Enter som standard. Du må kanskje konfigurere terminalen til å sende `Shift+Enter` som en escape-sekvens. + +### Windows Terminal + +Åpne `settings.json` på: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +Legg dette til `actions`-matrisen på rotnivå: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Legg dette til `keybindings`-matrisen på rotnivå: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Lagre filen og start Windows Terminal på nytt eller åpne en ny fane. diff --git a/packages/web/src/content/docs/nb/lsp.mdx b/packages/web/src/content/docs/nb/lsp.mdx new file mode 100644 index 00000000000..c52b79a32d3 --- /dev/null +++ b/packages/web/src/content/docs/nb/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: LSP-servere +description: opencode integreres med LSP-serverne dine. +--- + +OpenCode integreres med din Language Server Protocol (LSP) for å hjelpe LLM med å samhandle med kodebasen din. Den bruker diagnostikk for å gi tilbakemelding til LLM. + +--- + +## Innebygde servere + +OpenCode kommer med flere innebygde LSP-servere for populære språk: + +| LSP Server | Filendelser | Krav | +| ------------------ | ------------------------------------------------------------------- | ----------------------------------------------------------------------- | +| astro | .astro | Installeres automatisk for Astro-prosjekter | +| bash | .sh, .bash, .zsh, .ksh | Installerer bash-language-server automatisk | +| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | Installeres automatisk for C/C++-prosjekter | +| csharp | .cs | `.NET SDK` installert | +| clojure-lsp | .clj, .cljs, .cljc, .edn | `clojure-lsp` kommando tilgjengelig | +| dart | .dart | `dart` kommando tilgjengelig | +| deno | .ts, .tsx, .js, .jsx, .mjs | `deno` kommando tilgjengelig (automatisk oppdager deno.json/deno.jsonc) | +| elixir-ls | .ex, .exs | `elixir` kommando tilgjengelig | +| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | `eslint` avhengighet i prosjekt | +| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` installert | +| gleam | .gleam | `gleam` kommando tilgjengelig | +| gopls | .go | `go` kommando tilgjengelig | +| hls | .hs, .lhs | `haskell-language-server-wrapper` kommando tilgjengelig | +| jdtls | .java | `Java SDK (version 21+)` installert | +| kotlin-ls | .kt, .kts | Installeres automatisk for Kotlin-prosjekter | +| lua-ls | .lua | Installeres automatisk for Lua-prosjekter | +| nixd | .nix | `nixd` kommando tilgjengelig | +| ocaml-lsp | .ml, .mli | `ocamllsp` kommando tilgjengelig | +| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | `oxlint` avhengighet i prosjekt | +| php intelephense | .php | Installeres automatisk for PHP-prosjekter | +| prisma | .prisma | `prisma` kommando tilgjengelig | +| pyright | .py, .pyi | `pyright` avhengighet installert | +| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | `ruby` og `gem` kommandoer tilgjengelig | +| rust | .rs | `rust-analyzer` kommando tilgjengelig | +| sourcekit-lsp | .swift, .objc, .objcpp | `swift` installert (`xcode` på macOS) | +| svelte | .svelte | Installeres automatisk for Svelte-prosjekter | +| terraform | .tf, .tfvars | Installeres automatisk fra GitHub-utgivelser | +| tinymist | .typ, .typc | Installeres automatisk fra GitHub-utgivelser | +| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` avhengighet i prosjekt | +| vue | .vue | Installeres automatisk for Vue-prosjekter | +| yaml-ls | .yaml, .yml | Installerer Red Hat yaml-language-server automatisk | +| zls | .zig, .zon | `zig` kommando tilgjengelig | + +LSP-servere aktiveres automatisk når en av filtypene ovenfor oppdages og kravene oppfylles. + +:::note +Du kan deaktivere automatiske LSP-servernedlastinger ved å sette miljøvariabelen `OPENCODE_DISABLE_LSP_DOWNLOAD` til `true`. +::: + +--- + +## Slik fungerer det + +Når opencode åpner en fil, gjør den: + +1. Kontrollerer filtypen mot alle aktiverte LSP-servere. +2. Starter den riktige LSP-serveren hvis den ikke allerede kjører. + +--- + +## Konfigurasjon + +Du kan tilpasse LSP-servere gjennom `lsp`-delen i OpenCode-konfigurasjonen. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +Hver LSP-server støtter følgende: + +| Egenskap | Type | Beskrivelse | +| ---------------- | -------- | -------------------------------------------------------- | +| `disabled` | boolean | Sett dette til `true` for å deaktivere LSP-serveren | +| `command` | string[] | Kommandoen for å starte LSP-serveren | +| `extensions` | string[] | Filendelser denne LSP-serveren skal håndtere | +| `env` | object | Miljøvariabler som skal angis når serveren startes | +| `initialization` | object | Initialiseringsalternativer for å sende til LSP-serveren | + +La oss se på noen eksempler. + +--- + +### Miljøvariabler + +Bruk egenskapen `env` til å angi miljøvariabler når du starter LSP-serveren: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### Initialiseringsalternativer + +Bruk egenskapen `initialization` til å sende initialiseringsalternativer til LSP-serveren. Dette er serverspesifikke innstillinger sendt under LSP `initialize`-forespørselen: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +Initialiseringsalternativer varierer etter LSP-server. Sjekk dokumentasjonen til LSP-serveren for tilgjengelige alternativer. +::: + +--- + +### Deaktivering av LSP-servere + +For å deaktivere **alle** LSP-servere globalt, sett `lsp` til `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +For å deaktivere en **spesifikk** LSP-server, sett `disabled` til `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### Egendefinerte LSP-servere + +Du kan legge til egendefinerte LSP-servere ved å spesifisere kommandoen og filtypene: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## Tilleggsinformasjon + +### PHP Intelephense + +PHP Intelephense tilbyr førsteklasses funksjoner gjennom en lisensnøkkel. Du kan oppgi en lisensnøkkel ved å plassere (bare) nøkkelen i en tekstfil på: + +- På macOS/Linux: `$HOME/intelephense/license.txt` +- På Windows: `%USERPROFILE%/intelephense/license.txt` + +Filen skal bare inneholde lisensnøkkelen uten ekstra innhold. diff --git a/packages/web/src/content/docs/nb/mcp-servers.mdx b/packages/web/src/content/docs/nb/mcp-servers.mdx new file mode 100644 index 00000000000..c7908eb9880 --- /dev/null +++ b/packages/web/src/content/docs/nb/mcp-servers.mdx @@ -0,0 +1,624 @@ +--- +title: MCP-servere +description: Legg til lokale og eksterne MCP-verktøy. +--- + +Du kan legge til eksterne verktøy i OpenCode ved å bruke _Model Context Protocol_ eller MCP. OpenCode støtter både lokale og eksterne servere. + +Når de er lagt til, er MCP-verktøy automatisk tilgjengelige for LLM sammen med innebygde verktøy. + +--- + +#### Advarsler + +Når du bruker en MCP-server, legger den til konteksten. Dette kan fort gå opp hvis du har mange verktøy. Så vi anbefaler å være forsiktig med hvilke MCP-servere du bruker. + +:::tip +MCP-servere legger til konteksten din, så du vil være forsiktig med hvilke du aktiverer. +::: + +Enkelte MCP-servere, som GitHub MCP-serveren, har en tendens til å legge til mange tokens og kan lett overskride kontekstgrensen. + +--- + +## Aktivering + +Du kan definere MCP-servere i [OpenCode Config](https://opencode.ai/docs/config/) under `mcp`. Legg til hver MCP med et unikt navn. Du kan referere til den MCP ved navn når du spør LLM-en. + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +Du kan også deaktivere en server ved å sette `enabled` til `false`. Dette er nyttig hvis du vil deaktivere en server midlertidig uten å fjerne den fra konfigurasjonen. + +--- + +### Overstyring av fjernstandarder + +Organisasjoner kan tilby standard MCP-servere via deres `.well-known/opencode`-endepunkt. Disse serverne kan være deaktivert som standard, slik at brukere kan melde seg på de de trenger. + +For å aktivere en spesifikk server fra organisasjonens eksterne konfigurasjon, legg den til i din lokale konfigurasjon med `enabled: true`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +Dine lokale konfigurasjonsverdier overstyrer de eksterne standardinnstillingene. Se [config precedence](/docs/config#precedence-order) for flere detaljer. + +--- + +## Lokal + +Legg til lokale MCP-servere ved å bruke `type` til `"local"` i MCP-objektet. + +```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", + }, + }, + }, +} +``` + +Kommandoen er hvordan den lokale MCP-serveren startes. Du kan også sende inn en liste over miljøvariabler. + +For eksempel, her er hvordan du kan legge til test [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) MCP serveren. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "mcp_everything": { + "type": "local", + "command": ["npx", "-y", "@modelcontextprotocol/server-everything"], + }, + }, +} +``` + +Og for å bruke den kan du legge til `use the mcp_everything tool` i ledetekstene mine. + +```txt "mcp_everything" +use the mcp_everything tool to add the number 3 and 4 +``` + +--- + +#### Alternativer + +Her er alle alternativene for å konfigurere en lokal MCP-server. + +| Alternativ | Type | Påkrevd | Beskrivelse | +| ------------- | ------- | ------- | ---------------------------------------------------------------------------------------- | +| `type` | String | Y | Type MCP servertilkobling, må være `"local"`. | +| `command` | Array | Y | Kommando og argumenter for å kjøre MCP-serveren. | +| `environment` | Object | | Miljøvariabler som skal angis når serveren kjøres. | +| `enabled` | Boolean | | Aktiver eller deaktiver MCP-serveren ved oppstart. | +| `timeout` | Number | | Tidsavbrudd i ms for henting av verktøy fra MCP-serveren. Standard er 5000 (5 sekunder). | + +--- + +## Ekstern + +Legg til eksterne MCP-servere ved å sette `type` til `"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" + } + } + } +} +``` + +`url` er URL til den eksterne MCP serveren og med alternativet `headers` kan du sende inn en liste over headere. + +--- + +#### Alternativer + +| Alternativ | Type | Påkrevd | Beskrivelse | +| ---------- | ------- | ------- | ---------------------------------------------------------------------------------------- | +| `type` | String | Y | Type MCP servertilkobling, må være `"remote"`. | +| `url` | String | Y | URL av den eksterne MCP-serveren. | +| `enabled` | Boolean | | Aktiver eller deaktiver MCP-serveren ved oppstart. | +| `headers` | Object | | Headere å sende med forespørselen. | +| `oauth` | Object | | OAuth-autentiseringskonfigurasjon. Se delen [OAuth](#oauth) nedenfor. | +| `timeout` | Number | | Tidsavbrudd i ms for henting av verktøy fra MCP-serveren. Standard er 5000 (5 sekunder). | + +--- + +## OAuth + +OpenCode håndterer automatisk OAuth-autentisering for eksterne MCP-servere. Når en server krever autentisering, vil OpenCode: + +1. Oppdag 401-svaret og start OAuth-flyten +2. Bruk **Dynamisk klientregistrering (RFC 7591)** hvis det støttes av serveren +3. Lagre tokens sikkert for fremtidige forespørsler + +--- + +### Automatisk + +For de fleste OAuth-aktiverte MCP-servere er ingen spesiell konfigurasjon nødvendig. Bare konfigurer den eksterne serveren: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "my-oauth-server": { + "type": "remote", + "url": "https://mcp.example.com/mcp" + } + } +} +``` + +Hvis serveren krever autentisering, vil OpenCode be deg om å autentisere når du prøver å bruke den for første gang. Hvis ikke, kan du [utløse flyten manuelt](#authenticating) med `opencode mcp auth `. + +--- + +### Forhåndsregistrert + +Hvis du har klientlegitimasjon fra MCP-serverleverandøren, kan du konfigurere dem: + +```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" + } + } + } +} +``` + +--- + +### Autentisering + +Du kan utløse autentisering manuelt eller administrere legitimasjon. + +Autentiser med en spesifikk MCP-server: + +```bash +opencode mcp auth my-oauth-server +``` + +Liste alle MCP-servere og deres autentiseringsstatus: + +```bash +opencode mcp list +``` + +Fjern lagret legitimasjon: + +```bash +opencode mcp logout my-oauth-server +``` + +Kommandoen `mcp auth` åpner nettleseren din for autorisasjon. Etter at du har godkjent, vil OpenCode lagre tokens sikkert i `~/.local/share/opencode/mcp-auth.json`. + +--- + +#### Deaktivering av OAuth + +Hvis du vil deaktivere automatisk OAuth for en server (f.eks. for servere som bruker API-nøkler i stedet), setter du `oauth` til `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-alternativer + +| Alternativ | Type | Beskrivelse | +| -------------- | --------------- | -------------------------------------------------------------------------------------- | +| `oauth` | Object \| false | OAuth-konfigurasjonsobjekt, eller `false` for å deaktivere automatisk OAuth-deteksjon. | +| `clientId` | String | OAuth-klient ID. Hvis ikke oppgitt, vil dynamisk klientregistrering bli forsøkt. | +| `clientSecret` | String | OAuth-klienthemmelighet, hvis det kreves av autorisasjonsserveren. | +| `scope` | String | OAuth-omfang å be om under autorisasjon. | + +#### Feilsøking + +Hvis en ekstern MCP-server ikke klarer å autentisere, kan du diagnostisere problemer med: + +```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 +``` + +Kommandoen `mcp debug` viser gjeldende autentiseringsstatus, tester HTTP-tilkoblingen og forsøker OAuth-oppdagelsesflyten. + +--- + +## Administrering + +MCP-ene dine er tilgjengelige som verktøy i OpenCode, sammen med innebygde verktøy. Så du kan administrere dem gjennom OpenCode-konfigurasjonen som alle andre verktøy. + +--- + +### Globalt + +Dette betyr at du kan aktivere eller deaktivere dem globalt. + +```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 + } +} +``` + +Vi kan også bruke et globmønster for å deaktivere alle matchende MCP-er. + +```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 + } +} +``` + +Her bruker vi globmønsteret `my-mcp*` for å deaktivere alle MCP-er. + +--- + +### Per agent + +Hvis du har et stort antall MCP-servere, vil du kanskje bare aktivere dem per agent og deaktivere dem globalt. Slik gjør du dette: + +1. Deaktiver det som et verktøy globalt. +2. Aktiver MCP-serveren som et verktøy i [agent config](/docs/agents#tools). + +```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 + } + } + } +} +``` + +--- + +#### Glob-mønstre + +Glob-mønsteret bruker enkle regex-globing-mønstre: + +- `*` samsvarer med null eller flere av alle tegn (f.eks. `"my-mcp*"` samsvarer med `my-mcp_search`, `my-mcp_list`, osv.) +- `?` samsvarer med nøyaktig ett tegn +- Alle andre karakterer samsvarer bokstavelig talt + +:::note +MCP serververktøy er registrert med servernavn som prefiks, så for å deaktivere alle verktøy for en server bruker du bare: + +``` +"mymcpservername_*": false +``` + +::: + +--- + +## Eksempler + +Nedenfor er eksempler på noen vanlige MCP-servere. Du kan sende inn en PR hvis du vil dokumentere andre servere. + +--- + +### Sentry + +Legg til [Sentry MCP-serveren](https://mcp.sentry.dev) for å samhandle med Sentry-prosjektene og problemene dine. + +```json title="opencode.json" {4-8} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "sentry": { + "type": "remote", + "url": "https://mcp.sentry.dev/mcp", + "oauth": {} + } + } +} +``` + +Etter å ha lagt til konfigurasjonen, autentiser med Sentry: + +```bash +opencode mcp auth sentry +``` + +Dette åpner et nettleservindu for å fullføre OAuth-flyten og koble OpenCode til Sentry-kontoen din. + +Når du er autentisert, kan du bruke Sentry-verktøy i ledetekstene dine for å spørre etter problemer, prosjekter og feildata. + +```txt "use sentry" +Show me the latest unresolved issues in my project. use sentry +``` + +--- + +### Context7 + +Legg til [Context7 MCP-serveren](https://github.com/upstash/context7) for å søke gjennom dokumenter. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "context7": { + "type": "remote", + "url": "https://mcp.context7.com/mcp" + } + } +} +``` + +Hvis du har registrert deg for en gratis konto, kan du bruke API-nøkkelen din og få høyere satsgrenser. + +```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}" + } + } + } +} +``` + +Her antar vi at du har `CONTEXT7_API_KEY` miljøvariabelen satt. + +Legg til `use context7` i instruksjonene for å bruke Context7 MCP-serveren. + +```txt "use context7" +Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 +``` + +Alternativt kan du legge til noe slikt til din [AGENTS.md](/docs/rules/). + +```md title="AGENTS.md" +When you need to search docs, use `context7` tools. +``` + +--- + +### Grep by Vercel + +Legg til [Grep by Vercel](https://grep.app) MCP-serveren for å søke gjennom kodebiter på GitHub. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "gh_grep": { + "type": "remote", + "url": "https://mcp.grep.app" + } + } +} +``` + +Siden vi kalte MCP-serveren vår `gh_grep`, kan du legge til `use the gh_grep tool` i spørsmålene dine for å få agenten til å bruke den. + +```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 +``` + +Alternativt kan du legge til noe slikt til din [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. +``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) er en LLM observerbarhetsplattform som gir logging, overvåking og analyser for AI-applikasjonene dine. Helicone AI Gateway ruter forespørslene dine til riktig leverandør automatisk basert på modellen. + +1. Gå over til [Helicone](https://helicone.ai), opprett en konto og generer en API nøkkel fra dashbordet. + +2. Kjør kommandoen `/connect` og søk etter **Helicone**. + + ```txt + /connect + ``` + +3. Skriv inn Helicone API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell. + + ```txt + /models + ``` + +For flere leverandører og avanserte funksjoner som bufring og hastighetsbegrensning, sjekk [Helicone-dokumentasjonen](https://docs.helicone.ai). + +#### Valgfrie konfigurasjoner + +I tilfelle du ser en funksjon eller modell fra Helicone som ikke konfigureres automatisk gjennom OpenCode, kan du alltid konfigurere den selv. + +Her er [Helicone's Model Directory](https://helicone.ai/models), du trenger denne for å hente ID-ene til modellene du vil legge til. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### Egendefinerte headere + +Helicone støtter tilpassede headere for funksjoner som bufring, brukersporing og øktadministrasjon. Legg dem til leverandørkonfigurasjonen din ved å bruke `options.headers`: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### Sesjonssporing + +Helicones [Sessions](https://docs.helicone.ai/features/sessions) funksjon lar deg gruppere relaterte LLM forespørsler sammen. Bruk [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) plugin for automatisk å logge hver OpenCode-samtale som en økt i Helicone. + +```bash +npm install -g opencode-helicone-session +``` + +Legg den til i konfigurasjonen din. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +Programtillegget injiserer `Helicone-Session-Id` og `Helicone-Session-Name` overskrifter i forespørslene dine. På Helicones Sessions-side vil du se hver OpenCode-samtale oppført som en separat økt. + +##### Vanlige Helicone-headere + +| Overskrift | Beskrivelse | +| -------------------------- | -------------------------------------------------------------------------- | +| `Helicone-Cache-Enabled` | Aktiver responsbufring (`true`/`false`) | +| `Helicone-User-Id` | Spor beregninger etter bruker | +| `Helicone-Property-[Name]` | Legg til egendefinerte egenskaper (f.eks. `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | Knytt forespørsler til spørsmålsversjoner | + +Se [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory) for alle tilgjengelige overskrifter. diff --git a/packages/web/src/content/docs/nb/models.mdx b/packages/web/src/content/docs/nb/models.mdx new file mode 100644 index 00000000000..fe53d9661d0 --- /dev/null +++ b/packages/web/src/content/docs/nb/models.mdx @@ -0,0 +1,223 @@ +--- +title: Modeller +description: Konfigurere en LLM leverandør og modell. +--- + +OpenCode bruker [AI SDK](https://ai-sdk.dev/) og [Models.dev](https://models.dev) for å støtte **75+ LLM leverandører** og den støtter kjøring av lokale modeller. + +--- + +## Leverandører + +De fleste populære leverandørene er forhåndslastet som standard. Hvis du har lagt til legitimasjonen for en leverandør gjennom kommandoen `/connect`, vil den være tilgjengelig når du starter OpenCode. + +Finn ut mer om [leverandører](/docs/providers). + +--- + +## Velge en modell + +Når du har konfigurert leverandøren din, kan du velge modellen du ønsker ved å skrive inn: + +```bash frame="none" +/models +``` + +--- + +## Anbefalte modeller + +Det er mange modeller der ute, med nye modeller som kommer ut hver uke. + +:::tip +Vurder å bruke en av modellene vi anbefaler. +::: + +Imidlertid er det bare noen få av dem som er gode til både å generere kode og verktøykalling. + +Her er flere modeller som fungerer godt med OpenCode, uten spesiell rekkefølge. (Dette er ikke en uttømmende liste og er heller ikke nødvendigvis oppdatert): + +- GPT 5.2 +- GPT 5.1 Codex +- Claude Opus 4.5 +- Claude Sonnet 4.5 +- Minimax M2.1 +- Gemini 3 Pro + +--- + +## Angi en standard + +For å angi en av disse som standardmodell, kan du angi `model`-tasten i din +OpenCode-konfigurasjon. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +Her er hele ID `provider_id/model_id`. For eksempel, hvis du bruker [OpenCode Zen](/docs/zen), vil du bruke `opencode/gpt-5.1-codex` for GPT 5.1 Codex. + +Hvis du har konfigurert en [egendefinert leverandør](/docs/providers#custom), er `provider_id` nøkkelen fra `provider`-delen av konfigurasjonen din, og `model_id` er nøkkelen fra `provider.models`. + +--- + +## Konfigurer modeller + +Du kan konfigurere en modells alternativer globalt gjennom konfigurasjonen. + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +Her konfigurerer vi globale innstillinger for to innebygde modeller: `gpt-5` når de åpnes via `openai`-leverandøren, og `claude-sonnet-4-20250514` når de åpnes via `anthropic`-leverandøren. +De innebygde leverandør- og modellnavnene finnes på [Models.dev](https://models.dev). + +Du kan også konfigurere disse alternativene for alle agenter du bruker. Agentkonfigurasjonen overstyrer alle globale alternativer her. [Finn ut mer](/docs/agents/#additional). + +Du kan også definere tilpassede varianter som utvider de innebygde. Varianter lar deg konfigurere forskjellige innstillinger for samme modell uten å opprette dupliserte oppføringer: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## Varianter + +Mange modeller støtter flere varianter med forskjellige konfigurasjoner. opencode leveres med innebygde standardvarianter for populære leverandører. + +### Innebygde varianter + +OpenCode leveres med standardvarianter for mange leverandører: + +**Anthropic**: + +- `high` - Høyt tenkebudsjett (standard) +- `max` - Maksimalt tenkebudsjett + +**OpenAI**: + +Varierer etter modell, men omtrent: + +- `none` - Ingen resonnement +- `minimal` - Minimal resonnementinnsats +- `low` - Lav resonnementinnsats +- `medium` - Middels resonnementinnsats +- `high` - Høy resonnementinnsats +- `xhigh` - Ekstra høy resonnementinnsats + +**Google**: + +- `low` - Lavere innsats/tokenbudsjett +- `high` - Høyere innsats/tokenbudsjett + +:::tip +Denne listen er ikke uttømmende. Mange andre leverandører har også innebygde standardinnstillinger. +::: + +### Egendefinerte varianter + +Du kan overstyre eksisterende varianter eller legge til dine egne: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### Bytt varianter + +Bruk tastebindingen `variant_cycle` for raskt å bytte mellom varianter. [Finn ut mer](/docs/keybinds). + +--- + +## Lasting av modeller + +Når OpenCode starter opp, ser den etter modeller i følgende prioriterte rekkefølge: + +1. Kommandolinjeflagget `--model` eller `-m`. Formatet er det samme som i konfigurasjonsfilen: `provider_id/model_id`. + +2. Modelllisten i OpenCode-konfigurasjonen. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + + Formatet her er `provider/model`. + +3. Den sist brukte modellen. + +4. Den første modellen bruker en intern prioritet. diff --git a/packages/web/src/content/docs/nb/modes.mdx b/packages/web/src/content/docs/nb/modes.mdx new file mode 100644 index 00000000000..0322f069302 --- /dev/null +++ b/packages/web/src/content/docs/nb/modes.mdx @@ -0,0 +1,74 @@ +--- +title: Moduser +description: Ulike moduser for forskjellige brukstilfeller. +--- + +:::caution +Moduser er nå konfigurert gjennom alternativet `agent` i OpenCode-konfigurasjonen. De +Alternativet `mode` er nå utdatert. [Finn ut mer](/docs/agents). +::: + +Moduser i OpenCode lar deg tilpasse oppførselen, verktøyene og prompter for ulike brukstilfeller. + +Den kommer med to innebygde moduser: **bygg** og **plan**. Du kan tilpasse +disse eller konfigurer din egen gjennom OpenCode-konfigurasjonen. + +--- + +### Bygg + +Bygg er **standard**-modusen med alle verktøy aktivert. Dette er standardmodusen for utviklingsarbeid der du trenger full tilgang til filoperasjoner og systemkommandoer. + +--- + +### Plan + +En begrenset modus designet for planlegging og analyse. I planmodus er følgende verktøy deaktivert som standard: + +- `write` - Kan ikke opprette nye filer +- `edit` - Kan ikke endre eksisterende filer, bortsett fra filer som ligger på `.opencode/plans/*.md` for å detaljere selve planen +- `patch` - Kan ikke bruke patcher +- `bash` - Kan ikke utføre shell-kommandoer + +Denne modusen er nyttig når du vil at AI skal analysere kode, foreslå endringer eller lage planer uten å gjøre noen faktiske endringer i kodebasen. + +--- + +### 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. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +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.6-1.0**: Mer kreative og varierte svar, nyttig for idédugnad og utforskning + +Hvis ingen temperatur er spesifisert, bruker OpenCode modellspesifikke standardinnstillinger (vanligvis 0 for de fleste modeller, 0,55 for Qwen-modeller). + +--- + +### Bruksområder + +Her er noen vanlige bruksområder for forskjellige moduser. + +- **Bygg-modus**: Fullt utviklingsarbeid med alle verktøy aktivert +- **Plan-modus**: Analyse og planlegging uten å gjøre endringer +- **Review-modus**: Kodegjennomgang med skrivebeskyttet tilgang pluss dokumentasjonsverktøy +- **Debug-modus**: Fokusert på etterforskning med bash- og leseverktøy aktivert +- **Docs-modus**: Dokumentasjonsskriving med filoperasjoner, men ingen systemkommandoer + +Du kan også finne at forskjellige modeller er gode for forskjellige bruksområder. diff --git a/packages/web/src/content/docs/nb/network.mdx b/packages/web/src/content/docs/nb/network.mdx new file mode 100644 index 00000000000..418cc6d277c --- /dev/null +++ b/packages/web/src/content/docs/nb/network.mdx @@ -0,0 +1,57 @@ +--- +title: Nettverk +description: Konfigurer proxyer og tilpassede sertifikater. +--- + +OpenCode støtter standard proxy-miljøvariabler og tilpassede sertifikater for bedriftsnettverksmiljøer. + +--- + +## Mellomtjener + +OpenCode respekterer standard proxy-miljøvariabler. + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +TUI-en kommuniserer med en lokal HTTP-server. Du må unngå proxy for denne tilkoblingen for å unngå rutingsløyfer. +::: + +Du kan konfigurere serverens port og vertsnavn ved å bruke [CLI-flagg](/docs/cli#run). + +--- + +### Autentisering + +Hvis proxyen din krever grunnleggende autentisering, inkluder påloggingsinformasjon i URL-en. + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +Unngå hardkoding av passord. Bruk miljøvariabler eller sikker lagring av påloggingsinformasjon. +::: + +For proxyer som krever avansert autentisering som NTLM eller Kerberos, bør du vurdere en LLM Gateway som støtter din autentiseringsmetode. + +--- + +## Egendefinerte sertifikater + +Hvis bedriften din bruker egendefinerte CA-er for HTTPS-tilkoblinger, konfigurer OpenCode til å stole på dem. + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +Dette fungerer for både proxy-tilkoblinger og direkte API-tilgang. diff --git a/packages/web/src/content/docs/nb/permissions.mdx b/packages/web/src/content/docs/nb/permissions.mdx new file mode 100644 index 00000000000..e551a7fee30 --- /dev/null +++ b/packages/web/src/content/docs/nb/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: Tillatelser +description: Kontroller hvilke handlinger som krever godkjenning for å kjøre. +--- + +OpenCode bruker `permission`-konfigurasjonen for å bestemme om en gitt handling skal kjøres automatisk, spørre deg eller blokkeres. + +Fra og med `v1.1.1` er den eldre `tools` boolske konfigurasjonen avviklet og har blitt slått sammen til `permission`. Den gamle `tools`-konfigurasjonen støttes fortsatt for bakoverkompatibilitet. + +--- + +## Handlinger + +Hver tillatelsesregel løses til en av: + +- `"allow"` — kjør uten godkjenning +- `"ask"` — be om godkjenning +- `"deny"` — blokker handlingen + +--- + +## Konfigurasjon + +Du kan angi tillatelser globalt (med `*`), og overstyre spesifikke verktøy. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +Du kan også angi alle tillatelser samtidig: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## Granulære regler (objektsyntaks) + +For de fleste tillatelser kan du bruke et objekt til å bruke forskjellige handlinger basert på verktøyinndata. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +Regler evalueres etter mønstermatch, med **siste samsvarende regel som vinner**. Et vanlig mønster er å sette oppsamlingsregelen `"*"` først, og mer spesifikke regler etter den. + +### Jokertegn + +Tillatelsesmønstre bruker enkel jokertegnsamsvar: + +- `*` samsvarer med null eller flere av alle tegn +- `?` samsvarer med nøyaktig ett tegn +- Alle andre karakterer samsvarer bokstavelig talt + +### Utvidelse av hjemmekatalog + +Du kan bruke `~` eller `$HOME` i starten av et mønster for å referere til hjemmekatalogen din. Dette er spesielt nyttig for [`external_directory`](#external-directories) regler. + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### Eksterne kataloger + +Bruk `external_directory` for å tillate verktøyanrop som berører stier utenfor arbeidskatalogen der OpenCode ble startet. Dette gjelder alle verktøy som tar en bane som input (for eksempel `read`, `edit`, `list`, `glob`, `grep` og mange `bash`-kommandoer). + +Hjemmeutvidelse (som `~/...`) påvirker bare hvordan et mønster skrives. Den gjør ikke en ekstern bane til en del av det gjeldende arbeidsområdet, så stier utenfor arbeidskatalogen må fortsatt tillates via `external_directory`. + +For eksempel gir dette tilgang til alt under `~/projects/personal/`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +Enhver katalog som er tillatt her, arver de samme standardinnstillingene som gjeldende arbeidsområde. Siden [`read` er standard til `allow`](#defaults), er lesing også tillatt for oppføringer under `external_directory` med mindre overstyrt. Legg til eksplisitte regler når et verktøy skal begrenses i disse banene, for eksempel blokkering av redigeringer mens du beholder lesninger: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +Hold listen fokusert på klarerte baner, og lag ekstra tillat eller avslå regler etter behov for andre verktøy (for eksempel `bash`). + +--- + +## Tilgjengelige tillatelser + +OpenCode-tillatelser tastes inn etter verktøynavn, pluss et par sikkerhetsvakter: + +- `read` — lesing av en fil (tilsvarer filbanen) +- `edit` — alle filendringer (dekker `edit`, `write`, `patch`, `multiedit`) +- `glob` — fil-globing (tilsvarer glob-mønsteret) +- `grep` — innholdssøk (samsvarer med regex-mønsteret) +- `list` — viser filer i en katalog (tilsvarer katalogbanen) +- `bash` — kjører skallkommandoer (matcher analyserte kommandoer som `git status --porcelain`) +- `task` — start av subagenter (tilsvarer subagenttypen) +- `skill` — laster en ferdighet (tilsvarer navnet på ferdigheten) +- `lsp` — kjører LSP-spørringer (for øyeblikket ikke-granulære) +- `todoread`, `todowrite` — lesing/oppdatering av gjøremålslisten +- `webfetch` — henter en URL (tilsvarer URL) +- `websearch`, `codesearch` - nett-/kodesøk (samsvarer med søket) +- `external_directory` - utløses når et verktøy berører stier utenfor prosjektets arbeidskatalog +- `doom_loop` — utløses når det samme verktøykallet gjentas 3 ganger med identisk inndata + +--- + +## Standarder + +Hvis du ikke spesifiserer noe, starter OpenCode fra tillatte standardinnstillinger: + +- De fleste tillatelser er satt til `"allow"` som standard. +- `doom_loop` og `external_directory` er standard til `"ask"`. +- `read` er `"allow"`, men `.env` filer nektes som standard: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## Hva "ask" gjør + +Når OpenCode ber om godkjenning, gir brukergrensesnittet tre alternativer: + +- `once` — godkjenne nettopp denne forespørselen +- `always` — godkjenn fremtidige forespørsler som samsvarer med de foreslåtte mønstrene (for resten av den nåværende OpenCode-økten) +- `reject` — avslå forespørselen + +Settet med mønstre som `always` vil godkjenne, leveres av verktøyet (for eksempel, bash-godkjenninger hvitlister vanligvis et trygt kommandoprefiks som `git status*`). + +--- + +## Agenter + +Du kan overstyre tillatelser per agent. Agenttillatelser slås sammen med den globale konfigurasjonen, og agentregler har forrang. [Finn ut mer](/docs/agents#permissions) om agenttillatelser. + +:::note +Se avsnittet [Granular Rules (Object Syntax)](#granular-rules-object-syntax) ovenfor for mer detaljerte eksempler på mønstertilpasning. +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +Du kan også konfigurere agenttillatelser i Markdown: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +Bruk mønstertilpasning for kommandoer med argumenter. `"grep *"` tillater `grep pattern file.txt`, mens `"grep"` alene ville blokkert den. Kommandoer som `git status` fungerer for standard oppførsel, men krever eksplisitt tillatelse (som `"git status *"`) når argumenter sendes. +::: diff --git a/packages/web/src/content/docs/nb/plugins.mdx b/packages/web/src/content/docs/nb/plugins.mdx new file mode 100644 index 00000000000..6b6e1edf3f0 --- /dev/null +++ b/packages/web/src/content/docs/nb/plugins.mdx @@ -0,0 +1,385 @@ +--- +title: Programtillegg +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. + +For eksempler, sjekk ut [plugins](/docs/ecosystem#plugins) opprettet av fellesskapet. + +--- + +## Bruk av en plugin + +Det er to måter å laste inn plugins. + +--- + +### Fra lokale filer + +Plasser JavaScript- eller TypeScript-filer i plugin-katalogen. + +- `.opencode/plugins/` - Programtillegg på prosjektnivå +- `~/.config/opencode/plugins/` - Globale plugins + +Filer i disse katalogene lastes automatisk ved oppstart. + +--- + +### Fra npm + +Spesifiser npm-pakker i konfigurasjonsfilen. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +Både vanlige og scoped npm-pakker støttes. + +Bla gjennom tilgjengelige plugins i [økosystemet](/docs/ecosystem#plugins). + +--- + +### Hvordan plugins installeres + +**npm-plugins** installeres automatisk ved hjelp av Bun ved oppstart. Pakker og deres avhengigheter er bufret i `~/.cache/opencode/node_modules/`. + +**Lokale plugins** lastes direkte fra plugin-katalogen. For å bruke eksterne pakker, må du opprette en `package.json` i konfigurasjonskatalogen din (se [Dependencies](#dependencies)), eller publisere plugin-en til npm og [legg den til i konfigurasjonen din](/docs/config#plugins). + +--- + +### Lasterekkefølge + +Plugins lastes inn fra alle kilder og alle kroker kjøres i rekkefølge. Lastrekkefølgen er: + +1. Global konfigurasjon (`~/.config/opencode/opencode.json`) +2. Prosjektkonfigurasjon (`opencode.json`) +3. Global plugin-katalog (`~/.config/opencode/plugins/`) +4. Prosjektpluginkatalog (`.opencode/plugins/`) + +Dupliserte npm-pakker med samme navn og versjon lastes inn én gang. Imidlertid lastes en lokal plugin og en npm plugin med lignende navn begge separat. + +--- + +## Opprette en plugin + +En plugin er en **JavaScript/TypeScript-modul** som eksporterer en eller flere plugin-moduler +funksjoner. Hver funksjon mottar et kontekstobjekt og returnerer et krokobjekt. + +--- + +### Avhengigheter + +Lokale plugins og tilpassede verktøy kan bruke eksterne npm-pakker. Legg til en `package.json` til konfigurasjonskatalogen med avhengighetene du trenger. + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +OpenCode kjører `bun install` ved oppstart for å installere disse. Programtilleggene og verktøyene dine kan deretter importere dem. + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### Grunnleggende struktur + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +Plugin-funksjonen mottar: + +- `project`: Gjeldende prosjektinformasjon. +- `directory`: Gjeldende arbeidskatalog. +- `worktree`: Git-arbeidstrebanen. +- `client`: En OpenCode SDK klient for samhandling med AI. +- `$`: Buns [shell API](https://bun.com/docs/runtime/shell) for å utføre kommandoer. + +--- + +### TypeScript-støtte + +For TypeScript-plugins kan du importere typer fra plugin-pakken: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### Hendelser + +Plugins kan abonnere på hendelser som vist nedenfor i Eksempler-delen. Her er en liste over de forskjellige hendelsene som er tilgjengelige. + +#### Kommandohendelser + +- `command.executed` + +#### Filhendelser + +- `file.edited` +- `file.watcher.updated` + +#### Installasjonshendelser + +- `installation.updated` + +#### LSP Hendelser + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### Meldingshendelser + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### Tillatelseshendelser + +- `permission.asked` +- `permission.replied` + +#### Serverhendelser + +- `server.connected` + +#### Sesjonshendelser + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### Todo-hendelser + +- `todo.updated` + +#### Shell-hendelser + +- `shell.env` + +#### Verktøyhendelser + +- `tool.execute.after` +- `tool.execute.before` + +#### TUI Hendelser + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## Eksempler + +Her er noen eksempler på plugins du kan bruke for å utvide OpenCode. + +--- + +### Send varsler + +Send varsler når visse hendelser inntreffer: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +Vi bruker `osascript` for å kjøre AppleScript på macOS. Her bruker vi den til å sende varsler. + +:::note +Hvis du bruker OpenCode-skrivebordsappen, kan den sende systemvarsler automatisk når et svar er klart eller når en økt feiler. +::: + +--- + +### .env-beskyttelse + +Hindre OpenCode fra å lese `.env` filer: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### Injiser miljøvariabler + +Injiser miljøvariabler i all shell-utførelse (AI-verktøy og brukerterminaler): + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### Egendefinerte verktøy + +Plugins kan også legge til egendefinerte verktøy til OpenCode: + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +`tool`-hjelperen lager et tilpasset verktøy som OpenCode kan kalle. Den tar en Zod-skjemafunksjon og returnerer en verktøydefinisjon med: + +- `description`: Hva verktøyet gjør +- `args`: Zod-skjema for verktøyets argumenter + - `execute`: Funksjon som kjører når verktøyet kalles + +Dine egendefinerte verktøy vil være tilgjengelige for OpenCode sammen med innebygde verktøy. + +--- + +### Logging + +Bruk `client.app.log()` i stedet for `console.log` for strukturert logging: + +```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" }, + }, + }) +} +``` + +Nivåer: `debug`, `info`, `warn`, `error`. Se [SDK dokumentasjon](https://opencode.ai/docs/sdk) for detaljer. + +--- + +### Komprimerings-hooks + +Tilpass konteksten inkludert når en økt komprimeres: + +```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`-kroken trigges før LLM genererer et fortsettelsessammendrag. Bruk den til å injisere domenespesifikk kontekst som standard komprimeringsprompt ville gå glipp av. + +Du kan også erstatte komprimeringsprompten helt ved å stille inn `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. +` + }, + } +} +``` + +Når `output.prompt` er angitt, erstatter den standard komprimeringsprompt fullstendig. `output.context`-matrisen ignoreres i dette tilfellet. diff --git a/packages/web/src/content/docs/nb/providers.mdx b/packages/web/src/content/docs/nb/providers.mdx new file mode 100644 index 00000000000..58d325cab8c --- /dev/null +++ b/packages/web/src/content/docs/nb/providers.mdx @@ -0,0 +1,1889 @@ +--- +title: Leverandører +description: Bruke en hvilken som helst LLM-leverandør i OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console + +OpenCode bruker [AI SDK](https://ai-sdk.dev/) og [Models.dev](https://models.dev) for å støtte **75+ LLM leverandører** og den støtter kjøring av lokale modeller. + +For å legge til en leverandør må du: + +1. Legg til API-nøkkelen for leverandøren ved å bruke kommandoen `/connect`. +2. Konfigurer leverandøren i OpenCode-konfigurasjonen. + +--- + +### Legitimasjon + +Når du legger til en leverandørs API-nøkler med `/connect`-kommandoen, lagres de +i `~/.local/share/opencode/auth.json`. + +--- + +### Konfigurasjon + +Du kan tilpasse leverandørene gjennom `provider`-delen i OpenCode +konfig. + +--- + +#### Base-URL + +Du kan tilpasse base-URL-en for enhver leverandør ved å angi alternativet `baseURL`. Dette er nyttig når du bruker proxy-tjenester eller tilpassede endepunkter. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen er en liste over modeller levert av OpenCode-teamet som har vært +testet og verifisert for å fungere godt med OpenCode. [Finn ut mer](/docs/zen). + +:::tip +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). + + ```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 +liste, åpne gjerne en PR. + +:::note +Ser du ikke en leverandør her? Send inn en PR. +::: + +--- + +### 302.AI + +1. Gå over til [302.AI-konsollen](https://302.ai/), opprett en konto og generer en API-nøkkel. + +2. Kjør kommandoen `/connect` og søk etter **302.AI**. + + ```txt + /connect + ``` + +3. Skriv inn 302.AI API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell. + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +Slik bruker du Amazon Bedrock med OpenCode: + +1. Gå over til **modellkatalogen** i Amazon Bedrock-konsollen og be om + tilgang til modellene du ønsker. + + :::tip + Du må ha tilgang til modellen du ønsker i Amazon Bedrock. + ::: + +2. **Konfigurer autentisering** ved å bruke en av følgende metoder: + + #### Miljøvariabler (hurtigstart) + + Angi en av disse miljøvariablene mens du kjører OpenCode: + + ```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode + ``` + + Eller legg dem til bash-profilen din: + + ```bash title="~/.bash_profile" + export AWS_PROFILE=my-dev-profile + export AWS_REGION=us-east-1 + ``` + + #### Konfigurasjonsfil (anbefalt) + + For prosjektspesifikk eller vedvarende konfigurasjon, bruk `opencode.json`: + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile" + } + } + } + } + ``` + + **Tilgjengelige alternativer:** + - `region` - AWS region (f.eks. `us-east-1`, `eu-west-1`) + - `profile` - AWS navngitt profil fra `~/.aws/credentials` + - `endpoint` - Egendefinert endepunkt URL for VPC-endepunkter (alias for generisk `baseURL`-alternativ) + + :::tip + Alternativer for konfigurasjonsfil har forrang over miljøvariabler. + ::: + + #### Avansert: VPC-endepunkter + + Hvis du bruker VPC-endepunkter for Bedrock: + + ```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 + Alternativet `endpoint` er et alias for det generiske alternativet `baseURL`, ved å bruke AWS-spesifikk terminologi. Hvis både `endpoint` og `baseURL` er spesifisert, har `endpoint` forrang. + ::: + + #### Autentiseringsmetoder + - **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: Opprett en IAM-bruker og generer tilgangsnøkler i AWS-konsollen + - **`AWS_PROFILE`**: Bruk navngitte profiler fra `~/.aws/credentials`. Konfigurer først med `aws configure --profile my-profile` eller `aws sso login` + - **`AWS_BEARER_TOKEN_BEDROCK`**: Generer langsiktige API-nøkler fra Amazon Bedrock-konsollen + - **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: For EKS IRSA (IAM roller for tjenestekontoer) eller andre Kubernetes-miljøer med OIDC føderasjon. Disse miljøvariablene injiseres automatisk av Kubernetes når du bruker tjenestekontokommentarer. + + #### Autentiseringsprioritet + + Amazon Bedrock bruker følgende autentiseringsprioritet: + 1. **Bearer Token** - `AWS_BEARER_TOKEN_BEDROCK` miljøvariabel eller token fra kommandoen `/connect` + 2. **AWS legitimasjonskjede** - profil, tilgangsnøkler, delt legitimasjon, IAM roller, nettidentitetstokener (EKS IRSA), forekomstmetadata + + :::note + Når et bærertoken er angitt (via `/connect` eller `AWS_BEARER_TOKEN_BEDROCK`), har det forrang over alle AWS legitimasjonsmetoder inkludert konfigurerte profiler. + ::: + +3. Kjør kommandoen `/models` for å velge modellen du ønsker. + + ```txt + /models + ``` + +:::note +For egendefinerte slutningsprofiler, bruk modellen og leverandørnavnet i nøkkelen og sett egenskapen `id` til arn. Dette sikrer korrekt caching: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. Når du har registrert deg, kjør kommandoen `/connect` og velg Anthropic. + + ```txt + /connect + ``` + +2. Her kan du velge alternativet **Claude Pro/Max** og det vil åpne nettleseren din + og ber deg om å autentisere. + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. Nå skal alle Anthropic-modellene være tilgjengelige når du bruker kommandoen `/models`. + + ```txt + /models + ``` + +:::info +Å bruke Claude Pro/Max-abonnementet ditt i opencode støttes ikke offisielt av [Anthropic](https://anthropic.com). +::: + +##### Bruke API-nøkler + +Du kan også velge **Opprett en API nøkkel** hvis du ikke har et Pro/Max-abonnement. Den åpner også nettleseren din og ber deg logge på Anthropic og gi deg en kode du kan lime inn i terminalen din. + +Eller hvis du allerede har en API-nøkkel, kan du velge **Angi API-nøkkel manuelt** og lime den inn i terminalen. + +--- + +### Azure OpenAI + +:::note +Hvis du støter på «Beklager, men jeg kan ikke hjelpe med den forespørselen»-feil, kan du prøve å endre innholdsfilteret fra **DefaultV2** til **Default** i Azure-ressursen. +::: + +1. Gå over til [Azure-portalen](https://portal.azure.com/) og lag en **Azure OpenAI**-ressurs. Du trenger: + - **Ressursnavn**: Dette blir en del av API-endepunktet (`https://RESOURCE_NAME.openai.azure.com/`) + - **API nøkkel**: Enten `KEY 1` eller `KEY 2` fra ressursen din + +2. Gå til [Azure AI Foundry](https://ai.azure.com/) og distribuer en modell. + + :::note + Distribusjonsnavnet må samsvare med modellnavnet for at OpenCode skal fungere skikkelig. + ::: + +3. Kjør kommandoen `/connect` og søk etter **Azure**. + + ```txt + /connect + ``` + +4. Skriv inn API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Angi ressursnavnet ditt som en miljøvariabel: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + Eller legg den til bash-profilen din: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. Kjør kommandoen `/models` for å velge den distribuerte modellen. + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. Gå over til [Azure-portalen](https://portal.azure.com/) og lag en **Azure OpenAI**-ressurs. Du trenger: + - **Ressursnavn**: Dette blir en del av API-endepunktet (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) + - **API nøkkel**: Enten `KEY 1` eller `KEY 2` fra ressursen din + +2. Gå til [Azure AI Foundry](https://ai.azure.com/) og distribuer en modell. + + :::note + Distribusjonsnavnet må samsvare med modellnavnet for at OpenCode skal fungere skikkelig. + ::: + +3. Kjør kommandoen `/connect` og søk etter **Azure Cognitive Services**. + + ```txt + /connect + ``` + +4. Skriv inn API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Angi ressursnavnet ditt som en miljøvariabel: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + Eller legg den til bash-profilen din: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. Kjør kommandoen `/models` for å velge den distribuerte modellen. + + ```txt + /models + ``` + +--- + +### Baseten + +1. Gå over til [Baseten](https://app.baseten.co/), opprett en konto og generer en API nøkkel. + +2. Kjør kommandoen `/connect` og søk etter **Baseten**. + + ```txt + /connect + ``` + +3. Skriv inn din Baseten API nøkkel. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell. + + ```txt + /models + ``` + +--- + +### Cerebras + +1. Gå over til [Cerebras-konsollen](https://inference.cerebras.ai/), opprett en konto og generer en API-nøkkel. + +2. Kjør kommandoen `/connect` og søk etter **Cerebras**. + + ```txt + /connect + ``` + +3. Skriv inn Cerebras API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell som _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +Cloudflare AI Gateway lar deg få tilgang til modeller fra OpenAI, Anthropic, Workers AI og mer gjennom et enhetlig endepunkt. Med [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) trenger du ikke separate API-nøkler for hver leverandør. + +1. Gå over til [Cloudflare-dashbordet](https://dash.cloudflare.com/), naviger til **AI** > **AI Gateway**, og lag en ny gateway. + +2. Angi konto ID og gateway ID som miljøvariabler. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. Kjør kommandoen `/connect` og søk etter **Cloudflare AI Gateway**. + + ```txt + /connect + ``` + +4. Skriv inn Cloudflare API-tokenet ditt. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + Eller angi den som en miljøvariabel. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. Kjør kommandoen `/models` for å velge en modell. + + ```txt + /models + ``` + + Du kan også legge til modeller gjennom OpenCode-konfigurasjonen. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +### Cortecs + +1. Gå over til [Cortecs-konsollen](https://cortecs.ai/), opprett en konto og generer en API-nøkkel. + +2. Kjør kommandoen `/connect` og søk etter **Cortecs**. + + ```txt + /connect + ``` + +3. Skriv inn Cortecs API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell som _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. Gå over til [DeepSeek-konsollen](https://platform.deepseek.com/), opprett en konto og klikk på **Opprett ny API-nøkkel**. + +2. Kjør kommandoen `/connect` og søk etter **DeepSeek**. + + ```txt + /connect + ``` + +3. Skriv inn DeepSeek API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en DeepSeek-modell som _DeepSeek Reasoner_. + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. Gå over til [Deep Infra-dashbordet](https://deepinfra.com/dash), opprett en konto og generer en API-nøkkel. + +2. Kjør kommandoen `/connect` og søk etter **Deep Infra**. + + ```txt + /connect + ``` + +3. Skriv inn Deep Infra API nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell. + + ```txt + /models + ``` + +--- + +### Firmware + +1. Gå over til [Firmware dashboard](https://app.firmware.ai/signup), opprett en konto og generer en API nøkkel. + +2. Kjør kommandoen `/connect` og søk etter **Firmware**. + + ```txt + /connect + ``` + +3. Skriv inn firmware API nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell. + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. Gå over til [Fireworks AI-konsollen](https://app.fireworks.ai/), opprett en konto og klikk på **Create API Key**. + +2. Kjør kommandoen `/connect` og søk etter **Fireworks AI**. + + ```txt + /connect + ``` + +3. Skriv inn Fireworks AI API nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell som _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo gir AI-drevet agentchat med native verktøyoppringingsfunksjoner gjennom GitLabs Anthropic-proxy. + +1. Kjør kommandoen `/connect` og velg GitLab. + + ```txt + /connect + ``` + +2. Velg autentiseringsmetoden din: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ + ``` + + #### Bruke OAuth (anbefalt) + + Velg **OAuth** og nettleseren din åpnes for autorisasjon. + + #### Bruker personlig tilgangstoken + 1. Gå til [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens) + 2. Klikk på **Legg til nytt token** + 3. Navn: `OpenCode`, omfang: `api` + 4. Kopier tokenet (starter med `glpat-`) + 5. Skriv den inn i terminalen + +3. Kjør kommandoen `/models` for å se tilgjengelige modeller. + + ```txt + /models + ``` + + Tre Claude-baserte modeller er tilgjengelige: + - **duo-chat-haiku-4-5** (standard) - Raske svar for raske oppgaver + - **duo-chat-sonnet-4-5** - Balansert ytelse for de fleste arbeidsflyter + - **duo-chat-opus-4-5** - Mest egnet for kompleks analyse + +:::note +Du kan også spesifisere 'GITLAB_TOKEN' miljøvariabel hvis du ikke vil +for å lagre token i OpenCode auth-lagring. +::: + +##### Selvhostet GitLab + +:::note[Merknad om samsvar] +OpenCode bruker en liten modell for noen AI oppgaver som å generere økttittelen. +Den er konfigurert til å bruke gpt-5-nano som standard, hostet av Zen. For å låse OpenCode +for kun å bruke din egen GitLab-hostede forekomst, legg til følgende i din +`opencode.json` fil. Det anbefales også å deaktivere øktdeling. + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +For selvhostede GitLab-forekomster: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +Hvis forekomsten din kjører en tilpasset AI-gateway: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +Eller legg til bash-profilen din: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +GitLab-administratoren din må aktivere følgende: + +1. [Duo Agent Platform](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) for brukeren, gruppen eller forekomsten +2. Funksjonsflagg (via Rails-konsollen): + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: + +##### OAuth for selvvertsbaserte forekomster + +For å få Oauth til å fungere for din selvhostede forekomst, må du opprette +en ny applikasjon (Innstillinger → Programmer) med +tilbakeringing URL `http://127.0.0.1:8080/callback` og følgende omfang: + +- api (Få tilgang til API på dine vegne) +- read_user (Les din personlige informasjon) +- read_repository (tillater skrivebeskyttet tilgang til depotet) + +Utsett deretter applikasjonen ID som miljøvariabel: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +Mer dokumentasjon på [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth) hjemmeside. + +##### Konfigurasjon + +Tilpass gjennom `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### GitLab API Verktøy (valgfritt, men sterkt anbefalt) + +For å få tilgang til GitLab-verktøy (sammenslåingsforespørsler, problemer, pipelines, CI/CD, etc.): + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +Denne plugin-en gir omfattende GitLab-repository-administrasjonsfunksjoner, inkludert MR-anmeldelser, problemsporing, pipeline-overvåking og mer. + +--- + +### GitHub Copilot + +Slik bruker du GitHub Copilot-abonnementet med OpenCode: + +:::note +Noen modeller kan trenge en [Pro+ +abonnement](https://github.com/features/copilot/plans) å bruke. + +Noen modeller må aktiveres manuelt i [GitHub Copilot-innstillingene](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use). +::: + +1. Kjør kommandoen `/connect` og søk etter GitHub Copilot. + + ```txt + /connect + ``` + +2. Naviger til [github.com/login/device](https://github.com/login/device) og skriv inn koden. + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + └ Waiting for authorization... + ``` + +3. Kjør nå kommandoen `/models` for å velge modellen du ønsker. + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +Slik bruker du Google Vertex AI med OpenCode: + +1. Gå over til **Model Garden** i Google Cloud Console og sjekk + modeller tilgjengelig i din region. + + :::note + Du må ha et Google Cloud-prosjekt med Vertex AI API aktivert. + ::: + +2. Angi de nødvendige miljøvariablene: + - `GOOGLE_CLOUD_PROJECT`: Google Cloud-prosjektet ditt ID + - `VERTEX_LOCATION` (valgfritt): Regionen for verteks AI (standard til `global`) + - Autentisering (velg en): + - `GOOGLE_APPLICATION_CREDENTIALS`: Bane til tjenestekontoen JSON nøkkelfil + - Autentiser med gcloud CLI: `gcloud auth application-default login` + + Sett dem mens du kjører OpenCode. + + ```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode + ``` + + Eller legg dem til på bash-profilen din. + + ```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`-regionen forbedrer tilgjengeligheten og reduserer feil uten ekstra kostnad. Bruk regionale endepunkter (f.eks. `us-central1`) for krav til dataopphold. [Finn ut mer](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. Kjør kommandoen `/models` for å velge modellen du ønsker. + + ```txt + /models + ``` + +--- + +### Groq + +1. Gå over til [Groq-konsollen](https://console.groq.com/), klikk på **Create API Key**, og kopier nøkkelen. + +2. Kjør kommandoen `/connect` og søk etter Groq. + + ```txt + /connect + ``` + +3. Skriv inn API-nøkkelen for leverandøren. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge den du ønsker. + + ```txt + /models + ``` + +--- + +### Hugging Face + +[Hugging Face Inference Providers](https://huggingface.co/docs/inference-providers) gir tilgang til åpne modeller som støttes av 17+ leverandører. + +1. Gå over til [Hugging Face-innstillinger](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained) for å opprette et token med tillatelse til å ringe til inferensleverandører. + +2. Kjør kommandoen `/connect` og søk etter **Hugging Face**. + + ```txt + /connect + ``` + +3. Skriv inn ditt Hugging Face-token. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell som _Kimi-K2-Instruct_ eller _GLM-4.6_. + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) er en LLM observerbarhetsplattform som gir logging, overvåking og analyser for AI-applikasjonene dine. Helicone AI Gateway ruter forespørslene dine til riktig leverandør automatisk basert på modellen. + +1. Gå over til [Helicone](https://helicone.ai), opprett en konto og generer en API nøkkel fra dashbordet. + +2. Kjør kommandoen `/connect` og søk etter **Helicone**. + + ```txt + /connect + ``` + +3. Skriv inn Helicone API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell. + + ```txt + /models + ``` + +For flere leverandører og avanserte funksjoner som bufring og hastighetsbegrensning, sjekk [Helicone-dokumentasjonen](https://docs.helicone.ai). + +#### Valgfrie konfigurasjoner + +I tilfelle du ser en funksjon eller modell fra Helicone som ikke konfigureres automatisk gjennom OpenCode, kan du alltid konfigurere den selv. + +Her er [Helicone's Model Directory](https://helicone.ai/models), du trenger denne for å hente ID-ene til modellene du vil legge til. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### Egendefinerte headere + +Helicone støtter tilpassede headere for funksjoner som bufring, brukersporing og øktadministrasjon. Legg dem til leverandørkonfigurasjonen din ved å bruke `options.headers`: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### Sesjonssporing + +Helicones [Sessions](https://docs.helicone.ai/features/sessions) funksjon lar deg gruppere relaterte LLM forespørsler sammen. Bruk [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) plugin for automatisk å logge hver OpenCode-samtale som en økt i Helicone. + +```bash +npm install -g opencode-helicone-session +``` + +Legg den til i konfigurasjonen din. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +Programtillegget injiserer `Helicone-Session-Id` og `Helicone-Session-Name` headere i forespørslene dine. På Helicones Sessions-side vil du se hver OpenCode-samtale oppført som en separat økt. + +##### Vanlige Helicone-headere + +| Overskrift | Beskrivelse | +| -------------------------- | -------------------------------------------------------------------------- | +| `Helicone-Cache-Enabled` | Aktiver responsbufring (`true`/`false`) | +| `Helicone-User-Id` | Spor beregninger etter bruker | +| `Helicone-Property-[Name]` | Legg til egendefinerte egenskaper (f.eks. `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | Knytt forespørsler til spørsmålsversjoner | + +Se [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory) for alle tilgjengelige overskrifter. + +--- + +### llama.cpp + +Du kan konfigurere OpenCode for å bruke lokale modeller gjennom [llama.cpp](https://github.com/ggml-org/llama.cpp) llama-server-verktøyet. + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +I dette eksemplet: + +- `llama.cpp` er den tilpassede leverandøren ID. Dette kan være hvilken som helst streng du vil. +- `npm` spesifiserer pakken som skal brukes for denne leverandøren. Her brukes `@ai-sdk/openai-compatible` for enhver OpenAI-kompatibel API. +- `name` er visningsnavnet for leverandøren i UI. +- `options.baseURL` er endepunktet for den lokale serveren. +- `models` er et kart over modell-ID-er til deres konfigurasjoner. Modellnavnet vil vises i modellvalglisten. + +--- + +### IO.NET + +IO.NET tilbyr 17 modeller optimert for ulike brukstilfeller: + +1. Gå over til [IO.NET-konsollen](https://ai.io.net/), opprett en konto og generer en API-nøkkel. + +2. Kjør kommandoen `/connect` og søk etter **IO.NET**. + + ```txt + /connect + ``` + +3. Skriv inn nøkkelen IO.NET API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell. + + ```txt + /models + ``` + +--- + +### LM Studio + +Du kan konfigurere OpenCode for å bruke lokale modeller gjennom LM Studio. + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +I dette eksemplet: + +- `lmstudio` er den tilpassede leverandøren ID. Dette kan være hvilken som helst streng du vil. +- `npm` spesifiserer pakken som skal brukes for denne leverandøren. Her brukes `@ai-sdk/openai-compatible` for enhver OpenAI-kompatibel API. +- `name` er visningsnavnet for leverandøren i UI. +- `options.baseURL` er endepunktet for den lokale serveren. +- `models` er et kart over modell-ID-er til deres konfigurasjoner. Modellnavnet vil vises i modellvalglisten. + +--- + +### Moonshot AI + +Slik bruker du Kimi K2 fra Moonshot AI: + +1. Gå over til [Moonshot AI-konsollen](https://platform.moonshot.ai/console), opprett en konto og klikk på **Opprett API-nøkkel**. + +2. Kjør kommandoen `/connect` og søk etter **Moonshot AI**. + + ```txt + /connect + ``` + +3. Skriv inn Moonshot API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge _Kimi K2_. + + ```txt + /models + ``` + +--- + +### MiniMax + +1. Gå over til [MiniMax API-konsollen](https://platform.minimax.io/login), opprett en konto og generer en API-nøkkel. + +2. Kjør kommandoen `/connect` og søk etter **MiniMax**. + + ```txt + /connect + ``` + +3. Skriv inn MiniMax API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell som _M2.1_. + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. Gå over til [Nebius Token Factory-konsollen](https://tokenfactory.nebius.com/), opprett en konto og klikk på **Legg til nøkkel**. + +2. Kjør kommandoen `/connect` og søk etter **Nebius Token Factory**. + + ```txt + /connect + ``` + +3. Skriv inn Nebius Token Factory API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell som _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Ollama + +Du kan konfigurere OpenCode for å bruke lokale modeller gjennom Ollama. + +:::tip +Ollama kan automatisk konfigurere seg selv for OpenCode. Se [Ollama-integrasjonsdokumentene](https://docs.ollama.com/integrations/opencode) for detaljer. +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +I dette eksemplet: + +- `ollama` er den tilpassede leverandøren ID. Dette kan være hvilken som helst streng du vil. +- `npm` spesifiserer pakken som skal brukes for denne leverandøren. Her brukes `@ai-sdk/openai-compatible` for enhver OpenAI-kompatibel API. +- `name` er visningsnavnet for leverandøren i UI. +- `options.baseURL` er endepunktet for den lokale serveren. +- `models` er et kart over modell-ID-er til deres konfigurasjoner. Modellnavnet vil vises i modellvalglisten. + +:::tip +Hvis verktøykall ikke fungerer, prøv å øke `num_ctx` i Ollama. Start rundt 16k - 32k. +::: + +--- + +### Ollama Cloud + +Slik bruker du Ollama Cloud med OpenCode: + +1. Gå over til [https://ollama.com/](https://ollama.com/) og logg på eller opprett en konto. + +2. Naviger til **Innstillinger** > **Nøkler** og klikk på **Legg til API nøkkel** for å generere en ny API nøkkel. + +3. Kopier API-nøkkelen for bruk i OpenCode. + +4. Kjør kommandoen `/connect` og søk etter **Ollama Cloud**. + + ```txt + /connect + ``` + +5. Skriv inn din Ollama Cloud API nøkkel. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **Viktig**: Før du bruker skymodeller i OpenCode, må du hente modellinformasjonen lokalt: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. Kjør kommandoen `/models` for å velge din Ollama Cloud-modell. + + ```txt + /models + ``` + +--- + +### OpenAI + +Vi anbefaler at du registrerer deg for [ChatGPT Plus eller Pro](https://chatgpt.com/pricing). + +1. Når du har registrert deg, kjør kommandoen `/connect` og velg OpenAI. + + ```txt + /connect + ``` + +2. Her kan du velge alternativet **ChatGPT Plus/Pro** og det åpner nettleseren din + og ber deg om å autentisere. + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. Nå skal alle OpenAI-modellene være tilgjengelige når du bruker kommandoen `/models`. + + ```txt + /models + ``` + +##### Bruke API-nøkler + +Hvis du allerede har en API-nøkkel, kan du velge **Angi API-nøkkel manuelt** og lime den inn i terminalen. + +--- + +### OpenCode Zen + +OpenCode Zen er en liste over testede og verifiserte modeller levert av OpenCode-teamet. [Finn ut mer](/docs/zen). + +1. Logg på **OpenCode Zen** og klikk på **Create API Key**. + +2. Kjør kommandoen `/connect` og søk etter **OpenCode Zen**. + + ```txt + /connect + ``` + +3. Skriv inn OpenCode API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell som _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### OpenRouter + +1. Gå over til [OpenRouter-dashbordet](https://openrouter.ai/settings/keys), klikk på **Create API Key**, og kopier nøkkelen. + +2. Kjør kommandoen `/connect` og søk etter OpenRouter. + + ```txt + /connect + ``` + +3. Skriv inn API-nøkkelen for leverandøren. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Mange OpenRouter-modeller er forhåndslastet som standard, kjør kommandoen `/models` for å velge den du ønsker. + + ```txt + /models + ``` + + Du kan også legge til flere modeller gjennom OpenCode-konfigurasjonen. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +5. Du kan også tilpasse dem gjennom OpenCode-konfigurasjonen. Her er et eksempel på å spesifisere en leverandør + + ```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 gir tilgang til 40+ modeller fra OpenAI, Anthropic, Google, Amazon, Meta, Mistral og AI21 gjennom en enhetlig plattform. + +1. Gå til din [SAP BTP Cockpit](https://account.hana.ondemand.com/), naviger til din SAP AI kjernetjenesteforekomst, og lag en tjenestenøkkel. + + :::tip + Tjenestenøkkelen er et JSON-objekt som inneholder `clientid`, `clientsecret`, `url` og `serviceurls.AI_API_URL`. Du finner AI kjerneforekomsten din under **Tjenester** > **Forekomster og abonnementer** i BTP Cockpit. + ::: + +2. Kjør kommandoen `/connect` og søk etter **SAP AI Core**. + + ```txt + /connect + ``` + +3. Skriv inn tjenestenøkkelen JSON. + + ```txt + ┌ Service key + │ + │ + └ enter + ``` + + Eller angi miljøvariabelen `AICORE_SERVICE_KEY`: + + ```bash + AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode + ``` + + Eller legg den til bash-profilen din: + + ```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' + ``` + +4. Angi eventuelt distribusjon ID og ressursgruppe: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + Disse innstillingene er valgfrie og bør konfigureres i henhold til SAP AI kjerneoppsettet. + ::: + +5. Kjør kommandoen `/models` for å velge fra 40+ tilgjengelige modeller. + + ```txt + /models + ``` + +--- + +### OVHcloud AI Endpoints + +1. Gå over 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å **Opprett en ny API-nøkkel**. + +2. Kjør kommandoen `/connect` og søk etter **OVHcloud AI Endpoints**. + + ```txt + /connect + ``` + +3. Skriv inn OVHcloud AI Endpoints API nøkkel. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell som _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Scaleway + +Slik bruker du [Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/) med OpenCode: + +1. Gå over til [Scaleway Console IAM innstillinger](https://console.scaleway.com/iam/api-keys) for å generere en ny API nøkkel. + +2. Kjør kommandoen `/connect` og søk etter **Scaleway**. + + ```txt + /connect + ``` + +3. Skriv inn Scaleway API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell som _devstral-2-123b-instruct-2512_ eller _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Together AI + +1. Gå over til [Together AI-konsollen](https://api.together.ai), opprett en konto og klikk på **Legg til nøkkel**. + +2. Kjør kommandoen `/connect` og søk etter **Together AI**. + + ```txt + /connect + ``` + +3. Skriv inn Together AI API nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell som _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Venice AI + +1. Gå over til [Venice AI-konsollen](https://venice.ai), opprett en konto og generer en API-nøkkel. + +2. Kjør kommandoen `/connect` og søk etter **Venice AI**. + + ```txt + /connect + ``` + +3. Skriv inn Venice AI API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell som _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + +### Vercel AI Gateway + +Vercel AI Gateway lar deg få tilgang til modeller fra OpenAI, Anthropic, Google, xAI og mer gjennom et enhetlig endepunkt. Modeller tilbys til listepris uten påslag. + +1. Gå over til [Vercel dashboard](https://vercel.com/), naviger til fanen **AI Gateway**, og klikk på **API nøkler** for å opprette en ny API nøkkel. + +2. Kjør kommandoen `/connect` og søk etter **Vercel AI Gateway**. + + ```txt + /connect + ``` + +3. Skriv inn Vercel AI Gateway API nøkkel. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell. + + ```txt + /models + ``` + +Du kan også tilpasse modeller gjennom OpenCode-konfigurasjonen. Her er et eksempel på spesifisering av leverandørrutingsrekkefølge. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "vercel": { + "models": { + "anthropic/claude-sonnet-4": { + "options": { + "order": ["anthropic", "vertex"] + } + } + } + } + } +} +``` + +Noen nyttige rutealternativer: + +| Alternativ | Beskrivelse | +| ------------------- | ------------------------------------------------------------- | +| `order` | Providersekvens for å prøve | +| `only` | Begrens til spesifikke leverandører | +| `zeroDataRetention` | Bruk kun leverandører med null retningslinjer for datalagring | + +--- + +### xAI + +1. Gå over til [xAI-konsollen](https://console.x.ai/), opprett en konto og generer en API-nøkkel. + +2. Kjør kommandoen `/connect` og søk etter **xAI**. + + ```txt + /connect + ``` + +3. Skriv inn xAI API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell som _Grok Beta_. + + ```txt + /models + ``` + +--- + +### Z.AI + +1. Gå over til [Z.AI API-konsollen](https://z.ai/manage-apikey/apikey-list), opprett en konto og klikk på **Opprett en ny API-nøkkel**. + +2. Kjør kommandoen `/connect` og søk etter **Z.AI**. + + ```txt + /connect + ``` + + Hvis du abonnerer på **GLM Coding Plan**, velg **Z.AI Coding Plan**. + +3. Skriv inn Z.AI API-nøkkelen. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kjør kommandoen `/models` for å velge en modell som _GLM-4.7_. + + ```txt + /models + ``` + +--- + +### ZenMux + +1. Gå over til [ZenMux-dashbordet](https://zenmux.ai/settings/keys), klikk på **Create API Key**, og kopier nøkkelen. + +2. Kjør kommandoen `/connect` og søk etter ZenMux. + + ```txt + /connect + ``` + +3. Skriv inn API-nøkkelen for leverandøren. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Mange ZenMux-modeller er forhåndslastet som standard, kjør kommandoen `/models` for å velge den du ønsker. + + ```txt + /models + ``` + + Du kan også legge til flere modeller gjennom OpenCode-konfigurasjonen. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "zenmux": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +--- + +## Egendefinert leverandør + +Slik legger du til en **OpenAI-kompatibel**-leverandør som ikke er oppført i `/connect`-kommandoen: + +:::tip +Du kan bruke hvilken som helst OpenAI-kompatibel leverandør med OpenCode. De fleste moderne AI-leverandører tilbyr OpenAI-kompatible APIer. +::: + +1. Kjør kommandoen `/connect` og rull ned til **Annet**. + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. Skriv inn en unik ID for leverandøren. + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::note + Velg en minneverdig ID, du vil bruke denne i konfigurasjonsfilen din. + ::: + +3. Skriv inn API-nøkkelen for leverandøren. + + ```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. Opprett eller oppdater `opencode.json`-filen i prosjektkatalogen: + + ```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" + } + } + } + } + } + ``` + + Her er konfigurasjonsalternativene: + - **npm**: AI SDK pakke å bruke, `@ai-sdk/openai-compatible` for OpenAI-kompatible leverandører + - **navn**: Visningsnavn i UI. + - **modeller**: Tilgjengelige modeller. + - **options.baseURL**: API endepunkt URL. + - **options.apiKey**: Angi API-nøkkelen hvis du ikke bruker auth. + - **options.headers**: Angi egendefinerte overskrifter. + + Mer om de avanserte alternativene i eksemplet nedenfor. + +5. Kjør kommandoen `/models` og din egendefinerte leverandør og modeller vil vises i utvalgslisten. + +--- + +##### Eksempel + +Her er et eksempel på innstilling av alternativene `apiKey`, `headers` og modell `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 + } + } + } + } + } +} +``` + +Konfigurasjonsdetaljer: + +- **apiKey**: Angi med `env` variabel syntaks, [finn ut mer](/docs/config#env-vars). +- **headere**: Egendefinerte headere sendt med hver forespørsel. +- **limit.context**: Maksimalt Input Tokens som modellen godtar. +- **limit.output**: Maksimalt antall tokens modellen kan generere. + +`limit`-feltene lar OpenCode forstå hvor mye kontekst du har igjen. Standardleverandører henter disse automatisk fra models.dev. + +--- + +## Feilsøking + +Hvis du har problemer med å konfigurere en leverandør, sjekk følgende: + +1. **Sjekk autentiseringsoppsettet**: Kjør `opencode auth list` for å se om legitimasjonen + for leverandøren legges til konfigurasjonen din. + + Dette gjelder ikke leverandører som Amazon Bedrock, som er avhengige av miljøvariabler for godkjenning. + +2. For tilpassede leverandører, sjekk OpenCode-konfigurasjonen og: + - Sørg for at leverandør-ID-en som brukes i `/connect`-kommandoen samsvarer med ID i OpenCode-konfigurasjonen. + - Den riktige npm-pakken brukes for leverandøren. Bruk for eksempel `@ai-sdk/cerebras` for Cerebras. Og for alle andre OpenAI-kompatible leverandører, bruk `@ai-sdk/openai-compatible`. + - Kontroller at riktig API-endepunkt er brukt i `options.baseURL`-feltet. diff --git a/packages/web/src/content/docs/nb/rules.mdx b/packages/web/src/content/docs/nb/rules.mdx new file mode 100644 index 00000000000..38d5b77110d --- /dev/null +++ b/packages/web/src/content/docs/nb/rules.mdx @@ -0,0 +1,180 @@ +--- +title: Regler +description: Set custom instructions for OpenCode. +--- + +Du kan gi tilpassede instruksjoner for å OpenCode ved å opprette en `AGENTS.md`-fil. Dette ligner på Cursors regler. Den inneholder instruksjoner som vil bli inkludert i LLMs kontekst for å tilpasse oppførselen til ditt spesifikke prosjekt. + +--- + +## Initialisering + +For å lage en ny `AGENTS.md` fil, kan du kjøre kommandoen `/init` i OpenCode. + +:::tip +Du bør sjekke inn prosjektets `AGENTS.md`-fil i Git. +::: + +Dette vil skanne prosjektet og alt dets innhold for å forstå hva prosjektet handler om og generere en `AGENTS.md`-fil med det. Dette hjelper OpenCode å navigere i prosjektet bedre. + +Hvis du har en eksisterende `AGENTS.md`-fil, vil denne prøve å legge til den. + +--- + +## Eksempel + +Du kan også bare lage denne filen manuelt. Her er et eksempel på noen ting du kan legge inn i en `AGENTS.md`-fil. + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +Vi legger til prosjektspesifikke instruksjoner her, og dette vil bli delt på tvers av teamet ditt. + +--- + +## Typer + +OpenCode støtter også lesing av `AGENTS.md`-filen fra flere steder. Og dette tjener forskjellige formål. + +### Prosjekt + +Plasser en `AGENTS.md` i prosjektroten for prosjektspesifikke regler. Disse gjelder kun når du arbeider i denne katalogen eller dens underkataloger. + +### Globalt + +Du kan også ha globale regler i en `~/.config/opencode/AGENTS.md`-fil. Dette blir brukt på alle OpenCode-økter. + +Siden dette ikke er forpliktet til Git eller delt med teamet ditt, anbefaler vi å bruke dette til å spesifisere eventuelle personlige regler som LLM bør følge. + +### Claude Code-kompatibilitet + +For brukere som migrerer fra Claude Code, støtter OpenCode Claude Codes filkonvensjoner som fallbacks: + +- **Prosjektregler**: `CLAUDE.md` i prosjektkatalogen din (brukes hvis ingen `AGENTS.md` eksisterer) +- **Globale regler**: `~/.claude/CLAUDE.md` (brukes hvis ingen `~/.config/opencode/AGENTS.md` eksisterer) +- **Skills**: `~/.claude/skills/` — se [Agent Skills](/docs/skills/) for detaljer + +For å deaktivere Claude Code-kompatibilitet, sett en av disse miljøvariablene: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## Forrang + +Når OpenCode starter, ser den etter regelfiler i denne rekkefølgen: + +1. **Lokale filer** ved å gå opp fra gjeldende katalog (`AGENTS.md`, `CLAUDE.md`) +2. **Global fil** på `~/.config/opencode/AGENTS.md` +3. **Claude Code-fil** på `~/.claude/CLAUDE.md` (med mindre de er deaktivert) + +Den første matchende filen vinner i hver kategori. For eksempel, hvis du har både `AGENTS.md` og `CLAUDE.md`, brukes bare `AGENTS.md`. På samme måte har `~/.config/opencode/AGENTS.md` forrang over `~/.claude/CLAUDE.md`. + +--- + +## Egendefinerte instruksjoner + +Du kan spesifisere egendefinerte instruksjonsfiler i din `opencode.json` eller den globale `~/.config/opencode/opencode.json`. Dette lar deg og teamet ditt gjenbruke eksisterende regler i stedet for å måtte duplisere dem til AGENTS.md. + +Eksempel: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Du kan også bruke eksterne URL-er for å laste instruksjoner fra nettet. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +Eksterne instruksjoner hentes med 5 sekunders tidsavbrudd. + +Alle instruksjonsfilene er kombinert med `AGENTS.md`-filene dine. + +--- + +## Referere til eksterne filer + +Selv om OpenCode ikke automatisk analyserer filreferanser i `AGENTS.md`, kan du oppnå lignende funksjonalitet på to måter: + +### Bruker opencode.json + +Den anbefalte tilnærmingen er å bruke feltet `instructions` i `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### Manuelle instruksjoner i AGENTS.md + +Du kan lære OpenCode å lese eksterne filer ved å gi eksplisitte instruksjoner i `AGENTS.md`. Her er et praktisk eksempel: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +Denne tilnærmingen lar deg: + +- Lage modulære, gjenbrukbare regelfiler +- Dele regler på tvers av prosjekter via symbolkoblinger eller git-undermoduler +- Holde AGENTS.md kortfattet mens du refererer til detaljerte retningslinjer +- Sørge for at OpenCode laster filer kun når det er nødvendig for den spesifikke oppgaven + +:::tip +For monorepos eller prosjekter med delte standarder er bruk av `opencode.json` med glob-mønstre (som `packages/*/AGENTS.md`) mer vedlikeholdbart enn manuelle instruksjoner. +::: diff --git a/packages/web/src/content/docs/nb/sdk.mdx b/packages/web/src/content/docs/nb/sdk.mdx new file mode 100644 index 00000000000..bbff8ebecea --- /dev/null +++ b/packages/web/src/content/docs/nb/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: Typesikker JS-klient for OpenCode-server. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +OpenCode JS/TS SDK gir en typesikker klient for samhandling med serveren. +Bruk den til å bygge integrasjoner og kontrollere OpenCode programmatisk. + +[Finn ut mer](/docs/server) om hvordan serveren fungerer. For eksempler, sjekk ut [prosjektene](/docs/ecosystem#projects) bygget av fellesskapet. + +--- + +## Installasjon + +Installer SDK fra npm: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## Opprette klient + +Opprett en forekomst av OpenCode: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +Dette starter både en server og en klient + +#### Alternativer + +| Alternativ | Type | Beskrivelse | Standard | +| ---------- | ------------- | -------------------------------- | ----------- | +| `hostname` | `string` | Server vertsnavn | `127.0.0.1` | +| `port` | `number` | Serverport | `4096` | +| `signal` | `AbortSignal` | AbortSignal for avbrudd | `undefined` | +| `timeout` | `number` | Tidsavbrudd i ms for serverstart | `5000` | +| `config` | `Config` | Konfigurasjonsobjekt | `{}` | + +--- + +## Konfigurasjon + +Du kan sende et konfigurasjonsobjekt for å tilpasse virkemåten. Forekomsten henter fortsatt din `opencode.json`, men du kan overstyre eller legge til konfigurasjon inline: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## Kun klient + +Hvis du allerede har en kjørende forekomst av OpenCode, kan du opprette en klientforekomst for å koble til den: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### Alternativer + +| Alternativ | Type | Beskrivelse | Standard | +| --------------- | ---------- | --------------------------------- | ----------------------- | +| `baseUrl` | `string` | URL av serveren | `http://localhost:4096` | +| `fetch` | `function` | Egendefinert fetch-implementasjon | `globalThis.fetch` | +| `parseAs` | `string` | Metode for responsparsing | `auto` | +| `responseStyle` | `string` | Returstil: `data` eller `fields` | `fields` | +| `throwOnError` | `boolean` | Kast feil i stedet for retur | `false` | + +--- + +## Typer + +SDK inkluderer TypeScript-definisjoner for alle API-typer. Importer dem direkte: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +Alle typer er generert fra serverens OpenAPI-spesifikasjon og tilgjengelig i type-filen. + +--- + +## Feil + +SDK kan gi feil som du kan fange opp og håndtere: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## API-er + +SDK-en eksponerer alle server-API-er gjennom en typesikker klient. + +--- + +### Globalt + +| Metode | Beskrivelse | Svar | +| ----------------- | ----------------------------- | ------------------------------------ | +| `global.health()` | Sjekk serverstatus og versjon | `{ healthy: true, version: string }` | + +--- + +#### Eksempler + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### App + +| Metode | Beskrivelse | Svar | +| -------------- | ------------------------------- | ------------------------------------------- | +| `app.log()` | Skriv en loggoppføring | `boolean` | +| `app.agents()` | List alle tilgjengelige agenter | Agent[] | + +--- + +#### Eksempler + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### Prosjekt + +| Metode | Beskrivelse | Svar | +| ------------------- | ----------------------- | --------------------------------------------- | +| `project.list()` | List alle prosjekter | Project[] | +| `project.current()` | Hent gjeldende prosjekt | Project | + +--- + +#### Eksempler + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### Sti + +| Metode | Beskrivelse | Svar | +| ------------ | ------------------- | ---------------------------------------- | +| `path.get()` | Hent gjeldende bane | Path | + +--- + +#### Eksempler + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### Konfigurasjon + +| Metode | Beskrivelse | Svar | +| -------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | Hent konfigurasjonsinformasjon | Config | +| `config.providers()` | List leverandører og standardmodeller | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### Eksempler + +```javascript +const config = await client.config.get() + +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` | + +--- + +#### Eksempler + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### Filer + +| Metode | Beskrivelse | Svar | +| ------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------ | +| `find.text({ query })` | Søk etter tekst i filer | En rekke matchobjekter med `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `find.files({ query })` | Finn filer og kataloger etter navn | `string[]` (baner) | +| `find.symbols({ query })` | Finn symboler i arbeidsområdet | Symbol[] | +| `file.read({ query })` | Les en fil | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | Hent status for sporede filer | File[] | + +`find.files` støtter noen få valgfrie søkefelt: + +- `type`: `"file"` eller `"directory"` +- `directory`: overstyr prosjektroten for søket +- `limit`: maksimalt antall resultater (1–200) + +--- + +#### Eksempler + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| Metode | Beskrivelse | Svar | +| ------------------------------ | ------------------------- | --------- | +| `tui.appendPrompt({ body })` | Legg til tekst i prompten | `boolean` | +| `tui.openHelp()` | Åpne hjelpedialogen | `boolean` | +| `tui.openSessions()` | Åpne øktvelgeren | `boolean` | +| `tui.openThemes()` | Åpne temavelgeren | `boolean` | +| `tui.openModels()` | Åpne modellvelgeren | `boolean` | +| `tui.submitPrompt()` | Send inn gjeldende prompt | `boolean` | +| `tui.clearPrompt()` | Tøm prompten | `boolean` | +| `tui.executeCommand({ body })` | Utfør en kommando | `boolean` | +| `tui.showToast({ body })` | Vis toast-varsel | `boolean` | + +--- + +#### Eksempler + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### Auth + +| Metode | Beskrivelse | Svar | +| ------------------- | ------------------------------ | --------- | +| `auth.set({ ... })` | Angi autentiseringsinformasjon | `boolean` | + +--- + +#### Eksempler + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### Hendelser + +| Metode | Beskrivelse | Svar | +| ------------------- | -------------------------------- | -------------------------------- | +| `event.subscribe()` | Strøm av server-sendte hendelser | Strøm av server-sendte hendelser | + +--- + +#### Eksempler + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/nb/server.mdx b/packages/web/src/content/docs/nb/server.mdx new file mode 100644 index 00000000000..a6ad8c6dfb1 --- /dev/null +++ b/packages/web/src/content/docs/nb/server.mdx @@ -0,0 +1,287 @@ +--- +title: Tjener +description: Samhandle med OpenCode-tjener over HTTP. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +Kommandoen `opencode serve` kjører en hodeløs HTTP-server som eksponerer et OpenAPI-endepunkt som en OpenCode-klient kan bruke. + +--- + +### Bruk + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### Alternativer + +| Flagg | Beskrivelse | Standard | +| --------------- | --------------------------------------------- | ---------------- | +| `--port` | Port å lytte på | `4096` | +| `--hostname` | Vertsnavn å lytte på | `127.0.0.1` | +| `--mdns` | Aktiver mDNS-oppdagelse | `false` | +| `--mdns-domain` | Egendefinert domenenavn for mDNS-tjeneste | `opencode.local` | +| `--cors` | Ytterligere nettleseropprinnelse som tillates | `[]` | + +`--cors` kan angis flere ganger: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### Autentisering + +Sett `OPENCODE_SERVER_PASSWORD` for å beskytte serveren med HTTP grunnleggende autentisering. Brukernavnet er satt til `opencode` som standard, eller sett `OPENCODE_SERVER_USERNAME` for å overstyre det. Dette gjelder både `opencode serve` og `opencode web`. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### Slik fungerer det + +Når du kjører `opencode` starter den en TUI og en server. Der TUI er +klient som snakker med serveren. Serveren viser en OpenAPI 3.1-spesifikasjon +endepunkt. Dette endepunktet brukes også til å generere en [SDK](/docs/sdk). + +:::tip +Bruk OpenCode-serveren til å samhandle med OpenCode programmatisk. +::: + +Denne arkitekturen lar OpenCode støtte flere klienter og lar deg samhandle med OpenCode programmatisk. + +Du kan kjøre `opencode serve` for å starte en frittstående server. Hvis du har +OpenCode TUI kjører, vil `opencode serve` starte en ny server. + +--- + +#### Koble til en eksisterende server + +Når du starter TUI, tildeler den tilfeldig en port og vertsnavn. Du kan i stedet sende inn `--hostname` og `--port` [flagg](/docs/cli). Bruk deretter denne til å koble til serveren. + +[`/tui`](#tui) endepunktet kan brukes til å kjøre TUI gjennom serveren. Du kan for eksempel forhåndsutfylle eller kjøre en forespørsel. Dette oppsettet brukes av OpenCode [IDE](/docs/ide) plugins. + +--- + +## Spes + +Serveren publiserer en OpenAPI 3.1-spesifikasjon som kan vises på: + +``` +http://:/doc +``` + +For eksempel `http://localhost:4096/doc`. Bruk spesifikasjonen til å generere klienter eller inspisere forespørsels- og svartyper. Eller se den i en Swagger-utforsker. + +--- + +## APIer + +opencode-serveren viser følgende APIer. + +--- + +### Globalt + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ---------------- | -------------------------------- | ------------------------------------ | +| `GET` | `/global/health` | Få serverhelse og versjon | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | Få globale hendelser (SSE strøm) | Eventstrøm | + +--- + +### Prosjekt + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------------------ | ----------------------- | --------------------------------------------- | +| `GET` | `/project` | List alle prosjekter | Project[] | +| `GET` | `/project/current` | Hent gjeldende prosjekt | Project | + +--- + +### Bane og VCS + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------- | ------------------------------------ | ------------------------------------------- | +| `GET` | `/path` | Hent gjeldende bane | Path | +| `GET` | `/vcs` | Hent VCS-info for gjeldende prosjekt | VcsInfo | + +--- + +### Forekomst + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------------------- | --------------------------- | --------- | +| `POST` | `/instance/dispose` | Avslutt gjeldende forekomst | `boolean` | + +--- + +### Konfigurasjon + +| Metode | Sti | Beskrivelse | Svar | +| ------- | ------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------- | +| `GET` | `/config` | Hent konfigurasjonsinformasjon | Config | +| `PATCH` | `/config` | Oppdater konfigurasjon | Config | +| `GET` | `/config/providers` | List leverandører og standardmodeller | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +### Leverandør + +| Metode | Sti | Beskrivelse | Svar | +| ------ | -------------------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------- | +| `GET` | `/provider` | List alle leverandører | `{ all: `Provider[]`, default: {...}, connected: string[] }` | +| `GET` | `/provider/auth` | Hent autentiseringsmetoder for leverandør | `{ [providerID: string]: `ProviderAuthMethod[]` }` | +| `POST` | `/provider/{id}/oauth/authorize` | Autoriser en leverandør ved å bruke OAuth | ProviderAuthAuthorization | +| `POST` | `/provider/{id}/oauth/callback` | Håndter OAuth-tilbakeringing for en leverandør | `boolean` | + +--- + +### Sesjoner + +| Metode | Sti | Beskrivelse | Merknader | +| -------- | ---------------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------- | +| `GET` | `/session` | List alle økter | Returnerer Session[] | +| `POST` | `/session` | Opprett en ny økt | body: `{ parentID?, title? }`, returnerer Session | +| `GET` | `/session/status` | Hent øktstatus for alle økter | Returnerer `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | Hent øktdetaljer | Returnerer Session | +| `DELETE` | `/session/:id` | Slett en økt og alle dens data | Returnerer `boolean` | +| `PATCH` | `/session/:id` | Oppdater øktegenskaper | body: `{ title? }`, returnerer Session | +| `GET` | `/session/:id/children` | Hent en økts barneøkter | Returnerer Session[] | +| `GET` | `/session/:id/todo` | Hent gjøremålslisten for en økt | Returnerer Todo[] | +| `POST` | `/session/:id/init` | Analyser appen og lag `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returnerer `boolean` | +| `POST` | `/session/:id/fork` | Fork en eksisterende økt ved en melding | body: `{ messageID? }`, returnerer Session | +| `POST` | `/session/:id/abort` | Avbryt en kjørende økt | Returnerer `boolean` | +| `POST` | `/session/:id/share` | Del en økt | Returnerer Session | +| `DELETE` | `/session/:id/share` | Slutt å dele en økt | Returnerer Session | +| `GET` | `/session/:id/diff` | Hent diff for denne økten | spørring: `messageID?`, returnerer FileDiff[] | +| `POST` | `/session/:id/summarize` | Oppsummer økten | body: `{ providerID, modelID }`, returnerer `boolean` | +| `POST` | `/session/:id/revert` | Tilbakestill en melding | body: `{ messageID, partID? }`, returnerer `boolean` | +| `POST` | `/session/:id/unrevert` | Gjenopprett alle tilbakestilte meldinger | Returnerer `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | Svar på en tillatelsesforespørsel | body: `{ response, remember? }`, returnerer `boolean` | + +--- + +### Meldinger + +| Metode | Sti | Beskrivelse | Merknader | +| ------ | --------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `GET` | `/session/:id/message` | List meldinger i en økt | spørring: `limit?`, returnerer `{ info: `Message`, parts: `Part[]`}[]` | +| `POST` | `/session/:id/message` | Send en melding og vent på svar | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, returnerer `{ info: `Message`, parts: `Part[]`}` | +| `GET` | `/session/:id/message/:messageID` | Hent meldingsdetaljer | Returnerer `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/prompt_async` | Send en melding asynkront (ingen vent) | body: samme som `/session/:id/message`, returnerer `204 No Content` | +| `POST` | `/session/:id/command` | Utfør en slash-kommando | body: `{ messageID?, agent?, model?, command, arguments }`, returnerer `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/shell` | Kjør en shell-kommando | body: `{ agent, model?, command }`, returnerer `{ info: `Message`, parts: `Part[]`}` | + +--- + +### Kommandoer + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ---------- | -------------------- | --------------------------------------------- | +| `GET` | `/command` | List alle kommandoer | Command[] | + +--- + +### Filer + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------ | +| `GET` | `/find?pattern=` | Søk etter tekst i filer | En rekke matchobjekter med `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `GET` | `/find/file?query=` | Finn filer og kataloger etter navn | `string[]` (baner) | +| `GET` | `/find/symbol?query=` | Finn symboler i arbeidsområdet | Symbol[] | +| `GET` | `/file?path=` | List filer og kataloger | FileNode[] | +| `GET` | `/file/content?path=

` | Les en fil | FileContent | +| `GET` | `/file/status` | Hent status for sporede filer | File[] | + +#### `/find/file` spørringsparametere + +- `query` (obligatorisk) - søkestreng (uklar samsvar) +- `type` (valgfritt) - begrense resultatene til `"file"` eller `"directory"` +- `directory` (valgfritt) — overstyr prosjektroten for søket +- `limit` (valgfritt) - maks. resultater (1–200) +- `dirs` (valgfritt) - eldre flagg (`"false"` returnerer kun filer) + +--- + +### Verktøy (eksperimentelt) + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------------------------------------------- | -------------------------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | Vis alle verktøy-ID-er | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | List verktøy med JSON-skjemaer for en modell | ToolList | + +--- + +### LSP, formattere og MCP + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------------ | ---------------------------- | -------------------------------------------------------- | +| `GET` | `/lsp` | Hent LSP-serverstatus | LSPStatus[] | +| `GET` | `/formatter` | Hent formateringsstatus | FormatterStatus[] | +| `GET` | `/mcp` | Hent MCP-serverstatus | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | Legg til MCP-server dynamisk | body: `{ name, config }`, returnerer MCP statusobjekt | + +--- + +### Agenter + +| Metode | Sti | Beskrivelse | Svar | +| ------ | -------- | ------------------------------- | ------------------------------------------- | +| `GET` | `/agent` | List alle tilgjengelige agenter | Agent[] | + +--- + +### Logging + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------ | ---------------------------------------------------------------- | --------- | +| `POST` | `/log` | Skriv loggoppføring. Body: `{ service, level, message, extra? }` | `boolean` | + +--- + +### TUI + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ----------------------- | ------------------------------------------- | -------------------------- | +| `POST` | `/tui/append-prompt` | Legg til tekst i prompten | `boolean` | +| `POST` | `/tui/open-help` | Åpne hjelpedialogen | `boolean` | +| `POST` | `/tui/open-sessions` | Åpne øktvelgeren | `boolean` | +| `POST` | `/tui/open-themes` | Åpne temavelgeren | `boolean` | +| `POST` | `/tui/open-models` | Åpne modellvelgeren | `boolean` | +| `POST` | `/tui/submit-prompt` | Send inn gjeldende prompt | `boolean` | +| `POST` | `/tui/clear-prompt` | Tøm prompten | `boolean` | +| `POST` | `/tui/execute-command` | Utfør en kommando (`{ command }`) | `boolean` | +| `POST` | `/tui/show-toast` | Vis toast (`{ title?, message, variant }`) | `boolean` | +| `GET` | `/tui/control/next` | Vent på neste kontrollforespørsel | Kontrollforespørselsobjekt | +| `POST` | `/tui/control/response` | Svar på en kontrollforespørsel (`{ body }`) | `boolean` | + +--- + +### Auth + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ----------- | --------------------------------------------------------------------- | --------- | +| `PUT` | `/auth/:id` | Angi autentiseringsinformasjon. Body må samsvare med leverandørskjema | `boolean` | + +--- + +### Hendelser + +| Metode | Sti | Beskrivelse | Svar | +| ------ | -------- | ----------------------------------------------------------------------------------------------- | -------------------------------- | +| `GET` | `/event` | Strøm av server-sendte hendelser. Første hendelse er `server.connected`, deretter busshendelser | Strøm av server-sendte hendelser | + +--- + +### Dokumentasjon + +| Metode | Sti | Beskrivelse | Svar | +| ------ | ------ | ------------------------- | ----------------------------------- | +| `GET` | `/doc` | OpenAPI 3.1-spesifikasjon | HTML side med OpenAPI-spesifikasjon | diff --git a/packages/web/src/content/docs/nb/share.mdx b/packages/web/src/content/docs/nb/share.mdx new file mode 100644 index 00000000000..370477d1cfc --- /dev/null +++ b/packages/web/src/content/docs/nb/share.mdx @@ -0,0 +1,128 @@ +--- +title: Deling +description: Del dine OpenCode-samtaler. +--- + +Delingsfunksjonen i OpenCode lar deg lage offentlige lenker til dine OpenCode-samtaler, slik at du kan samarbeide med lagkamerater eller få hjelp fra andre. + +:::note +Delte samtaler er offentlig tilgjengelige for alle med linken. +::: + +--- + +## Slik fungerer det + +Når du deler en samtale, OpenCode: + +1. Oppretter en unik offentlig URL for økten din +2. Synkroniserer samtaleloggen din til serverne våre +3. Gjør samtalen tilgjengelig via den delbare lenken — `opncd.ai/s/` + +--- + +## Deling + +OpenCode støtter tre delingsmoduser som kontrollerer hvordan samtaler deles: + +--- + +### Manuell (standard) + +Som standard bruker OpenCode manuell delingsmodus. Økter deles ikke automatisk, men du kan dele dem manuelt ved å bruke kommandoen `/share`: + +``` +/share +``` + +Dette vil generere en unik URL som vil bli kopiert til utklippstavlen din. + +For å eksplisitt angi manuell modus i [konfigurasjonsfilen](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### Automatisk deling + +Du kan aktivere automatisk deling for alle nye samtaler ved å sette alternativet `share` til `"auto"` i [konfigurasjonsfilen](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +Med automatisk deling aktivert, vil hver nye samtale automatisk bli delt og en kobling vil bli generert. + +--- + +### Deaktivert + +Du kan deaktivere deling helt ved å sette alternativet `share` til `"disabled"` i [konfigurasjonsfilen](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +For å håndheve dette på tvers av teamet ditt for et gitt prosjekt, legg det til `opencode.json` i prosjektet ditt og sjekk det inn i Git. + +--- + +## Opphev deling + +Slik slutter du å dele en samtale og fjerner den fra offentlig tilgang: + +``` +/unshare +``` + +Dette vil fjerne delelinken og slette dataene knyttet til samtalen. + +--- + +## Personvern + +Det er et par ting du må huske på når du deler en samtale. + +--- + +### Datalagring + +Delte samtaler forblir tilgjengelige til du eksplisitt opphever deling av dem. Dette +inkluderer: + +- Full samtalehistorikk +- Alle meldinger og svar +- Metadata for økter + +--- + +### Anbefalinger + +- Del kun samtaler som ikke inneholder sensitiv informasjon. +- Se gjennom samtaleinnholdet før du deler. +- Opphev deling av samtaler når samarbeidet er fullført. +- Unngå å dele samtaler med proprietær kode eller konfidensielle data. +- For sensitive prosjekter, deaktiver deling helt. + +--- + +## For bedrifter + +For bedriftsimplementeringer kan delingsfunksjonen være: + +- **Deaktivert** helt for overholdelse av sikkerhet +- **Begrenset** til brukere som kun er autentisert gjennom SSO +- **Selv-hostet** på din egen infrastruktur + +[Finn ut mer](/docs/enterprise) om bruk av opencode i organisasjonen din. diff --git a/packages/web/src/content/docs/nb/skills.mdx b/packages/web/src/content/docs/nb/skills.mdx new file mode 100644 index 00000000000..717ad87df41 --- /dev/null +++ b/packages/web/src/content/docs/nb/skills.mdx @@ -0,0 +1,222 @@ +--- +title: "Agentferdigheter" +description: "Definer gjenbrukbar oppførsel via SKILL.md-definisjoner" +--- + +Agentferdigheter lar OpenCode oppdage gjenbrukbare instruksjoner fra repo- eller hjemmekatalogen din. +Ferdigheter lastes inn på forespørsel via det innebygde `skill`-verktøyet – agenter ser tilgjengelige ferdigheter og kan laste inn hele innholdet når det er nødvendig. + +--- + +## Plasser filer + +Opprett én mappe per ferdighetsnavn og legg inn en `SKILL.md` i den. +opencode søker etter disse stedene: + +- Prosjektkonfigurasjon: `.opencode/skills//SKILL.md` +- Global konfigurasjon: `~/.config/opencode/skills//SKILL.md` +- Prosjekt Claude-kompatibel: `.claude/skills//SKILL.md` +- Global Claude-kompatibel: `~/.claude/skills//SKILL.md` +- Prosjektagent-kompatibel: `.agents/skills//SKILL.md` +- Global agent-kompatibel: `~/.agents/skills//SKILL.md` + +--- + +## Forstå oppdagelsen + +For prosjektlokale stier går opencode opp fra din nåværende arbeidskatalog til den når git-arbeidstreet. +Den laster alle matchende `skills/*/SKILL.md` i `.opencode/` og alle matchende `.claude/skills/*/SKILL.md` eller `.agents/skills/*/SKILL.md` underveis. + +Globale definisjoner lastes også inn fra `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md` og `~/.agents/skills/*/SKILL.md`. + +--- + +## Skriv frontmatter + +Hver `SKILL.md` må starte med YAML frontmatter. +Bare disse feltene gjenkjennes: + +- `name` (påkrevd) +- `description` (påkrevd) +- `license` (valgfritt) +- `compatibility` (valgfritt) +- `metadata` (valgfritt, streng-til-streng kart) + +Ukjente frontmatter-felt ignoreres. + +--- + +## Bekreft navn + +`name` må: + +- Bestå av 1–64 tegn +- Vær alfanumerisk med små bokstaver, adskilt med enkel bindestrek +- Ikke begynne eller slutte med `-` +- Ikke inneholde påfølgende `--` +- Samsvare med katalognavnet som inneholder `SKILL.md` + +Ekvivalent regulært uttrykk: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## Følg lengdereglene + +`description` må bestå av 1-1024 tegn. +Hold det spesifikt nok til at agenten kan velge riktig. + +--- + +## Bruk et eksempel + +Lag `.opencode/skills/git-release/SKILL.md` slik: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## Forstå verktøybeskrivelsen + +opencode viser tilgjengelige ferdigheter i `skill`-verktøybeskrivelsen. +Hver oppføring inneholder ferdighetsnavnet og beskrivelsen: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +Agenten laster inn en ferdighet ved å kalle verktøyet: + +``` +skill({ name: "git-release" }) +``` + +--- + +## Konfigurer tillatelser + +Kontroller hvilke ferdigheter agenter har tilgang til ved å bruke mønsterbaserte tillatelser i `opencode.json`: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| Tillatelse | Atferd | +| ---------- | ------------------------------------------- | +| `allow` | Ferdigheter lastes umiddelbart | +| `deny` | Ferdighet skjult for agent, tilgang avvist | +| `ask` | Bruker blir bedt om godkjenning før lasting | + +Mønstre støtter jokertegn: `internal-*` samsvarer med `internal-docs`, `internal-tools` osv. + +--- + +## Overstyring per agent + +Gi spesifikke agenter andre tillatelser enn de globale standardinnstillingene. + +**For egendefinerte agenter** (i agent frontmatter): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**For innebygde agenter** (i `opencode.json`): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## Deaktiver ferdighetsverktøyet + +Deaktiver ferdigheter fullstendig for agenter som ikke bør bruke dem: + +**For egendefinerte agenter**: + +```yaml +--- +tools: + skill: false +--- +``` + +**For innebygde agenter**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +Når den er deaktivert, blir ``-delen utelatt helt. + +--- + +## Feilsøk lasting + +Hvis en ferdighet ikke vises: + +1. Kontroller at `SKILL.md` er stavet med store bokstaver +2. Sjekk at frontmatter inkluderer `name` og `description` +3. Sørg for at ferdighetsnavnene er unike på alle steder +4. Sjekk tillatelser – ferdigheter med `deny` er skjult for agenter diff --git a/packages/web/src/content/docs/nb/themes.mdx b/packages/web/src/content/docs/nb/themes.mdx new file mode 100644 index 00000000000..a294a6a0fa4 --- /dev/null +++ b/packages/web/src/content/docs/nb/themes.mdx @@ -0,0 +1,369 @@ +--- +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. + +Som standard bruker opencode vårt eget `opencode`-tema. + +--- + +## Terminalkrav + +For at temaer skal vises riktig med fullfargepalett, må terminalen din støtte **truecolor** (24-biters farger). De fleste moderne terminaler støtter dette som standard, men du må kanskje aktivere det: + +- **Sjekk støtte**: Kjør `echo $COLORTERM` - den skal gi ut `truecolor` eller `24bit` +- **Aktiver truecolor**: Sett miljøvariabelen `COLORTERM=truecolor` i shell-profilen din +- **Terminalkompatibilitet**: Sørg for at terminalemulatoren din støtter 24-bits farger (de fleste moderne terminaler som iTerm2, Alacritty, Kitty, Windows Terminal og nyere versjoner av GNOME Terminal gjør det) + +Uten truecolor-støtte kan temaer vises med redusert fargenøyaktighet eller falle tilbake til nærmeste 256-fargers tilnærming. + +--- + +## Innebygde temaer + +opencode kommer med flere innebygde temaer. + +| Navn | Beskrivelse | +| ---------------------- | ------------------------------------------------------------------------- | +| `system` | Tilpasser seg terminalens bakgrunnsfarge | +| `tokyonight` | Basert på [tokyonight](https://github.com/folke/tokyonight.nvim)-temaet | +| `everforest` | Basert på [Everforest](https://github.com/sainnhe/everforest)-temaet | +| `ayu` | Basert på [Ayu](https://github.com/ayu-theme) mørke tema | +| `catppuccin` | Basert på [Catppuccin](https://github.com/catppuccin)-temaet | +| `catppuccin-macchiato` | Basert på [Catppuccin](https://github.com/catppuccin)-temaet | +| `gruvbox` | Basert på [Gruvbox](https://github.com/morhetz/gruvbox)-temaet | +| `kanagawa` | Basert på [Kanagawa](https://github.com/rebelot/kanagawa.nvim)-temaet | +| `nord` | Basert på [Nord](https://github.com/nordtheme/nord)-temaet | +| `matrix` | Hacker-stil grønt på svart tema | +| `one-dark` | Basert på [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Mørkt tema | + +Og mer, vi legger stadig til nye temaer. + +--- + +## Systemtema + +`system`-temaet er designet for å automatisk tilpasse seg terminalens fargeskjema. I motsetning til tradisjonelle temaer som bruker faste farger, er _system_-temaet: + +- **Genererer gråtone**: Oppretter en tilpasset gråskala basert på terminalens bakgrunnsfarge, og sikrer optimal kontrast. +- **Bruker ANSI-farger**: Bruker standard ANSI farger (0-15) for syntaksutheving og UI elementer, som respekterer terminalens fargepalett. +- **Bevarer terminalens standardinnstillinger**: Bruker `none` for tekst- og bakgrunnsfarger for å opprettholde terminalens opprinnelige utseende. + +Systemtemaet er for brukere som: + +- Vil at opencode skal matche terminalens utseende +- Bruker tilpassede terminalfargeskjemaer +- Foretrekker et konsistent utseende på tvers av alle terminalapplikasjoner + +--- + +## Bruke et tema + +Du kan velge et tema ved å åpne temavelgeren med kommandoen `/theme`. Eller du kan spesifisere det i [config](/docs/config). + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## Egendefinerte temaer + +opencode støtter et fleksibelt JSON-basert temasystem som lar brukere enkelt lage og tilpasse temaer. + +--- + +### Hierarki + +Temaer lastes inn fra flere kataloger i følgende rekkefølge der senere kataloger overstyrer tidligere: + +1. **Innebygde temaer** - Disse er innebygd i binæren +2. **Brukerkonfigurasjonskatalog** - Definert i `~/.config/opencode/themes/*.json` eller `$XDG_CONFIG_HOME/opencode/themes/*.json` +3. **Prosjektrotkatalog** - Definert i `/.opencode/themes/*.json` +4. **Gjeldende arbeidskatalog** - Definert i `./.opencode/themes/*.json` + +Hvis flere kataloger inneholder et tema med samme navn, vil temaet fra katalogen med høyere prioritet bli brukt. + +--- + +### Opprette et tema + +For å lage et tilpasset tema, lag en JSON-fil i en av temakatalogene. + +For brukerspesifikke temaer: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +Og for prosjektspesifikke temaer. + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### JSON-format + +Temaer bruker et fleksibelt JSON-format med støtte for: + +- **Hex-farger**: `"#ffffff"` +- **ANSI-farger**: `3` (0-255) +- **Fargereferanser**: `"primary"` eller egendefinerte definisjoner +- **Mørke/lyse varianter**: `{"dark": "#000", "light": "#fff"}` +- **Ingen farge**: `"none"` - Bruker terminalens standardfarge eller transparent + +--- + +### Fargedefinisjoner + +`defs`-delen er valgfri, og den lar deg definere gjenbrukbare farger som kan refereres til i temaet. + +--- + +### Terminalstandarder + +Spesialverdien `"none"` kan brukes for hvilken som helst farge for å arve terminalens standardfarge. Dette er spesielt nyttig for å lage temaer som passer sømløst med terminalens fargeskjema: + +- `"text": "none"` - Bruker terminalens standard forgrunnsfarge +- `"background": "none"` - Bruker terminalens standard bakgrunnsfarge + +--- + +### Eksempel + +Her er et eksempel på et tilpasset tema: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/nb/tools.mdx b/packages/web/src/content/docs/nb/tools.mdx new file mode 100644 index 00000000000..089a0cbb52f --- /dev/null +++ b/packages/web/src/content/docs/nb/tools.mdx @@ -0,0 +1,379 @@ +--- +title: Verktøy +description: Administrer verktøyene en LLM kan bruke. +--- + +Verktøy lar LLM utføre handlinger i kodebasen din. OpenCode kommer med et sett med innebygde verktøy, men du kan utvide det med [egendefinerte verktøy](/docs/custom-tools) eller [MCP servere](/docs/mcp-servers). + +Som standard er alle verktøy **aktivert** og trenger ikke tillatelse for å kjøre. Du kan kontrollere verktøyets oppførsel gjennom [tillatelser](/docs/permissions). + +--- + +## Konfigurasjon + +Bruk feltet `permission` for å kontrollere verktøyets oppførsel. Du kan tillate, avslå eller kreve godkjenning for hvert verktøy. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +Du kan også bruke jokertegn for å kontrollere flere verktøy samtidig. For eksempel, for å kreve godkjenning for alle verktøy fra en MCP-server: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[Finn ut mer](/docs/permissions) om konfigurering av tillatelser. + +--- + +## Innebygd + +Her er alle de innebygde verktøyene som er tilgjengelige i OpenCode. + +--- + +### bash + +Utfør skallkommandoer i prosjektmiljøet ditt. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +Dette verktøyet lar LLM kjøre terminalkommandoer som `npm install`, `git status` eller en hvilken som helst annen skallkommando. + +--- + +### edit + +Endre eksisterende filer ved å bruke eksakte strengerstatninger. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Dette verktøyet utfører nøyaktige redigeringer av filer ved å erstatte eksakte teksttreff. Det er den primære måten LLM endrer kode på. + +--- + +### write + +Opprett nye filer eller overskriv eksisterende. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Bruk denne for å la LLM lage nye filer. Den vil overskrive eksisterende filer hvis de allerede eksisterer. + +:::note +`write`-verktøyet kontrolleres av tillatelsen `edit`, som dekker alle filendringer (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### read + +Les filinnholdet fra kodebasen din. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +Dette verktøyet leser filer og returnerer innholdet. Den støtter lesing av spesifikke linjeområder for store filer. + +--- + +### grep + +Søk i filinnhold ved hjelp av regulære uttrykk. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +Rask innholdssøk på tvers av kodebasen din. Støtter full regex-syntaks og filmønsterfiltrering. + +--- + +### glob + +Finn filer etter mønstermatching. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +Søk etter filer ved å bruke glob-mønstre som `**/*.js` eller `src/**/*.ts`. Returnerer samsvarende filbaner sortert etter endringstid. + +--- + +### list + +List filer og kataloger i en gitt bane. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +Dette verktøyet viser kataloginnhold. Den aksepterer glob-mønstre for å filtrere resultater. + +--- + +### lsp (eksperimentell) + +Samhandle med dine konfigurerte LSP-servere for å få kodeintelligens-funksjoner som definisjoner, referanser, hover-informasjon og kallhierarki. + +:::note +Dette verktøyet er bare tilgjengelig når `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (eller `OPENCODE_EXPERIMENTAL=true`). +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +Støttede operasjoner inkluderer `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls` og `outgoingCalls`. + +For å konfigurere hvilke LSP-servere som er tilgjengelige for prosjektet ditt, se [LSP-servere](/docs/lsp). + +--- + +### patch + +Bruk patcher på filer. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Dette verktøyet bruker oppdateringsfiler til kodebasen din. Nyttig for å påføre diffs og patcher fra forskjellige kilder. + +:::note +`patch`-verktøyet kontrolleres av tillatelsen `edit`, som dekker alle filendringer (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### skill + +Last inn en [ferdighet](/docs/skills) (en `SKILL.md` fil) og returner innholdet i samtalen. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +Administrer gjøremålslister under kodingsøkter. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +Oppretter og oppdaterer oppgavelister for å spore fremdrift under komplekse operasjoner. LLM bruker dette til å organisere flertrinnsoppgaver. + +:::note +Dette verktøyet er deaktivert for subagenter som standard, men du kan aktivere det manuelt. [Finn ut mer](/docs/agents/#permissions) +::: + +--- + +### todoread + +Les eksisterende gjøremålslister. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +Leser gjeldende gjøremålslistestatus. Brukes av LLM for å spore hvilke oppgaver som venter eller er fullført. + +:::note +Dette verktøyet er deaktivert for subagenter som standard, men du kan aktivere det manuelt. [Finn ut mer](/docs/agents/#permissions) +::: + +--- + +### webfetch + +Hent nettinnhold. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +Lar LLM hente og lese nettsider. Nyttig for å slå opp dokumentasjon eller forske på nettressurser. + +--- + +### websearch + +Søk på nettet for informasjon. + +:::note +Dette verktøyet er bare tilgjengelig når du bruker OpenCode-leverandøren eller når miljøvariabelen `OPENCODE_ENABLE_EXA` er satt til en sann verdi (f.eks. `true` eller `1`). + +Slik aktiverer du når du starter OpenCode: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +Utfører nettsøk med Exa AI for å finne relevant informasjon på nettet. Nyttig for å undersøke emner, finne aktuelle hendelser eller samle informasjon utover treningsdataavbruddet. + +Ingen API-nøkkel kreves — verktøyet kobles direkte til Exa AIs vertsbaserte MCP-tjeneste uten autentisering. + +:::tip +Bruk `websearch` når du trenger å finne informasjon (oppdagelse), og `webfetch` når du trenger å hente innhold fra en bestemt URL (henting). +::: + +--- + +### question + +Still brukeren spørsmål under utførelse. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +Dette verktøyet lar LLM stille spørsmål til brukeren under en oppgave. Det er nyttig for: + +- Samle brukerpreferanser eller krav +- Avklarende tvetydige instruksjoner +- Få beslutninger om gjennomføringsvalg +- Tilbyr valg om hvilken retning du skal ta + +Hvert spørsmål inkluderer en overskrift, spørsmålsteksten og en liste over alternativer. Brukere kan velge fra de angitte alternativene eller skrive inn et tilpasset svar. Når det er flere spørsmål, kan brukerne navigere mellom dem før de sender inn alle svarene. + +--- + +## Egendefinerte verktøy + +Egendefinerte verktøy lar deg definere dine egne funksjoner som LLM kan kalle. Disse er definert i konfigurasjonsfilen din og kan kjøre vilkårlig kode. + +[Finn ut mer](/docs/custom-tools) om å lage tilpassede verktøy. + +--- + +## MCP servere + +MCP (Model Context Protocol) servere lar deg integrere eksterne verktøy og tjenester. Dette inkluderer databasetilgang, API-integrasjoner og tredjepartstjenester. + +[Les mer](/docs/mcp-servers) om konfigurering av MCP-servere. + +--- + +## Internaler + +Internt bruker verktøy som `grep`, `glob` og `list` [ripgrep](https://github.com/BurntSushi/ripgrep) i bakgrunnen. Som standard respekterer ripgrep `.gitignore`-mønstre, noe som betyr at filer og kataloger som er oppført i `.gitignore` vil bli ekskludert fra søk og oppføringer. + +--- + +### Ignorer mønstre + +For å inkludere filer som normalt vil bli ignorert, lag en `.ignore`-fil i prosjektroten. Denne filen kan eksplisitt tillate visse stier. + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +For eksempel lar denne `.ignore` filen ripgrep søke i `node_modules/`, `dist/` og `build/` kataloger selv om de er oppført i `.gitignore`. diff --git a/packages/web/src/content/docs/nb/troubleshooting.mdx b/packages/web/src/content/docs/nb/troubleshooting.mdx new file mode 100644 index 00000000000..00600841566 --- /dev/null +++ b/packages/web/src/content/docs/nb/troubleshooting.mdx @@ -0,0 +1,225 @@ +--- +title: Feilsøking +description: Vanlige problemer og hvordan de kan løses. +--- + +For å feilsøke problemer med OpenCode, start med å sjekke loggene og lokale data den lagrer på disken. + +--- + +## Logger + +Loggfiler skrives til: + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: Trykk `WIN+R` og lim inn `%USERPROFILE%\.local\share\opencode\log` + +Loggfiler navngis med tidsstempler (f.eks. `2025-01-09T123456.log`) og de siste 10 loggfilene beholdes. + +Du kan angi loggnivået med kommandolinjealternativet `--log-level` for å få mer detaljert feilsøkingsinformasjon. For eksempel `opencode --log-level DEBUG`. + +--- + +## Lagring + +OpenCode lagrer øktdata og andre applikasjonsdata på disken på: + +- **macOS/Linux**: `~/.local/share/opencode/` +- **Windows**: Trykk `WIN+R` og lim inn `%USERPROFILE%\.local\share\opencode` + +Denne katalogen inneholder: + +- `auth.json` - Autentiseringsdata som API-nøkler, OAuth-tokens +- `log/` - Applikasjonslogger +- `project/` - Prosjektspesifikke data som økt- og meldingsdata + - Hvis prosjektet er innenfor en Git-repo, lagres det i `.//storage/` + - Hvis det ikke er en Git-repo, lagres det i `./global/storage/` + +--- + +## Skrivebordsapp + +OpenCode Desktop kjører en lokal OpenCode-server (`opencode-cli` sidevognen) i bakgrunnen. De fleste problemene er forårsaket av en plugin som fungerer dårlig, en ødelagt cache eller en dårlig serverinnstilling. + +### Raske sjekker + +- Avslutt og start appen på nytt. +- Hvis appen viser en feilskjerm, klikker du på **Start på nytt** og kopierer feildetaljene. +- Bare macOS: `OpenCode`-meny -> **Last nettvisning på nytt** (hjelper hvis UI er tom/frosset). + +--- + +### Deaktiver plugins + +Hvis skrivebordsappen krasjer ved oppstart, henger eller oppfører seg merkelig, start med å deaktivere plugins. + +#### Sjekk den globale konfigurasjonen + +Åpne den globale konfigurasjonsfilen og se etter en `plugin`-nøkkel. + +- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (eller `~/.config/opencode/opencode.json`) +- **macOS/Linux** (eldre installasjoner): `~/.local/share/opencode/opencode.jsonc` +- **Windows**: Trykk `WIN+R` og lim inn `%USERPROFILE%\.config\opencode\opencode.jsonc` + +Hvis du har konfigurert plugins, deaktiver dem midlertidig ved å fjerne nøkkelen eller sette den til en tom matrise: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### Sjekk plugin-kataloger + +OpenCode kan også laste lokale plugins fra disken. Flytt disse midlertidig ut av veien (eller gi nytt navn til mappen) og start skrivebordsappen på nytt: + +- **Globale plugins** + - **macOS/Linux**: `~/.config/opencode/plugins/` + - **Windows**: Trykk `WIN+R` og lim inn `%USERPROFILE%\.config\opencode\plugins` +- **Prosjektplugins** (bare hvis du bruker konfigurasjon per prosjekt) + - `/.opencode/plugins/` + +Hvis appen begynner å fungere igjen, aktiverer du plugins én om gangen for å finne ut hvilken som forårsaker problemet. + +--- + +### Tøm hurtigbufferen + +Hvis deaktivering av plugins ikke hjelper (eller en plugin-installasjon sitter fast), tøm hurtigbufferen slik at OpenCode kan gjenoppbygge den. + +1. Avslutt OpenCode Desktop helt. +2. Slett hurtigbufferkatalogen: + +- **macOS**: Finder -> `Cmd+Shift+G` -> lim inn `~/.cache/opencode` +- **Linux**: slett `~/.cache/opencode` (eller kjør `rm -rf ~/.cache/opencode`) +- **Windows**: Trykk `WIN+R` og lim inn `%USERPROFILE%\.cache\opencode` + +3. Start OpenCode Desktop på nytt. + +--- + +### Løs problemer med servertilkobling + +OpenCode Desktop kan enten starte sin egen lokale server (standard) eller koble til en server URL du har konfigurert. + +Hvis du ser en **"Tilkobling mislyktes"**-dialogboks (eller appen kommer aldri forbi splash-skjermen), se etter en tilpasset server URL. + +#### Slett skrivebordsappens standardserver-URL + +Fra startskjermen klikker du på servernavnet (med statusprikken) for å åpne servervelgeren. I delen **Standardserver** klikker du på **Slett**. + +#### Fjern `server.port` / `server.hostname` fra konfigurasjonen din + +Hvis `opencode.json(c)` inneholder en `server`-del, fjern den midlertidig og start skrivebordsappen på nytt. + +#### Sjekk miljøvariabler + +Hvis du har `OPENCODE_PORT` satt i miljøet ditt, vil skrivebordsappen prøve å bruke den porten for den lokale serveren. + +- Deaktiver `OPENCODE_PORT` (eller velg en ledig port) og start på nytt. + +--- + +### Linux: Wayland / X11 problemer + +På Linux kan noen Wayland-oppsett forårsake tomme vinduer eller kompositorfeil. + +- Hvis du er på Wayland og appen er tom/krasj, prøv å starte med `OC_ALLOW_WAYLAND=1`. +- Hvis det gjør ting verre, fjern det og prøv å starte under en X11-økt i stedet. + +--- + +### Windows: WebView2 kjøretid + +På Windows krever OpenCode Desktop Microsoft Edge **WebView2 Runtime**. Hvis appen åpnes i et tomt vindu eller ikke starter, installer/oppdater WebView2 og prøv igjen. + +--- + +### Windows: Generelle ytelsesproblemer + +Hvis du opplever treg ytelse, problemer med filtilgang eller terminalproblemer på Windows, kan du prøve å bruke [WSL (Windows Subsystem for Linux)](/docs/windows-wsl). WSL gir et Linux-miljø som fungerer mer sømløst med funksjonene til OpenCode. + +--- + +### Varsler vises ikke + +OpenCode Desktop viser bare systemvarsler når: + +- varsler er aktivert for OpenCode i OS-innstillingene dine, og +- appvinduet er ikke fokusert. + +--- + +### Tilbakestill skrivebordsapplagring (siste utvei) + +Hvis appen ikke starter og du ikke kan slette innstillingene fra UI-et, tilbakestill skrivebordsappens lagrede tilstand. + +1. Avslutt OpenCode Desktop. +2. Finn og slett disse filene (de finnes i OpenCode Desktop-appens datakatalog): + +- `opencode.settings.dat` (stasjonær standardserver URL) +- `opencode.global.dat` og `opencode.workspace.*.dat` (UI tilstand som nylige servere/prosjekter) + +--- + +### Modellen er ikke tilgjengelig + +1. Sjekk at du har autentisert deg med leverandøren +2. Kontroller at modellnavnet i konfigurasjonen er riktig +3. Noen modeller kan kreve spesifikk tilgang eller abonnement + +Hvis du støter på `ProviderModelNotFoundError` refererer du mest sannsynlig feil +til en modell et sted. +Modeller skal refereres slik: `/` + +--- + +### AI_APICallError og leverandørpakkeproblemer + +Hvis du støter på API-anropsfeil, kan dette skyldes utdaterte provider-pakker. OpenCode installerer dynamisk provider-pakker (OpenAI, Anthropic, Google, etc.) etter behov og cacher dem lokalt. + +For å løse problemer med leverandørpakke: + +1. Tøm leverandørens pakkebuffer: + + ```bash + rm -rf ~/.cache/opencode + ``` + + På Windows, trykk `WIN+R` og slett: `%USERPROFILE%\.cache\opencode` + +2. Start OpenCode på nytt for å installere de nyeste provider-pakkene på nytt + +Dette vil tvinge OpenCode til å laste ned de nyeste versjonene av provider-pakkene, som ofte løser kompatibilitetsproblemer med modellparametere og API-endringer. + +--- + +### Kopier/lim inn fungerer ikke på Linux + +Linux-brukere må ha ett av følgende utklippstavle-verktøy installert for at kopier/lim inn-funksjonalitet skal fungere: + +**For X11-systemer:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**For Wayland-systemer:** + +```bash +apt install -y wl-clipboard +``` + +**For headless-miljøer:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +OpenCode vil oppdage om du bruker Wayland og foretrekker `wl-clipboard`, ellers vil den prøve å finne utklippstavle-verktøy i rekkefølgen: `xclip` og `xsel`. diff --git a/packages/web/src/content/docs/nb/tui.mdx b/packages/web/src/content/docs/nb/tui.mdx new file mode 100644 index 00000000000..fae2a2364c1 --- /dev/null +++ b/packages/web/src/content/docs/nb/tui.mdx @@ -0,0 +1,390 @@ +--- +title: TUI +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. + +Å kjøre opencode starter TUI for gjeldende katalog. + +```bash +opencode +``` + +Eller du kan starte den for en spesifikk arbeidskatalog. + +```bash +opencode /path/to/project +``` + +Når du er i TUI, kan du stille den spørsmål med en prompt. + +```text +Give me a quick summary of the codebase. +``` + +--- + +## Filreferanser + +Du kan referere til filer i meldingene dine ved å bruke `@`. Dette gjør et fuzzy-filsøk i gjeldende arbeidskatalog. + +:::tip +Du kan også bruke `@` til å referere til filer i meldingene dine. +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +Innholdet i filen legges automatisk til samtalen. + +--- + +## Bash-kommandoer + +Start en melding med `!` for å kjøre en skallkommando. + +```bash frame="none" +!ls -la +``` + +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: + +```bash frame="none" +/help +``` + +De fleste kommandoer har også tastebinding som bruker `ctrl+x` som leader-tast, der `ctrl+x` er standard leader-tast. [Finn ut mer](/docs/keybinds). + +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. + +```bash frame="none" +/connect +``` + +--- + +### compact + +Komprimer gjeldende økt. _Alias_: `/summarize` + +```bash frame="none" +/compact +``` + +**Nøkkelbinding:** `ctrl+x c` + +--- + +### details + +Veksle visning av verktøydetaljer. + +```bash frame="none" +/details +``` + +**Nøkkelbinding:** `ctrl+x d` + +--- + +### editor + +Åpne eksternt tekstredigeringsprogram for å skrive meldinger. Bruker redigeringssettet i miljøvariabelen `EDITOR`. [Finn ut mer](#editor-setup). + +```bash frame="none" +/editor +``` + +**Nøkkelbinding:** `ctrl+x e` + +--- + +### exit + +Avslutt opencode. _Aliaser_: `/quit`, `/q` + +```bash frame="none" +/exit +``` + +**Nøkkelbinding:** `ctrl+x q` + +--- + +### export + +Eksporter gjeldende samtale til Markdown og åpne i standardredigeringsprogrammet. Bruker redigeringssettet i miljøvariabelen `EDITOR`. [Finn ut mer](#editor-setup). + +```bash frame="none" +/export +``` + +**Nøkkelbinding:** `ctrl+x x` + +--- + +### help + +Vis hjelpedialogen. + +```bash frame="none" +/help +``` + +**Nøkkelbinding:** `ctrl+x h` + +--- + +### init + +Opprett eller oppdater `AGENTS.md`-fil. [Finn ut mer](/docs/rules). + +```bash frame="none" +/init +``` + +**Nøkkelbinding:** `ctrl+x i` + +--- + +### models + +Liste over tilgjengelige modeller. + +```bash frame="none" +/models +``` + +**Nøkkelbinding:** `ctrl+x m` + +--- + +### new + +Start en ny økt. _Alias_: `/clear` + +```bash frame="none" +/new +``` + +**Nøkkelbinding:** `ctrl+x n` + +--- + +### redo + +Gjenta en tidligere angret melding. Kun tilgjengelig etter bruk av `/undo`. + +:::tip +Eventuelle filendringer vil også bli gjenopprettet. +::: + +Internt bruker dette Git til å administrere filendringene. Så ditt prosjekt **må +være et Git-repo**. + +```bash frame="none" +/redo +``` + +**Nøkkelbinding:** `ctrl+x r` + +--- + +### sessions + +List opp og bytt mellom økter. _Aliaser_: `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +**Nøkkelbinding:** `ctrl+x l` + +--- + +### share + +Del gjeldende økt. [Finn ut mer](/docs/share). + +```bash frame="none" +/share +``` + +**Nøkkelbinding:** `ctrl+x s` + +--- + +### theme + +Liste over tilgjengelige temaer. + +```bash frame="none" +/theme +``` + +**Nøkkelbinding:** `ctrl+x t` + +--- + +### thinking + +Veksle mellom synligheten av tenke-/resonneringsblokker i samtalen. Når den er aktivert, kan du se modellens resonneringsprosess for modeller som støtter utvidet tenkning. + +:::note +Denne kommandoen kontrollerer bare om tenkeblokker **vises** - den aktiverer eller deaktiverer ikke modellens resonneringsmuligheter. For å veksle mellom faktiske resonneringsmuligheter, bruk `ctrl+t` for å bla gjennom modellvarianter. +::: + +```bash frame="none" +/thinking +``` + +--- + +### undo + +Angre siste melding i samtalen. Fjerner den siste brukermeldingen, alle påfølgende svar og eventuelle filendringer. + +:::tip +Eventuelle filendringer vil også bli tilbakestilt. +::: + +Internt bruker dette Git til å administrere filendringene. Så ditt prosjekt **må +være et Git-repo**. + +```bash frame="none" +/undo +``` + +**Nøkkelbinding:** `ctrl+x u` + +--- + +### unshare + +Opphev deling av gjeldende økt. [Finn ut mer](/docs/share#un-sharing). + +```bash frame="none" +/unshare +``` + +--- + +## Oppsett av editor + +Både kommandoene `/editor` og `/export` bruker editoren som er spesifisert i miljøvariabelen `EDITOR`. + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + + For å gjøre det permanent, legg dette til i shell-profilen din; + `~/.bashrc`, `~/.zshrc` osv. + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + + For å gjøre det permanent, bruk **Systemegenskaper** > **Miljø + Variabler**. + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + + For å gjøre det permanent, legg dette til i PowerShell-profilen din. + + + + +Populære editor-alternativer inkluderer: + +- `code` - Visual Studio Code +- `cursor` - Cursor +- `windsurf` - Windsurf +- `nvim` - Neovim-editor +- `vim` - Vim editor +- `nano` - Nano-editor +- `notepad` - Windows Notisblokk +- `subl` - Sublime Text + +:::note +Noen editorer som VS Code må startes med flagget `--wait`. +::: + +Noen editorer trenger kommandolinjeargumenter for å kjøre i blokkeringsmodus. `--wait`-flagget gjør at editor-prosessen blokkeres til den lukkes. + +--- + +## Konfigurasjon + +Du kan tilpasse TUI-oppførselen gjennom opencode-konfigurasjonsfilen. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### 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`.** + +--- + +## Tilpasning + +Du kan tilpasse ulike aspekter av TUI-visningen ved å bruke kommandopaletten (`ctrl+x h` eller `/help`). Disse innstillingene vedvarer ved omstarter. + +--- + +#### Visning av brukernavn + +Veksle om brukernavnet ditt vises i chat-meldinger. Få tilgang til dette gjennom: + +- Kommandopalett: Søk etter "brukernavn" eller "skjul brukernavn" +- Innstillingen vedvarer automatisk og vil bli husket over TUI økter diff --git a/packages/web/src/content/docs/nb/web.mdx b/packages/web/src/content/docs/nb/web.mdx new file mode 100644 index 00000000000..c8cc9d413fb --- /dev/null +++ b/packages/web/src/content/docs/nb/web.mdx @@ -0,0 +1,105 @@ +--- +title: Web +description: Bruke OpenCode i nettleseren din. +--- + +OpenCode kan kjøres som en nettapplikasjon i nettleseren din, og gir den samme kraftige AI-kodingsopplevelsen uten at du trenger en terminal. + +![OpenCode Web - Ny økt](../../../assets/web/web-homepage-new-session.png) + +## Komme i gang + +Start web-grensesnittet ved å kjøre: + +```bash +opencode web +``` + +Dette starter en lokal server på `127.0.0.1` med en tilfeldig tilgjengelig port og åpner automatisk OpenCode i standard nettleser. + +--- + +## Konfigurasjon + +Du kan konfigurere webserveren ved å bruke kommandolinjeflagg eller i [konfigurasjonsfilen](/docs/config). + +### Port + +Som standard velger OpenCode en tilgjengelig port. Du kan spesifisere en port: + +```bash +opencode web --port 4096 +``` + +### Vertsnavn + +Som standard binder serveren seg til `127.0.0.1` (kun localhost). Slik gjør du OpenCode tilgjengelig på nettverket ditt: + +```bash +opencode web --hostname 0.0.0.0 +``` + +--- + +### Autentisering + +For å beskytte tilgang, angi et passord ved hjelp av miljøvariabelen `OPENCODE_SERVER_PASSWORD`: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +Brukernavnet er satt til `opencode` som standard, men kan endres med `OPENCODE_SERVER_USERNAME`. + +--- + +## Bruke webgrensesnittet + +Når den er startet, gir nettgrensesnittet tilgang til dine OpenCode-økter. + +### Sesjoner + +Se og administrer øktene dine fra hjemmesiden. Du kan se aktive økter og starte nye. + +![OpenCode Web - Active Session](../../../assets/web/web-homepage-active-session.png) + +### Serverstatus + +Klikk på "Se servere" for å se tilkoblede servere og deres status. + +![OpenCode Web - Se servere](../../../assets/web/web-homepage-see-servers.png) + +--- + +## Koble til en terminal + +Du kan koble en terminal TUI til en kjørende webserver: + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +Dette lar deg bruke både nettgrensesnittet og terminalen samtidig, og deler samme økter og tilstand. + +--- + +## Konfigurasjonsfil + +Du kan også konfigurere serverinnstillinger i `opencode.json` konfigurasjonsfilen: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +Kommandolinjeflagg har forrang over konfigurasjonsfilinnstillinger. diff --git a/packages/web/src/content/docs/nb/windows-wsl.mdx b/packages/web/src/content/docs/nb/windows-wsl.mdx new file mode 100644 index 00000000000..7ffc141cdde --- /dev/null +++ b/packages/web/src/content/docs/nb/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: Kjør OpenCode på Windows med WSL for best opplevelse. +--- + +import { Steps } from "@astrojs/starlight/components" + +Selv om OpenCode kan kjøre direkte på Windows, anbefaler vi å bruke [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) for best mulig opplevelse. WSL gir et Linux-miljø som fungerer godt med funksjonene i OpenCode. + +:::tip[Hvorfor WSL?] +WSL gir bedre filsystemytelse, full terminalstøtte og kompatibilitet med utviklingsverktøyene OpenCode er avhengig av. +::: + +--- + +## Oppsett + + + +1. **Installer WSL** + + Hvis du ikke har gjort det ennå, [installer WSL](https://learn.microsoft.com/en-us/windows/wsl/install) med den offisielle guiden fra Microsoft. + +2. **Installer OpenCode i WSL** + + Når WSL er satt opp, åpner du WSL-terminalen og installerer OpenCode med en av [installasjonsmetodene](/docs/). + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **Bruk OpenCode fra WSL** + + Gå til prosjektmappen din (Windows-filer er tilgjengelige via `/mnt/c/`, `/mnt/d/` osv.) og kjør OpenCode. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## Skrivebordsapp + WSL-server + +Hvis du foretrekker OpenCode-skrivebordsappen, men vil kjøre serveren i WSL: + +1. **Start serveren i WSL** med `--hostname 0.0.0.0` for å tillate eksterne tilkoblinger: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **Koble skrivebordsappen** til `http://localhost:4096` + +:::note +Hvis `localhost` ikke fungerer i oppsettet ditt, bruk WSL-IP-adressen i stedet (fra WSL: `hostname -I`) og koble til `http://:4096`. +::: + +:::caution +Når du bruker `--hostname 0.0.0.0`, sett `OPENCODE_SERVER_PASSWORD` for å sikre serveren. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## Web-klient + WSL + +For best web-opplevelse på Windows: + +1. **Kjør `opencode web` i WSL-terminalen** i stedet for PowerShell: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Åpne i Windows-nettleseren** på `http://localhost:` (OpenCode skriver ut URL-en) + +Når du kjører `opencode web` fra WSL, får du riktig filsystemtilgang og terminalintegrasjon, samtidig som det er tilgjengelig fra Windows-nettleseren din. + +--- + +## Tilgang til Windows-filer + +WSL kan få tilgang til alle Windows-filer via `/mnt/`-katalogen: + +- `C:`-stasjon → `/mnt/c/` +- `D:`-stasjon → `/mnt/d/` +- Og så videre... + +Eksempel: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +For en jevnere opplevelse kan du klone/kopiere repoet ditt inn i WSL-filsystemet (for eksempel under `~/code/`) og kjøre OpenCode der. +::: + +--- + +## Tips + +- Kjør OpenCode i WSL for prosjekter lagret på Windows-stasjoner: filtilgang fungerer smidig +- Bruk [WSL-utvidelsen i VS Code](https://code.visualstudio.com/docs/remote/wsl) sammen med OpenCode for en integrert utviklingsflyt +- OpenCode-konfigurasjon og sesjoner lagres i WSL-miljøet på `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/nb/zen.mdx b/packages/web/src/content/docs/nb/zen.mdx new file mode 100644 index 00000000000..f8dac0f3919 --- /dev/null +++ b/packages/web/src/content/docs/nb/zen.mdx @@ -0,0 +1,254 @@ +--- +title: Zen +description: Utvalgt liste over modeller levert av OpenCode. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen er en liste over testede og verifiserte modeller levert av OpenCode-teamet. + +:::note +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 +OpenCode. + +--- + +## Bakgrunn + +Det er et stort antall modeller der ute, men bare noen få av dem +disse modellene fungerer godt som kodeagenter. I tillegg er de fleste tilbydere +konfigurert veldig annerledes; slik at du får veldig forskjellig ytelse og kvalitet. + +:::tip +Vi testet en utvalgt gruppe modeller og leverandører som fungerer godt med OpenCode. +::: + +Så hvis du bruker en modell gjennom noe som OpenRouter, kan du aldri bli det +sikker på om du får den beste versjonen av modellen du ønsker. + +For å fikse dette gjorde vi et par ting: + +1. Vi testet en utvalgt gruppe modeller og snakket med teamene deres om hvordan + best kjøre dem. +2. Vi samarbeidet deretter med noen få leverandører for å sikre at disse ble servert + riktig. +3. Til slutt benchmarket vi kombinasjonen av modell/leverandør og kom frem + med en liste som vi har lyst til å anbefale. + +OpenCode Zen er en AI gateway som gir deg tilgang til disse modellene. + +--- + +## Slik fungerer det + +OpenCode Zen fungerer som alle andre leverandører i OpenCode. + +1. Du logger på **OpenCode Zen**, legg til fakturering + detaljer, og kopier API-nøkkelen. +2. Du kjører kommandoen `/connect` i TUI, velger OpenCode Zen og limer inn API-nøkkelen. +3. Kjør `/models` i TUI for å se listen over modeller vi anbefaler. + +Du belastes per forespørsel, og du kan legge til kreditt på kontoen din. + +--- + +## Endepunkter + +Du kan også få tilgang til modellene våre gjennom følgende API-endepunkter. + +| Modell | Modell ID | Endepunkt | AI SDK Pakke | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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` | + +[modell-id](/docs/config/#models) i OpenCode-konfigurasjonen +bruker formatet `opencode/`. For eksempel, for GPT 5.2 Codex, ville du +bruk `opencode/gpt-5.2-codex` i konfigurasjonen din. + +--- + +### Modeller + +Du kan hente hele listen over tilgjengelige modeller og deres metadata fra: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## Priser + +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.1 | $0,30 | $1,20 | $0,10 | - | +| GLM 4.7 Free | Gratis | Gratis | Gratis | - | +| 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 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 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.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 | Gratis | Gratis | Gratis | - | + +Du legger kanskje merke til _Claude Haiku 3.5_ i brukshistorikken din. Dette er en [lavprismodell](/docs/config/#models) som brukes til å generere titlene på øktene dine. + +:::note +Kredittkortgebyrer overføres til kostpris (4,4 % + $0,30 per transaksjon); vi belaster ikke noe utover det. +::: + +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. +- 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. + +--- + +### Automatisk påfylling + +Hvis saldoen din går under $5, vil Zen automatisk fylle på med $20. + +Du kan endre beløpet for automatisk påfylling. Du kan også deaktivere automatisk påfylling helt. + +--- + +### Månedlige grenser + +Du kan også angi en månedlig bruksgrense for hele arbeidsområdet og for hver +medlem av teamet ditt. + +La oss for eksempel si at du setter en månedlig bruksgrense til $20, Zen vil ikke bruke +mer enn $20 på en måned. Men hvis du har automatisk påfylling aktivert, kan Zen ende opp +belaster deg mer enn $20 hvis saldoen din går under $5. + +--- + +## Personvern + +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. +- 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). + +--- + +## For lag + +Zen fungerer også utmerket for team. Du kan invitere lagkamerater, tildele roller, kuratere +modellene laget ditt bruker, og mer. + +:::note +Arbeidsområder er for øyeblikket gratis for team som en del av betaversjonen. +::: + +Å administrere arbeidsområdet ditt er for øyeblikket gratis for team som en del av betaversjonen. Det blir vi +deler mer informasjon om prisene snart. + +--- + +### Roller + +Du kan invitere lagkamerater til arbeidsområdet ditt og tildele roller: + +- **Admin**: Administrer modeller, medlemmer, API-nøkler og fakturering +- **Medlem**: Administrer kun sine egne API-nøkler + +Administratorer kan også sette månedlige forbruksgrenser for hvert medlem for å holde kostnadene under kontroll. + +--- + +### Modelltilgang + +Administratorer kan aktivere eller deaktivere spesifikke modeller for arbeidsområdet. Forespørsler til en deaktivert modell vil returnere en feil. + +Dette er nyttig for tilfeller der du ønsker å deaktivere bruken av en modell som +samler inn data. + +--- + +### Ta med egen nøkkel + +Du kan bruke dine egne OpenAI- eller Anthropic API-nøkler mens du fortsatt har tilgang til andre modeller i Zen. + +Når du bruker dine egne nøkler, faktureres tokens direkte av leverandøren, ikke av Zen. + +For eksempel kan organisasjonen din allerede ha en nøkkel for OpenAI eller Anthropic +og du vil bruke det i stedet for det Zen gir. + +--- + +## Mål + +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å. diff --git a/packages/web/src/content/docs/pl/acp.mdx b/packages/web/src/content/docs/pl/acp.mdx new file mode 100644 index 00000000000..3b3c4720ecb --- /dev/null +++ b/packages/web/src/content/docs/pl/acp.mdx @@ -0,0 +1,158 @@ +--- +title: ACP +description: Używanie OpenCode z protokołem Agent Client Protocol (ACP). +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode obsługuje [Agent Client Protocol](https://agentclientprotocol.com) (ACP), który umożliwia korzystanie z OpenCode bezpośrednio w edytorach i środowiskach IDE. + +:::tip +Listę edytorów i narzędzi obsługujących ACP znajdziesz w [raporcie postępu ACP](https://zed.dev/blog/acp-progress-report#available-now). +::: + +ACP to otwarty standard, który ujednolica komunikację między edytorami kodu a agentami kodującymi AI. + +--- + +## Konfiguracja + +Aby używać OpenCode przez ACP, skonfiguruj swój edytor tak, aby uruchamiał polecenie `opencode acp`. + +Uruchamia to OpenCode jako podproces zgodny z ACP, który komunikuje się z edytorem za pomocą JSON-RPC przez stdio. + +Poniżej znajdują się przykłady dla edytorów obsługujących ACP. + +--- + +### Zed + +Dodaj do konfiguracji [Zed](https://zed.dev) (`~/.config/zed/settings.json`): + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +Aby użyć, wybierz `agent: new thread` w **Palecie poleceń** (Command Palette). + +Możesz także przypisać skrót klawiszowy, edytując `keymap.json`: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### JetBrains IDE + +Dodaj do swojego [JetBrains IDE](https://www.jetbrains.com/) plik `acp.json` zgodnie z [dokumentacją](https://www.jetbrains.com/help/ai-assistant/acp.html): + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +Następnie wybierz „OpenCode” w selektorze agentów AI Chat. + +--- + +### Avante.nvim + +Dodaj do konfiguracji [Avante.nvim](https://github.com/yetone/avante.nvim): + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +Jeśli potrzebujesz przekazać klucz API: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +Aby używać OpenCode jako agenta ACP w [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim), dodaj następującą konfigurację do Neovim: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +Ta konfiguracja sprawia, że CodeCompanion używa OpenCode jako agenta ACP do czatu. + +Jeśli wymagany jest `OPENCODE_API_KEY`, zapoznaj się z sekcją [Konfigurowanie adapterów: Zmienne środowiskowe](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) w dokumentacji CodeCompanion.nvim, aby uzyskać szczegółowe informacje. + +## Wsparcie + +OpenCode działa przez ACP tak samo, jak w terminalu. Obsługiwane są wszystkie główne funkcje: + +:::note +Niektóre polecenia z ukośnikiem, takie jak `/undo` i `/redo`, nie są obecnie obsługiwane przez ACP. +::: + +- Narzędzia wbudowane (operacje na plikach, terminal itp.) +- Niestandardowe narzędzia i polecenia z ukośnikiem +- Serwery MCP zdefiniowane w konfiguracji OpenCode +- Zasady projektu z `AGENTS.md` +- Niestandardowe formatery i lintery +- Agenci systemowi i uprawnienia diff --git a/packages/web/src/content/docs/pl/agents.mdx b/packages/web/src/content/docs/pl/agents.mdx new file mode 100644 index 00000000000..7a4d7a9960c --- /dev/null +++ b/packages/web/src/content/docs/pl/agents.mdx @@ -0,0 +1,746 @@ +--- +title: Agenci +description: Konfiguruj i używaj potężnych agentów. +--- + +Agenci to asystenci AI, których można przypisać do ról i workflow. Umożliwiają tworzenie ukierunkowanych narzędzi z niestandardowymi promptami, modelami i dostępem do narzędzi. + +:::tip +Użyj agenta Plan, aby uzyskać dostęp do kodu i przeglądać informacje bez wprowadzania zmian w kodzie. +::: + +Możesz przełączać się między agentami podczas sesji lub wywoływać ich za pomocą wzmianki `@`. + +--- + +## Typy + +W OpenCode obowiązuje zasada dwóch typów agentów: Primary (Główni) i Subagents (Subagenci). + +--- + +### Primary Agents (Agenci główni) + +Główni asystenci, z którymi prowadzisz interakcję. Możesz przełączać się między nimi za pomocą klawisza **Tab** lub skrótu klawiszowego `switch_agent`. Ci agenci obsługują główną pętlę. Dostęp do narzędzi jest konfigurowany za pomocą uprawnień — na przykład w agencie Build wszystkie narzędzia są dostępne, a w agencie Plan są ograniczone. + +:::tip +Użyj klawisza **Tab**, aby przełączać się między agentami podczas sesji. +::: + +OpenCode zawiera dwa wbudowane agenty główne: **Build** i **Plan**. Przyjrzymy się im poniżej. + +--- + +### Subagents (Subagenci) + +Subagenci to asystenci pomocniczy, których mogą przywoływać agenci główni w celu wykonania konkretnych zadań. Możesz także wywoływać ich ręcznie, **wzmiankując ich (@)** w swoich wiadomościach. + +OpenCode ma dwóch wbudowanych subagentów: **General** i **Explore**. Przyjrzymy się im poniżej. + +--- + +## Wbudowane + +OpenCode ma dwa wbudowane agenty główne i dwa wbudowane subagenty. + +--- + +### Build + +_Mode_: `primary` + +Build to **domyślny** agent ogólnego przeznaczenia z pełnym zestawem narzędzi. Jest to standardowy agent do prac programistycznych, który ma dostęp do operacji na plikach i poleceń systemowych. + +--- + +### Plan + +_Mode_: `primary` + +Dedykowany agent do analizy. Używa zestawu narzędzi tylko do odczytu, aby zmniejszyć ryzyko i zapobiec niezamierzonym zmianom. +Domyślnie uprawnienia są ustawione na `ask` dla: + +- `file edits`: Wszystkie zapisy, patche i edycje +- `bash`: Wszystkie polecenia bash + +Ten agent jest zalecany, gdy chcesz, aby LLM zapoznał się z kodem, stworzył plan lub odpowiedział na pytania bez ryzyka modyfikacji bazy kodu. + +--- + +### General + +_Mode_: `subagent` + +Rozwiązuje złożone zadania wieloetapowe. Pełny dostęp do narzędzi (z możliwością modyfikacji plików), dzięki czemu może w razie potrzeby wprowadzać zmiany w plikach. Używany przez agenta nadrzędnego do delegowania jednostek pracy. + +--- + +### Explore + +_Mode_: `subagent` + +Szybki agent tylko do odczytu do eksploracji baz kodu. Nie może modyfikować plików. Używany, gdy chcesz szybko znaleźć pliki według wzorców, wyszukać w kodzie słowa kluczowe lub uzyskać odpowiedzi na pytania dotyczące bazy kodu. + +--- + +### Compaction + +_Mode_: `primary` + +Ukryty agent systemowy, który kompresuje kontekst w zwięzłe podsumowanie. Działa automatycznie i nie jest widoczny w interfejsie użytkownika. + +--- + +### Title + +_Mode_: `primary` + +Ukryty agent systemowy, który generuje krótki tytuł sesji. Działa automatycznie i nie jest widoczny w interfejsie użytkownika. + +--- + +### Summary + +_Mode_: `primary` + +Ukryty agent systemowy, który generuje podsumowanie sesji. Działa automatycznie i nie jest widoczny w interfejsie użytkownika. + +--- + +## Użycie + +1. W przypadku agentów głównych użyj klawisza **Tab**, aby przełączać się między nimi podczas sesji. Można to również zrobić za pomocą skrótu klawiszowego `switch_agent`. + +2. Subagentów można wywoływać: + - **Automatycznie** przez głównych agentów do specjalistycznych zadań na podstawie ich opisów. + - Ręcznie, **wzmiankując (@)** subagenta w swoich wiadomościach. Na przykład: + + ```txt frame="none" + @explore help me search for this function + ``` + +3. **Nawigacja pomiędzy sesjami**: Kiedy sesja ma sesje podrzędne, możesz nawigować pomiędzy sesją nadrzędną a sesjami podrzędnymi za pomocą: + - **\+Prawo** (lub skonfigurowanego klawisza `session_child_cycle`), aby przełączać się w dół: rodzic → dziecko 1 → dziecko 2 → ... → rodzic + - **\+Lewo** (lub skonfigurowanego klawisza `session_child_cycle_reverse`), aby przełączać się w górę: rodzic ← dziecko 1 ← dziecko 2 ← ... ← rodzic + + Umożliwia to płynne przełączanie się między główną rozmową a pracą specjalistyczną wykonywaną przez subagentów. + +--- + +## Konfiguracja + +Możesz tworzyć własnych agentów lub dostosowywać istniejących. Agentów można definiować na dwa sposoby: + +--- + +### JSON + +Skonfiguruj agenta w pliku `opencode.json`: + +```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 + +Możesz także definiować agentów za pomocą plików markdown. Przechowuj je w: + +- Globalnie: `~/.config/opencode/agents/` +- W projekcie: `.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. +``` + +Nazwa pliku markdown staje się nazwą agenta. Na przykład `review.md` tworzy agenta `review`. + +--- + +## Opcje + +Przyjrzyjmy się szczegółowo opcjom konfiguracji. + +--- + +### Description (Opis) + +Użyj `description`, aby krótko opisać, co robi agent i kiedy go używać. + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +Jest to **wymagana** opcja konfiguracji. + +--- + +### Temperature (Temperatura) + +Kontroluj losowość i kreatywność odpowiedzi LLM za pomocą konfiguracji `temperature`. + +Niższe wartości sprawiają, że odpowiedzi są bardziej skupione i deterministyczne, podczas gdy wyższe wartości wprowadzają więcej różnorodności i kreatywności. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Wartość temperatury zwykle waha się od 0.0 do 1.0: + +- **0.0-0.2**: Bardzo skoncentrowane i deterministyczne odpowiedzi, idealne do analizy kodu i debugowania +- **0.3-0.5**: Zrównoważone odpowiedzi, dobre do ogólnych zadań programistycznych +- **0.6-1.0**: Bardziej kreatywne i zróżnicowane odpowiedzi, przydatne podczas burzy mózgów i eksploracji + +```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}" + } + } +} +``` + +Jeśli nie zostanie skonfigurowana, OpenCode używa wartości domyślnej dla danego modelu; 0 dla modeli rozumowania (reasoning models), 0.55 dla modeli Qwen. + +--- + +### Steps (Kroki) + +Kontroluj maksymalną liczbę iteracji, jaką agent może wykonać, zanim poprosi o interwencję użytkownika. Pomaga to kontrolować koszty i zapobiegać pętlom. + +Jeśli ta opcja nie zostanie skonfigurowana, agent będzie kontynuował iterację, dopóki model nie zakończy zadania lub użytkownik nie przerwie działania. + +```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 + } + } +} +``` + +Po osiągnięciu limitu agent otrzymuje specjalny monit systemowy nakazujący podsumowanie swojej pracy i zarekomendowanie kolejnych kroków. + +:::caution +Starsze pole `maxSteps` jest przestarzałe. Zamiast tego użyj `steps`. +::: + +--- + +### Disabled (Wyłączony) + +Ustaw na `true`, aby wyłączyć agenta. + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### Prompt (Monit) + +Podaj niestandardowy prompt systemowy dla tego agenta za pomocą konfiguracji `prompt`. Prompt powinien zawierać instrukcje dotyczące celu i zachowania agenta. + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Ścieżka jest względna do miejsca, w którym znajduje się plik konfiguracyjny. Działa to zarówno w przypadku globalnej konfiguracji OpenCode, jak i konfiguracji specyficznej dla projektu. + +--- + +### Model + +Użyj `model`, aby określić model dla tego agenta. Przydatne do używania różnych modeli do różnych zadań. Na przykład użycie modelu rozumowania do planowania, ale szybszego modelu do edycji. + +:::tip +Jeśli model nie zostanie określony, agenci główni używają [modelu skonfigurowanego globalnie](/docs/config#models), a agenci podrzędni używają modelu agenta, który ich wywołał. +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +Identyfikator modelu jest taki sam, jak w konfiguracji OpenCode w `provider/model-id`. Na przykład, [OpenCode Zen](/docs/zen), użyj `opencode/gpt-5.1-codex` dla GPT 5.1 Codex. + +--- + +### Tools (Narzędzia) + +Kontroluj, które narzędzia są dostępne dla tego agenta, za pomocą konfiguracji `tools`. Możesz włączyć lub wyłączyć określone narzędzia, ustawiając je na `true` lub `false`. + +```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 +Konfiguracja specyficzna dla agenta nadpisuje konfigurację globalną. +::: + +Możesz także używać symboli wieloznacznych (wildcards), aby kontrolować wiele narzędzi jednocześnie. Na przykład, aby wyłączyć wszystkie narzędzia z serwera MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[Dowiedz się więcej o narzędziach](/docs/tools). + +--- + +### Permissions (Uprawnienia) + +Możesz skonfigurować uprawnienia dla potencjalnie wrażliwych działań wykonywanych przez agenta. Obecnie obsługiwane dla narzędzi `edit`, `bash` i `webfetch`: + +- `"ask"` — Pytaj o zatwierdzenie przed użyciem narzędzia +- `"allow"` — Zezwalaj na użycie bez zatwierdzenia +- `"deny"` — Zabroń użycia narzędzia + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +Możesz nadpisać to dla każdego agenta. + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +Można to również ustawić w agentach Markdown. + +```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. +``` + +Możesz to skonfigurować szczegółowo dla poleceń bash. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +Można to połączyć z globalnym symbolem wieloznacznym. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +Możesz także użyć symbolu wieloznacznego `*`, aby zarządzać wszystkimi innymi poleceniami. +Najbardziej szczegółowa reguła ma pierwszeństwo, symbol wieloznaczny `*` jest sprawdzany na końcu. + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[Dowiedz się więcej o uprawnieniach](/docs/permissions). + +--- + +### Mode (Tryb) + +Kontroluj tryb agenta za pomocą konfiguracji `mode`. Opcja `mode` określa, w jaki sposób agent może być używany. + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +Opcję `mode` można ustawić na `primary`, `subagent` lub `all`. Jeśli nie podano `mode`, domyślnie jest to `all`. + +--- + +### Hidden (Ukryty) + +Ukryj subagenta w menu autouzupełniania `@` za pomocą `hidden: true`. Przydatne w przypadku subagentów narzędziowych, którzy powinni być wywoływani tylko programowo przez innych agentów, a nie bezpośrednio przez użytkownika. + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +Wpływa to tylko na widoczność w menu autouzupełniania. Model nadal może wywoływać ukrytych agentów za pomocą narzędzia zadania, jeśli ma do nich dostęp. + +:::note +Dotyczy tylko agentów z `mode: subagent`. +::: + +--- + +### Task Permissions (Uprawnienia zadań) + +Kontroluj, których subagentów może wywołać ten agent za pomocą narzędzia zadania, używając `permission.task`. Używa wzorców glob do elastycznego dopasowywania. + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +Po ustawieniu wartości `deny` subagent zostanie usunięty z definicji narzędzia Zadania, więc model nie będzie nawet wiedział o jego istnieniu. + +:::tip +Reguły są oceniane w kolejności i **wygrywa ostatnia pasująca reguła**. W powyższym przykładzie `orchestrator-planner` pasuje zarówno do `*` (odmowa), jak i `orchestrator-*` (zezwolenie), ale ponieważ `orchestrator-*` występuje po `*`, wynikiem jest `allow`. +::: + +:::tip +Zawsze możesz wywołać subagenta ręcznie, wspominając go bezpośrednio (`@`), nawet jeśli obecny agent ma uprawnienia ustawione na `deny`. +::: + +--- + +### Color (Kolor) + +Dostosuj wygląd agenta w interfejsie użytkownika za pomocą opcji `color`. Wpływa to na ikonę i obramowanie agenta w interfejsie. + +Użyj kodu hex (np. `#FF5733`) lub nazwy koloru motywu: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +Kontroluj różnorodność odpowiedzi za pomocą opcji `top_p`. Alternatywa dla temperatury w celu kontrolowania losowości. + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +Wartość waha się od 0.0 do 1.0. Niższe wartości są bardziej skoncentrowane, wyższe wartości są bardziej zróżnicowane. + +--- + +### Passthrough (Przekazywanie) + +Wszelkie inne konfiguracje w agentach są **przekazywane bezpośrednio** do dostawcy modelu. Pozwala to na korzystanie z funkcji i parametrów specyficznych dla dostawcy. + +Na przykład, używając modelu rozumowania OpenAI, możesz kontrolować wysiłek rozumowania: + +```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" + } + } +} +``` + +Te dodatkowe właściwości zależą od modelu i dostawcy. Sprawdź dokumentację swojego dostawcy pod kątem dostępnych parametrów. + +:::tip +Uruchom `opencode models`, aby zobaczyć dostępne modele. +::: + +--- + +## Tworzenie agentów + +Możesz stworzyć nowych agentów interaktywnie za pomocą polecenia: + +```bash +opencode agent create +``` + +Poprowadzi Cię to przez proces: + +1. Pytanie o miejsce zapisu agenta (globalnie lub dla projektu). +2. Opis tego, co agent powinien robić. +3. Wygenerowanie odpowiedniego promptu systemowego i identyfikatora. +4. Wybór narzędzi, do których agent powinien mieć dostęp. +5. Zapisanie pliku markdown z konfiguracją agenta. + +--- + +## Przypadki użycia + +Oto kilka typowych zastosowań różnych agentów: + +- **Agent programista**: Pełne prace programistyczne z dostępem do wszystkich narzędzi. +- **Agent Plan**: Analiza i planowanie bez ryzyka modyfikacji kodu. +- **Agent recenzujący**: Przegląd kodu z dostępem do odczytu plików i narzędzi dokumentacyjnych. +- **Agent debugujący**: Koncentruje się na rozwiązywaniu problemów z dostępem do narzędzi bash i odczytu plików. +- **Agent Documentation**: Tworzenie i utrzymywanie dokumentacji z dostępem do operacji na plikach, ale bez poleceń systemowych. + +--- + +## Przykłady + +Oto kilka przykładowych agentów, którzy mogą być przydatni. + +:::tip +Masz agenta, którym warto się podzielić? [Prześlij PR](https://github.com/anomalyco/opencode). +::: + +--- + +### Agent Documentation + +```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 +``` + +--- + +### Security Auditor + +```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/pl/cli.mdx b/packages/web/src/content/docs/pl/cli.mdx new file mode 100644 index 00000000000..35218590181 --- /dev/null +++ b/packages/web/src/content/docs/pl/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: Opcje i polecenia wiersza poleceń OpenCode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +CLI OpenCode domyślnie uruchamia [TUI](/docs/tui), gdy wywołasz je bez argumentów. + +```bash +opencode +``` + +CLI obsługuje też polecenia opisane na tej stronie, więc możesz używać OpenCode programowo. + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +Uruchamia interfejs terminalowy (TUI) OpenCode. + +```bash +opencode [project] +``` + +#### Flagi + +| Flaga | Skrót | Opis | +| ------------ | ----- | ----------------------------------------------------------------------- | +| `--continue` | `-c` | Kontynuuj ostatnią sesję | +| `--session` | `-s` | Identyfikator sesji do kontynuowania | +| `--fork` | | Sklonuj sesję podczas kontynuacji (użyj z `--continue` lub `--session`) | +| `--prompt` | | Monit do użycia | +| `--model` | `-m` | Model do użycia w formacie dostawca/model | +| `--agent` | | Agent do użycia | +| `--port` | | Port do nasłuchiwania | +| `--hostname` | | Nazwa hosta, do której należy się powiązać | + +--- + +## Polecenia + +Interfejs CLI OpenCode zawiera także dodatkowe polecenia. + +--- + +### agent + +Zarządzaj agentami OpenCode. + +```bash +opencode agent [command] +``` + +--- + +### attach + +Dołącz terminal do już działającego serwera backendu OpenCode uruchomionego za pomocą `serve` lub `web`. + +```bash +opencode attach [url] +``` + +Pozwala to połączyć TUI ze zdalnym backendem OpenCode. Na przykład: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### Flagi + +| Flaga | Skrót | Opis | +| ----------- | ----- | --------------------------------------- | +| `--dir` | | Katalog roboczy, w którym uruchomić TUI | +| `--session` | `-s` | Identyfikator sesji do kontynuowania | + +--- + +#### create + +Utwórz nowego agenta z niestandardową konfiguracją. + +```bash +opencode agent create +``` + +To polecenie poprowadzi Cię przez proces tworzenia nowego agenta z niestandardowym promptem systemowym i konfiguracją narzędzi. + +--- + +#### list + +Wyświetl listę wszystkich agentów. + +```bash +opencode agent list +``` + +--- + +### auth + +Zarządzaj danymi uwierzytelniającymi i logowaniem dla dostawców. + +```bash +opencode auth [command] +``` + +--- + +#### login + +OpenCode integruje się z wieloma dostawcami. Możesz użyć `opencode auth login`, aby skonfigurować klucz API dla dowolnego obsługiwanego dostawcy. Klucze są bezpiecznie przechowywane w `~/.local/share/opencode/auth.json`. + +```bash +opencode auth login +``` + +Podczas uruchamiania OpenCode ładuje dostawców z pliku poświadczeń, a także ze zmiennych środowiskowych lub pliku `.env` w Twoim projekcie. + +--- + +#### list + +Wyświetl listę wszystkich uwierzytelnionych dostawców przechowywanych w pliku poświadczeń. + +```bash +opencode auth list +``` + +Lub skrócona wersja: + +```bash +opencode auth ls +``` + +--- + +#### logout + +Wyloguj się z dostawcy, usuwając go z pliku poświadczeń. + +```bash +opencode auth logout +``` + +--- + +### github + +Zarządzaj agentem GitHub w celu automatyzacji repozytorium. + +```bash +opencode github [command] +``` + +--- + +#### install + +Zainstaluj agenta GitHub w swoim repozytorium. + +```bash +opencode github install +``` + +Spowoduje to utworzenie pliku workflow GitHub Actions i poprowadzi Cię przez proces konfiguracji. [Dowiedz się więcej](/docs/github). + +--- + +#### run + +Uruchom agenta na GitHubie. Zwykle używane w GitHub Actions. + +```bash +opencode github run +``` + +##### Flagi + +| Flaga | Opis | +| --------- | ---------------------------------------- | +| `--event` | Zdarzenie GitHub, które wyzwoliło agenta | +| `--token` | Osobisty token dostępu GitHub | + +--- + +### mcp + +Zarządzaj serwerami Model Context Protocol (MCP). + +```bash +opencode mcp [command] +``` + +--- + +#### add + +Dodaj serwer MCP do swojej konfiguracji. + +```bash +opencode mcp add +``` + +To polecenie poprowadzi Cię przez proces dodawania lokalnego lub zdalnego serwera MCP. + +--- + +#### list + +Wyświetl listę wszystkich skonfigurowanych serwerów MCP i ich status. + +```bash +opencode mcp list +``` + +Lub skrócona wersja: + +```bash +opencode mcp ls +``` + +--- + +#### auth + +Uwierzytelnij się w serwerze MCP z włączoną funkcją OAuth. + +```bash +opencode mcp auth [name] +``` + +Jeśli nie podasz nazwy serwera, zostaniesz poproszony o wybranie jednego z serwerów wymagających uwierzytelnienia. + +Możesz także wyświetlić listę serwerów obsługujących OAuth i ich status uwierzytelnienia. + +```bash +opencode mcp auth list +``` + +Lub skrócona wersja: + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +Usuń tokeny OAuth dla serwera MCP. + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +Debuguj problemy z połączeniem OAuth dla serwera MCP. + +```bash +opencode mcp debug +``` + +--- + +### models + +Wyświetl listę modeli ze wszystkich skonfigurowanych dostawców. + +```bash +opencode models [provider] +``` + +Pokazuje modele dostępne do użycia w `provider/model`. + +Jest to identyfikator modelu, którego używasz w [konfiguracji](/docs/config). + +Opcjonalnie możesz podać identyfikator dostawcy, aby filtrować modele według tego dostawcy. + +```bash +opencode models anthropic +``` + +#### Flagi + +| Flaga | Opis | +| ----------- | ------------------------------------------------------------------------------- | +| `--refresh` | Odśwież pamięć podręczną modeli | +| `--verbose` | Bardziej szczegółowe dane wyjściowe modelu (zawiera metadane, takie jak koszty) | + +Użyj flagi `--refresh`, aby zaktualizować listę modeli w pamięci podręcznej. Jest to przydatne, gdy dostawca dodał nowe modele, które chcesz zobaczyć w OpenCode. + +```bash +opencode models --refresh +``` + +--- + +### run + +Uruchom OpenCode w trybie nieinteraktywnym, przekazując bezpośrednio prompt. + +```bash +opencode run [message..] +``` + +Jest to przydatne do tworzenia skryptów, automatyzacji lub gdy chcesz wysłać szybkie zapytanie bez uruchamiania TUI. Na przykład: + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +Można również użyć tego z działającym `opencode serve`, aby uniknąć zimnego startu serwera MCP przy każdym uruchomieniu: + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### Flagi + +| Flaga | Skrót | Opis | +| ------------ | ----- | ----------------------------------------------------------------------- | +| `--command` | | Polecenie do uruchomienia, reszta to argumenty | +| `--continue` | `-c` | Kontynuuj ostatnią sesję | +| `--session` | `-s` | Identyfikator sesji do kontynuowania | +| `--fork` | | Sklonuj sesję podczas kontynuacji (użyj z `--continue` lub `--session`) | +| `--share` | | Udostępnij sesję po zakończeniu | +| `--model` | `-m` | Model do użycia w formacie dostawca/model | +| `--agent` | | Agent do użycia | +| `--file` | `-f` | Pliki do załączenia do wiadomości | +| `--format` | | Format wyjściowy: `default` (sformatowany) lub `json` (surowy JSON) | +| `--title` | | Tytuł sesji (jeśli nie podano, zostanie wygenerowany z promptu) | +| `--attach` | | Dołącz do działającego serwera OpenCode (np. http://localhost:4096) | +| `--port` | | Port dla serwera lokalnego (domyślnie losowy) | + +--- + +### serve + +Uruchom serwer OpenCode (bez interfejsu) w celu uzyskania dostępu do API. Pełny opis API HTTP znajduje się w [dokumentacji serwera](/docs/server). + +```bash +opencode serve +``` + +Uruchamia to serwer HTTP, który zapewnia dostęp do API OpenCode bez interfejsu TUI. Ustaw `OPENCODE_SERVER_PASSWORD`, aby włączyć podstawowe uwierzytelnianie HTTP (domyślna nazwa użytkownika to `opencode`). + +#### Flagi + +| Flaga | Opis | +| ------------ | ------------------------------------------ | +| `--port` | Port do nasłuchiwania | +| `--hostname` | Nazwa hosta, do której należy się powiązać | +| `--mdns` | Włącz wykrywanie mDNS | +| `--cors` | Dodatkowe dozwolone źródła CORS | + +--- + +### session + +Zarządzaj sesjami OpenCode. + +```bash +opencode session [command] +``` + +--- + +#### list + +Lista wszystkich sesji OpenCode. + +```bash +opencode session list +``` + +##### Flagi + +| Flaga | Skrót | Opis | +| ------------- | ----- | ------------------------------------------ | +| `--max-count` | `-n` | Ogranicz do ostatnich N sesji | +| `--format` | | Format wyjściowy: tabela lub json (tabela) | + +--- + +### stats + +Pokaż statystyki wykorzystania tokenów i sesji OpenCode. + +```bash +opencode stats +``` + +#### Flagi + +| Flaga | Opis | +| ----------- | ------------------------------------------------------------------------------------- | +| `--days` | Pokaż statystyki z ostatnich N dni (domyślnie: cały czas) | +| `--tools` | Pokaż użycie poszczególnych narzędzi (domyślnie: wszystkie) | +| `--models` | Pokaż podział na modele (domyślnie ukryty). Podaj liczbę, aby pokazać N najczęstszych | +| `--project` | Filtruj według projektu (domyślnie: wszystkie projekty, pusty ciąg: bieżący projekt) | + +--- + +### export + +Eksportuj dane sesji jako JSON. + +```bash +opencode export [sessionID] +``` + +Jeśli nie podasz identyfikatora sesji, zostaniesz poproszony o wybranie jednej z ostatnich sesji. + +--- + +### import + +Importuj dane sesji z pliku JSON lub adresu URL udostępniania OpenCode. + +```bash +opencode import +``` + +Możesz importować z pliku lokalnego lub adresu URL. + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +Uruchom serwer OpenCode z interfejsem internetowym. + +```bash +opencode web +``` + +Uruchamia to serwer HTTP i udostępnia OpenCode przez interfejs przeglądarkowy. Ustaw `OPENCODE_SERVER_PASSWORD`, aby włączyć podstawowe uwierzytelnianie HTTP (domyślna nazwa użytkownika to `opencode`). + +#### Flagi + +| Flaga | Opis | +| ------------ | ------------------------------------------ | +| `--port` | Port do nasłuchiwania | +| `--hostname` | Nazwa hosta, do której należy się powiązać | +| `--mdns` | Włącz wykrywanie mDNS | +| `--cors` | Dodatkowe dozwolone źródła CORS | + +--- + +### acp + +Uruchom serwer ACP (Agent Client Protocol). + +```bash +opencode acp +``` + +Uruchamia serwer ACP, który komunikuje się przez stdin/stdout przy użyciu JSON-RPC. + +#### Flagi + +| Flaga | Opis | +| ------------ | ------------------------------------------ | +| `--cwd` | Katalog roboczy | +| `--port` | Port do nasłuchiwania | +| `--hostname` | Nazwa hosta, do której należy się powiązać | + +--- + +### uninstall + +Odinstaluj OpenCode i usuń wszystkie powiązane pliki. + +```bash +opencode uninstall +``` + +#### Flagi + +| Flaga | Skrót | Opis | +| --------------- | ----- | ----------------------------- | +| `--keep-config` | `-c` | Zachowaj pliki konfiguracyjne | +| `--keep-data` | `-d` | Zachowaj dane sesji i migawki | +| `--dry-run` | | Pokaż co zostanie usunięte | +| `--force` | `-f` | Pomiń monity o potwierdzenie | + +--- + +### upgrade + +Aktualizuj OpenCode do najnowszej lub określonej wersji. + +```bash +opencode upgrade [target] +``` + +Aby zaktualizować do najnowszej wersji: + +```bash +opencode upgrade +``` + +Aby zaktualizować do konkretnej wersji: + +```bash +opencode upgrade v0.1.48 +``` + +#### Flagi + +| Flaga | Skrót | Opis | +| ---------- | ----- | --------------------------------------------------- | +| `--method` | `-m` | Wymuś metodę instalacji: curl, npm, pnpm, bun, brew | + +--- + +## Flagi globalne + +Interfejs CLI OpenCode przyjmuje następujące flagi globalne dla każdego polecenia. + +| Flaga | Skrót | Opis | +| -------------- | ----- | ------------------------------------------- | +| `--help` | `-h` | Wyświetl pomoc | +| `--version` | `-v` | Wydrukuj numer wersji | +| `--print-logs` | | Drukuj logi na stderr | +| `--log-level` | | Poziom logowania (DEBUG, INFO, WARN, ERROR) | + +--- + +## Zmienne środowiskowe + +OpenCode można skonfigurować za pomocą zmiennych środowiskowych. + +| Zmienna | Typ | Opis | +| ------------------------------------- | ------- | ----------------------------------------------------------- | +| `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_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 | +| `OPENCODE_DISABLE_PRUNE` | boolean | Wyłącz czyszczenie starych wyników (pruning) | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | Wyłącz automatyczne ustawianie tytułu terminala | +| `OPENCODE_PERMISSION` | string | Konfiguracja uprawnień w JSON (inline) | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | Wyłącz domyślne wtyczki | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | Wyłącz automatyczne pobieranie serwerów LSP | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | Włącz modele eksperymentalne | +| `OPENCODE_DISABLE_AUTOCOMPACT` | boolean | Wyłącz automatyczne kompaktowanie kontekstu | +| `OPENCODE_DISABLE_CLAUDE_CODE` | boolean | Wyłącz integrację z `.claude` (prompt + skills) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | Wyłącz czytanie `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | Wyłącz ładowanie `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | boolean | Wyłącz pobieranie modeli ze źródeł zewnętrznych | +| `OPENCODE_FAKE_VCS` | string | Fałszywy dostawca VCS do celów testowych | +| `OPENCODE_DISABLE_FILETIME_CHECK` | boolean | Wyłącz sprawdzanie czasu modyfikacji plików (optymalizacja) | +| `OPENCODE_CLIENT` | string | Identyfikator klienta (domyślnie `cli`) | +| `OPENCODE_ENABLE_EXA` | boolean | Włącz narzędzie wyszukiwania internetowego Exa | +| `OPENCODE_SERVER_PASSWORD` | string | Włącz uwierzytelnianie podstawowe dla `serve`/`web` | +| `OPENCODE_SERVER_USERNAME` | string | Nazwa użytkownika do autoryzacji (domyślnie `opencode`) | +| `OPENCODE_MODELS_URL` | string | Niestandardowy adres URL do pobierania konfiguracji modeli | + +--- + +### Eksperymentalne + +Te zmienne włączają funkcje eksperymentalne, które mogą ulec zmianie lub zostać usunięte. + +| Zmienna | Typ | Opis | +| ----------------------------------------------- | ------- | -------------------------------------------- | +| `OPENCODE_EXPERIMENTAL` | boolean | Włącz wszystkie funkcje eksperymentalne | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | Włącz wykrywanie ikon | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | Wyłącz kopiowanie przy zaznaczaniu w TUI | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number | Domyślny limit czasu dla narzędzia bash w ms | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | number | Maksymalne tokeny wyjściowe dla LLM | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolean | Włącz obserwatora plików dla całego katalogu | +| `OPENCODE_EXPERIMENTAL_OXFMT` | boolean | Włącz formater oxfmt | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolean | Włącz eksperymentalne narzędzie LSP | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | Wyłącz obserwatora plików | +| `OPENCODE_EXPERIMENTAL_EXA` | boolean | Włącz funkcje eksperymentalne Exa | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolean | Włącz eksperymentalne sprawdzanie typów LSP | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolean | Włącz funkcje eksperymentalne Markdown | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolean | Włącz tryb planowania | diff --git a/packages/web/src/content/docs/pl/commands.mdx b/packages/web/src/content/docs/pl/commands.mdx new file mode 100644 index 00000000000..4c5dad7d6f5 --- /dev/null +++ b/packages/web/src/content/docs/pl/commands.mdx @@ -0,0 +1,323 @@ +--- +title: Polecenia +description: Twórz polecenia dla powtarzalnych zadań. +--- + +Polecenia to zdefiniowane prompty, które można uruchomić w TUI. + +```bash frame="none" +/my-command +``` + +Polecenia są dodatkiem do wbudowanych, takich jak `/init`, `/undo`, `/redo`, `/share`, `/help`. [Dowiedz się więcej](/docs/tui#commands). + +--- + +## Utwórz pliki źródłowe + +Utwórz pliki Markdown w katalogu `commands/`, aby zdefiniować polecenia. + +Utwórz `.opencode/commands/test.md`: + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Frontmatter definiuje właściwości. Treść staje się szablonem. + +Uruchom polecenie, wpisując `/`, a następnie nazwę polecenia. + +```bash frame="none" +"/test" +``` + +--- + +## Konfiguracja + +Możesz zdefiniować polecenia w `opencode.json` lub w plikach w katalogu `commands/`. + +--- + +### JSON + +Użyj opcji `command` w swojej konfiguracji opencode: + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Teraz możesz wybrać opcję w TUI: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +Można także definiować polecenia za pomocą plików Markdown. Trzymaj je w: + +- Globalnie: `~/.config/opencode/commands/` +- Na projekt: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Nazwa pliku Markdown staje się nazwą polecenia. Na przykład `test.md` pozwala +uruchomić: + +```bash frame="none" +/test +``` + +--- + +## Składnia promptu + +Prompty niestandardowych poleceń obsługują kilka specjalnych symboli zastępczych. + +--- + +### Argumenty + +Przekazuj argumenty do promptu, używając symbolu zastępczego `$ARGUMENTS`. + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +Uruchomienie polecenia z argumentami: + +```bash frame="none" +/component Button +``` + +`$ARGUMENTS` zostanie zastąpione przez `Button`. + +Dostęp do poszczególnych argumentów można uzyskać za pomocą parametrów pozycyjnych: + +- `$1` - Pierwszy argument +- `$2` - Drugi argument +- `$3` - Trzeci argument +- I tak dalej... + +Na przykład: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +Uruchomienie polecenia: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +Wartości: + +- `$1` to `config.json` +- `$2` to `src` +- `$3` to `{ "key": "value" }` + +--- + +### Dane wyjściowe poleceń + +Użyj `!command`, aby wstawić dane wyjściowe [polecenia bash](/docs/tui#bash-commands) do promptu. + +Na przykład, aby przeanalizować pokrycie testami: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +Lub aby przejrzeć ostatnie zmiany: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +Polecenia są uruchamiane w powłoce, a ich dane wyjściowe są wstawiane do promptu. + +--- + +### Odwołania do plików + +Dołącz pliki do swojego polecenia, używając `@` i ścieżki do pliku. + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +Zawartość pliku jest automatycznie wstawiana do promptu. + +--- + +## Opcje + +Przyjrzyjmy się szczegółowo opcjom konfiguracji. + +--- + +### Template + +Opcja `template` to prompt wysyłany do LLM po wykonaniu polecenia. + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +Jest to **wymagana** opcja konfiguracji. + +--- + +### Description + +Użyj `description`, aby dodać krótki opis działania polecenia. + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +Jest wyświetlany jako opis w TUI po wpisaniu polecenia. + +--- + +### Agent + +Użyj opcji `agent`, aby określić, który [agent](/docs/agents) powinien wykonać to polecenie. +Jeśli jest to [subagent](/docs/agents/#subagents), zostanie on użyty. +Aby to zmienić, ustaw `subtask` na `false`. + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +Jest to **opcjonalna** opcja konfiguracji. Jeśli nie podano, użyty zostanie domyślny agent. + +--- + +### Subtask + +Użyj `subtask`, aby wymusić wywołanie polecenia jako subzadania. +Jest to przydatne, jeśli chcesz, aby polecenie nie zanieczyszczało kontekstu i **zmusiło** agenta do działania jako subagent, +nawet jeśli `mode` jest ustawiony na `primary` w konfiguracji [agent](/docs/agents). + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +Jest to **opcjonalna** opcja konfiguracji. + +--- + +### Model + +Użyj `model`, aby określić model dla tego polecenia. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Jest to **opcjonalna** opcja konfiguracji. + +--- + +## Wbudowane + +opencode zawiera kilka wbudowanych poleceń, takich jak `/init`, `/undo`, `/redo`, `/share`, `/help`; [dowiedz się więcej](/docs/tui#commands). + +:::note +Polecenia wbudowane mogą zostać nadpisane. +::: + +Jeśli zdefiniujesz tę samą nazwę, twoje polecenie będzie miało pierwszeństwo. diff --git a/packages/web/src/content/docs/pl/config.mdx b/packages/web/src/content/docs/pl/config.mdx new file mode 100644 index 00000000000..cde2e312eaa --- /dev/null +++ b/packages/web/src/content/docs/pl/config.mdx @@ -0,0 +1,680 @@ +--- +title: Konfiguracja +description: Ustawienia OpenCode w pliku JSON. +--- + +Możesz dostosować OpenCode za pomocą pliku konfiguracyjnego JSON. + +--- + +## Format + +OpenCode obsługuje formaty **JSON** i **JSONC** (JSON z komentarzami). + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + // Theme configuration + "theme": "opencode", + "model": "anthropic/claude-sonnet-4-5", + "autoupdate": true, +} +``` + +--- + +## Lokalizacje + +Możesz umieścić swoją konfigurację w kilku różnych lokalizacjach, które mają ustaloną kolejność pierwszeństwa. + +:::note +Pliki konfiguracyjne są **łączone**, a nie nadpisywane. +::: + +Pliki konfiguracyjne są łączone ze sobą. Ustawienia z lokalizacji o wyższym priorytecie nadpisują ustawienia z lokalizacji o niższym priorytecie tylko w przypadku konfliktów kluczy. Ustawienia niekolidujące ze wszystkich źródeł są zachowywane. + +Na przykład, jeśli konfiguracja globalna ustawi `theme: "opencode"` i `autoupdate: true`, a konfiguracja projektu ustawi `model: "anthropic/claude-sonnet-4-5"`, ostateczna konfiguracja będzie zawierać wszystkie trzy ustawienia. + +--- + +### Kolejność pierwszeństwa + +Źródła konfiguracji są ładowane w następującej kolejności (źródła występujące później mają pierwszeństwo): + +1. **Konfiguracja zdalna** (z `.well-known/opencode`) – ustawienia wymuszane przez organizację +2. **Konfiguracja globalna** (`~/.config/opencode/opencode.json`) – preferencje użytkownika +3. **Konfiguracja niestandardowa** (zmienna `OPENCODE_CONFIG`) — jawne nadpisanie +4. **Konfiguracja projektu** (`opencode.json` w projekcie) - ustawienia specyficzne dla projektu +5. **Katalogi `.opencode`** - agenci, polecenia, umiejętności +6. **Konfiguracja wbudowana** (zmienna `OPENCODE_CONFIG_CONTENT`) — nadpisanie środowiska uruchomieniowego + +Oznacza to, że konfiguracje projektu mogą nadpisywać konfiguracje globalne, a konfiguracje globalne mogą nadpisywać konfiguracje zdalne. + +:::note +W katalogach `.opencode` i `~/.config/opencode` używane są **nazwy w liczbie mnogiej** dla podkatalogów: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/` i `themes/`. Nazwy w liczbie pojedynczej (np. `agent/`) są również obsługiwane dla kompatybilności wstecznej. +::: + +--- + +### Zdalna + +Organizacje mogą publikować konfigurację pod adresem `.well-known/opencode`. Jest ona pobierana automatycznie po uwierzytelnieniu u dostawcy, który ją obsługuje. + +Konfiguracja zdalna jest ładowana jako pierwsza i stanowi bazę. Wszystkie inne źródła konfiguracji (globalne, projektowe) mogą ją nadpisywać. + +Na przykład, jeśli Twoja organizacja udostępnia serwery MCP, które są domyślnie wyłączone: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +Możesz włączyć serwer w konfiguracji projektu: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### 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. + +Konfiguracja globalna ma pierwszeństwo przed konfiguracją zdalną. + +--- + +### Projekt + +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. + +:::tip +Dodaj ten plik do kontroli wersji, aby udostępniać konfigurację zespołowi. +::: + +Kiedy OpenCode się uruchamia, szuka pliku konfiguracyjnego w katalogu głównym repozytorium Git. + +Może on być przechowywany w Git i mieć ten sam schemat, co konfiguracja globalna. + +--- + +### Niestandardowa ścieżka + +Możesz załadować niestandardowy plik konfiguracyjny, ustawiając zmienną środowiskową `OPENCODE_CONFIG`. + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +Konfiguracja niestandardowa jest ładowana po konfiguracji globalnej i przed konfiguracją projektu w kolejności priorytetów. + +--- + +### Niestandardowy katalog + +Możesz ustawić niestandardowy katalog konfiguracyjny za pomocą zmiennej środowiskowej `OPENCODE_CONFIG_DIR`. Katalog ten będzie przeszukiwany pod kątem agentów, poleceń, trybów i wtyczek, tak jak standardowy katalog `.opencode` i powinien zachować tę samą strukturę. + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +Katalog niestandardowy jest ładowany po globalnej konfiguracji i katalogach `.opencode`, więc **może być łączony** z ich zawartością. + +--- + +## Schemat + +Plik konfiguracyjny ma schemat JSON dostępny pod adresem [**`opencode.ai/config.json`**](https://opencode.ai/config.json). + +Twój edytor powinien zapewniać walidację i autouzupełnianie na podstawie tego schematu. + +--- + +### TUI + +Możesz skonfigurować zachowanie TUI za pomocą opcji `tui`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +Dostępne opcje: + +- `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ę. + +[Dowiedz się więcej o korzystaniu z TUI](/docs/tui). + +--- + +### Server (Serwer) + +Możesz skonfigurować serwer dla `opencode serve` i `opencode web` za pomocą opcji `server`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +Dostępne opcje: + +- `port` - Port do nasłuchiwania. +- `hostname` — Nazwa hosta, z którą należy się powiązać. Gdy `mdns` jest włączone i nie ustawiono innej nazwy hosta, domyślnie jest to `0.0.0.0`. +- `mdns` - Włącz wykrywanie usług mDNS. Dzięki temu inne urządzenia w sieci mogą łatwo znaleźć Twój serwer OpenCode. +- `mdnsDomain` - Niestandardowa nazwa domeny dla usług mDNS. Domyślnie `opencode.local`. Przydatne do uruchamiania wielu instancji w tej samej sieci. +- `cors` - Dozwolone źródła CORS podczas korzystania z serwera HTTP z przeglądarki. Wartość musi być listą źródeł (schemat + host + opcjonalny port), np. `https://app.example.com`. + +[Dowiedz się więcej o serwerze](/docs/server). + +--- + +### Tools (Narzędzia) + +Kontroluj, które narzędzia są dostępne dla LLM, za pomocą opcji `tools`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[Dowiedz się więcej o narzędziach](/docs/tools). + +--- + +### Models (Modele) + +Możesz skonfigurować dostawców i modele, których chcesz używać, za pomocą opcji `provider`, `model` i `small_model`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +Opcja `small_model` konfiguruje oddzielny model do lżejszych zadań, takich jak generowanie tytułów. Domyślnie OpenCode wybiera tańszy model od tego samego dostawcy, jeśli jest dostępny, w przeciwnym razie powraca do modelu głównego. + +Opcje dostawcy mogą zawierać `timeout` i `setCacheKey`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` - Limit czasu żądania w milisekundach (domyślnie: 300000). Ustaw na `false`, aby wyłączyć. +- `setCacheKey` — Wymuś ustawienie klucza pamięci podręcznej dla dostawcy. + +Możesz także skonfigurować [modele lokalne](/docs/models#local). [Dowiedz się więcej o modelach](/docs/models). + +--- + +#### Opcje specyficzne dla dostawców + +Niektórzy dostawcy obsługują dodatkowe opcje konfiguracji poza `timeout` i `apiKey`. + +##### Amazon Bedrock + +Amazon Bedrock umożliwia konfigurację połączenia z AWS: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` — Region AWS dla Bedrock (domyślnie `AWS_REGION` env var lub `us-east-1`) +- `profile` - Nazwa profilu AWS z `~/.aws/credentials` (domyślnie `AWS_PROFILE` env var) +- `endpoint` — Niestandardowy adres URL punktu końcowego (np. dla punktów końcowych VPC). Jest to alias dla opcji ogólnej `baseURL` przy użyciu terminologii AWS. Jeśli podano oba, pierwszeństwo ma `endpoint`. + +:::note +Token okaziciela (`AWS_BEARER_TOKEN_BEDROCK` lub `/connect`) ma pierwszeństwo przed uwierzytelnianiem opartym na profilu. Aby uzyskać szczegółowe informacje, zobacz [pierwszeństwo uwierzytelniania](/docs/providers#authentication-precedence). +::: + +[Dowiedz się więcej o Amazon Bedrock](/docs/providers#amazon-bedrock). + +--- + +### Theme (Motyw) + +Skonfiguruj motyw interfejsu OpenCode za pomocą opcji `theme`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[Dowiedz się więcej o motywach](/docs/themes). + +--- + +### Agents (Agenci) + +Możesz zdefiniować i skonfigurować agentów za pomocą opcji `agent`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +Możesz także definiować agentów przy użyciu plików markdown w `~/.config/opencode/agents/` lub `.opencode/agents/`. [Dowiedz się więcej o agentach](/docs/agents). + +--- + +### Default Agent (Domyślny agent) + +Domyślnego agenta można ustawić za pomocą opcji `default_agent`. Określa to agenta, który jest używany, jeśli nie wybrano żadnego innego. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +Agent domyślny musi być agentem typu `primary` (nie `subagent`). Może to być agent wbudowany, taki jak `"build"` lub `"plan"`, albo zdefiniowany przez Ciebie [agent niestandardowy](/docs/agents). Jeśli agent nie istnieje lub jest subagentem, OpenCode powróci do `"build"` z ostrzeżeniem. + +Dotyczy to wszystkich interfejsów: TUI, CLI (`opencode run`), aplikacji desktopowej i GitHub Actions. + +--- + +### Share (Udostępnianie) + +Możesz skonfigurować [udostępnianie](/docs/share) za pomocą opcji `share`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +Opcje: + +- `"manual"` – Zezwalaj na ręczne udostępnianie (domyślnie) +- `"auto"` - Automatycznie udostępniaj nowe rozmowy +- `"disabled"` - Całkowicie wyłącz udostępnianie + +Domyślnie ustawiony jest tryb ręczny, w którym należy jawnie udostępniać rozmowy za pomocą polecenia `/share`. + +--- + +### Commands (Polecenia) + +Możesz zdefiniować niestandardowe polecenia dla powtarzalnych zadań za pomocą opcji `command`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +Możesz także definiować polecenia przy użyciu plików Markdown w `~/.config/opencode/commands/` lub `.opencode/commands/`. [Dowiedz się więcej o poleceniach](/docs/commands). + +--- + +### Keybinds (Skróty klawiszowe) + +Możesz dostosować skróty klawiszowe za pomocą opcji `keybinds`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[Dowiedz się więcej o skrótach klawiszowych](/docs/keybinds). + +--- + +### Autoupdate (Automatyczna aktualizacja) + +OpenCode może automatycznie pobierać nowe wersje. Możesz to kontrolować za pomocą opcji `autoupdate`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +Jeśli nie chcesz automatycznych aktualizacji, ale chcesz być powiadamiany o nowych wersjach, ustaw `autoupdate` na `"notify"`. +Działa to tylko wtedy, gdy OpenCode nie został zainstalowany przez menedżera pakietów, takiego jak Homebrew. + +--- + +### Formatters (Formatery) + +Możesz skonfigurować formatery kodu za pomocą opcji `formatter`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[Dowiedz się więcej o formaterach](/docs/formatters). + +--- + +### Permissions (Uprawnienia) + +Domyślnie OpenCode **zezwala na wszystkie działania** bez konieczności zatwierdzania. Możesz to zmienić za pomocą opcji `permission`. + +Na przykład, aby wymagać zatwierdzenia dla narzędzi `edit` i `bash`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[Dowiedz się więcej o uprawnieniach](/docs/permissions). + +--- + +### Compaction (Kompaktowanie) + +Możesz kontrolować zachowanie kompaktowania kontekstu za pomocą opcji `compaction`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto` - Automatycznie kompaktuj, gdy kontekst jest pełny (domyślnie: `true`). +- `prune` - Usuń stare wyniki narzędzi, aby zaoszczędzić tokeny (domyślnie: `true`). + +--- + +### Watcher (Obserwator) + +Skonfiguruj ignorowane wzorce plików dla obserwatora plików za pomocą `watcher`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +Wzorce są zgodne ze składnią glob. Użyj tej opcji, aby wykluczyć często zmieniające się lub duże katalogi z monitorowania. + +--- + +### MCP Servers (Serwery MCP) + +Skonfiguruj serwery MCP, których chcesz używać, za pomocą opcji `mcp`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[Dowiedz się więcej o serwerach MCP](/docs/mcp-servers). + +--- + +### Plugins (Wtyczki) + +[Wtyczki](/docs/plugins) rozszerzają OpenCode o niestandardowe narzędzia, hooki i integracje. + +Umieść pliki wtyczek w `.opencode/plugins/` lub `~/.config/opencode/plugins/`. Możesz także załadować wtyczkę z npm za pomocą opcji `plugin`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[Dowiedz się więcej o wtyczkach](/docs/plugins). + +--- + +### Instructions (Instrukcje) + +Określ pliki instrukcji dla modelu, używając opcji `instructions`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Załadowane pliki są dołączane do promptu systemowego. Obsługuje wzorce glob. [Dowiedz się więcej o zasadach](/docs/rules). + +--- + +### Disabled Providers (Wyłączeni dostawcy) + +Zapobiegaj automatycznemu ładowaniu dostawców za pomocą opcji `disabled_providers`. Jest to przydatne, gdy chcesz wyłączyć niektórych dostawców, nawet jeśli masz dla nich dane uwierzytelniające. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +`disabled_providers` ma pierwszeństwo przed `enabled_providers`. +::: + +Opcja `disabled_providers` przyjmuje tablicę identyfikatorów dostawców. Gdy dostawca jest wyłączony: + +- Nie zostanie załadowany podczas startu. +- Nie zostanie załadowany, nawet jeśli podasz klucz API za pomocą `/connect`. +- Modele tego dostawcy nie pojawią się na liście wyboru modeli. + +--- + +### Enabled Providers (Włączeni dostawcy) + +Możesz określić listę dozwolonych dostawców za pomocą `enabled_providers`. Po ustawieniu, tylko wymienieni dostawcy będą ładowani. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +Jest to przydatne, gdy chcesz ograniczyć użycie OpenCode tylko do określonych dostawców. + +:::note +`disabled_providers` ma pierwszeństwo przed `enabled_providers`. +::: + +Jeśli dostawca jest wymieniony zarówno w `enabled_providers`, jak i `disabled_providers`, `disabled_providers` wygrywa. + +--- + +### Experimental (Eksperymentalne) + +Klucz `experimental` zawiera opcje, które są we wczesnej fazie rozwoju. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +Opcje eksperymentalne nie są stabilne. Mogą ulec zmianie lub zostać usunięte bez ostrzeżenia. +::: + +--- + +## Zmienne + +Możesz używać specjalnej składni w plikach konfiguracyjnych, aby odwoływać się do zmiennych środowiskowych i zawartości plików. + +--- + +### Env vars (Zmienne środowiskowe) + +Użyj `{env:VARIABLE_NAME}`, aby wstawić wartość zmiennej środowiskowej: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +Jeśli zmienna środowiskowa nie jest ustawiona, zostanie zastąpiona pustym ciągiem. + +--- + +### Files (Pliki) + +Użyj `{file:path/to/file}`, aby wstawić zawartość pliku: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +Ścieżki plików mogą być: + +- Względne do pliku konfiguracyjnego +- Lub absolutne, zaczynające się od `/` lub `~` + +Zalecamy używanie tego do: + +- Przechowywania wrażliwych danych, takich jak klucze API, w oddzielnych plikach. +- Ładowania dużych promptów bez zaśmiecania konfiguracji. +- Dzielenia fragmentów konfiguracji między wieloma plikami. diff --git a/packages/web/src/content/docs/pl/custom-tools.mdx b/packages/web/src/content/docs/pl/custom-tools.mdx new file mode 100644 index 00000000000..eaf403d2de8 --- /dev/null +++ b/packages/web/src/content/docs/pl/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +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`. + +--- + +## Tworzenie narzędzia + +Narzędzia tworzą pliki **TypeScript** lub **JavaScript**. Definicja narzędzia może być odwoływana do skryptów napisanych w **dowolnym języku** — TypeScript lub JavaScript są używane tylko w tym samym narzędziu. + +--- + +### Lokalizacja + +Można je uruchomić: + +- Lokalnie, umieszczając je w katalogu `.opencode/tools/` swojego projektu. +- Lub globalnie, umieszczając je w `~/.config/opencode/tools/`. + +--- + +### Struktura + +Najłatwiejszym sposobem tworzenia narzędzia jest pomocnika `tool()`, który zapewnia bezpieczeństwo i sprawdzanie poprawności. + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +**Nazwa pliku** staje się **nazwą narzędzia**. Pierwotne narzędzie `database`. + +--- + +#### Wiele narzędzi na plik + +Można także eksportować wiele narzędzi z jednego pliku. Każdy eksport staje się **oddzielnym językiem** o nazwie **`_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +Tworzy do dwóch narzędzi: `math_add` i `math_multiply`. + +--- + +### Argumenty + +Do zdefiniowania argumentów można zastosować `tool.schema`, czyli po prostu [Zod](https://zod.dev). + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +Można także bezpośrednio zaimportować [Zod](https://zod.dev) i zwyczajowo zwykły obiekt: + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### Kontekst + +Narzędzia kontekstowe charakterystycznej sesji: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +`context.directory` jako katalogowy pracodawczy. +`context.worktree` dla katalogu głównego zwalczającego git. + +--- + +## Przykład + +### 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. + +Fragment utworu jako skrypt w języku Python: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +Utwór instrumentalny, który jest ukryty: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +Tutaj istnieje narzędzie [`Bun.$`](https://bun.com/docs/runtime/shell) uruchamiające skryptu w języku Python. diff --git a/packages/web/src/content/docs/pl/ecosystem.mdx b/packages/web/src/content/docs/pl/ecosystem.mdx new file mode 100644 index 00000000000..7c75340c57d --- /dev/null +++ b/packages/web/src/content/docs/pl/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: Ekosystem +description: Projekty i integracje zbudowane w opencode. +--- + +Zgromadzenie stowarzyszenia organizacji na opencode. + +:::note +Chcesz zadać swój projekt badawczy z opencode do tej listy? Prześlij PR. +::: + +Możesz także sprawdzić [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) i [opencode.cafe](https://opencode.cafe), grupę skupiającą ekosystem i społeczność. + +--- + +## Wtyki + +| Imię | Opis | +| --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | Automatycznie uruchamiaj sesje opencode w izolowanych piaskownicach Daytona z synchronizacją git i podglądami na żywo | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | Automatycznie wstawiaj nagłówki sesji Helicone w celu grupowania urządzeń | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | Automatyczne wstrzykiwacze TypeScript/Svelte do odczytania plików za pomocą narzędzi wyszukiwania | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | wykorzystać do wykorzystania ChatGPT Plus/Pro zamiast kredytu API | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | korzystać z planu Gemini zamiast rozliczeń API | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | Wykorzystanie z bezpłatnych modeli Antigravity zamiast rozliczeń API | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Izolacja wielooddziałowych kontenerów deweloperskich z płytkami klonami i automatycznie przypisywanymi portami | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Wtyczka Google Antigravity OAuth z obsługą obsługi Google i bardziej niezawodną obsługą API | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Zoptymalizuj wykorzystanie tokena, usuwając przestarzałe dane wyjściowe narzędzia | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Dodaj natywną obsługę wyszukiwania w sieci dla dostawców w stylu opartym na Google | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Uruchomienie agenta AI uruchamiającego się w tle w PTY i wytwarzanie ich interaktywnych danych. | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Instrukcje dla nieinteraktywnych obowiązków - zaniechanie zawieszenia operacji zależnych od TTY | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Śledź udostępnić opencode za pomocą Wakatime | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Oczyść tabelę przecenioną przez LLM | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | 10x szybsza edycja kodu dzięki Morph Fast Apply API i znacznikom leniwej edycji | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Agencje odpowiedzialne w tle, gotowe narzędzia LSP/AST/MCP, wyselekcjonowani agenci, kompatybilni z Claude Code | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | Powiadomienia na pulpicie i alerty dźwiękowe dotyczące sesji opencode | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Powiadomienia na pulpicie i alerty dźwiękowe dotyczące uprawnień, wyników i zdarzeń o błędach | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | Automatyczne nazewnictwo sesji Zellij oparte na sztucznej inteligencji w oparciu o kontekst opencode | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Zezwalaj agentom opencode na leniwe ładowanie podpowiedzi na podstawie odkrywania możliwości i wstrzykiwania | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Trwała pamięć w sesjach przy użyciu Supermemory | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Interaktywny przegląd planu z adnotacją wizualną i użytkową prywatną/offline | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Rozszerzony opencode/polecenia do połączenia sieciowego ze szczegółową kontrolą bezpieczeństwa | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | Zaplanuj powtarzające się zadania, używając launchd (Mac) lub systemd (Linux) ze składaną cron | +| [micode](https://github.com/vtemian/micode) | Ustrukturyzowana burza mózgów → Plan → Wdrożenie wyjścia z ciągłością sesji | +| [octto](https://github.com/vtemian/octto) | Interaktywny interfejs do burzy mózgów AI z formularzami kontrolnymi wielu pytań | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | Agencje krytyczne w tle w stylu Claude Code z delegowaniem asynchronicznym i trwałością kontekstu | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | Natywne uruchomienie systemu dla opencode – wiesz, kiedy zadania zostaną zakończone | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | Lista wiązek orkiestracji wieloagentowej – 16 dostępna, jedna instalacja | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | Drzewa robocze Git o zerowym tarciu dla opencode | + +--- + +## Projektowanie + +| Imię | Opis | +| ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- | +| [kimaki](https://github.com/remorses/kimaki) | Bot Discord do kontrolowania sesji opencode, zbudowany na SDK | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Wtyczka Neovim do podpowiedzi, zbudowana w oparciu o API | +| [portal](https://github.com/hosenur/portal) | Interfejs sieciowy do urządzeń mobilnych dla opencode poprzez Tailscale/VPN | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | Szablon do budowy wtyczek opencode | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Frontend Neovim dla opencode - agent kodujący AI oparty na terminalu | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Stosowanie Vercel AI SDK do użytku z opencode poprzez @opencode-ai/sdk | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | Aplikacja internetowa/stacjonarna i rozszerzenie VS Code dla opencode | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Wtyczka Obsidian osadzająca opencode w interfejsie użytkownika Obsidian | +| [OpenWork](https://github.com/different-ai/openwork) | Alternatywa typu open source dla Claude Cowork, obsługa przez opencode | +| [ocx](https://github.com/kdcokenny/ocx) | Menedżer rozszerzony opencode z przenośnymi, izolowanymi profilami. | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | Aplikacja komputerowa, internetowa, mobilna i zdalna dla opencode | + +--- + +## Agencja + +| Imię | Opis | +| ----------------------------------------------------------------- | ------------------------------------------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | Modułowi agencje i polecenia AI do rozwoju strukturalnego | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | Konfiguracje, podpowiedzi, agencje i wtyczki usprawniające przepływ pracy | diff --git a/packages/web/src/content/docs/pl/enterprise.mdx b/packages/web/src/content/docs/pl/enterprise.mdx new file mode 100644 index 00000000000..e5dbd196404 --- /dev/null +++ b/packages/web/src/content/docs/pl/enterprise.mdx @@ -0,0 +1,170 @@ +--- +title: Przedsiębiorstwo +description: Bezpieczne korzystanie z opencode w Twojej organizacji. +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +opencode Przedsiębiorstwo jest przeznaczone dla organizacji, która ma dostęp do zasobów, że ich kod i dane nigdy nie opuszczą infrastruktury. Może zostać zarejestrowany za pomocą zapachuralizowanej konfiguracji, która integruje się z logowaniem jednokrotnym i uruchomieniem bramą AI. + +:::note +opencode nie przechowuje żadnego kodu ani danych kontekstowych. +::: + +Aby skorzystać z pracy z opencode Przedsiębiorstwo: + +1. Przeprowadź próbę wewnętrzną ze swoim systemem. +2. **Skontaktuj się z nami**, aby omówić ceny i opcję konfiguracji. + +--- + +## Test + +opencode jest oprogramowaniem typu open source i nie przechowuje żadnego kodu ani danych kontekstowych, więc programiści mogą po prostu [zacząć](/docs/) i próbować próbną. + +--- + +### Obsługa danych + +**opencode nie dotyczy kodu źródłowego ani danych kontekstowych.** Całe zdarzenie odbywa się lokalnie lub poprzez bezpośrednio wywołane API do twojego dostawcy AI. + +to, że korzystasz z usług dostawcy, lub dostawcy zaufania +Brama AI, możesz bezpłatnie korzystać z opencode. + +Zastrzeżeniem jest opcjonalna funkcja `/share`. + +--- + +#### Dzielenie się rozmowami + +Jeśli użytkownicy są połączeni z `/share`, połączenie jest połączone z danymi, które zostały przesłane do usług, które są udostępniane przez hosty tych użytkowników w opencode.ai. + +Dane są aktualnie dostępne przez sieć brzegową naszego CDN i są buforowane na brzegu w pobliżu Twoich użytkowników. + +Zalecamy tę opcję na okres próbny. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[Więcej informacji o udostępnianiu](/docs/share). + +--- + +### Własność kodu + +**Jesteś właścicielem całości kodu źródłowego przez opencode.** Nie ma żadnych ograniczeń licencyjnych ani należących do własności. + +--- + +## Wycena + +W przypadku opencode Enterprise model per-seat. Jeśli posiadasz własną bramkę LLM, nie pobieramy opłat za korzystanie z tokenów. Aby uzyskać więcej informacji na temat, jeśli jest możliwe, **skontaktuj się z nami**. + +--- + +## Zastosowanie + +Gdy zasięgsz okres próbny i nadzorujesz użytkowanie z opencode na +swoją organizację, możesz **skontaktować się z nami**, aby omówić te dźwięki +opcja cenowa i wdrożeniowa. + +--- + +### Konfiguracja centralna + +Możliwości wykorzystania opencode tak, aby skorzystać z jednego zastosowania dla całej organizacji. + +Tę zapachową konfigurację można zintegrować z dostawcą SSO i specyfikacje wszyscy użytkownicy mają dostęp wyłącznie do bram wewnętrznych AI. + +--- + +### Integracja SSO + +Dzięki zastosowaniu konfiguracji opencode może zostać włączone z dostawcą SSO Twojej organizacji w celu uwierzytelnienia. + +Dzięki temu opencode może uzyskać dane uwierzytelniające dla wewnętrznej bramy AI za pośrednictwem transmisji systemu zarządzania tożsamością. + +--- + +### Wewnętrzna bramka AI + +Dzięki zastosowaniu konfiguracji opencode można również skorzystać z tego, że można korzystać tylko z wewnętrznych bram AI. + +Możesz także dołączyć do wszystkich innych dostawców sztucznej inteligencji, upewniając się, że wszystkie elementy przechodzą przez zatwierdzenie wykorzystania Twojej organizacji. + +--- + +### Hosting własny + +Zalecamy, aby można było je udostępnić, aby Twoje dane nigdy nie zostały opuszczone +Twoja organizacja może być pomocna w utrzymaniu ich w Twojej infrastrukturze. + +Jest to obecnie w naszym planie działania. Jeśli jesteś zainteresowany, **daj nam znać**. + +--- + +## Często zadawane pytania + +

+What is opencode Enterprise? + +opencode Przedsiębiorstwo jest przeznaczone dla organizacji, która ma dostęp do zasobów, że ich kod i dane nigdy nie opuszczą infrastruktury. Może zostać zarejestrowany za pomocą zapachuralizowanej konfiguracji, która integruje się z logowaniem jednokrotnym i uruchomieniem bramą AI. + +
+ +
+How do I get started with opencode Enterprise? + +Po prostu uruchom wersję próbną ze swoim. opencode urządzenia niezabezpieczone kodu ani danych kontekstowych, co ułatwia uruchomienie pracy. + +**skontaktuj się z nami**, aby omówić ceny i wybrać opcję. + +
+ +
+How does enterprise pricing work? + +Oferujemy ceny korporacyjne za jedno stanowisko. Jeśli posiadasz własną bramkę LLM, nie pobieramy opłat za korzystanie z tokenów. Aby uzyskać więcej informacji, **skontaktuj się z nami**, aby uzyskać wynik określony dla potrzeb Twojej organizacji. + +
+ +
+Is my data secure with opencode Enterprise? + +Tak. opencode nie przechowuje kodu ani danych kontekstowych. Całe zdarzenie odbywa się lokalnie lub poprzez bezpośrednie wywołanie API przez dostawcę AI. Dostęp do konfiguracji i integracji z logowaniem jednokrotnym Twoje dane pozostają bezpieczne w infrastrukturze organizacji. + +
+ +
+Can we use our own private NPM registry? + +opencode obsługuje prywatny rejestry npm poprzez natywną usługę plików `.npmrc` Buna. Jeśli Twoja organizacja korzysta z rejestru prywatnego, takiego jak JFrog Artifactory, Nexus lub wylot, przed uruchomieniem opencode się, że programiści zostali uwierzytelnieni. + +Aby zapewnić uwierzytelnianie w rejestrze prywatnym: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +Spowoduje to do `~/.npmrc` ze szczegółami uwierzytelniania. opencode zrobi to automatycznie +podniesc do. + +:::caution +Przed uruchomieniem opencode musisz być zalogowany do rejestru prywatnego. +::: + +Alternatywnie możesz skorzystać z pliku `.npmrc`: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +Programiści muszą się zgłosić do rejestru prywatnego przed uruchomieniem opencode, aby mieć dostęp, że pakiety będą dostępne z rejestru przedsiębiorstwa. + +
diff --git a/packages/web/src/content/docs/pl/formatters.mdx b/packages/web/src/content/docs/pl/formatters.mdx new file mode 100644 index 00000000000..154c55ef8e1 --- /dev/null +++ b/packages/web/src/content/docs/pl/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: Formatery +description: OpenCode używa formaterów specyficznych dla języka. +--- + +OpenCode automatycznie formatuje pliki po ich zapisaniu lub edycji przy użyciu formaterów specyficznych dla języka. Zapewnia to, że wygenerowany kod jest zgodny ze stylem kodu Twojego projektu. + +--- + +## Wbudowane + +OpenCode zawiera kilka wbudowanych formaterów dla popularnych języków i frameworków. Poniższa tabela zawiera listę formaterów, obsługiwanych plików oraz wymagań konfiguracyjnych. + +| Formater | Rozszerzenia | Wymagania | +| -------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | +| gofmt | .go | Dostępne polecenie `gofmt` | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | Dostępne polecenie `mix` | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml i [więcej](https://prettier.io/docs/en/index.html) | Zależność `prettier` w `package.json` | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml i [więcej](https://biomejs.dev/) | Plik konfiguracyjny `biome.json(c)` | +| zig | .zig, .zon | Dostępne polecenie `zig` | +| clang-format | .c, .cpp, .h, .hpp, .ino i [więcej](https://clang.llvm.org/docs/ClangFormat.html) | Plik konfiguracyjny `.clang-format` | +| ktlint | .kt, .kts | Dostępne polecenie `ktlint` | +| ruff | .py, .pyi | Dostępne polecenie `ruff` | +| rustfmt | .rs | Dostępne polecenie `rustfmt` | +| cargo | .rs | Dostępne polecenie `cargo fmt` | +| uv | .py, .pyi | Dostępne polecenie `uv` | +| rubocop | .rb, .rake, .gemspec, .ru | Dostępne polecenie `rubocop` | +| standardrb | .rb, .rake, .gemspec, .ru | Dostępne polecenie `standardrb` | +| htmlbeautifier | .erb, .html.erb | Dostępne polecenie `htmlbeautifier` | +| air | .R | Dostępne polecenie `air` | +| dart | .dart | Dostępne polecenie `dart` | +| ocamlformat | .ml, .mli | Dostępne polecenie `ocamlformat` i plik konfiguracyjny `.ocamlformat` | +| terraform | .tf, .tfvars | Dostępne polecenie `terraform` | +| gleam | .gleam | Dostępne polecenie `gleam` | +| nixfmt | .nix | Dostępne polecenie `nixfmt` | +| shfmt | .sh, .bash | Dostępne polecenie `shfmt` | +| pint | .php | Zależność `laravel/pint` w `composer.json` | +| oxfmt (experimental) | .js, .jsx, .ts, .tsx | Zależność `oxfmt` w `package.json` i [eksperymentalna flaga](/docs/cli/#experimental) | +| ormolu | .hs | Dostępne polecenie `ormolu` | + +Jeśli więc Twój projekt zawiera `prettier` w `package.json`, OpenCode automatycznie go użyje. + +--- + +## Jak to działa + +Kiedy OpenCode zapisuje lub edytuje plik: + +1. Sprawdza plik pod kątem wszystkich dostępnych formaterów. +2. Uruchamia odpowiedni formater na pliku. +3. Automatycznie stosuje zmiany formatowania. + +Ten proces odbywa się w tle, zapewniając spójność stylu kodu bez konieczności ręcznej interwencji. + +--- + +## Konfiguracja + +Możesz dostosować formatery za pomocą sekcji `formatter` w konfiguracji OpenCode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +Każdy formater obsługuje następujące właściwości: + +| Właściwość | Typ | Opis | +| ------------- | -------- | -------------------------------------------------------- | +| `disabled` | boolean | Ustaw na `true`, aby wyłączyć ten formater | +| `command` | string[] | Polecenie uruchomienia formatera | +| `environment` | object | Zmienne środowiskowe ustawiane podczas uruchamiania | +| `extensions` | string[] | Rozszerzenia plików, które powinny używać tego formatera | + +Spójrzmy na kilka przykładów. + +--- + +### Wyłączanie formaterów + +Aby globalnie wyłączyć **wszystkie** formatery, ustaw `formatter` na `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +Aby wyłączyć **określony** formater, ustaw `disabled` na `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### Niestandardowe formatery + +Możesz dodać niestandardowe formatery, podając polecenie, zmienne środowiskowe i rozszerzenia plików: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +Symbol zastępczy **`$FILE`** w poleceniu jest zastępowany ścieżką do formatowanego pliku. diff --git a/packages/web/src/content/docs/pl/github.mdx b/packages/web/src/content/docs/pl/github.mdx new file mode 100644 index 00000000000..9b22ac4d5b4 --- /dev/null +++ b/packages/web/src/content/docs/pl/github.mdx @@ -0,0 +1,321 @@ +--- +title: GitHub +description: Użyj opencode w problemach z GitHubem i zastosujch ściągnięcia. +--- + +opencode integruje się z przepływem pracy w GitHub. Wspomnij o `/opencode` lub `/oc` w swoim komentarzu, a opencode wykonaj zadania w ramach modułu uruchamiającego GitHub Actions. + +--- + +## Cechy + +- **Problem związany z segregacją**: Poproś opencode o szczegółowe wyjaśnienie problemu i wyjaśnienie go. +- **Napraw i zaimplementuj**: Poproś opencode o naprawienie problemu lub zaimplementowanie funkcji. Będzie dostępny w następnym oddziale i wysyłać PR ze stosowaniem dodatku. +- **Bezpieczny**: opencode działa w modułach sprzętowych GitHuba. + +--- + +## Instalacja + +Uruchomione dalsze postępowanie w przypadku wystąpienia w repozytorium GitHub: + +```bash +opencode github install +``` + +Aby przeprowadzić Cię przez proces instalacji aplikacji GitHub, utwórz działanie i skonfiguruj wpisy tajnych. + +--- + +### Konfiguracja ręczna + +Można też uszkodzić to rozwiązanie. + +1. **Zainstaluj aplikację GitHub** + + Wejdź na [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). wystąpienie się, że jest natychmiastowe w repozytorium usuwam. + +2. **Dodaj przepływ pracy** + + Dodaj zdalny plik pracy do `.github/workflows/opencode.yml` w swoim repozytorium. wystąpił, że ustawiłeś sędziego `model` i wymagany klucz API w `env`. + + ```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx + ``` + +3. **Przechowuj klucze API w tajemnicy** + + W **ustawieniach** swojej organizacji lub projektu rozwiń **Sekretne i zmienne** po lewej stronie i wybierz **Działania**. Dodałem wymagane klucze API. + +--- + +## Konfiguracja + +- `model`: Model używany z opencode. Przyjmuje format `provider/model`. To **wymagane**. +- `agent`: Agent, którego należy używać. Musi być odległym agentem. Wraca do `default_agent` z konfiguracją lub `"build"`, jeśli nie został znaleziony. +- `share`: Czyć funkcję sesji opencode. Domyślnie **true** dla repozytoriów publicznych. +- `prompt`: Opcjonalny niestandardowy monit o zastąpienie przestrzegania zachowania. Wykorzystanie tego, aby dostosować sposób przetwarzania przez opencode. +- `token`: opcjonalny token dostępu GitHub podstawowe operacje, takie jak tworzenie komentarzy, zatwierdzanie zmian i otwieranie zastosowania ściągnięcia. Domyślnie opencode używa tokena dostępu do instalacji z aplikacji opencode GitHub, więc zatwierdzenia, komentarze i zasady ściągnięcia widoczne jako źródło z aplikacji. + + Alternatywnie możesz użyć [wbudowanego `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) modułu uruchamiającego GitHub Action bez instalacji aplikacji opencode GitHub. Pamiętaj tylko o przyznaniu wymaganych mocy w przepływie pracy: + + ```yaml + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + ``` + + Jeśli chcesz, możesz także użyć [osobistych tokenów dostępu](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT). + +--- + +## Obsługiwane wydarzenia + +opencode może zostać wywołany przez zdarzenie GitHub: + +| Typ zdarzenia | Wywołane przez | Szczegóły | +| ----------------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| `issue_comment` | Skomentuj problem lub PR | Wspomnij o `/opencode` lub `/oc` w swoim komentarzu. opencode odczytuje kontekst i może być częścią składową, otwieraną przez PR lub odpowiedzialną. | +| `pull_request_review_comment` | Komentarz określonym kodem w PR | Wspomnij o `/opencode` lub `/oc` podczas przeglądania kodu. opencode źródło pochodzenia, numery linii i kontekst różnicowy. | +| `issues` | Wydanie otwarte lub edytowane | Automatycznie wyzwalaj opencode po utworzeniu lub zmodyfikowaniu problemów. Wymaga wejścia `prompt`. | +| `pull_request` | PR otwarty lub zaktualizowany | Automatycznie wyzwalaj opencode, gdy PR są otwierane, synchronizowane lub ponownie otwierane. Przydatne w przypadku automatycznych znajomych. | +| `schedule` | Harmonogram oparty na Cron | Uruchom opencode zgodnie z harmonogramem. Wymagane wejście `prompt`. Dane wejściowe trafiają do dzienników i trafiań PR (nie ma problemu z recenzją). | +| `workflow_dispatch` | Ręczny wyłącznik z interfejsu użytkownika GitHub | Uruchom opencode na karcie Akcje. Wymagane wejście `prompt`. Dane wejściowe trafiają do dzienników i odbiorców PR. | + +### Przykład harmonogramu + +Uruchamiaj opencode zgodnie z harmonogramem, aby wykonać zautomatyzowane zadania: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +W przypadku wystąpienia danych wyjściowych `prompt` są **wymagane**, które nie są dostarczane, z których można wyodrębnić instrukcje. Zaplanowane przepływomierze pracy bez kontekstu użytkownika, który został uruchomiony, więc przepływ pracy musi `contents: write` i `pull-requests: write`, wystąpisz, że opencode utworzył główne lub PR. + +--- + +### Przykład żądania ściągnięcia + +Automatycznie przeglądaj żądania ściągnięcia po ich otwarciu lub aktualizacji: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +W przypadku zdarzenia `pull_request`, jeśli nie podano `prompt`, opencode użytkownika przeglądającego ściągnięcie. + +--- + +### Przykład segregacji problemów + +Automatycznie segreguj nowe problemy. Dziesięć przykładów filtruje do kont starszych niż 30 dni w celu ograniczenia spamu: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +W przypadku zdarzenia `issues` wprowadzenie `prompt` jest **wymagane**, ponieważ nie ma komentarza, z którego można wyodrębnić instrukcje. + +--- + +## Niestandardowe monity + +Zastąp domyślne monit, aby zastosować zachowanie opencode do twojego własnego pracy. + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Jest to przepis wykonawczy, który podlega przepisom kodowania lub zakresów tematycznych dla twojego projektu. + +--- + +## Przykłady + +Oto kilka możliwości wykorzystania opencode w GitHubie. + +- **Wyjaśnij problem** + + Dodaj dziesięć komentarzy w numerze GitHub. + + ``` + /opencode explain this issue + ``` + + opencode przeczytaj całość, zawierając dodatek z komentarzami i odpowiedzią z jasnym wyjaśnieniem. + +- **Napraw problem** + + W numerze GitHub powiedz: + + ``` + /opencode fix this + ``` + + A opencode utworzy nową podstawę, wdroży zmiany i zastąpi PR ze zmiany. + +- **Przegląd zmiany PR i wprowadzenie zmiany** + + Zostaw komentarz w PR GitHub. + + ``` + Delete the attachment from S3 when the note is removed /oc + ``` + + opencode zaimplementuje uruchomioną zmianę i zatwierdzi ją do tego samego PR. + +- **Przejrzyj konkretne linie kodu** + + Zostaw komentarz bezpośrednio w wierszu kodu w dodatku „Pliki” PR. opencode automatyczne wykrywanie pliku, numery linii i kontekst różnicowy, aby sprawdzić odpowiedzi. + + ``` + [Comment on specific lines in Files tab] + /oc add error handling here + ``` + + Komentując określone linie, opencode otrzymuje: + - Dokładny plik, który jest sprawdzany + - Konkretne linie kodu + - Otaczający kontekst różnicowy + - Informacje o numerze linii + + Dostępne na bardziej szczegółowe rozwiązanie bez konieczności stosowania ręcznego określania plików lub numerów wierszy. diff --git a/packages/web/src/content/docs/pl/gitlab.mdx b/packages/web/src/content/docs/pl/gitlab.mdx new file mode 100644 index 00000000000..660ed467e93 --- /dev/null +++ b/packages/web/src/content/docs/pl/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: użyj opencode w problemach z GitLabem i zastosujch scalania. +--- + +opencode integruje się z przepływem pracy GitLab poprzez potok GitLab CI/CD lub z GitLab Duo. + +W obu przypadkach opencode będzie modułem GitLab. + +--- + +## GitLab CI + +opencode działa w zwykłym potoku GitLab. Możesz wbudować go w potok jako [komponent CI](https://docs.gitlab.com/ee/ci/components/) + +Tutaj obowiązkowego przez społeczność komponentu CI/CD dla opencode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### Cechy + +- **Użyj konfiguracji dla każdego zadania**: Skonfiguruj opencode z niestandardowym katalogiem konfiguracyjnym, na przykładzie `./config/#custom-directory`, aby włączyć lub funkcjonalności na każde wywołanie opencode. +- **Konfiguracja minimalna**: Komponent CI konfiguruje opencode w tle, wystarczy skonfigurować opencode i początkowy monit. +- **Elastyczny**: Komponent CI obsługuje kilka danych, które są stosowane w celu dostosowania jego zachowania + +--- + +### Organizować coś + +1. Przechowuj dane uwierzytelniające opencode w formacie JSON jako zmienne parametry CI typu pliku w specyfikacji **Ustawienia** > **CI/CD** > **Zmienne**. Zachowaj, aby być oznaczony jako „Zamaskowane i ukryte”. +2. Dodaj elementy do swojego pliku `.gitlab-ci.yml`. + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +Więcej danych dotyczących użycia [sprawdź opis](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) tego komponentu. + +--- + +## Duet GitLab + +opencode integruje się z przepływem pracy GitLab. +Wspomnij o `@opencode` w komentarzu, a opencode wykonaj zadania w ramach swojego potoku GitLab CI. + +--- + +### Cechy + +- **Problem związany z segregacją**: Poproś opencode o szczegółowe wyjaśnienie problemu i wyjaśnienie go. +- **Napraw i zaimplementuj**: Poproś opencode o naprawienie problemu lub zaimplementowanie funkcji. + Utworzył nowy oddział i zgłosi ataku ze sobą. +- **Bezpieczny**: opencode działa na modułach GitLab. + +--- + +### Organizować coś + +opencode działa w potoku CI/CD GitLab. Oto, czego potrzebujesz, aby przejść do: + +:::tip +Aktualne instrukcje dotyczące [**dokumentacji GitLab**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/). +::: + +1. Skonfiguruj swoje środowisko GitLab +2. Skonfiguruj CI/CD +3. Uzyskaj klucz API dostawca modelu AI +4. Utwórz konto usługi +5. Skonfiguruj zmienne CI/CD +6. Utwórz plik konfiguracyjny, oto przykład: + +
+ + Flow configuration + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +Szczegółowe instrukcje w [dokumentacji agentów GitLab CLI](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/). + +--- + +### Przykłady + +Oto kilka możliwości wykorzystania opencode w GitLabie. + +:::tip +Można zastosować inną metodę ograniczającą niż `@opencode`. +::: + +- **Wyjaśnij problem** + + Dodaj dziesięć komentarzy w numerze GitLab. + + ``` + @opencode explain this issue + ``` + + opencode przeczytaj problem i odpowiedź z wyjaśnieniem. + +- **Napraw problem** + + W numerze GitLab powiedz: + + ``` + @opencode fix this + ``` + + opencode utworzy nową podstawę, zaimplementuje zmiany i spowoduje, że skalowanie będzie możliwe. + +- **Przejrzyj prośby o połączenie** + + Zostaw komentarz w sprawie rozwiązania połączenia GitLab. + + ``` + @opencode review this merge request + ``` + + opencode sprawdzenie rozwiązania i przepuszczenie. diff --git a/packages/web/src/content/docs/pl/ide.mdx b/packages/web/src/content/docs/pl/ide.mdx new file mode 100644 index 00000000000..6c78c800007 --- /dev/null +++ b/packages/web/src/content/docs/pl/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: Rozszerzenie opencode dla VS Code, Cursor i innych IDE +--- + +opencode integruje się z VS Code, Cursorem lub obsługującym terminal IDE. Aby uruchomić, po prostu uruchom `opencode` w terminalu. + +--- + +## Stosowanie + +- **Szybkie uruchomienie**: użycie `Cmd+Esc` (Mac) lub `Ctrl+Esc` (Windows/Linux), aby uruchomić opencode w uruchamianiu terminala lub skoncentruj się na uruchamianiu terminala, jeśli jest już uruchomiony. +- **Nowa sesja**: `Cmd+Shift+Esc` (Mac) lub `Ctrl+Shift+Esc` (Windows/Linux), aby została nowa konfiguracja terminala opencode, nawet jeśli jest już otwarta. Możesz także kliknąć przycisk opencode w interfejsie użytkownika. +- **Świadomość kontekstu**: Automatycznie udostępnia wybór lub kartę za pomocą opencode. +- **Skróty do odwołania do plików**: `Cmd+Option+K` (Mac) lub `Alt+Ctrl+K` (Linux/Windows), aby wstawić odnośnik do plików. Na przykład `@File#L37-42`. + +--- + +## Instalacja + +Aby poznać opencode na VS Code w forkach, takich jak Cursor, Windsurf, VSCodium: + +1. Otwórz kod VS +2. Otwórz innowacyjny terminal +3. Uruchom `opencode` — rozszerzenie instaluje się automatycznie + +Jeśli z drugiej strony chcesz zainstalować własne IDE po uruchomieniu `/editor` lub `/export` z TUI, należy zainstalować `export EDITOR="code --wait"`. [Dowiedz się więcej](/docs/tui/#editor-setup). + +--- + +### Instalacja ręczna + +Wyszukaj **opencode** na rynku rozszerzonym i kliknij **Zainstaluj**. + +--- + +### Rozwiązywanie problemów + +Jeśli rozwiązanie nie zostanie zainstalowane automatycznie: + +- zastosowanie się, że użycie `opencode` w terminalu. +- zadziałanie, że CLI dla Twojego IDE jest zainstalowane: + - Dla kodu VS: polecenie `code` + - Dla kura: polecenie `cursor` + - Dla windsurfingu: decyzja `windsurf` + - Dla VSCodium: decyzja `codium` + - Jeśli nie, uruchom `Cmd+Shift+P` (Mac) lub `Ctrl+Shift+P` (Windows/Linux) i wyszukaj „Polecenie: zastosowanie decyzji„ kod ”w PATH” (lub właściwyk dla twojego IDE) +- zadziałanie, że VS Code ma pozwolenie na instalację rozszerzoną diff --git a/packages/web/src/content/docs/pl/index.mdx b/packages/web/src/content/docs/pl/index.mdx new file mode 100644 index 00000000000..1c4ea7ea2b0 --- /dev/null +++ b/packages/web/src/content/docs/pl/index.mdx @@ -0,0 +1,346 @@ +--- +title: Wstęp +description: Zacznij pracę z opencode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**opencode**](/) to agent kodujący AI typu open source. Jest dostępny jako interfejs terminalowy, aplikacja desktopowa i rozszerzenie IDE. + +![opencode TUI z motywem opencode](../../../assets/lander/screenshot.png) + +Zacznijmy. + +--- + +#### Warunki wstępne + +Aby uzyskać dostęp do opencode w swoim terminalu, będziesz potrzebować: + +1. Nowoczesny emulator terminala, taki jak: + - [WezTerm](https://wezterm.org), wieloplatformowy + - [Alacritty](https://alacritty.org), wieloplatformowy + - [Ghostty](https://ghostty.org), Linux i macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux i macOS + +2. Klucze API dla dostawców LLM, z których korzystasz. + +--- + +## Instalacja + +Najłatwiej zainstalować opencode za pomocą skryptu instalacyjnego. + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +Możesz też użyć poniższych metod instalacji: + +- **Przy użyciu Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **Korzystanie z Homebrew na macOS i Linux** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > W celu uzyskania najbardziej aktualnej wersji zalecamy korzystanie z opencode. Oficjalna formuła `brew install opencode` jest utrzymywana przez zespół Homebrew i jest aktualizowana. + +- **Korzystanie z Paru na Arch Linux** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[Zalecane: Uruchamianie w WSL] +Aby najlepiej wykorzystać działanie w systemie Windows, zalecamy włączenie [Podsystemu Windows dla systemu Linux (WSL)](/docs/windows-wsl). Zapewnia to pełną kompatybilność z funkcjami opencode. +::: + +- **Używając Chocolatey** + + ```bash + choco install opencode + ``` + +- **Korzystanie z Scoop** + + ```bash + scoop install opencode + ``` + +- **Przy użyciu NPM** + + ```bash + npm install -g opencode-ai + ``` + +- **Używając Mise’a** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **Korzystanie z Dockera** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +Obecnie pracujemy nad instalacją opencode w systemie Windows za pomocą Bun. + +Możesz także pobrać plik binarny z [Releases](https://github.com/anomalyco/opencode/releases). + +--- + +## Konfiguracja + +Dzięki opencode możesz korzystać z dowolnego dostawcy LLM, konfigurując jego klucze API. + +Jeśli będziesz korzystać z wielu dostawców LLM, zalecamy skorzystanie z [OpenCode Zen](/docs/zen). +Aby uzyskać dostęp do wyselekcjonowanej listy modeli, które zostały zatwierdzone i zweryfikowane przez zespół opencode. + +1. Uruchom polecenie `/connect` w TUI, wybierz opencode i przejdź do [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. Zaloguj się, dodaj szczegóły rozliczeniowe i skopiuj klucz API. + +3. Wklej swój klucz API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +Alternatywnie możesz wybrać jednego z dodatkowych dostawców. [Dowiedz się więcej](/docs/providers#directory). + +--- + +## Inicjalizacja + +Po skonfigurowaniu dostawcy możesz przejść do projektu, nad którym chcesz pracować. + +```bash +cd /path/to/project +``` + +Uruchom opencode. + +```bash +opencode +``` + +Następnie zainicjuj opencode dla projektu, uruchamiając odpowiednie polecenie. + +```bash frame="none" +/init +``` + +Spowoduje to, że opencode przeanalizuje Twój projekt i utworzy plik `AGENTS.md` w katalogu głównym projektu. + +:::tip +Powinieneś zacommitować plik `AGENTS.md` swojego projektu w Git. +::: + +Pomaga to opencode zrozumieć strukturę projektu i stosowane wzorce kodowania. + +--- + +## Użycie + +Teraz możesz pracować nad swoim projektem. Możesz zapytać o wszystko! + +Jeśli dopiero zaczynasz korzystać z agenta kodującego AI, oto kilka wskazówek, które mogą być pomocne. + +--- + +### Zadawaj pytania + +Możesz poprosić opencode o wyjaśnienie bazy kodu. + +:::tip +Użyj `@` do wyszukiwania rozmytego plików w projekcie. +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +Jest to pomocne, jeśli istnieje część bazy kodu, nad którą nie pracowałeś. + +--- + +### Dodaj funkcje + +Możesz poprosić opencode o dodanie nowej funkcji do Twojego projektu. Najpierw zalecamy poproszenie o przygotowanie planu. + +1. **Stwórz Plan** + + opencode ma _Plan Mode_, który umożliwia wyłączenie zmian i + zamiast tego zasugeruje, jak zaimplementować tę funkcję. + + Przejdź do niego za pomocą klawisza **Tab**. Zobaczysz odpowiedni wskaźnik w prawym dolnym rogu. + + ```bash frame="none" title="Switch to Plan mode" + + ``` + + Opiszmy teraz, co chcemy, żeby zrobił. + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + Wersja opencode jest bardzo inteligentna, aby zrozumieć, czego chcesz. To pomaga + rozmawiaj z nim tak, jakbyś rozmawiał z młodszym programistą w swoim zespole. + + :::tip + Podaj opencode kontekst, aby zrozumiał, czego chcesz. + ::: + +2. **Udoskonalanie planu** + + Gdy będziesz mieć plan, możesz zostawić go lub dodać więcej. + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + + :::tip + Przeciągnij i upuść obrazy do terminala, aby dodać je do monitu. + ::: + + opencode może zeskanować obrazy, które mu przekażesz i zrozumieć je. Możesz to zrobić, przeciągając i upuszczając obraz do terminala. + +3. **Wprowadź zmiany** + + Kiedy już będziesz zadowolony z planu, przełącz się z powrotem do _Act Mode_ naciskając klawisz **Tab**. + + ```bash frame="none" + + ``` + + Poproś o wprowadzenie zmian. + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### Wprowadź zmiany + +Aby wprowadzić kolejną zmianę, możesz poprosić opencode lub zrobić to bezpośrednio bez konieczności wcześniejszego przeglądania planu. + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +Musisz upewnić się, że dostarczyłeś odpowiednie pliki, aby opencode mógł wprowadzić zmiany. + +--- + +### Cofnij zmiany + +Załóżmy, że prosisz opencode o wprowadzenie zmian. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Ale zdajesz sobie sprawę, że to nie jest to, czego chciałeś. **Możesz cofnąć** zmiany +za pomocą polecenia `/undo`. + +```bash frame="none" +/undo +``` + +opencode cofnie teraz zmiany i wyświetli wiadomość ponownie. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Możesz edytować monit i poprosić opencode o ponowną próbę. + +:::tip +Możesz użyć `/undo` wiele razy, aby cofnąć wiele zmian. +::: + +Możesz też **przywrócić** zmianę za pomocą polecenia `/redo`. + +```bash frame="none" +/redo +``` + +--- + +## Udostępnianie + +Rozmowy z opencode można [udostępniać swojemu zespołowi](/docs/share). + +```bash frame="none" +/share +``` + +Spowoduje to, że link do bieżącej rozmowy zostanie skopiowany do schowka. + +:::note +Rozmowy nie są ogólnodostępne. +::: + +Oto [przykładowa rozmowa](https://opencode.ai/s/4XP1fce5) z opencode. + +--- + +## Dostosuj + +To tyle! Jesteś teraz profesjonalistą w korzystaniu z opencode. + +Aby dostosować go do potrzeb, zalecamy [wybranie motywu](/docs/themes), [dostosowanie skrótów klawiaturowych](/docs/keybinds), [konfigurowanie programów formatujących kod](/docs/formatters), [tworzenie niestandardowych poleceń](/docs/commands) lub zabawę z [konfiguracją opencode](/docs/config). diff --git a/packages/web/src/content/docs/pl/keybinds.mdx b/packages/web/src/content/docs/pl/keybinds.mdx new file mode 100644 index 00000000000..f4995600dac --- /dev/null +++ b/packages/web/src/content/docs/pl/keybinds.mdx @@ -0,0 +1,192 @@ +--- +title: Skróty klawiszowe +description: Dostosuj swoje skróty klawiszowe. +--- + +opencode zawiera listę skrótów klawiszowych, które można zastosować poprzez opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## Klucz lidera + +opencode używa klucza `leader` dla głównych skrótów klawiszowych. Rozwiązanie problemu konfliktów w terminalu. + +Domyślnie `ctrl+x` jest klawiszem głównym i główną akcją wymaga najpierw naciśnięcia klawisza lidera, a następnie skrótu. Na przykład, aby ponownie zastosować, następnie następuje `ctrl+x`, a następnie następuje `n`. + +Nie musisz mieć klawisza wiodącego do skrótów klawiszowych, ale zalecamy to Reg. + +--- + +## Wyłącz powiązanie klawiszy + +Możesz podłączyć powiązanie klawiszy, dodając klucz do swojej konfiguracji z wartością „none”. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## Skróty monitów na pulpicie + +Pole sprawdzania aplikacji komputerowej opencode obsługuje popularne skróty w stylu Readline/Emacs do edycji tekstu. Są one dostępne i obecnie nie można ich skonfigurować za pomocą `opencode.json`. + +| Skrót | Akcja | +| -------- | ------------------------------------------------------------- | +| `ctrl+a` | Przejdź do źródła regularnej linii | +| `ctrl+e` | Przejdź na koniec bieżącej linii | +| `ctrl+b` | Przesuń kursor do tyłu o jeden znak | +| `ctrl+f` | Przesuń kursor o jeden znak do przodu | +| `alt+b` | Przesuń kursor o jedno słowo wstecz | +| `alt+f` | Przesuń kursor do przodu o jedno słowo | +| `ctrl+d` | Usuń znak pod kursorem | +| `ctrl+k` | Zabij do końca linii | +| `ctrl+u` | Zabij na początek linii | +| `ctrl+w` | Zabij poprzednie słowo | +| `alt+d` | Zabij następne słowo | +| `ctrl+t` | Transponuj znaki | +| `ctrl+g` | Anuluj wyskakujące okienka / przerwij uruchamianie odpowiedzi | + +--- + +## Shift+Enter + +Istnieją terminale, które nie wysyłają klawiszy modyfikujących z Enterem. Może być konieczne skonfigurowanie terminala tak, aby wysłać `Shift+Enter` jako przerwanie zakończenia. + +### Terminal Windowsowy + +Otwórz swój `settings.json` pod adresem: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +Dodaj do tablicy `actions` na poziomie wyższym: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Dodaj do tablicy `keybindings` na poziomie wyższym: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Zapisz plik i uruchom ponownie terminal Windows lub otwórz nową kartę. diff --git a/packages/web/src/content/docs/pl/lsp.mdx b/packages/web/src/content/docs/pl/lsp.mdx new file mode 100644 index 00000000000..8430bd9ca91 --- /dev/null +++ b/packages/web/src/content/docs/pl/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: Serwery LSP +description: OpenCode integruje się z serwerami LSP. +--- + +OpenCode integruje się z protokołem Language Server Protocol (LSP), aby zapewnić modelom LLM kontekst bazy kodu. Wykorzystuje diagnostykę, aby przekazywać informacje zwrotne do LLM. + +--- + +## Wbudowane + +OpenCode posiada kilka wbudowanych serwerów LSP dla następujących języków: + +| Serwer LSP | Rozszerzenia | Wymagania | +| ------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| astro | .astro | Automatyczna instalacja dla Astro | +| bash | .sh, .bash, .zsh, .ksh | Automatycznie instaluje serwer języka bash | +| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | Automatyczna instalacja dla C/C++ | +| csharp | .cs | Zainstalowany `.NET SDK` | +| clojure-lsp | .clj, .cljs, .cljc, .edn | Dostępne polecenie `clojure-lsp` | +| dart | .dart | Dostępne polecenie `dart` | +| deno | .ts, .tsx, .js, .jsx, .mjs | Dostępne polecenie `deno` (automatyczne wykrywanie deno.json/deno.jsonc) | +| elixir-ls | .ex, .exs | Dostępne polecenie `elixir` | +| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | Zależność `eslint` w projekcie | +| fsharp | .fs, .fsi, .fsx, .fsscript | Zainstalowany `.NET SDK` | +| gleam | .gleam | Dostępne polecenie `gleam` | +| gopls | .go | Dostępne polecenie `go` | +| hls | .hs, .lhs | Dostępne polecenie `haskell-language-server-wrapper` | +| jdtls | .java | Zainstalowany `Java SDK (version 21+)` | +| kotlin-ls | .kt, .kts | Automatyczna instalacja dla Kotlin | +| lua-ls | .lua | Automatyczna instalacja dla Lua | +| nixd | .nix | Dostępne polecenie `nixd` | +| ocaml-lsp | .ml, .mli | Dostępne polecenie `ocamllsp` | +| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | Zależność `oxlint` w projekcie | +| php intelephense | .php | Automatyczna instalacja dla PHP | +| prisma | .prisma | Dostępne polecenie `prisma` | +| pyright | .py, .pyi | Zainstalowana zależność `pyright` | +| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | Dostępne polecenie `ruby` i `gem` | +| rust | .rs | Dostępne polecenie `rust-analyzer` | +| sourcekit-lsp | .swift, .objc, .objcpp | Zainstalowany `swift` (`xcode` na macOS) | +| svelte | .svelte | Automatyczna instalacja dla aplikacji Svelte | +| terraform | .tf, .tfvars | Automatyczna instalacja z wydań GitHub | +| tinymist | .typ, .typc | Automatyczna instalacja z wydań GitHub | +| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | Zależność `typescript` w projekcie | +| vue | .vue | Automatyczna instalacja dla Vue | +| yaml-ls | .yaml, .yml | Automatycznie instaluje serwer języka yaml Red Hat | +| zls | .zig, .zon | Dostępne polecenie `zig` | + +Serwery LSP są automatycznie włączane po wykryciu jednego z obsługiwanych plików i spełnieniu wymagań. + +:::note +Możesz wyłączyć automatyczne pobieranie serwerów LSP, ustawiając zmienną środowiskową `OPENCODE_DISABLE_LSP_DOWNLOAD` na `true`. +::: + +--- + +## Jak to działa + +Gdy OpenCode otwiera plik: + +1. Sprawdza plik pod kątem wszystkich dostępnych serwerów LSP. +2. Uruchamia odpowiedni serwer LSP, jeśli jeszcze nie działa. + +--- + +## Konfiguracja + +Możesz dostosować serwery LSP poprzez sekcję `lsp` w konfiguracji OpenCode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +Każdy serwer LSP obsługuje następujące właściwości: + +| Właściwość | Typ | Opis | +| ---------------- | -------- | ------------------------------------------------------ | +| `disabled` | boolean | Ustaw na `true`, aby wyłączyć ten serwer LSP | +| `command` | string[] | Polecenie uruchomienia serwera LSP | +| `extensions` | string[] | Rozszerzenia plików, które powinny używać tego serwera | +| `env` | object | Zmienne środowiskowe ustawiane podczas uruchamiania | +| `initialization` | object | Opcje inicjalizacji do wysłania do serwera LSP | + +Spójrzmy na kilka przykładów. + +--- + +### Zmienne środowiskowe + +Użyj `env`, aby ustawić zmienne środowiskowe podczas uruchamiania serwera LSP: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### Opcje inicjalizacji + +Użyj właściwości `initialization`, aby przekazać niestandardowe opcje inicjalizacji do serwera LSP. Są one wysyłane w żądaniu `initialize` protokołu LSP: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +Opcje inicjalizacji różnią się w zależności od serwera LSP. Sprawdź dokumentację swojego serwera LSP. +::: + +--- + +### Wyłączanie serwerów LSP + +Aby wyłączyć **wszystkie** serwery LSP globalnie, ustaw `lsp` na `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +Aby wyłączyć **określony** serwer LSP, ustaw `disabled` na `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### Niestandardowe serwery LSP + +Możesz dodać niestandardowe serwery LSP, podając polecenie i rozszerzenia plików: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## Dodatkowe informacje + +### PHP Intelephense + +PHP Intelephense oferuje funkcje premium poprzez klucz licencyjny. Możesz użyć klucza licencyjnego, umieszczając go (sam klucz) w pliku tekstowym pod adresem: + +- macOS/Linux: `$HOME/intelephense/license.txt` +- Windows: `%USERPROFILE%/intelephense/license.txt` + +Plik powinien zawierać wyłącznie klucz licencyjny, bez białych znaków. diff --git a/packages/web/src/content/docs/pl/mcp-servers.mdx b/packages/web/src/content/docs/pl/mcp-servers.mdx new file mode 100644 index 00000000000..6aea7a47546 --- /dev/null +++ b/packages/web/src/content/docs/pl/mcp-servers.mdx @@ -0,0 +1,511 @@ +--- +title: Serwery MCP +description: Dodaj lokalne i zdalne narzędzie MCP. +--- + +Możesz dodać dodatkowe informacje do opencode za pomocą _Model Context Protocol_, w skrócie MCP. opencode obsługuje zarówno serwery lokalne, jak i zdalne. + +Po dodaniu narzędzi MCP są automatycznie dostępne dla LLM wraz z narzędziami narzędziowymi. + +--- + +#### Zastrzeżenia + +Kiedy używasz serwera MCP, zmieniając kontekst. Może szybko się sumować, jeśli masz dużo narzędzia. Zalecamy ostrożność, z jakich serwerów MCP korzystasz. + +:::tip +Serwery MCP dodają do twojego kontekstu, dlatego należy zachować ostrożność przy wyłączaniu tych serwerów. +::: + +Niektóre serwery MCP, takie jak serwer MCP GitHub, mają szerokie możliwości dodawania wielu tokenów i mogą łatwo przekraczać limit kontekstu. + +--- + +## Włączać + +Dostępny serwery MCP w [opencode Config](https://opencode.ai/docs/config/) w `mcp`. Dodaj każdy MCP z unikalną nazwą. Możesz zgłosić się do tego MCP po nazwie, pytając LLM. + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +Możesz także wyłączyć serwer, ustawiając `enabled` na `false`. Jest to urządzenie, które jest urządzeniem biologicznym, bez usuwania z urządzenia. + +--- + +### Zastępowanie zdalnych ustawień domyślnych + +Organizacje mogą udostępniać serwery MCP za pośrednictwem punktu końcowego `.well-known/opencode`. Serwer może być podłączony, dzięki czemu użytkownicy mogą wybrać te, których. + +Aby włączyć serwer ze zdalnej konfiguracji organizacji, dodaj go do wyłączenia za pomocą `enabled: true`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +Lokalne wartości konfiguracyjne za występujące zdalne wartości. Aby uzyskać więcej informacji, zobacz [pierwszeństwo konfiguracji](/docs/config#precedence-order). + +--- + +## Lokalny + +Dodaj lokalne serwery MCP za pomocą `type` do `"local"` w obiekcie 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", + }, + }, + }, +} +``` + +Polecenie sposobu uruchamiania lokalnego serwera MCP. Można także zainstalować listę konfiguracyjną. + +Oto przykładowy sposób dodania testowego serwera MCP [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything). + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "mcp_everything": { + "type": "local", + "command": ["npx", "-y", "@modelcontextprotocol/server-everything"], + }, + }, +} +``` + +Aby z niego skorzystać, można dodać `use the mcp_everything tool` do moich podpowiedzi. + +```txt "mcp_everything" +use the mcp_everything tool to add the number 3 and 4 +``` + +--- + +#### Opcje + +Oto wszystkie opcje lokalnego serwera MCP. + +| Opcja | Wpisz | Wymagane | Opis | +| ------------- | ------- | -------- | -------------------------------------------------------------------------------------------- | +| `type` | String | Y | Typ połączenia z serwerem MCP musi być `"local"`. | +| `command` | Array | Y | Polecenie i argumenty uruchamiające serwer MCP. | +| `environment` | Object | | Zmienne ustawienia podczas uruchamiania serwera. | +| `enabled` | Boolean | | Włącz lub wyłącz serwer MCP podczas uruchamiania. | +| `timeout` | Number | | Limit czasu w ms na pobieranie narzędzia z serwera MCP. Wartość domyślna do 5000 (5 sekund). | + +--- + +## Zdalny + +Dodaj zdalne serwery MCP, ustawiając `type` na `"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" + } + } + } +} +``` + +`url` na adres URL zdalnego serwera MCP i za pomocą opcji `headers` można znaleźć listę nagłówków. + +--- + +#### Opcje + +| Opcja | Wpisz | Wymagane | Opis | +| --------- | ------- | -------- | -------------------------------------------------------------------------------------------- | +| `type` | String | Y | Typ połączenia z serwerem MCP musi być `"remote"`. | +| `url` | String | Y | Adres URL zdalnego serwera MCP. | +| `enabled` | Boolean | | Włącz lub wyłącz serwer MCP podczas uruchamiania. | +| `headers` | Object | | Nagłówki do wysłania z wprowadzenia. | +| `oauth` | Object | | Konfiguracja uwierzytelniania OAuth. Zobacz sekcję [OAuth](#oauth) poniżej. | +| `timeout` | Number | | Limit czasu w ms na pobieranie narzędzia z serwera MCP. Wartość domyślna do 5000 (5 sekund). | + +--- + +## OAuth + +opencode automatyczne uwierzytelnianie OAuth dla zdalnych serwerów MCP. Gdy serwer wymaga uwierzytelnienia, opencode: + +1. Wykryj odpowiedź 401 i zainijuj przepływ OAuth +2. używa **Dynamicznej rejestracji klienta (RFC 7591)**, jeśli jest obsługiwana przez serwer +3. Bezpiecznie przechowuj tokeny na wypadek ewentualnego zastosowania + +--- + +### Automatyczny + +W innym serwerze MCP z włączoną funkcją OAuth nie jest wymagana specjalna funkcja. Dostępny serwer bezprzewodowy: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "my-oauth-server": { + "type": "remote", + "url": "https://mcp.example.com/mcp" + } + } +} +``` + +Jeśli serwer wymaga uwierzytelnienia, opencode poprosi Cię o uwierzytelnienie przy próbie jego użycia. Jeśli nie, możesz [ręcznie podłączyć przepływ] (#authenticating) za pomocą `opencode mcp auth `. + +--- + +### Wstępnie zarejestrowany + +Jeśli posiadasz dostęp do klienta od dostawcy serwera MCP, możesz je udostępnić: + +```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" + } + } + } +} +``` + +--- + +### Uwierzytelnianie + +Możesz podać potwierdzenie lub potwierdzenie poświadczenia. + +Uwierzytelnij się za pomocą standardowego serwera MCP: + +```bash +opencode mcp auth my-oauth-server +``` + +Lista wszystkich serwerów MCP i ich status uwierzytelnienia: + +```bash +opencode mcp list +``` + +Usuń zapisane dane uwierzytelniające: + +```bash +opencode mcp logout my-oauth-server +``` + +Komenda `mcp auth` została udostępniona w celu autoryzacji. Po autoryzacji opencode bezpieczne przechowa tokeny w `~/.local/share/opencode/mcp-auth.json`. + +--- + +#### Wyłączanie OAuth + +Jeśli chcesz włączyć automatyczne OAuth dla serwera (np. dla serwerów, które zamiast tego używać kluczy API), ustaw `oauth` na `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}" + } + } + } +} +``` + +--- + +#### Opcje OAuth + +| Opcja | Wpisz | Opis | +| -------------- | --------------- | ---------------------------------------------------------------------------------------------------------------- | +| `oauth` | Object \| false | Obiekt konfiguracyjny OAuth lub `false`, aby wyłączyć automatyczne wykrywanie OAuth. | +| `clientId` | String | Identyfikator klienta OAuth. Jeżeli nie zostanie podany, zostanie podjęta próba dynamicznej rejestracji klienta. | +| `clientSecret` | String | Sekret klienta OAuth, plik jest wymagany przez serwer autoryzacji. | +| `scope` | String | Zakresy protokołu OAuth, których należy żądać podczas autoryzacji. | + +#### Debugowanie + +Jeśli serwer MCP nie może zostać uwierzytelniony, możesz zdiagnozować problemy z: + +```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 +``` + +Komenda `mcp debug` wyświetlanie stanu uwierzytelniania, testuje sprawdzanie protokołu HTTP i sprawdzenie sprawdzenia procesu OAuth. + +--- + +## Zarządzać + +Twoje MCP są dostępne jako narzędzie w opencode, obok narzędzi dodatkowych. Można to zrobić poprzez podłączenie opencode, jak również w innym przypadku. + +--- + +### Światowy + +Możesz to włączyć lub wyłączyć globalnie. + +```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 + } +} +``` + +Dostępne są również wzorca globu, aby wyłączyć wszystkie dyski 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 + } +} +``` + +Tutaj znajdziesz wzorca globalnego `my-mcp*`, aby wyłączyć wszystkie MCP. + +--- + +### Na agenta + +Jeśli masz największe serwery MCP, możesz włączyć je tylko dla poszczególnych agentów i być globalnie. Aby to zrobić: + +1. Wyłącz go jako narzędzie globalnie. +2. W [konfiguracji agenta](/docs/agents#tools) włącz serwer MCP jako narzędzie. + +```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 + } + } + } +} +``` + +--- + +#### Wzory globusów + +Wzorzec glob wykorzystuje proste wzorce globowania regularnych: + +- `*` dopasowuje zero lub więcej dowolnego znaku (np. `"my-mcp*"` dopasowuje `my-mcp_search`, `my-mcp_list` itd.) +- `?` odpowiada dokładnie jednemu znakowi +- Wszystkie pozostałe znaki pasują dosłownie + +:::note +Narzędzia serwera MCP są rejestrowane z nazwą serwera jako prefiksem, więc aby uzyskać dostęp do wszystkich narzędzi dla serwera, po prostu dostęp do: + +``` +"mymcpservername_*": false +``` + +::: + +--- + +## Przykłady + +Poniżej znajdują się przykłady niektórych serwerów MCP. Twój prywatny PR, udostępniany przez inne serwery. + +--- + +### Sentry + +Dodaj [serwer Sentry MCP](https://mcp.sentry.dev), aby móc wejść w interakcję z projektem i udostępnić Sentry. + +```json title="opencode.json" {4-8} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "sentry": { + "type": "remote", + "url": "https://mcp.sentry.dev/mcp", + "oauth": {} + } + } +} +``` + +Po dodaniu konfiguracji uwierzytelnij się za pomocą Sentry: + +```bash +opencode mcp auth sentry +``` + +Spowoduje otwarcie okna konfiguracji, w którym można zakończyć proces OAuth i połączyć opencode z kontem Sentry. + +Po uwierzytelnieniu oprogramowania Sentry w swoich monitach, aby rozprzestrzeniać zagrożenia, dane i błędy. + +```txt "use sentry" +Show me the latest unresolved issues in my project. use sentry +``` + +--- + +### Context7 + +Dodaj [serwer Context7 MCP](https://github.com/upstash/context7), aby przeszukać dokumenty. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "context7": { + "type": "remote", + "url": "https://mcp.context7.com/mcp" + } + } +} +``` + +Jeśli założyłeś darmowe konto, możesz użyć klucza API i uzyskać wyższy limit stawek. + +```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}" + } + } + } +} +``` + +Załóż tutaj, że masz ustawioną zmienną środowiskową `CONTEXT7_API_KEY`. + +Dodaj `use context7` do swoich podpowiedzi, aby skorzystać z serwera Context7 MCP. + +```txt "use context7" +Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 +``` + +Alternatywnie możesz zadać coś takiego do pliku [AGENTS.md](/docs/rules/). + +```md title="AGENTS.md" +When you need to search docs, use `context7` tools. +``` + +--- + +### Grep by Vercel + +Dodaj serwer MCP [Grep by Vercel](https://grep.app), aby przeszukać fragmenty kodu w serwisie GitHub. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "gh_grep": { + "type": "remote", + "url": "https://mcp.grep.app" + } + } +} +``` + +Nazwaliśmy nasz serwer MCP `gh_grep`, możesz dodać `use the gh_grep tool` do swoich podpowiedzi, aby agent mógł z niego korzystać. + +```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 +``` + +Alternatywnie możesz zadać coś takiego do pliku [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/pl/models.mdx b/packages/web/src/content/docs/pl/models.mdx new file mode 100644 index 00000000000..e1c79229047 --- /dev/null +++ b/packages/web/src/content/docs/pl/models.mdx @@ -0,0 +1,223 @@ +--- +title: Modele +description: Konfigurowanie dostawcy i modelu LLM. +--- + +opencode używa [AI SDK](https://ai-sdk.dev/) i [Models.dev](https://models.dev) do obsługi **ponad 75 dostawców LLM** i obsługi uruchamiania modeli pierwszych. + +--- + +## Dostawcy + +Dostępna usługa dostawcy jest dostępna. Jeśli otrzymasz poświadczenie dostawcy za pomocą polecenia `/connect`, będzie on dostępny po uruchomieniu opencode. + +Dowiedz się więcej o [dostawcach](/docs/providers). + +--- + +## Wybierz model + +Po skonfigurowaniu dostawcy możesz wybrać dostępny model, wpisując: + +```bash frame="none" +/models +``` + +--- + +## Polecane modele + +Na rynku jest mnóstwo modeli, co tydzień pojawia się nowe. + +:::tip +Rozważ skorzystanie z jednego z rekomendowanych przez nas modeli. +::: + +Jednak tylko kilka z nich jest dobrych przy generowaniu kodu, jak i wywołaniu narzędzia. + +Oto kilka modeli, które dobrze współpracują z opencode, w kolejności. (Nie jest to lista wyczerpująca i nie jest konieczna aktualna): + +- GPT 5.2 +- Kodeks GPT 5.1 +- Klaudiusz Opus 4.5 +- Claude Sonnet 4.5 +- Minimax M2.1 +- Bliźnięta 3Pro + +--- + +## Ustaw wartość domyślną + +Aby zainstalować jeden z nich jako model domyślny, możesz zainstalować klucz `model` w swoim +opencode konfiguracja + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +Tutaj pełny identyfikator do `provider_id/model_id`. Na przykład, użycie [OpenCode Zen](/docs/zen), przestrzeganie `opencode/gpt-5.1-codex` dla Kodeksu GPT 5.1. + +Jeśli skonfigurowałeś [dostawcę zwykłegogo] (./providers#custom), `provider_id` jest kluczem z części `provider` twojej konfiguracji, a `model_id` jest kluczem z `provider.models`. + +--- + +## Skonfiguruj modele + +Można globalnie skorzystać z opcji modelu poprzez plik config. + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +Tutaj konfigurujemy urządzenia globalne dla dwóch modeli: `gpt-5` w przypadku dostępu za pośrednictwem dostawcy `openai` i `claude-sonnet-4-20250514` w przypadku dostępu za pośrednictwem dostawcy `anthropic`. +Wbudowane nazwy dostawców i modele można znaleźć na [Models.dev](https://models.dev). + +Można także skorzystać z opcji dla dowolnych agentów, których używa się. Konfiguracja agenta jest dostępna jako opcja globalna. [Dowiedz się więcej](/docs/agents/#additional). + +Można również zastosować alternatywne warianty, które wykluczają. Warianty konfiguracji ustawień konfiguracyjnych dla tego samego modelu bez tworzenia duplikatów wpisów: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## Warianty + +Wiele modeli obsługuje wiele wariantów lub różnych wybranych. opencode jest dostarczany z podstawowymi wariantami wariantów dla dostawców. + +### Wbudowane warianty + +opencode jest dostarczany z domyślnymi wariantami dla wielu dostawców: + +**Antropiczny**: + +- `high` – Wysoki budżet na przemyślenie (domyślnie) +- `max` - Maksymalny budżet na myślenie + +**OpenAI**: + +Różni się zależnością od modelu, ale mniej więcej: + +- `none` – Brak uzasadnienia +- `minimal` - Minimalny wysiłek rozumowania +- `low` - Niewielki wysiłek w zakresie rozumowania +- `medium` – Średni wysiłek rozumowania +- `high` - Duży wysiłek w zakresie rozumowania +- `xhigh` - Bardzo duży wysiłek w zakresie rozumowania + +**Google**: + +- `low` — Mniejszy nakład pracy/budżet tokena +- `high` — Większy nakład pracy/budżet tokena + +:::tip +Lista ta nie jest kompletna. Wielu innych dostawców oferuje także opcję odchylenia ustawień. +::: + +### Warianty niestandardowe + +Można uwzględnić warianty lub dodać własne: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### Przełączanie wariantów + +Naciśnij klawisza `variant_cycle`, aby szybko przełączać się między wariantami. [Dowiedz się więcej](/docs/keybinds). + +--- + +## Ładowanie modeli + +Po uruchomieniu opencode sprawdzanie modeli w następującej kolejności: + +1. Flaga wiersza autora `--model` lub `-m`. Format jest taki sam jak w pliku konfiguracyjnym: `provider_id/model_id`. + +2. Lista modeli w konstrukcji opencode. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + + Sformatuj tutaj na `provider/model`. + +3. Ostatni używany model. + +4. Pierwszy model sterujący priorytetem wewnętrznym. diff --git a/packages/web/src/content/docs/pl/modes.mdx b/packages/web/src/content/docs/pl/modes.mdx new file mode 100644 index 00000000000..52ab1633463 --- /dev/null +++ b/packages/web/src/content/docs/pl/modes.mdx @@ -0,0 +1,331 @@ +--- +title: Tryby +description: Różne tryby dla różnych zastosowań. +--- + +:::caution +Tryby są teraz konfigurowane za pomocą opcji `agent` w konfiguracji opencode. +Opcja `mode` jest obecnie przestarzała. [Dowiedz się więcej](/docs/agents). +::: + +Tryb udostępniania możliwości stosowania, narzędzie i podpowiedzi do różnych zastosowań. + +Posiadanie dwa tryby: **Build** i **Plan**. Można dostosować +te lub skonfiguruj własne za pomocą konfiguracji opencode. + +Można przełączać się między trybami podczas sesji lub konfigurować je w pliku konfiguracyjnym. + +--- + +## Wbudowane + +opencode ma dwa puste tryby. + +--- + +### Build + +Build jest trybem **domyślnym** z dostępnymi narzędziami. Jest to standardowy tryb pracy programistycznej, który jest dostępny z pełnym dostępem do operacji na plikach i oryginalnych systemach systemowych. + +--- + +### Plan + +Tryb ograniczony do analizy. W urządzeniu planowym narzędzia są przydatne: + +- `write` - Nie można stworzyć nowych plików +- `edit` — Nie można zastosować naruszenia plików, z naruszeniem praw autorskich w `.opencode/plans/*.md` w celu uszczegółowienia samego planu +- `patch` - Nie można zastosować poprawek +- `bash` - Nie można wykonać poleceń shell + +Ten tryb jest alternatywny, gdy chcesz, aby sztuczna inteligencja analizowała kod, sugerowała zmianę lub tworzyła projekty bez źródła zewnętrznego, które stanowi bazę kodu. + +--- + +## Przełączanie + +Możesz przełączać się między trybami podczas sesji za pomocą klawisza _Tab_. Lub skrót klawiszowy `switch_mode`. + +Zobacz także: [Formaterzy](/docs/formatters), aby uzyskać informacje na temat konfiguracji formatowania kodu. + +--- + +## Skonfiguruj + +Możliwość dostosowania alternatywnego trybu lub konfiguracji poprzez własną konfigurację. Tryb można skonfigurować na dwa systemy: + +### Konfiguracja JSON + +Skonfiguruj tryb w pliku konfiguracyjnym `opencode.json`: + +```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 + } + } + } +} +``` + +### Konfiguracja Markdown + +Można także definiować tryby za pomocą plików przecen. Trzymaj je w: + +- Globalnie: `~/.config/opencode/modes/` +- Projekt: `.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. +``` + +Nazwa pliku przecen staje się kluczem trybu (np. `review.md` tworzy tryb `review`). + +Przyjrzyjmy się szczegółowo tym opcjom konfiguracji. + +--- + +### Model + +Zastosowanie konstrukcji `model`, aby zastosować domyślny model dla tego trybu. Przydatne przy wykorzystaniu różnych modeli dostępnych w różnych zadaniach. Na przykład zastosowanie modelu, skuteczniejsze wykonanie modelu. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### Temperatura + +Kontroluj losowość i kreatywność reakcji AI za pomocą konstrukcji `temperature`. Niższe wartości, że odpowiedzi są bardziej skupione i deterministyczne, podczas gdy najwyższa wartość jest innowacyjna i złożona. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Wartości temperatury zazwyczaj wahają się od 0,0 do 1,0: + +- **0,0-0,2**: Bardzo skoncentrowane i deterministyczne odpowiedzi, idealne do analizy i kodu źródłowego +- **0,3-0,5**: Zrównoważona odpowiedź z chwilą powstania, dobre do ogólnych zadań rozwojowych +- **0,6–1,0**: Bardziej kreatywne i odpowiedzi, rozstrzygnięte podczas burzy mózgów i eksploracji + +```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}" + } + } +} +``` + +Jeśli nie ma wpływu na temperaturę, opencode stosuje się narzędzia badawcze dla modelu (zwykle 0 dla największych modeli, 0,55 dla modeli Qwen). + +--- + +### Prompt (Monit) + +niestandardowy plik podpowiedzi systemowych dla tej procedury za pomocą konfiguracji `prompt`. Plik informacyjny powinien zawierać instrukcje dotyczące przeznaczenia trybu. + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Ścieżka ta zależy od miejsca, w którym znajduje się plik konfiguracyjny. Więc to dla działa +zarówno globalna opencode, jak i specjalna dla projektu. + +--- + +### Narzędzia + +Kontroluj, które narzędzia są dostępne w tym urządzeniu, za pomocą konfiguracji `tools`. Można włączyć lub dostępne narzędzie, ustawiając je na `true` lub `false`. + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +Jeśli nie ma żadnych narzędzi, wszystkie narzędzia są wyłączone. + +--- + +#### Dostępne narzędzia + +Oto wszystkie narzędzia, które można sterować za pomocą konfiguracji trybów. + +| Narzędzie | Opis | +| ----------- | ------------------------------------- | +| `bash` | Wykonaj polecenia shell | +| `edit` | Modyfikuj istniejące pliki | +| `write` | Utwórz nowe pliki | +| `read` | Przeczytaj zawartość pliku | +| `grep` | Wyszukaj zawartość pliku | +| `glob` | Znajdź pliki według wzorca | +| `list` | Lista zawartości katalogu | +| `patch` | Zastosuj poprawki do plików | +| `todowrite` | Zarządzaj listami rzeczy do wykonania | +| `todoread` | Przeczytaj listy rzeczy do zrobienia | +| `webfetch` | Pobierz zawartość internetową | + +--- + +## Tryby niestandardowe + +Możesz stworzyć własny tryb prywatny, dodając je do konfiguracji. Oto zastosowanie obu rozwiązań: + +### Korzystanie z konfiguracji JSON + +```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 + } + } + } +} +``` + +### Korzystanie z plików Markdown + +Utwórz pliki trybów w `.opencode/modes/` dla trybów zapisanych dla projektu lub `~/.config/opencode/modes/` dla trybów globalnych: + +```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 +``` + +--- + +### Przypadki użycia + +Oto kilka typowych zastosowań dla różnych trybów. + +- **Build mode**: Pełne prace programistyczne z dostępnymi narzędziami +- **Plan mode**: Analiza i planowanie bez zmian +- **Review mode**: Przegląd kodu z możliwością odczytu i narzędzi do dokumentacji +- **Debug mode**: Koncentruje się na urządzeniu z dostępnymi narzędziami bash i odczytu +- **Docs mode**: Zapisywanie dokumentacji przy użyciu operacji na plikach, ale bez oryginalnych systemów systemowych + +Może się również zdarzyć, że różne modele są dobre w różnych wersjach użycia. diff --git a/packages/web/src/content/docs/pl/network.mdx b/packages/web/src/content/docs/pl/network.mdx new file mode 100644 index 00000000000..d010343eca5 --- /dev/null +++ b/packages/web/src/content/docs/pl/network.mdx @@ -0,0 +1,57 @@ +--- +title: Sieć +description: Skonfiguruj serwery proxy i certyfikaty uwierzytelniające. +--- + +opencode obsługa standardowego zmiennego proxy i certyfikatów dla usług sieciowych przedsiębiorstw. + +--- + +## Pełnomocnik + +opencode respektuje standardowe zmienne środowiskowe proxy. + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +TUI komunikuje się z popularnym serwerem HTTP. Aby zapobiec łączem routingu, należy ominąć serwer proxy dla tego połączenia. +::: + +Możesz pozostawić port serwera i hosta za pomocą [flaga CLI](/docs/cli#run). + +--- + +### Uwierzytelniać + +Jeśli Twój serwer proxy wymaga podstawowego uwierzytelniania, dołącz dane uwierzytelniające w adresie URL. + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +Unikaj kodowania haseł na stałe. Użyj testów kontrolnych lub oprogramowania poświadczeń. +::: + +W przypadku serwera proxy zaawansowanego uwierzytelniania, jak NTLM lub Kerberos, dostęp do bram LLM, który umożliwia uwierzytelnianie. + +--- + +## Certyfikaty niestandardowe + +Jeśli Twoje przedsiębiorstwo korzysta z niestandardowych usług, urzędów dostępu do HTTPS, skonfiguruj opencode tak, aby im ufać. + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +Działają tylko w przypadku proxy, jak i bezpośredniego dostępu do API. diff --git a/packages/web/src/content/docs/pl/permissions.mdx b/packages/web/src/content/docs/pl/permissions.mdx new file mode 100644 index 00000000000..c9f50a8aa77 --- /dev/null +++ b/packages/web/src/content/docs/pl/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: Uprawnienia +description: Kontroluj, które Akcje wymagają zatwierdzenia do uruchomienia. +--- + +opencode używa `permission`, aby uniknąć, czy dana akcja została wykonana automatycznie, zachowana monit lub została zablokowana. + +Od `v1.1.1` starsza stworzona logiczna `tools` jest przestarzała i została stworzona scalona z `permission`. Stara wersja `tools` jest nadal obsługiwana w celu zapewnienia zgodności wstecznej. + +--- + +## Działania + +Każda reguła uprawnień skutkuje jedną z: + +- `"allow"` — uruchamiany bez zgody +- `"ask"` — monit o zatwierdzenie +- `"deny"` — zablokuj akcję + +--- + +## Konfiguracja + +Możesz zainstalować uprawnienia globalnie (za pomocą `*`) i znajdującego się w nim narzędzia. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +Możesz także zainstalować wszystkie uprawnienia na raz: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## Szczegółowe reguły (składnia obiektu) + +Można skorzystać z różnych działań, które zależą od danych użytkowych. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +Reguły są zalecane na podstawie odpowiedniego wzorca, przy czym **ostatnia wynikaca reguła wygrywa**. Powszechnym wzorcem jest umieszczenie na pierwszym miejscu odpowiedniego catch-all `"*"`, a po bardziej szczegółowe zasady. + +### Symbole wieloznaczne + +Wzorce uprawnień z prostych dopasowywania symboli wieloznacznych: + +- `*` dopasowuje zero lub więcej dowolnego znaku +- `?` odpowiada dokładnie jednemu znakowi +- Wszystkie pozostałe znaki pasują dosłownie + +### Rozszerzenie katalogu domowego + +Możesz używać `~` lub `$HOME` na początku wzorca, aby zastosować się do swojego katalogu domowego. Jest to szczególnie szczególne w przypadku reguły [`external_directory`](#external-directories). + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### Katalogi zewnętrzne + +Użycie `external_directory`, aby zezwolić na wywołanie narzędzia, które obsługuje obsługę poza katalogiem roboczym, z uruchomieniem opencode. Dotyczy każdego narzędzia, które jako dane wejściowe zostało przyjęte (na przykład `read`, `edit`, `list`, `glob`, `grep` i wiele założycieli `bash`). + +Rozszerzenie domu (jak `~/...`) wpływa tylko na sposób za zwyczajowy wzorca. Nie powoduje to, że strategie zewnętrzne stają się stosowane przez `external_directory`. + +Na przykład umożliwia dostęp do wszystkiego pod `~/projects/personal/`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +Każdy dopuszczony tutaj katalog jest dziedziczy tych samych ustawień, co dostęp do obszaru roboczego. Ponieważ [`read` ma wartość domyślną `allow`](#defaults), odczyty są również dostępne dla wpisów poniżej `external_directory`, chyba że zagłębione. Dodaj dodatkowe rozwiązanie, kiedy narzędzie powinno być rozwiązaniem w tych ścieżkach, np. blokowanie edycji przy zachowaniu odczytów: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +Skoncentruj listę na zaufanych ścieżkach i dodaj dodatkowe zezwolenie lub odmowę, jeśli jest potrzebne w innych narzędziach (na przykład `bash`). + +--- + +## Dostępne uprawnienia + +Uprawnienia opencode są określane na podstawie nazwy narzędzia i kilku zabezpieczeń: + +- `read` — odczyt pliku (odpowiada ścieżce pliku) +- `edit` — wszystkie modyfikacje plików (obejmuje `edit`, `write`, `patch`, `multiedit`) +- `glob` — maglowanie plików (pasuje do wzorców globowania) +- `grep` — wyszukiwanie treści (pasuje do wzorca regularnego) +- `list` — wyświetlanie listy plików w katalogu (pasuje do katalogu) +- `bash` — uruchamianie poleceń shell (pasuje do poleceń przeanalizowanych, takich jak `git status --porcelain`) +- `task` — uruchamianie podagentów (odpowiada typowi podagenta) +- `skill` — ładowanie umiejętności (pasuje do nazwy umiejętności) +- `lsp` — uruchamianie zapytań LSP (obecnie nieszczegółowych) +- `todoread`, `todowrite` — czytanie/aktualizacja list rzeczy do wykonania +- `webfetch` — pobieranie adresu URL (pasuje do adresu URL) +- `websearch`, `codesearch` — wyszukiwanie sieci/kodu (pasuje do zapytań) +- `external_directory` — wywoływacz, gdy narzędzie jest dostępne poza katalogiem roboczym projektu +- `doom_loop` — wyzwalane, gdy samo wywołanie narzędzia zostanie powtórzone 3 razy z tymi samymi danymi podstawowymi + +--- + +## Domyślne + +Jeżeli nic nie jest określone, opencode zostanie uruchomione od dopuszczalnych rozwiązań diagnostycznych: + +- Dostępne uprawnienia ma wartość domyślną `"allow"`. +- `doom_loop` i `external_directory` zamek ma wartość `"ask"`. +- `read` do `"allow"`, ale pliki `.env` są odrzucane: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## Co robi „Zapytaj”. + +Gdy opencode poprosi o zatwierdzenie, interfejs użytkownika oferujący trzy wyniki: + +- `once` — zatwierdź tylko tę prośbę +- `always` — zastosowanie, które następuje po zastosowaniu sugerowanych wzorców (przez następczą bieżącą sesję opencode) +- `reject` — odrzucić + +Zestaw wzorców, które `always` zatwierdziłby, jest udostępniony przez narzędzie (na przykładzie zatwierdzenia bash zazwyczaj umieszczają na częstotliwości bezpiecznej prefiksy polecenia, takie jak `git status*`). + +--- + +## Agenci + +Można uzyskać dostęp do poszczególnych agentów. Uprawnienia agenta są skalowane z konfiguracją globalną, a następnie agenta ma pierwszeństwo. [Dowiedz się więcej](/docs/agents#permissions) o prawach agenta. + +:::note +Bardziej szczegółowe przykłady dopasowywania wzorców można znaleźć w sekcji [Reguły szczegółowe (składnia obiektu) (#granular-rules-object-syntax) powyżej. +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +Możesz także mieć pozwolenie na agenta w Markdown: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +zastosowanie dopasowywania wzorców dla pierwotnych z argumentami. `"grep *"` pozwala na `grep pattern file.txt`, podczas gdy sam `"grep"` blokuje to. Polecenia takie jak `git status` w przypadku postępowania dyscyplinarnego, ale ostatecznego zastosowania (np. `"git status *"`) podczas stosowania argumentów. +::: diff --git a/packages/web/src/content/docs/pl/plugins.mdx b/packages/web/src/content/docs/pl/plugins.mdx new file mode 100644 index 00000000000..e91900ad270 --- /dev/null +++ b/packages/web/src/content/docs/pl/plugins.mdx @@ -0,0 +1,385 @@ +--- +title: Wtyczki +description: Napisz własną wtyczkę, aby rozszerzyć opencode. +--- + +Wtyczki umożliwiające wyłączenie opencode poprzez podjęcie różnych zdarzeń i zachowanie. Można utworzyć wtyczkę, aby sprawdzić nowe funkcje, integrować się z usługami lub sprawdzaniem zachowania opencode. + +Aby znaleźć się z przykładami, przejrzyj [wtyczki](/docs/ecosystem#plugins) utworzone przez społeczność. + +--- + +## użyj wtyczki + +Istnieją dwa sposoby ładowania wtyczek. + +--- + +### Z plików lokalnych + +Miejsce plików JavaScript lub TypeScript w katalogu wtyczki. + +- `.opencode/plugins/` - Wtyczki na poziomie projektu +- `~/.config/opencode/plugins/` - Wtyczki globalne + +Pliki w tych katalogach są automatycznie ładowane podczas uruchamiania. + +--- + +### Z npm + +szczegółowy pakiet npm w pliku konfiguracyjnym. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +Obsługiwane są zarówno pakiety zwykłe, jak i pakiety npm o określonym zakresie. + +Przeglądaj dostępną wtyczkę w [ekosystemie](/docs/ecosystem#plugins). + +--- + +### Sposób instalacji wtyczek + +**wtyczki npm** są instalowane automatycznie przy użyciu Bun podczas uruchamiania. Pakiety i ich zależności są buforowane w `~/.cache/opencode/node_modules/`. + +**Wtyczki lokalne** są ładowane bezpośrednio z katalogu wtyczek. Aby uzyskać dostęp do zewnętrznych pakietów, musisz zainstalować `package.json` w swoim katalogu konfiguracyjnym (zobacz [Zależności](#dependencies)) lub opublikować wtyczkę w npm i [dodaj ją do swojej konfiguracji](/docs/config#plugins). + +--- + +### Załaduj zamówienie + +Wtyczki są ładowane ze wszystkich źródeł, a wszystkie hooki napisane po kolei. Kolejność ładowania do: + +1. Konfiguracja globalna (`~/.config/opencode/opencode.json`) +2. Konfiguracja projektu (`opencode.json`) +3. Globalny katalog wtyczek (`~/.config/opencode/plugins/`) +4. Katalog wtyczek projektu (`.opencode/plugins/`) + +Zduplikowane pakiety npm o tej samej nazwie i wersji są ładowane raz. Równie ważny jest dostęp lokalny i zewnętrzny npm o dodatkowych nazwach, które są zewnętrzne. + +--- + +## Utwórz wtyczkę + +Wtyczka do **moduł JavaScript/TypeScript**, który eksportuje jeden lub więcej wtyczek +funkcje. dostępna funkcja korzystania z obiektu kontekstu i głównego obiektu hooks. + +--- + +### Zależności + +Lokalne narzędzie i narzędzie, które można wykorzystać z zewnętrznych pakietów npm. Dodaj `package.json` do swojego katalogu konfiguracyjnego z zależnościami. + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +opencode uruchomienie `bun install` przy uruchomieniu, aby je uruchomić. Twoje dodatkowe funkcje będą dostępne po zaimportowaniu. + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### Podstawowa struktura + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +Funkcja dostępu do: + +- `project`: Aktualne informacje o projekcie. +- `directory`: Bieżący katalog roboczy. +- `worktree`: Ścieżka eksploatacyjna Git. +- `client`: Klient SDK z opencode do sztucznej inteligencji. +- `$`: [API obudowy](https://bun.com/docs/runtime/shell) Buna do wykonywania oprogramowania. + +--- + +### Obsługa TypeScriptu + +W przypadku wtyczek TypeScript możesz importować typy z pakietu wtyczek: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### Wydarzenia + +Wtyczki mogą subskrybować zdarzenia, jak zastosować poniżej sekcji Przykłady. Oto lista różnych działań. + +#### Wydarzenia dowodzenia + +- `command.executed` + +#### Plik Wydarzenia + +- `file.edited` +- `file.watcher.updated` + +#### Wydarzenia instalacyjne + +- `installation.updated` + +#### Wydarzenia LSP + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### Wydarzenia w wiadomościach + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### Wydarzenia związane z uprawnieniami + +- `permission.asked` +- `permission.replied` + +#### Wydarzenia serwerowe + +- `server.connected` + +#### Wydarzenia sesyjne + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### Wydarzenia do zrobienia + +- `todo.updated` + +#### Wydarzenia shell + +- `shell.env` + +#### Wydarzenia narzędziowe + +- `tool.execute.after` +- `tool.execute.before` + +#### Wydarzenia TUI + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## Przykłady + +Oto kilka dostępnych wtyczek, które można udostępnić do opencode. + +--- + +### Wysyłaj powiadomienia + +Wysyłaj powiadomienia, gdy wystąpią określone zdarzenia: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +Używamy `osascript` do uruchamiania AppleScript na macOS. Tutaj możesz przejść do wysyłania pozostałości. + +:::note +Jeśli korzystasz z aplikacji komputerowej opencode, może ona automatycznie wysłać wiadomość systemową, gdy odpowiedź jest gotowa lub gdy wystąpią błędy sesji. +::: + +--- + +### ochrona .env + +Zablokuj opencode czytanie plików `.env`: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### Wstrzyknij zmienne środowiskowe + +Wstrzyknij zmienne konsekwencje dla wszystkich wykonań (narzędzia AI i terminale użytkownika): + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### Niestandardowe narzędzia + +Wtyczki mogą również dodawać niestandardowe narzędzia do opencode: + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +Pomocnik `tool` tworzy narzędzie użytkowe, które może wywołać kod opencode. Pobierane schematu Zoda i narzędzie wyszukiwania za pomocą: + +- `description`: Co robi do narzędzia +- `args`: Schemat Zoda dla narzędzi argumentów +- `execute`: Funkcja uruchamiania po wywołaniu narzędzia + +Twoje narzędzie będzie dostępne dla otwartego kodu wraz z narzędziami użytkowymi. + +--- + +### Wycięcie lasu + +użyj `client.app.log()` zamiast `console.log` do rejestracji strukturalnego: + +```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" }, + }, + }) +} +``` + +Poziomy: `debug`, `info`, `warn`, `error`. Aby uzyskać szczegółowe informacje, zobacz [dokumentację pakietu SDK](https://opencode.ai/docs/sdk). + +--- + +### Haki zagęszczające + +Dostosuj kontekst dołączony podczas kompaktowania sesji: + +```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 +`) + }, + } +} +``` + +Hak `experimental.session.compacting` jest uruchamiany, zanim LLM wygeneruje podsumowanie kontynuacji. go, aby wstrzyknąć kontekst kontekstu dla domeny, której nie dostrzeżono przez domyślny monit o zagęszczenie. + +Można także umieścić kompletny monit o zagęszczenie, ustawiając `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. +` + }, + } +} +``` + +Gdy urządzenie jest `output.prompt`, jest całkowicie dostępne na domyślnym monit o zagęszczanie. Tablica `output.context` jest w tym przypadku poniesiona. diff --git a/packages/web/src/content/docs/pl/providers.mdx b/packages/web/src/content/docs/pl/providers.mdx new file mode 100644 index 00000000000..58f824764ef --- /dev/null +++ b/packages/web/src/content/docs/pl/providers.mdx @@ -0,0 +1,1888 @@ +--- +title: Dostawcy +description: Korzystanie z dowolnego dostawcy LLM w opencode. +--- + +import config from "../../../../config.mjs" +export const console = config.console + +opencode używa [AI SDK](https://ai-sdk.dev/) i [Models.dev](https://models.dev) do obsługi **ponad 75 dostawców LLM** i obsługuje uruchamianie modeli lokalnych. + +Aby dodać dostawcę należy: + +1. Dodaj klucze API dla dostawcy za pomocą komendy `/connect`. +2. Skonfiguruj dostawcę w konfiguracji opencode. + +--- + +### Credentials + +Po dodaniu kluczy API dostawcy za pomocą polecenia `/connect` są one przechowywane +w `~/.local/share/opencode/auth.json`. + +--- + +### Konfiguracja + +Możesz dostosować dostawców za pomocą sekcji `provider` w swoim opencode +config. + +--- + +#### Base URL + +Możesz dostosować podstawowy adres URL dla dowolnego dostawcy, ustawiając opcję `baseURL`. Jest to przydatne podczas korzystania z usług proxy lub niestandardowych punktów końcowych. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen to lista modeli dostarczonych przez zespół opencode, które zostały +przetestowane i zweryfikowane, aby dobrze współpracować z opencode. [Dowiedz się więcej](/docs/zen). + +:::tip +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). + + ```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. + +--- + +## Katalog + +Przyjrzyjmy się szczegółowo niektórym dostawcom. Jeśli chcesz dodać dostawcę do +listę, możesz otworzyć PR. + +:::note +Nie widzisz tutaj dostawcy? Prześlij PR. +::: + +--- + +### 302.AI + +1. Przejdź do [konsoli 302.AI](https://302.ai/), utwórz konto i wygeneruj klucz API. + +2. Uruchom komendę `/connect` i wyszukaj **302.AI**. + + ```txt + /connect + ``` + +3. Wpisz swój klucz API 302.AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom komendę `/models`, aby wybrać model. + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +Aby używać Amazon Bedrock z opencode: + +1. Przejdź do **Katalogu modeli** w konsoli Amazon Bedrock i poproś + dostęp do wybranych modeli. + + :::tip + Musisz mieć dostęp do żądanego modelu w Amazon Bedrock. + ::: + +2. **Skonfiguruj uwierzytelnianie** przy użyciu jednej z następujących metod: + + #### Zmienne środowiskowe (Szybki start) + + Ustaw jedną z tych zmiennych środowiskowych podczas uruchamiania opencode: + + ```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode + ``` + + Lub dodaj je do swojego profilu bash: + + ```bash title="~/.bash_profile" + export AWS_PROFILE=my-dev-profile + export AWS_REGION=us-east-1 + ``` + + #### Plik konfiguracyjny (zalecane) + + W przypadku konfiguracji specyficznej dla projektu lub trwałej użyj `opencode.json`: + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile" + } + } + } + } + ``` + + **Dostępne opcje:** + - `region` - region AWS (np. `us-east-1`, `eu-west-1`) + - `profile` - profil nazwany AWS z `~/.aws/credentials` + - `endpoint` — niestandardowy adres URL punktu końcowego dla punktów końcowych VPC (alias dla ogólnej opcji `baseURL`) + + :::tip + Opcje z pliku konfiguracyjnego mają pierwszeństwo przed zmiennymi środowiskowymi. + ::: + + #### Zaawansowane: Punkty końcowe VPC + + Jeśli używasz punktów końcowych VPC dla Bedrock: + + ```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 + Opcja `endpoint` jest aliasem ogólnej opcji `baseURL`, używając terminologii specyficznej dla AWS. Jeśli określono zarówno `endpoint`, jak i `baseURL`, pierwszeństwo ma `endpoint`. + ::: + + #### Metody uwierzytelniania + - **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: Utwórz użytkownika IAM i wygeneruj klucze dostępu w konsoli AWS + - **`AWS_PROFILE`**: Użyj nazwanych profili z `~/.aws/credentials`. Najpierw skonfiguruj za pomocą `aws configure --profile my-profile` lub `aws sso login` + - **`AWS_BEARER_TOKEN_BEDROCK`**: Wygeneruj długoterminowe klucze API z konsoli Amazon Bedrock + - **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: Dla EKS IRSA (Role IAM dla kont usług) lub innych środowisk Kubernetes z federacją OIDC. Te zmienne środowiskowe są automatycznie wstrzykiwane przez Kubernetes podczas korzystania z adnotacji konta usługi. + + #### Kolejność uwierzytelniania + + Amazon Bedrock wykorzystuje następujący priorytet uwierzytelniania: + 1. **Token nośnika** - zmienna środowiskowa `AWS_BEARER_TOKEN_BEDROCK` lub token z komendy `/connect` + 2. **AWS Credential Chain** - Profile, access keys, shared credentials, IAM roles, Web Identity Tokens (EKS IRSA), instance metadata + + :::note + Gdy ustawisz bearer token (przez `/connect` lub `AWS_BEARER_TOKEN_BEDROCK`), ma on pierwszeństwo nad wszystkimi metodami poświadczeń AWS, w tym profilami. + ::: + +3. Uruchom komendę `/models`, aby wybrać żądany model. + + ```txt + /models + ``` + +:::note +W przypadku niestandardowych profili wnioskowania użyj nazwy modelu i dostawcy w kluczu i ustaw właściwość `id` na wartość arn. Zapewnia to prawidłowe buforowanie: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. Po zarejestrowaniu się uruchom komendę `/connect` i wybierz opcję Anthropic. + + ```txt + /connect + ``` + +2. Tutaj możesz wybrać opcję **Claude Pro/Max**, co spowoduje otwarcie przeglądarki + i poproś o uwierzytelnienie. + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. Teraz wszystkie modele antropiczne powinny być dostępne po użyciu polecenia `/models`. + + ```txt + /models + ``` + +:::info +Korzystanie z subskrypcji Claude Pro/Max w opencode nie jest oficjalnie obsługiwane przez [Anthropic](https://anthropic.com). +::: + +##### Użycie kluczy API + +Możesz także wybrać opcję **Utwórz klucz API**, jeśli nie masz subskrypcji Pro/Max. Otworzy się także Twoja przeglądarka i poprosi Cię o zalogowanie się do Anthropic i poda kod, który możesz wkleić w terminalu. + +Lub jeśli masz już klucz API, możesz wybrać **Wprowadź klucz API ręcznie** i wkleić go w terminalu. + +--- + +### Azure OpenAI + +:::note +Jeśli napotkasz błędy „Przykro mi, ale nie mogę pomóc w tej prośbie”, spróbuj zmienić filtr zawartości z **DefaultV2** na **Default** w zasobie platformy Azure. +::: + +1. Przejdź do [Azure portal](https://portal.azure.com/) i utwórz zasób **Azure OpenAI**. Będziesz potrzebować: + - **Nazwa zasobu**: staje się częścią punktu końcowego API (`https://RESOURCE_NAME.openai.azure.com/`) + - **Klucz API**: `KEY 1` lub `KEY 2` z Twojego zasobu + +2. Przejdź do [Azure AI Foundry](https://ai.azure.com/) i wdróż model. + + :::note + Aby kod opencode działał poprawnie, nazwa wdrożenia musi być zgodna z nazwą modelu. + ::: + +3. Uruchom polecenie `/connect` i wyszukaj **Azure**. + + ```txt + /connect + ``` + +4. Wpisz swój klucz API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Ustaw nazwę zasobu jako zmienną środowiskową: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + Lub dodaj go do swojego profilu bash: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. Uruchom komendę `/models`, aby wybrać wdrożony model. + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. Przejdź do [Azure portal](https://portal.azure.com/) i utwórz zasób **Azure OpenAI**. Będziesz potrzebować: + - **Nazwa zasobu**: staje się częścią punktu końcowego API (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) + - **Klucz API**: `KEY 1` lub `KEY 2` z Twojego zasobu + +2. Przejdź do [Azure AI Foundry](https://ai.azure.com/) i wdróż model. + + :::note + Aby kod opencode działał poprawnie, nazwa wdrożenia musi być zgodna z nazwą modelu. + ::: + +3. Uruchom polecenie `/connect` i wyszukaj **Azure Cognitive Services**. + + ```txt + /connect + ``` + +4. Wpisz swój klucz API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Ustaw nazwę zasobu jako zmienną środowiskową: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + Lub dodaj go do swojego profilu bash: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. Uruchom komendę `/models`, aby wybrać wdrożony model. + + ```txt + /models + ``` + +--- + +### Baseten + +1. Udaj się do [Baseten](https://app.baseten.co/), utwórz konto i wygeneruj klucz API. + +2. Uruchom komendę `/connect` i wyszukaj **Baseten**. + + ```txt + /connect + ``` + +3. Wprowadź swój klucz API Baseten. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom komendę `/models`, aby wybrać model. + + ```txt + /models + ``` + +--- + +### Cerebras + +1. Przejdź do [konsoli Cerebras](https://inference.cerebras.ai/), utwórz konto i wygeneruj klucz API. + +2. Uruchom komendę `/connect` i wyszukaj **Cerebras**. + + ```txt + /connect + ``` + +3. Wprowadź swój klucz API Cerebras. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom polecenie `/models`, aby wybrać model taki jak _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +Cloudflare AI Gateway umożliwia dostęp do modeli z OpenAI, Anthropic, Workers AI i innych za pośrednictwem ujednoliconego punktu końcowego. Dzięki [Ujednoliconemu rozliczeniu](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) nie potrzebujesz oddzielnych kluczy API dla każdego dostawcy. + +1. Przejdź do [panelu Cloudflare](https://dash.cloudflare.com/), przejdź do **AI** > **AI Gateway** i utwórz nową bramę. + +2. Ustaw identyfikator konta i identyfikator bramy jako zmienne środowiskowe. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. Uruchom polecenie `/connect` i wyszukaj **Cloudflare AI Gateway**. + + ```txt + /connect + ``` + +4. Wprowadź swój token API Cloudflare. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + Or set it as an environment variable. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. Uruchom komendę `/models`, aby wybrać model. + + ```txt + /models + ``` + + Możesz także dodawać modele za pomocą konfiguracji opencode. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +### Cortecs + +1. Przejdź do [konsoli Cortecs](https://cortecs.ai/), utwórz konto i wygeneruj klucz API. + +2. Uruchom komendę `/connect` i wyszukaj **Cortecs**. + + ```txt + /connect + ``` + +3. Wprowadź klucz API Cortecs. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom polecenie `/models`, aby wybrać model taki jak _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. Przejdź do [konsoli DeepSeek](https://platform.deepseek.com/), utwórz konto i kliknij **Utwórz nowy klucz API**. + +2. Uruchom polecenie `/connect` i wyszukaj **DeepSeek**. + + ```txt + /connect + ``` + +3. Wprowadź klucz API DeepSeek. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom polecenie `/models`, aby wybrać model DeepSeek, np. _DeepSeek Reasoner_. + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. Przejdź do [panelu Deep Infra](https://deepinfra.com/dash), utwórz konto i wygeneruj klucz API. + +2. Uruchom komendę `/connect` i wyszukaj **Deep Infra**. + + ```txt + /connect + ``` + +3. Wprowadź swój klucz API Deep Infra. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom komendę `/models`, aby wybrać model. + + ```txt + /models + ``` + +--- + +### Firmware + +1. Przejdź do [Firmware dashboard](https://app.firmware.ai/signup), utwórz konto i wygeneruj klucz API. + +2. Uruchom polecenie `/connect` i wyszukaj **Firmware**. + + ```txt + /connect + ``` + +3. Wprowadź klucz API Firmware. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom komendę `/models`, aby wybrać model. + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. Przejdź do [konsoli Fireworks AI](https://app.fireworks.ai/), utwórz konto i kliknij **Utwórz klucz API**. + +2. Uruchom polecenie `/connect` i wyszukaj **Fireworks AI**. + + ```txt + /connect + ``` + +3. Wprowadź klucz API programu Fireworks AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom polecenie `/models`, aby wybrać model taki jak _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo zapewnia czat agentowy oparty na sztucznej inteligencji z natywnymi możliwościami wywoływania narzędzi za pośrednictwem Anthropic proxy GitLab. + +1. Uruchom komendę `/connect` i wybierz GitLab. + + ```txt + /connect + ``` + +2. Wybierz metodę uwierzytelniania: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ + ``` + + #### Using OAuth (Recommended) + + Wybierz **OAuth**, a Twoja przeglądarka otworzy się w celu autoryzacji. + + #### Użycie osobistego tokenu dostępu + 1. Przejdź do [Ustawienia użytkownika GitLab > Tokeny dostępu](https://gitlab.com/-/user_settings/personal_access_tokens) + 2. Click **Add new token** + 3. Name: `OpenCode`, Scopes: `api` + 4. Skopiuj token (zaczyna się od `glpat-`) + 5. Wpisz go w terminalu + +3. Uruchom komendę `/models`, aby zobaczyć dostępne modele. + + ```txt + /models + ``` + + Dostępne są trzy modele oparte na Claude: + - **duo-chat-haiku-4-5** (Domyślnie) - Szybkie odpowiedzi dla szybkich zadań + - **duo-chat-sonnet-4-5** - Zrównoważona wydajność dla większości przepływów pracy + - **duo-chat-opus-4-5** - Najbardziej zdolny do złożonej analizy + +:::note +Jeśli nie chcesz, możesz także określić zmienną środowiskową „GITLAB_TOKEN”. +to store token in opencode auth storage. +::: + +##### Self-Hosted GitLab + +:::note[compliance note] +opencode używa małego modelu do niektórych zadań AI, takich jak generowanie tytułu sesji. +Domyślnie jest skonfigurowany do używania gpt-5-nano, hostowanego przez Zen. Aby zablokować opencode +aby używać tylko własnej instancji hostowanej przez GitLab, dodaj następujące elementy do pliku +`opencode.json` plik. Zalecane jest również wyłączenie udostępniania sesji. + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +W przypadku samodzielnie hostowanych instancji GitLab: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +Jeśli w Twojej instancji działa niestandardowa brama AI: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +Lub dodaj do swojego profilu bash: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +Twój administrator GitLab musi włączyć następujące opcje: + +1. [Platforma Duo Agent](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) dla użytkownika, grupy lub instancji +2. Feature flags (via Rails console): + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: + +##### OAuth dla instancji hostowanych samodzielnie + +Aby Oauth mógł działać w przypadku Twojej instancji hostowanej samodzielnie, musisz utworzyć +nową aplikację (Ustawienia → Aplikacje) z +Adres URL wywołania zwrotnego `http://127.0.0.1:8080/callback` i następujące zakresy: + +- api (Uzyskaj dostęp do API w swoim imieniu) +- read_user (Przeczytaj swoje dane osobowe) +- read_repository (umożliwia dostęp do repozytorium tylko do odczytu) + +Następnie ustaw ID aplikacji jako zmienną środowiskową: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +Więcej informacji znajdziesz na stronie [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth). + +##### Konfiguracja + +Customize through `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### Narzędzia GitLab API (opcjonalne, ale wysoce zalecane) + +To access GitLab tools (merge requests, issues, pipelines, CI/CD, etc.): + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +Ta wtyczka zapewnia kompleksowe możliwości zarządzania repozytorium GitLab, w tym recenzje MR, śledzenie problemów, monitorowanie rurociągów i inne. + +--- + +### GitHub Copilot + +Aby korzystać z subskrypcji GitHub Copilot z kodem opencode: + +:::note +Niektóre modele mogą wymagać [subskrypcji Pro+](https://github.com/features/Copilot/plans), aby z nich korzystać. + +Niektóre modele należy włączyć ręcznie w [ustawieniach GitHub Copilot](https://docs.github.com/en/Copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use). +::: + +1. Uruchom komendę `/connect` i wyszukaj GitHub Copilot. + + ```txt + /connect + ``` + +2. Przejdź do [github.com/login/device](https://github.com/login/device) i wpisz kod. + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + └ Waiting for authorization... + ``` + +3. Teraz uruchom polecenie `/models`, aby wybrać żądany model. + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +Aby używać Google Vertex AI z opencode: + +1. Przejdź do **Model Garden** w Google Cloud Console i sprawdź + modele dostępne w Twoim regionie. + + :::note + Musisz mieć projekt Google Cloud z włączonym interfejsem API Vertex AI. + ::: + +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): + - `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. + + ```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode + ``` + + Lub dodaj je do swojego profilu bash. + + ```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 +Region `global` poprawia dostępność i zmniejsza liczbę błędów bez dodatkowych kosztów. Użyj regionalnych punktów końcowych (np. `us-central1`) w celu spełnienia wymagań dotyczących miejsca przechowywania danych. [Dowiedz się więcej](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. Uruchom komendę `/models`, aby wybrać żądany model. + + ```txt + /models + ``` + +--- + +### Groq + +1. Przejdź do [konsoli Groq](https://console.groq.com/), kliknij **Utwórz klucz API** i skopiuj klucz. + +2. Uruchom komendę `/connect` i wyszukaj Groq. + + ```txt + /connect + ``` + +3. Wprowadź klucz API dla dostawcy. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom polecenie `/models`, aby wybrać żądany. + + ```txt + /models + ``` + +--- + +### Hugging Face + +[Inference Providers Hugging Face](https://huggingface.co/docs/inference-providers) zapewniają dostęp do otwartych modeli obsługiwanych przez ponad 17 dostawców. + +1. Przejdź do [ustawień Hugging Face](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained), aby utworzyć token z uprawnieniami do wykonywania połączeń z dostawcami wnioskowania. + +2. Uruchom komendę `/connect` i wyszukaj **Hugging Face**. + + ```txt + /connect + ``` + +3. Wprowadź swój token Hugging Face. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom polecenie `/models`, aby wybrać model taki jak _Kimi-K2-Instruct_ lub _GLM-4.6_. + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) to platforma obserwowalności LLM, która zapewnia rejestrowanie, monitorowanie i analizy dla aplikacji AI. Helicone AI Gateway automatycznie kieruje Twoje żądania do odpowiedniego dostawcy w oparciu o model. + +1. Udaj się do [Helicone](https://helicone.ai), utwórz konto i wygeneruj klucz API ze swojego panelu. + +2. Uruchom komendę `/connect` i wyszukaj **Helicone**. + + ```txt + /connect + ``` + +3. Wprowadź swój klucz API Helicone. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom komendę `/models`, aby wybrać model. + + ```txt + /models + ``` + +Więcej dostawców i zaawansowanych funkcji, takich jak buforowanie i ograniczanie szybkości, znajdziesz w [dokumentacji Helicone](https://docs.helicone.ai). + +#### Opcjonalna konfiguracja + +Jeśli zobaczysz funkcję lub model firmy Helicone, która nie jest konfigurowana automatycznie za pomocą opencode, zawsze możesz ją skonfigurować samodzielnie. + +Oto [Katalog modeli Helicone](https://helicone.ai/models), będziesz go potrzebować, aby pobrać identyfikatory modeli, które chcesz dodać. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### Niestandardowe nagłówki + +Helicone obsługuje niestandardowe nagłówki dla funkcji takich jak buforowanie, śledzenie użytkowników i zarządzanie sesjami. Dodaj je do konfiguracji dostawcy za pomocą `options.headers`: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### Śledzenie sesji + +Funkcja [Sesje](https://docs.helicone.ai/features/sessions) firmy Helicone umożliwia grupowanie powiązanych żądań LLM. Użyj wtyczki [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session), aby automatycznie rejestrować każdą konwersację opencode jako sesję w Helicone. + +```bash +npm install -g opencode-helicone-session +``` + +Dodaj go do swojej konfiguracji. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +Wtyczka wstawia nagłówki `Helicone-Session-Id` i `Helicone-Session-Name` do Twoich żądań. Na stronie Sesje Helicone każda konwersacja opencode będzie wymieniona jako osobna sesja. + +##### Najczęstsze nagłówki Helicone + +| Header | Description | +| -------------------------- | ------------------------------------------------------------- | +| `Helicone-Cache-Enabled` | Enable response caching (`true`/`false`) | +| `Helicone-User-Id` | Track metrics by user | +| `Helicone-Property-[Name]` | Add custom properties (e.g., `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | Powiąż żądania z wersjami podpowiedzi | + +Zobacz [Katalog nagłówków Helicone](https://docs.helicone.ai/helicone-headers/header-directory), aby poznać wszystkie dostępne nagłówki. + +--- + +### llama.cpp + +Możesz skonfigurować opencode tak, aby korzystał z modeli lokalnych, za pomocą narzędzia llama-server [llama.cpp](https://github.com/ggml-org/llama.cpp) + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +W tym przykładzie: + +- `llama.cpp` to niestandardowy identyfikator dostawcy. Może to być dowolny ciąg znaków. +- `npm` określa pakiet, który ma być używany dla tego dostawcy. Tutaj `@ai-sdk/openai-compatible` jest używany dla dowolnego API zgodnego z OpenAI. +- `name` to nazwa wyświetlana dostawcy w interfejsie użytkownika. +- `options.baseURL` jest punktem końcowym serwera lokalnego. +- `models` to mapa identyfikatorów modeli do ich konfiguracji. Nazwa modelu zostanie wyświetlona na liście wyboru modelu. + +--- + +### IO.NET + +IO.NET oferuje 17 modeli zoptymalizowanych pod kątem różnych zastosowań: + +1. Przejdź do [konsoli IO.NET](https://ai.io.net/), utwórz konto i wygeneruj klucz API. + +2. Uruchom komendę `/connect` i wyszukaj **IO.NET**. + + ```txt + /connect + ``` + +3. Wprowadź swój klucz API IO.NET. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom komendę `/models`, aby wybrać model. + + ```txt + /models + ``` + +--- + +### LM Studio + +Możesz skonfigurować opencode tak, aby korzystał z modeli lokalnych poprzez LM Studio. + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +W tym przykładzie: + +- `lmstudio` to niestandardowy identyfikator dostawcy. Może to być dowolny ciąg znaków. +- `npm` określa pakiet, który ma być używany dla tego dostawcy. Tutaj `@ai-sdk/openai-compatible` jest używany dla dowolnego API zgodnego z OpenAI. +- `name` to nazwa wyświetlana dostawcy w interfejsie użytkownika. +- `options.baseURL` jest punktem końcowym serwera lokalnego. +- `models` to mapa identyfikatorów modeli do ich konfiguracji. Nazwa modelu zostanie wyświetlona na liście wyboru modelu. + +--- + +### Moonshot AI + +Aby użyć Kimi K2 z Moonshot AI: + +1. Przejdź do [konsoli Moonshot AI](https://platform.moonshot.ai/console), utwórz konto i kliknij **Utwórz klucz API**. + +2. Uruchom polecenie `/connect` i wyszukaj **Moonshot AI**. + + ```txt + /connect + ``` + +3. Wprowadź klucz API Moonshot. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom komendę `/models`, aby wybrać _Kimi K2_. + + ```txt + /models + ``` + +--- + +### MiniMax + +1. Przejdź do [konsoli API MiniMax](https://platform.minimax.io/login), utwórz konto i wygeneruj klucz API. + +2. Uruchom komendę `/connect` i wyszukaj **MiniMax**. + + ```txt + /connect + ``` + +3. Wprowadź swój klucz API MiniMax. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom komendę `/models`, aby wybrać model taki jak _M2.1_. + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. Przejdź do [konsoli Nebius Token Factory](https://tokenfactory.nebius.com/), utwórz konto i kliknij **Dodaj klucz**. + +2. Uruchom komendę `/connect` i wyszukaj **Nebius Token Factory**. + + ```txt + /connect + ``` + +3. Wprowadź klucz API Nebius Token Factory. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom polecenie `/models`, aby wybrać model taki jak _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Ollama + +Możesz skonfigurować opencode tak, aby korzystał z modeli lokalnych poprzez Ollamę. + +:::tip +Ollama może automatycznie skonfigurować się pod kątem opencode. Aby uzyskać szczegółowe informacje, zobacz [dokumentację integracji Ollama](https://docs.ollama.com/integrations/opencode). +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +W tym przykładzie: + +- `ollama` to niestandardowy identyfikator dostawcy. Może to być dowolny ciąg znaków. +- `npm` określa pakiet, który ma być używany dla tego dostawcy. Tutaj `@ai-sdk/openai-compatible` jest używany dla dowolnego API zgodnego z OpenAI. +- `name` to nazwa wyświetlana dostawcy w interfejsie użytkownika. +- `options.baseURL` jest punktem końcowym serwera lokalnego. +- `models` to mapa identyfikatorów modeli do ich konfiguracji. Nazwa modelu zostanie wyświetlona na liście wyboru modelu. + +:::tip +Jeśli wywołania narzędzi nie działają, spróbuj zwiększyć `num_ctx` w Ollama. Zacznij około 16 tys. - 32 tys. +::: + +--- + +### Ollama Cloud + +Aby korzystać z Ollama Cloud z opencode: + +1. Udaj się do [https://ollama.com/](https://ollama.com/) i zaloguj się lub utwórz konto. + +2. Przejdź do **Ustawienia** > **Klucze** i kliknij **Dodaj klucz API**, aby wygenerować nowy klucz API. + +3. Skopiuj klucz API do użycia w opencode. + +4. Uruchom polecenie `/connect` i wyszukaj **Ollama Cloud**. + + ```txt + /connect + ``` + +5. Wprowadź swój klucz API Ollama Cloud. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **Ważne**: Przed użyciem modeli chmurowych w opencode musisz pobrać informacje o modelu lokalnie: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. Uruchom polecenie `/models`, aby wybrać model Ollama Cloud. + + ```txt + /models + ``` + +--- + +### OpenAI + +Zalecamy zarejestrowanie się w [ChatGPT Plus lub Pro](https://chatgpt.com/pricing). + +1. Po zarejestrowaniu się uruchom komendę `/connect` i wybierz OpenAI. + + ```txt + /connect + ``` + +2. Tutaj możesz wybrać opcję **ChatGPT Plus/Pro**, co spowoduje otwarcie przeglądarki + i poproś o uwierzytelnienie. + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. Teraz wszystkie modele OpenAI powinny być dostępne po użyciu polecenia `/models`. + + ```txt + /models + ``` + +##### Użycie kluczy API + +Jeśli posiadasz już klucz API, możesz wybrać opcję **Wprowadź klucz API ręcznie** i wkleić go w terminalu. + +--- + +### OpenCode Zen + +OpenCode Zen to lista przetestowanych i zweryfikowanych modeli udostępniona przez zespół opencode. [Dowiedz się więcej](/docs/zen). + +1. Zaloguj się do **OpenCode Zen** i kliknij **Utwórz klucz API**. + +2. Uruchom polecenie `/connect` i wyszukaj **OpenCode Zen**. + + ```txt + /connect + ``` + +3. Wprowadź klucz API opencode. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom polecenie `/models`, aby wybrać model taki jak _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### OpenRouter + +1. Przejdź do [panelu OpenRouter](https://openrouter.ai/settings/keys), kliknij **Utwórz klucz API** i skopiuj klucz. + +2. Uruchom komendę `/connect` i wyszukaj OpenRouter. + + ```txt + /connect + ``` + +3. Wprowadź klucz API dla dostawcy. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Wiele modeli OpenRouter jest domyślnie załadowanych fabrycznie. Uruchom komendę `/models`, aby wybrać ten, który chcesz. + + ```txt + /models + ``` + + Możesz także dodać dodatkowe modele za pomocą konfiguracji opencode. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +5. Możesz je także dostosować za pomocą konfiguracji opencode. Oto przykład określenia dostawcy + + ```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 zapewnia dostęp do ponad 40 modeli z OpenAI, Anthropic, Google, Amazon, Meta, Mistral i AI21 za pośrednictwem ujednoliconej platformy. + +1. Przejdź do [SAP BTP Cockpit](https://account.hana.ondemand.com/), przejdź do instancji usługi SAP AI Core i utwórz klucz usługi. + + :::tip + Klucz usługi to obiekt JSON zawierający `clientid`, `clientsecret`, `url` i `serviceurls.AI_API_URL`. Instancję AI Core znajdziesz w sekcji **Usługi** > **Instancje i subskrypcje** w Kokpicie BTP. + ::: + +2. Uruchom polecenie `/connect` i wyszukaj **SAP AI Core**. + + ```txt + /connect + ``` + +3. Wpisz swój klucz usługi JSON. + + ```txt + ┌ Service key + │ + │ + └ enter + ``` + + Lub ustaw zmienną środowiskową `AICORE_SERVICE_KEY`: + + ```bash + AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode + ``` + + Lub dodaj go do swojego profilu bash: + + ```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' + ``` + +4. Opcjonalnie ustaw identyfikator wdrożenia i grupę zasobów: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + Te ustawienia są opcjonalne i należy je skonfigurować zgodnie z konfiguracją SAP AI Core. + ::: + +5. Uruchom polecenie `/models`, aby wybrać spośród ponad 40 dostępnych modeli. + + ```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**. + +2. Uruchom polecenie `/connect` i wyszukaj **Punkty końcowe AI OVHcloud**. + + ```txt + /connect + ``` + +3. Wpisz klucz API punktów końcowych AI OVHcloud. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom polecenie `/models`, aby wybrać model taki jak _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Scaleway + +Aby używać [generatywnych interfejsów API Scaleway](https://www.scaleway.com/en/docs/generative-apis/) z opencode: + +1. Przejdź do [Ustawień uprawnień konsoli Scaleway](https://console.scaleway.com/iam/api-keys), aby wygenerować nowy klucz API. + +2. Uruchom komendę `/connect` i wyszukaj **Scaleway**. + + ```txt + /connect + ``` + +3. Wprowadź swój klucz API Scaleway. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom komendę `/models`, aby wybrać model taki jak _devstral-2-123b-instruct-2512_ lub _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Together AI + +1. Przejdź do [konsoli Together AI](https://api.together.ai), utwórz konto i kliknij **Dodaj klucz**. + +2. Uruchom komendę `/connect` i wyszukaj **Together AI**. + + ```txt + /connect + ``` + +3. Wprowadź klucz API Together AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom polecenie `/models`, aby wybrać model taki jak _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Venice AI + +1. Przejdź do [konsoli Venice AI](https://venice.ai), utwórz konto i wygeneruj klucz API. + +2. Uruchom polecenie `/connect` i wyszukaj **Venice AI**. + + ```txt + /connect + ``` + +3. Wprowadź klucz API Venice AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom polecenie `/models`, aby wybrać model taki jak _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + +### Vercel AI Gateway + +Vercel AI Gateway umożliwia dostęp do modeli z OpenAI, Anthropic, Google, xAI i innych za pośrednictwem ujednoliconego punktu końcowego. Modele oferowane są po cenie katalogowej bez marży. + +1. Przejdź do [panelu Vercel](https://vercel.com/), przejdź do karty **AI Gateway** i kliknij **Klucze API**, aby utworzyć nowy klucz API. + +2. Uruchom polecenie `/connect` i wyszukaj **Vercel AI Gateway**. + + ```txt + /connect + ``` + +3. Wprowadź klucz API Vercel AI Gateway. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom komendę `/models`, aby wybrać model. + + ```txt + /models + ``` + +Możesz także dostosować modele za pomocą konfiguracji opencode. Oto przykład określenia kolejności routingu dostawcy. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "vercel": { + "models": { + "anthropic/claude-sonnet-4": { + "options": { + "order": ["anthropic", "vertex"] + } + } + } + } + } +} +``` + +Przydatne opcje routingu: + +| Opcja | Opis | +| ------------------- | ---------------------------------------------------------------------------- | +| `order` | Sekwencja dostawcy do wypróbowania | +| `only` | Ograniczenie do wskazanych dostawców | +| `zeroDataRetention` | Korzystaj wyłącznie z dostawców, którzy nie mają zasad przechowywania danych | + +--- + +### xAI + +1. Przejdź do [konsoli xAI](https://console.x.ai/), utwórz konto i wygeneruj klucz API. + +2. Uruchom komendę `/connect` i wyszukaj **xAI**. + + ```txt + /connect + ``` + +3. Wprowadź swój klucz API xAI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom polecenie `/models`, aby wybrać model taki jak _Grok Beta_. + + ```txt + /models + ``` + +--- + +### Z.AI + +1. Przejdź do [konsoli API Z.AI](https://z.ai/manage-apikey/apikey-list), utwórz konto i kliknij **Utwórz nowy klucz API**. + +2. Uruchom komendę `/connect` i wyszukaj **Z.AI**. + + ```txt + /connect + ``` + + Jeżeli jesteś abonentem **Planu kodowania GLM**, wybierz **Plan kodowania Z.AI**. + +3. Wpisz swój klucz API Z.AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom komendę `/models`, aby wybrać model taki jak _GLM-4.7_. + + ```txt + /models + ``` + +--- + +### ZenMux + +1. Przejdź do [panelu ZenMux](https://zenmux.ai/settings/keys), kliknij **Utwórz klucz API** i skopiuj klucz. + +2. Uruchom polecenie `/connect` i wyszukaj ZenMux. + + ```txt + /connect + ``` + +3. Wprowadź klucz API dla dostawcy. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Wiele modeli ZenMux jest domyślnie załadowanych fabrycznie. Uruchom komendę `/models`, aby wybrać żądany model. + + ```txt + /models + ``` + + Możesz także dodać dodatkowe modele za pomocą konfiguracji opencode. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "zenmux": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +--- + +## Niestandardowy dostawca + +Aby dodać dowolnego dostawcę **kompatybilnego z OpenAI**, którego nie ma na liście w poleceniu `/connect`: + +:::tip +Możesz użyć dowolnego dostawcy kompatybilnego z OpenAI z opencode. Większość nowoczesnych dostawców sztucznej inteligencji oferuje interfejsy API kompatybilne z OpenAI. +::: + +1. Uruchom polecenie `/connect` i przewiń w dół do **Inne**. + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. Wprowadź unikalny identyfikator dostawcy. + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::note + Wybierz niezapomniany identyfikator, użyjesz go w swoim pliku konfiguracyjnym. + ::: + +3. Wprowadź klucz API dla dostawcy. + + ```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. Utwórz lub zaktualizuj plik `opencode.json` w katalogu projektu: + + ```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" + } + } + } + } + } + ``` + + Oto opcje konfiguracji: + - **npm**: pakiet AI SDK do użycia, `@ai-sdk/openai-compatible` dla dostawców kompatybilnych z OpenAI + - **name**: Nazwa wyświetlana w UI. + - **modele**: Dostępne modele. + - **options.baseURL**: URL endpointu API. + - **options.apiKey**: Opcjonalnie ustaw klucz API, jeśli nie używasz autoryzacji. + - **options.headers**: Opcjonalnie ustaw niestandardowe nagłówki. + + Więcej o opcjach zaawansowanych w przykładzie poniżej. + +5. Uruchom polecenie `/models`, a niestandardowy dostawca i modele pojawią się na liście wyboru. + +--- + +##### Przykład + +Oto przykład ustawienia opcji `apiKey`, `headers` i modelu `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 + } + } + } + } + } +} +``` + +Szczegóły konfiguracji: + +- **apiKey**: Ustaw przy użyciu składni zmiennej `env`, [dowiedz się więcej](/docs/config#env-vars). +- **nagłówki**: niestandardowe nagłówki wysyłane z każdym żądaniem. +- **limit.context**: Maksymalna liczba tokenów wejściowych akceptowanych przez model. +- **limit.output**: Maksymalna liczba tokenów, które model może wygenerować. + +Pola `limit` pozwalają opencode zrozumieć, ile kontekstu pozostało. Standardowi dostawcy pobierają je automatycznie z models.dev. + +--- + +## Rozwiązywanie problemów + +Jeśli masz problemy z konfiguracją dostawcy, sprawdź następujące elementy: + +1. **Sprawdź konfigurację uwierzytelniania**: Uruchom `opencode auth list`, aby sprawdzić, czy poświadczenia + dla dostawcy są dodawane do Twojej konfiguracji. + + Nie dotyczy to dostawców takich jak Amazon Bedrock, którzy w procesie uwierzytelniania opierają się na zmiennych środowiskowych. + +2. W przypadku dostawców niestandardowych sprawdź konfigurację opencode i: + - Upewnij się, że identyfikator dostawcy użyty w poleceniu `/connect` jest zgodny z identyfikatorem w konfiguracji opencode. + - Dla dostawcy używany jest właściwy pakiet npm. Na przykład użyj `@ai-sdk/cerebras` dla Cerebras. W przypadku wszystkich innych dostawców zgodnych z OpenAI użyj `@ai-sdk/openai-compatible`. + - Sprawdź, czy w polu `options.baseURL` użyto prawidłowego punktu końcowego API. diff --git a/packages/web/src/content/docs/pl/rules.mdx b/packages/web/src/content/docs/pl/rules.mdx new file mode 100644 index 00000000000..1b5876f22ec --- /dev/null +++ b/packages/web/src/content/docs/pl/rules.mdx @@ -0,0 +1,180 @@ +--- +title: Zasady +description: Ustaw niestandardowe instrukcje dla opencode. +--- + +Możesz dostarczyć niestandardowe instrukcje do opencode, tworząc plik `AGENTS.md`. Jest to podobne do zasad Cursora. Zawiera instrukcje, które zostaną uwzględnione w kontekście LLM, aby dostosować jego zachowanie do konkretnego projektu. + +--- + +## Inicjalizacja + +Aby utworzyć nowy plik `AGENTS.md`, możesz uruchomić komendę `/init` w otwartym kodzie. + +:::tip +Powinieneś zatwierdzić plik `AGENTS.md` swojego projektu w Git. +::: + +Spowoduje to przeskanowanie projektu i całej jego zawartości, aby zrozumieć, czego dotyczy projekt i wygenerować z nim plik `AGENTS.md`. Pomaga to otwartemu kodowi lepiej poruszać się po projekcie. + +Jeśli masz istniejący plik `AGENTS.md`, spróbujemy go dodać. + +--- + +## Przykład + +Możesz także po prostu utworzyć ten plik ręcznie. Oto przykład niektórych rzeczy, które można umieścić w pliku `AGENTS.md`. + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +Dodajemy tutaj instrukcje dotyczące konkretnego projektu, które zostaną udostępnione całemu zespołowi. + +--- + +## Typy + +opencode obsługuje także odczytywanie pliku `AGENTS.md` z wielu lokalizacji. A to służy różnym celom. + +### Projekt + +Umieść `AGENTS.md` w katalogu głównym projektu, aby uzyskać reguły specyficzne dla projektu. Mają one zastosowanie tylko wtedy, gdy pracujesz w tym katalogu lub jego podkatalogach. + +### Globalne + +Możesz także mieć reguły globalne w pliku `~/.config/opencode/AGENTS.md`. Jest to stosowane we wszystkich sesjach opencode. + +Ponieważ nie jest to wymagane dla Git ani udostępniane Twojemu zespołowi, zalecamy użycie tego do określenia wszelkich osobistych zasad, których powinien przestrzegać LLM. + +### Kompatybilność z Claude Code + +W przypadku użytkowników migrujących z Claude Code opencode obsługuje konwencje plików Claude Code jako rozwiązania awaryjne: + +- **Zasady projektu**: `CLAUDE.md` w katalogu projektu (używane, jeśli nie istnieje `AGENTS.md`) +- **Zasady globalne**: `~/.claude/CLAUDE.md` (używane, jeśli nie istnieje `~/.config/opencode/AGENTS.md`) +- **Umiejętności**: `~/.claude/skills/` — szczegóły znajdziesz w [Umiejętnościach agenta](/docs/skills/) + +Aby wyłączyć kompatybilność z Claude Code, ustaw jedną z tych zmiennych środowiskowych: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## Priorytet + +Po uruchomieniu opencode szuka plików reguł w następującej kolejności: + +1. **Pliki lokalne** poprzez przejście z bieżącego katalogu (`AGENTS.md`, `CLAUDE.md`) +2. **Plik globalny** w `~/.config/opencode/AGENTS.md` +3. **Plik Claude Code** w `~/.claude/CLAUDE.md` (chyba że wyłączony) + +Pierwszy pasujący plik wygrywa w każdej kategorii. Na przykład, jeśli masz zarówno `AGENTS.md`, jak i `CLAUDE.md`, używany jest tylko `AGENTS.md`. Podobnie `~/.config/opencode/AGENTS.md` ma pierwszeństwo przed `~/.claude/CLAUDE.md`. + +--- + +## Instrukcje niestandardowe + +Możesz określić niestandardowe pliki instrukcji w swoim `opencode.json` lub globalnym `~/.config/opencode/opencode.json`. Dzięki temu Ty i Twój zespół możecie ponownie wykorzystać istniejące reguły, zamiast duplikować je w pliku AGENTS.md. + +Przykład: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Możesz także użyć zdalnych adresów URL, aby załadować instrukcje z Internetu. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +Instrukcje zdalne są pobierane z 5-sekundowym limitem czasu. + +Wszystkie pliki instrukcji są łączone z plikami `AGENTS.md`. + +--- + +## Odwoływanie się do plików zewnętrznych + +Chociaż opencode nie analizuje automatycznie odniesień do plików w `AGENTS.md`, możesz osiągnąć podobną funkcjonalność na dwa sposoby: + +### Używanie opencode.json + +Zalecanym podejściem jest użycie pola `instructions` w `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### Ręczne instrukcje w AGENTS.md + +Możesz nauczyć opencode czytać pliki zewnętrzne, podając wyraźne instrukcje w swoim `AGENTS.md`. Oto praktyczny przykład: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +Takie podejście pozwala: + +- Twórz modułowe pliki reguł wielokrotnego użytku +- Share rules across projects via symlinks or git submodules +- Keep AGENTS.md concise while referencing detailed guidelines +- Upewnij się, że opencode ładuje pliki tylko wtedy, gdy są potrzebne do konkretnego zadania + +:::tip +W przypadku monorepo lub projektów ze wspólnymi standardami użycie `opencode.json` ze wzorami globalnymi (takimi jak `packages/*/AGENTS.md`) jest łatwiejsze w utrzymaniu niż instrukcje ręczne. +::: diff --git a/packages/web/src/content/docs/pl/sdk.mdx b/packages/web/src/content/docs/pl/sdk.mdx new file mode 100644 index 00000000000..3236e38c29d --- /dev/null +++ b/packages/web/src/content/docs/pl/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: Typowany klient JS dla serwera OpenCode. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +Pakiet SDK JS/TS OpenCode zapewnia klienta z bezpiecznym typowaniem (type-safe) do interakcji z serwerem. +Użyj go do budowania integracji i programowej kontroli OpenCode. + +[Dowiedz się więcej](/docs/server) o działaniu serwera. Przykłady znajdziesz w [projektach](/docs/ecosystem#projects) stworzonych przez społeczność. + +--- + +## Instalacja + +Zainstaluj pakiet SDK z npm: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## Tworzenie klienta + +Utwórz instancję OpenCode: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +Spowoduje to uruchomienie zarówno serwera, jak i klienta. + +#### Opcje + +| Opcja | Typ | Opis | Domyślne | +| ---------- | ------------- | ----------------------------------------- | ----------- | +| `hostname` | `string` | Nazwa hosta serwera | `127.0.0.1` | +| `port` | `number` | Port serwera | `4096` | +| `signal` | `AbortSignal` | Sygnał przerwania w celu anulowania | `undefined` | +| `timeout` | `number` | Limit czasu w ms dla uruchomienia serwera | `5000` | +| `config` | `Config` | Obiekt konfiguracji | `{}` | + +--- + +## Konfiguracja + +Można przekazać obiekt konfiguracyjny, aby dostosować zachowanie. Instancja nadal pobiera `opencode.json`, ale możesz zastąpić lub dodać konfigurację bezpośrednio: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## Tylko klient + +Jeśli masz już działającą instancję OpenCode, możesz utworzyć instancję klienta, aby się z nią połączyć: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### Opcje + +| Opcja | Typ | Opis | Domyślne | +| --------------- | ---------- | ----------------------------------- | ----------------------- | +| `baseUrl` | `string` | Adres URL serwera | `http://localhost:4096` | +| `fetch` | `function` | Niestandardowa implementacja fetch | `globalThis.fetch` | +| `parseAs` | `string` | Metoda parsowania odpowiedzi | `auto` | +| `responseStyle` | `string` | Styl zwracania: `data` lub `fields` | `fields` | +| `throwOnError` | `boolean` | Rzucaj błędy zamiast zwracać je | `false` | + +--- + +## Typy + +Zestaw SDK zawiera definicje TypeScript dla wszystkich typów API. Zaimportuj je bezpośrednio: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +Wszystkie typy są generowane na podstawie specyfikacji OpenAPI serwera i dostępne w pliku typów. + +--- + +## Błędy + +SDK może generować błędy, które można przechwycić i obsłużyć: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## API + +Zestaw SDK udostępnia wszystkie interfejsy API serwera za pośrednictwem klienta bezpiecznego typu. + +--- + +### Globalne + +| Metoda | Opis | Odpowiedź | +| ----------------- | ----------------------------- | ------------------------------------ | +| `global.health()` | Sprawdź stan i wersję serwera | `{ healthy: true, version: string }` | + +--- + +#### Przykłady + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### Aplikacja + +| Metoda | Opis | Odpowiedź | +| -------------- | ----------------------------------- | ------------------------------------------- | +| `app.log()` | Zapisz wpis logu | `boolean` | +| `app.agents()` | Lista wszystkich dostępnych agentów | Agent[] | + +--- + +#### Przykłady + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### Projekt + +| Metoda | Opis | Odpowiedź | +| ------------------- | -------------------------- | --------------------------------------------- | +| `project.list()` | Lista wszystkich projektów | Project[] | +| `project.current()` | Pobierz bieżący projekt | Project | + +--- + +#### Przykłady + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### Ścieżka + +| Metoda | Opis | Odpowiedź | +| ------------ | ----------------------- | ---------------------------------------- | +| `path.get()` | Pobierz bieżącą ścieżkę | Path | + +--- + +#### Przykłady + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### Konfiguracja + +| Metoda | Opis | Odpowiedź | +| -------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | Pobierz informacje o konfiguracji | Config | +| `config.providers()` | Lista dostawców i modeli domyślnych | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### Przykłady + +```javascript +const config = await client.config.get() + +const { providers, default: defaults } = await client.config.providers() +``` + +--- + +### Sesje + +| Metoda | Opis | Uwagi | +| ---------------------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| `session.list()` | Lista sesji | Zwraca Session[] | +| `session.get({ path })` | Pobierz sesję | Zwraca Session | +| `session.children({ path })` | Lista sesji podrzędnych | Zwraca Session[] | +| `session.create({ body })` | Utwórz sesję | Zwraca Session | +| `session.delete({ path })` | Usuń sesję | Zwraca `boolean` | +| `session.update({ path, body })` | Aktualizuj właściwości sesji | Zwraca Session | +| `session.init({ path, body })` | Przeanalizuj aplikację i utwórz `AGENTS.md` | Zwraca `boolean` | +| `session.abort({ path })` | Przerwij trwającą sesję | Zwraca `boolean` | +| `session.share({ path })` | Udostępnij sesję | Zwraca Session | +| `session.unshare({ path })` | Cofnij udostępnianie sesji | Zwraca Session | +| `session.summarize({ path, body })` | Podsumuj sesję | Zwraca `boolean` | +| `session.messages({ path })` | Lista wiadomości w sesji | Zwraca `{ info: `Message`, parts: `Part[]`}[]` | +| `session.message({ path })` | Pobierz szczegóły wiadomości | Zwraca `{ info: `Message`, parts: `Part[]`}` | +| `session.prompt({ path, body })` | Wyślij wiadomość | `body.noReply: true` zwraca UserMessage (tylko kontekst). Domyślnie zwraca AssistantMessage z odpowiedzią AI | +| `session.command({ path, body })` | Wyślij polecenie do sesji | Zwraca `{ info: `AssistantMessage`, parts: `Part[]`}` | +| `session.shell({ path, body })` | Uruchom polecenie shell | Zwraca AssistantMessage | +| `session.revert({ path, body })` | Cofnij wiadomość (revert) | Zwraca Session | +| `session.unrevert({ path })` | Przywróć cofnięte wiadomości | Zwraca Session | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | Odpowiedz na żądanie uprawnienia | Zwraca `boolean` | + +--- + +#### Przykłady + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### Pliki + +| Metoda | Opis | Odpowiedź | +| ------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------- | +| `find.text({ query })` | Szukaj tekstu w plikach | Tablica obiektów dopasowania z `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `find.files({ query })` | Znajdź pliki i katalogi według nazwy | `string[]` (ścieżki) | +| `find.symbols({ query })` | Znajdź symbole w obszarze roboczym | Symbol[] | +| `file.read({ query })` | Odczytaj plik | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | Pobierz status śledzonych plików | File[] | + +`find.files` obsługuje kilka opcjonalnych pól zapytania: + +- `type`: `"file"` lub `"directory"` +- `directory`: zastąp katalog główny projektu dla wyszukiwania +- `limit`: maks. wyników (1–200) + +--- + +#### Przykłady + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| Metoda | Opis | Odpowiedź | +| ------------------------------ | --------------------------- | --------- | +| `tui.appendPrompt({ body })` | Dołącz tekst do promptu | `boolean` | +| `tui.openHelp()` | Otwórz okno pomocy | `boolean` | +| `tui.openSessions()` | Otwórz selektor sesji | `boolean` | +| `tui.openThemes()` | Otwórz selektor motywów | `boolean` | +| `tui.openModels()` | Otwórz selektor modelu | `boolean` | +| `tui.submitPrompt()` | Prześlij bieżący prompt | `boolean` | +| `tui.clearPrompt()` | Wyczyść prompt | `boolean` | +| `tui.executeCommand({ body })` | Wykonaj polecenie | `boolean` | +| `tui.showToast({ body })` | Pokaż powiadomienie (toast) | `boolean` | + +--- + +#### Przykłady + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### Uwierzytelnianie + +| Metoda | Opis | Odpowiedź | +| ------------------- | ------------------------------------ | --------- | +| `auth.set({ ... })` | Ustaw poświadczenia uwierzytelniania | `boolean` | + +--- + +#### Przykłady + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### Zdarzenia + +| Metoda | Opis | Odpowiedź | +| ------------------- | ---------------------------------------- | ---------------------------------------- | +| `event.subscribe()` | Strumień zdarzeń wysyłanych przez serwer | Strumień zdarzeń wysyłanych przez serwer | + +--- + +#### Przykłady + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/pl/server.mdx b/packages/web/src/content/docs/pl/server.mdx new file mode 100644 index 00000000000..0efcf486f63 --- /dev/null +++ b/packages/web/src/content/docs/pl/server.mdx @@ -0,0 +1,287 @@ +--- +title: Serwer +description: Interakcja z serwerem opencode za pośrednictwem protokołu HTTP. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +Komenda `opencode serve` uruchamia bezgłowy serwer HTTP, który udostępnia punkt końcowy OpenAPI, z którego może korzystać klient opencode. + +--- + +### Użycie + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### Opcje + +| Flaga | Opis | Domyślne | +| --------------- | -------------------------------------------- | ---------------- | +| `--port` | Port nasłuchiwania | `4096` | +| `--hostname` | Nazwa hosta do nasłuchiwania | `127.0.0.1` | +| `--mdns` | Włącz wykrywanie mDNS | `false` | +| `--mdns-domain` | Niestandardowa nazwa domeny dla usługi mDNS | `opencode.local` | +| `--cors` | Dodatkowe originy przeglądarki do dozwolenia | `[]` | + +`--cors` można przekazać wiele razy: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### Uwierzytelnianie + +Ustaw `OPENCODE_SERVER_PASSWORD`, aby chronić serwer za pomocą podstawowego uwierzytelniania HTTP. Domyślną nazwą użytkownika jest `opencode` lub ustaw `OPENCODE_SERVER_USERNAME`, aby ją zastąpić. Dotyczy to zarówno `opencode serve`, jak i `opencode web`. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### Jak to działa + +Kiedy uruchomisz `opencode`, uruchomi się TUI i serwer. Gdzie jest TUI +klient komunikujący się z serwerem. Serwer udostępnia specyfikację OpenAPI 3.1 +punkt końcowy. Ten punkt końcowy jest również używany do generowania [SDK](/docs/sdk). + +:::tip +Użyj serwera opencode do programowej interakcji z opencode. +::: + +Ta architektura umożliwia obsługę wielu klientów przez opencode i programową interakcję z kodem otwartym. + +Możesz uruchomić `opencode serve`, aby uruchomić samodzielny serwer. Jeśli masz +opencode TUI działa, `opencode serve` uruchomi nowy serwer. + +--- + +#### Połączenie z istniejącym serwerem + +Po uruchomieniu TUI losowo przypisuje port i nazwę hosta. Zamiast tego możesz przekazać `--hostname` i `--port` [flagi](/docs/cli). Następnie użyj tego, aby połączyć się z serwerem. + +Punktu końcowego [`/tui`](#TUI) można użyć do sterowania TUI przez serwer. Można na przykład wstępnie wypełnić lub uruchomić monit. Ta konfiguracja jest używana przez wtyczki opencode [IDE](/docs/ide). + +--- + +## Specyfikacja + +Serwer publikuje specyfikację OpenAPI 3.1, którą można obejrzeć pod adresem: + +``` +http://:/doc +``` + +Na przykład `http://localhost:4096/doc`. Użyj specyfikacji, aby wygenerować klientów lub sprawdzić typy żądań i odpowiedzi. Możesz też wyświetlić go w eksploratorze Swagger. + +--- + +## API + +Serwer opencode udostępnia następujące interfejsy API. + +--- + +### Globalne + +| Method | Path | Description | Response | +| ------ | ---------------- | ------------------------------ | ------------------------------------ | +| `GET` | `/global/health` | Uzyskaj stan i wersję serwera | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | Get global events (SSE stream) | Event stream | + +--- + +### Projekt + +| Method | Path | Description | Response | +| ------ | ------------------ | -------------------------- | --------------------------------------------- | +| `GET` | `/project` | Lista wszystkich projektów | Project[] | +| `GET` | `/project/current` | Pobierz bieżący projekt | Project | + +--- + +### Ścieżka i VCS + +| Method | Path | Description | Response | +| ------ | ------- | --------------------------------------------- | ------------------------------------------- | +| `GET` | `/path` | Pobierz bieżącą ścieżkę | Path | +| `GET` | `/vcs` | Uzyskaj informacje VCS dla bieżącego projektu | VcsInfo | + +--- + +### Instancja + +| Method | Path | Description | Response | +| ------ | ------------------- | ---------------------- | --------- | +| `POST` | `/instance/dispose` | Usuń bieżącą instancję | `boolean` | + +--- + +### Konfiguracja + +| Method | Path | Description | Response | +| ------- | ------------------- | ----------------------------------- | ---------------------------------------------------------------------------------------- | +| `GET` | `/config` | Get config info | Config | +| `PATCH` | `/config` | Update config | Config | +| `GET` | `/config/providers` | Lista dostawców i modeli domyślnych | `{ providers: `Dostawca[]`, default: { [key: string]: string } }` | + +--- + +### Dostawca + +| Method | Path | Description | Response | +| ------ | -------------------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------- | +| `GET` | `/provider` | Lista wszystkich dostawców | `{ all: `Dostawca[]`, default: {...}, connected: string[] }` | +| `GET` | `/provider/auth` | Uzyskaj metody uwierzytelniania dostawcy | `{ [providerID: string]: `ProviderAuthMethod[]` }` | +| `POST` | `/provider/{id}/oauth/authorize` | Autoryzuj dostawcę za pomocą protokołu OAuth | ProviderAuthAuthorization | +| `POST` | `/provider/{id}/oauth/callback` | Obsługa wywołania zwrotnego OAuth dla dostawcy | `boolean` | + +--- + +### Sesje + +| Method | Path | Description | Notes | +| -------- | ---------------------------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------- | +| `GET` | `/session` | Lista wszystkich sesji | Zwraca Session[] | +| `POST` | `/session` | Utwórz nową sesję | treść: `{ parentID?, title? }`, zwraca Session | +| `GET` | `/session/status` | Uzyskaj status sesji dla wszystkich sesji | Zwraca `{ [sessionID: string]: `Status sesji` }` | +| `GET` | `/session/:id` | Uzyskaj szczegóły sesji | Zwraca Session | +| `DELETE` | `/session/:id` | Usuń sesję i wszystkie jej dane | Zwraca `boolean` | +| `PATCH` | `/session/:id` | Aktualizuj właściwości sesji | treść: `{ title? }`, zwraca Session | +| `GET` | `/session/:id/children` | Pobierz sesje podrzędne sesji | Zwraca Session[] | +| `GET` | `/session/:id/todo` | Pobierz listę rzeczy do zrobienia dla sesji | Zwraca Todo[] | +| `POST` | `/session/:id/init` | Przeanalizuj aplikację i utwórz `AGENTS.md` | treść: `{ messageID, providerID, modelID }`, zwraca `boolean` | +| `POST` | `/session/:id/fork` | Rozwiń istniejącą sesję w wiadomości | treść: `{ messageID? }`, zwraca Session | +| `POST` | `/session/:id/abort` | Przerwij trwającą sesję | Zwraca `boolean` | +| `POST` | `/session/:id/share` | Udostępnij sesję | Zwraca Session | +| `DELETE` | `/session/:id/share` | Anuluj udostępnianie sesji | Zwraca Session | +| `GET` | `/session/:id/diff` | Pobierz różnicę dla tej sesji | zapytanie: `messageID?`, zwraca FileDiff[] | +| `POST` | `/session/:id/summarize` | Podsumuj sesję | treść: `{ providerID, modelID }`, zwraca `boolean` | +| `POST` | `/session/:id/revert` | Przywróć wiadomość | treść: `{ messageID, partID? }`, zwraca `boolean` | +| `POST` | `/session/:id/unrevert` | Przywróć wszystkie przywrócone wiadomości | Zwraca `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | Odpowiedz na prośbę o pozwolenie | treść: `{ response, remember? }`, zwraca `boolean` | + +--- + +### Wiadomości + +| Method | Path | Description | Notes | +| ------ | --------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `GET` | `/session/:id/message` | Lista wiadomości w sesji | zapytanie: `limit?`, zwraca `{ info: `Wiadomość`, parts: `Część[]`}[]` | +| `POST` | `/session/:id/message` | Wyślij wiadomość i poczekaj na odpowiedź | treść: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, zwraca `{ info: `Wiadomość`, parts: `Część[]`}` | +| `GET` | `/session/:id/message/:messageID` | Uzyskaj szczegóły wiadomości | Zwraca `{ info: `Wiadomość`, parts: `Część[]`}` | +| `POST` | `/session/:id/prompt_async` | Wyślij wiadomość asynchronicznie (bez czekania) | treść: taka sama jak `/session/:id/message`, zwraca `204 No Content` | +| `POST` | `/session/:id/command` | Wykonaj slash command | treść: `{ messageID?, agent?, model?, command, arguments }`, zwraca `{ info: `Wiadomość`, parts: `Część[]`}` | +| `POST` | `/session/:id/shell` | Uruchom polecenie shell | treść: `{ agent, model?, command }`, zwraca `{ info: `Wiadomość`, parts: `Część[]`}` | + +--- + +### Polecenia + +| Metoda | Ścieżka | Opis | Odpowiedź | +| ------ | ---------- | ------------------------ | --------------------------------------------- | +| `GET` | `/command` | Lista wszystkich poleceń | Command[] | + +--- + +### Pliki + +| Method | Path | Description | Response | +| ------ | ------------------------ | ------------------------------------ | ---------------------------------------------------------------------------------------------- | +| `GET` | `/find?pattern=` | Szukaj tekstu w plikach | Tablica obiektów dopasowania z `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `GET` | `/find/file?query=` | Znajdź pliki i katalogi według nazwy | `string[]` (ścieżki) | +| `GET` | `/find/symbol?query=` | Find workspace symbols | Symbol[] | +| `GET` | `/file?path=` | Lista plików i katalogów | FileNode[] | +| `GET` | `/file/content?path=

` | Read a file | FileContent | +| `GET` | `/file/status` | Uzyskaj status śledzonych plików | File[] | + +#### `/find/file` query parameters + +- `query` (required) — search string (fuzzy match) +- `type` (optional) — limit results to `"file"` or `"directory"` +- `directory` (opcjonalnie) — zastąp katalog główny projektu dla wyszukiwania +- `limit` (optional) — max results (1–200) +- `dirs` (optional) — legacy flag (`"false"` returns only files) + +--- + +### Narzędzia (Eksperymentalne) + +| Method | Path | Description | Response | +| ------ | ------------------------------------------- | -------------------------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | Lista wszystkich identyfikatorów narzędzi | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | Lista narzędzi ze schematami JSON dla modelu | ToolList | + +--- + +### LSP, Formatery i MCP + +| Method | Path | Description | Response | +| ------ | ------------ | ---------------------------- | -------------------------------------------------------- | +| `GET` | `/lsp` | Uzyskaj status serwera LSP | LSPStatus[] | +| `GET` | `/formatter` | Get formatter status | FormatterStatus[] | +| `GET` | `/mcp` | Uzyskaj status serwera MCP | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | Dodaj dynamicznie serwer MCP | treść: `{ name, config }`, zwraca obiekt stanu MCP | + +--- + +### Agenci + +| Method | Path | Description | Response | +| ------ | -------- | ----------------------------------- | ------------------------------------------- | +| `GET` | `/agent` | Lista wszystkich dostępnych agentów | Agent[] | + +--- + +### Logowanie + +| Method | Path | Description | Response | +| ------ | ------ | ------------------------------------------------------------ | --------- | +| `POST` | `/log` | Write log entry. Body: `{ service, level, message, extra? }` | `boolean` | + +--- + +### TUI + +| Method | Path | Description | Response | +| ------ | ----------------------- | -------------------------------------------- | ----------------------- | +| `POST` | `/tui/append-prompt` | Dołącz tekst do promptu | `boolean` | +| `POST` | `/tui/open-help` | Otwórz okno pomocy | `boolean` | +| `POST` | `/tui/open-sessions` | Otwórz selektor sesji | `boolean` | +| `POST` | `/tui/open-themes` | Otwórz selektor motywów | `boolean` | +| `POST` | `/tui/open-models` | Otwórz selektor modelu | `boolean` | +| `POST` | `/tui/submit-prompt` | Prześlij bieżący prompt | `boolean` | +| `POST` | `/tui/clear-prompt` | Wyczyść prompt | `boolean` | +| `POST` | `/tui/execute-command` | Wykonaj polecenie (`{ command }`) | `boolean` | +| `POST` | `/tui/show-toast` | Pokaż toast (`{ title?, message, variant }`) | `boolean` | +| `GET` | `/tui/control/next` | Poczekaj na następne żądanie kontroli | Obiekt żądania kontroli | +| `POST` | `/tui/control/response` | Respond to a control request (`{ body }`) | `boolean` | + +--- + +### Uwierzytelnianie + +| Method | Path | Description | Response | +| ------ | ----------- | --------------------------------------------------------------------- | --------- | +| `PUT` | `/auth/:id` | Ustaw dane uwierzytelniające. Treść musi pasować do schematu dostawcy | `boolean` | + +--- + +### Zdarzenia + +| Method | Path | Description | Response | +| ------ | -------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------- | +| `GET` | `/event` | Strumień zdarzeń wysyłanych przez serwer. Pierwsze wydarzenie to `server.connected`, następnie wydarzenia autobusowe | Strumień zdarzeń wysłanych przez serwer | + +--- + +### Dokumentacja + +| Method | Path | Description | Response | +| ------ | ------ | ------------------------ | ----------------------------------- | +| `GET` | `/doc` | Specyfikacja OpenAPI 3.1 | Strona HTML ze specyfikacją OpenAPI | diff --git a/packages/web/src/content/docs/pl/share.mdx b/packages/web/src/content/docs/pl/share.mdx new file mode 100644 index 00000000000..463019295a3 --- /dev/null +++ b/packages/web/src/content/docs/pl/share.mdx @@ -0,0 +1,128 @@ +--- +title: Udostępnianie +description: Udostępnij swoje rozmowy dotyczące opencode. +--- + +Funkcja udostępniania opencode umożliwia tworzenie publicznych linków do konwersacji opencode, dzięki czemu możesz współpracować z członkami zespołu lub uzyskać pomoc od innych. + +:::note +Udostępnione konwersacje są publicznie dostępne dla każdej osoby mającej link. +::: + +--- + +## Jak to działa + +Kiedy udostępniasz rozmowę, opencode: + +1. Tworzy unikalny publiczny adres URL sesji +2. Synchronizuje historię rozmów z naszymi serwerami +3. Udostępnia rozmowę za pośrednictwem łącza do udostępniania — `opncd.ai/s/` + +--- + +## Udostępnianie + +opencode obsługuje trzy tryby udostępniania, które kontrolują sposób udostępniania rozmów: + +--- + +### Ręczne (domyślne) + +Domyślnie opencode korzysta z ręcznego trybu udostępniania. Sesje nie są udostępniane automatycznie, ale możesz je udostępnić ręcznie za pomocą polecenia `/share`: + +``` +/share +``` + +Spowoduje to wygenerowanie unikalnego adresu URL, który zostanie skopiowany do schowka. + +Aby jawnie ustawić tryb ręczny w [pliku konfiguracyjnym] (./config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### Automatyczne udostępnianie + +Możesz włączyć automatyczne udostępnianie dla wszystkich nowych rozmów, ustawiając opcję `share` na `"auto"` w [pliku konfiguracyjnym] (./config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +Po włączeniu automatycznego udostępniania każda nowa rozmowa będzie automatycznie udostępniana i generowany będzie link. + +--- + +### Wyłączone + +Możesz całkowicie wyłączyć udostępnianie, ustawiając opcję `share` na `"disabled"` w [pliku konfiguracyjnym] (./config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +Aby wymusić to w całym zespole dla danego projektu, dodaj go do `opencode.json` w swoim projekcie i sprawdź w Git. + +--- + +## Cofnięcie udostępnienia + +Aby zatrzymać udostępnianie rozmowy i usunąć ją z dostępu publicznego: + +``` +/unshare +``` + +Spowoduje to usunięcie łącza udostępniania i danych związanych z rozmową. + +--- + +## Prywatność + +Podczas udostępniania rozmowy należy pamiętać o kilku rzeczach. + +--- + +### Przechowywanie danych + +Udostępnione rozmowy pozostają dostępne, dopóki wyraźnie ich nie udostępnisz. Ten +includes: + +- Pełna historia rozmów +- Wszystkie wiadomości i odpowiedzi +- Metadane sesji + +--- + +### Zalecenia + +- Udostępniaj tylko rozmowy, które nie zawierają poufnych informacji. +- Przejrzyj treść rozmowy przed udostępnieniem. +- Cofnij udostępnianie rozmów po zakończeniu współpracy. +- Unikaj udostępniania rozmów zawierających zastrzeżony kod lub poufne dane. +- W przypadku wrażliwych projektów całkowicie wyłącz udostępnianie. + +--- + +## Dla przedsiębiorstw + +W przypadku wdrożeń korporacyjnych funkcją udostępniania może być: + +- **Wyłączone** całkowicie ze względu na bezpieczeństwo +- **Restricted** to users authenticated through SSO only +- **Własny hosting** na własnej infrastrukturze + +[Dowiedz się więcej](/docs/enterprise) o używaniu opencode w Twojej organizacji. diff --git a/packages/web/src/content/docs/pl/skills.mdx b/packages/web/src/content/docs/pl/skills.mdx new file mode 100644 index 00000000000..9262d87e661 --- /dev/null +++ b/packages/web/src/content/docs/pl/skills.mdx @@ -0,0 +1,222 @@ +--- +title: "Umiejętności Agenta" +description: "Definiuj powtarzalne zachowania za pomocą definicji SKILL.md" +--- + +Umiejętności agenta pozwalają opencode odkryć instrukcje wielokrotnego użytku z repozytorium lub katalogu domowego. +Umiejętności są ładowane na żądanie za pośrednictwem natywnego narzędzia `skill` — agenci widzą dostępne umiejętności i w razie potrzeby mogą załadować pełną zawartość. + +--- + +## Lokalizacja plików + +Utwórz jeden folder na nazwę umiejętności i umieść w nim `SKILL.md`. +opencode przeszukuje te lokalizacje: + +- Project config: `.opencode/skills//SKILL.md` +- Global config: `~/.config/opencode/skills//SKILL.md` +- Project Claude-compatible: `.claude/skills//SKILL.md` +- Global Claude-compatible: `~/.claude/skills//SKILL.md` +- Project agent-compatible: `.agents/skills//SKILL.md` +- Global agent-compatible: `~/.agents/skills//SKILL.md` + +--- + +## Zrozumienie wykrywania + +W przypadku ścieżek lokalnych projektu opencode przechodzi od bieżącego katalogu roboczego, aż dotrze do drzewa roboczego git. +Ładuje po drodze dowolne pasujące `skills/*/SKILL.md` w `.opencode/` i dowolne pasujące `.claude/skills/*/SKILL.md` lub `.agents/skills/*/SKILL.md`. + +Ładowane są także definicje globalne z `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md` i `~/.agents/skills/*/SKILL.md`. + +--- + +## Tworzenie frontmatter + +Każdy `SKILL.md` musi zaczynać się od treści YAML. +Rozpoznawane są tylko te pola: + +- `name` (wymagane) +- `description` (wymagane) +- `license` (opcjonalnie) +- `compatibility` (opcjonalnie) +- `metadata` (opcjonalnie, mapa string-to-string) + +Nieznane pola frontmatter są ignorowane. + +--- + +## Walidacja nazw + +`name` musi: + +- Mieć od 1 do 64 znaków +- Należy używać małych liter alfanumerycznych i oddzielać je pojedynczym łącznikiem +- Nie zaczyna się ani nie kończy na `-` +- Nie może zawierać następujących po sobie `--` +- Dopasuj nazwę katalogu zawierającą `SKILL.md` + +Odpowiednik wyrażenia regularnego: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## Zasady dotyczące długości + +`description` musi mieć od 1 do 1024 znaków. +Zadbaj o to, aby agent mógł dokonać prawidłowego wyboru. + +--- + +## Przykład użycia + +Utwórz `.opencode/skills/git-release/SKILL.md` w ten sposób: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## Opis narzędzia + +opencode wymienia dostępne umiejętności w opisie narzędzia `skill`. +Każdy wpis zawiera nazwę i opis umiejętności: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +Agent ładuje umiejętność wywołując narzędzie: + +``` +skill({ name: "git-release" }) +``` + +--- + +## Konfiguracja uprawnień + +Kontroluj, do których umiejętności agenci mogą uzyskać dostęp, używając uprawnień opartych na wzorcach w `opencode.json`: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| Permission | Behavior | +| ---------- | ------------------------------------------------------ | +| `allow` | Skill loads immediately | +| `deny` | Skill hidden from agent, access rejected | +| `ask` | Użytkownik proszony o zatwierdzenie przed załadowaniem | + +Wzorce obsługują symbole wieloznaczne: `internal-*` odpowiada `internal-docs`, `internal-tools` itd. + +--- + +## Nadpisywanie dla agenta + +Nadaj konkretnym agentom inne uprawnienia niż globalne ustawienia domyślne. + +**Dla agentów niestandardowych** (w temacie agentów): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**Dla agentów wbudowanych** (w `opencode.json`): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## Wyłączanie narzędzia umiejętności + +Całkowicie wyłącz umiejętności agentów, którzy nie powinni ich używać: + +**Dla agentów niestandardowych** (w temacie agentów): + +```yaml +--- +tools: + skill: false +--- +``` + +**W przypadku agentów wbudowanych**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +Jeśli opcja jest wyłączona, sekcja `` jest całkowicie pomijana. + +--- + +## Rozwiązywanie problemów z ładowaniem + +Jeśli umiejętność nie pojawi się: + +1. Sprawdź, czy `SKILL.md` jest napisane wielkimi literami +2. Sprawdź, czy frontmatter zawiera `name` i `description` +3. Upewnij się, że nazwy umiejętności są unikalne we wszystkich lokalizacjach +4. Sprawdź uprawnienia — umiejętności z `deny` są ukryte przed agentami diff --git a/packages/web/src/content/docs/pl/themes.mdx b/packages/web/src/content/docs/pl/themes.mdx new file mode 100644 index 00000000000..d4272e2c9be --- /dev/null +++ b/packages/web/src/content/docs/pl/themes.mdx @@ -0,0 +1,369 @@ +--- +title: Themes +description: Wybierz wbudowany motyw lub zdefiniuj własny. +--- + +Dzięki opencode możesz wybrać jeden z kilku wbudowanych motywów, użyć motywu, który dostosowuje się do motywu terminala lub zdefiniować własny, niestandardowy motyw. + +Domyślnie opencode używa naszego własnego motywu `opencode`. + +--- + +## Wymagania terminala + +Aby motywy wyświetlały się poprawnie z pełną paletą kolorów, Twój terminal musi obsługiwać **truecolor** (kolor 24-bitowy). Większość nowoczesnych terminali domyślnie obsługuje tę opcję, ale może być konieczne jej włączenie: + +- **Sprawdź wsparcie**: Uruchom `echo $COLORTERM` - powinno wypisać `truecolor` lub `24bit` +- **Włącz truecolor**: Ustaw zmienną środowiskową `COLORTERM=truecolor` w swoim profilu shell +- **Zgodność terminala**: Upewnij się, że emulator terminala obsługuje 24-bitowy kolor (większość nowoczesnych terminali, takich jak iTerm2, Alacritty, Kitty, Windows Terminal i najnowsze wersje terminala GNOME tak) + +Bez obsługi Truecolor motywy mogą pojawiać się ze zmniejszoną dokładnością kolorów lub wracać do najbliższego przybliżenia 256 kolorów. + +--- + +## Wbudowane motywy + +opencode ma kilka wbudowanych motywów. + +| Name | Description | +| ---------------------- | --------------------------------------------------------------------------------- | +| `system` | Dopasowuje się do koloru tła terminala | +| `tokyonight` | Na podstawie motywu [tokyonight](https://github.com/folke/tokyonight.nvim) | +| `everforest` | Na podstawie motywu [Everforest](https://github.com/sainnhe/everforest) | +| `ayu` | Na podstawie ciemnego motywu [Ayu](https://github.com/ayu-theme) | +| `catppuccin` | Na podstawie motywu [Catppuccin](https://github.com/catppuccin) | +| `catppuccin-macchiato` | Na podstawie motywu [Catppuccin](https://github.com/catppuccin) | +| `gruvbox` | Na podstawie motywu [Gruvbox](https://github.com/morhetz/gruvbox) | +| `kanagawa` | Na podstawie motywu [Kanagawa](https://github.com/rebelot/kanagawa.nvim) | +| `nord` | Na podstawie motywu [Nord](https://github.com/nordtheme/nord) | +| `matrix` | Hacker-style green on black theme | +| `one-dark` | Na podstawie ciemnego motywu [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) | + +Co więcej, stale dodajemy nowe motywy. + +--- + +## Motyw systemowy + +Motyw `system` został zaprojektowany tak, aby automatycznie dostosowywał się do schematu kolorów terminala. W przeciwieństwie do tradycyjnych motywów, które używają stałych kolorów, motyw _system_: + +- **Generuje skalę szarości**: Tworzy niestandardową skalę szarości w oparciu o kolor tła terminala, zapewniając optymalny kontrast. +- **Używa kolorów ANSI**: Wykorzystuje standardowe kolory ANSI (0-15) do podświetlania składni i elementów interfejsu użytkownika, które odpowiadają palecie kolorów terminala. +- **Zachowuje ustawienia domyślne terminala**: Używa `none` dla kolorów tekstu i tła, aby zachować natywny wygląd terminala. + +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 + +--- + +## 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). + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## Motywy niestandardowe + +opencode obsługuje elastyczny system motywów oparty na JSON, który pozwala użytkownikom łatwo tworzyć i dostosowywać motywy. + +--- + +### Hierarchia + +Motywy są ładowane z wielu katalogów w następującej kolejności, przy czym późniejsze katalogi zastępują wcześniejsze: + +1. **Wbudowane motywy** – są osadzone w formacie binarnym +2. **Katalog konfiguracji użytkownika** - Zdefiniowany w `~/.config/opencode/themes/*.json` lub `$XDG_CONFIG_HOME/opencode/themes/*.json` +3. **Katalog główny projektu** - Zdefiniowany w `/.opencode/themes/*.json` +4. **Bieżący katalog roboczy** - Zdefiniowany w `./.opencode/themes/*.json` + +Jeśli wiele katalogów zawiera motyw o tej samej nazwie, zostanie użyty motyw z katalogu o wyższym priorytecie. + +--- + +### Tworzenie motywu + +Aby utworzyć niestandardowy motyw, utwórz plik JSON w jednym z katalogów motywów. + +W przypadku motywów dla całego użytkownika: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +Oraz dla tematów specyficznych dla projektu. + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### Format JSON + +Motywy korzystają z elastycznego formatu JSON z obsługą: + +- **Kolorów Hex**: `"#ffffff"` +- **Kolorów ANSI**: `3` (0-255) +- **Referencji kolorów**: `"primary"` lub definicje niestandardowe +- **Wariantów Ciemny/Jasny**: `{"dark": "#000", "light": "#fff"}` +- **Braku koloru**: `"none"` - Używa domyślnego koloru terminala lub przezroczystości + +--- + +### Definicje kolorów + +Sekcja `defs` jest opcjonalna i pozwala zdefiniować kolory wielokrotnego użytku, do których można się odwoływać w motywie. + +--- + +### Domyślne ustawienia terminala + +Wartość specjalna `"none"` może zostać użyta dla dowolnego koloru, aby przejąć domyślny kolor terminala. Jest to szczególnie przydatne do tworzenia motywów, które płynnie komponują się ze schematem kolorów terminala: + +- `"text": "none"` - Używa domyślnego koloru pierwszego planu terminala +- `"background": "none"` - Używa domyślnego koloru tła terminala + +--- + +### Przykład + +Oto przykład niestandardowego motywu: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/pl/tools.mdx b/packages/web/src/content/docs/pl/tools.mdx new file mode 100644 index 00000000000..3e5fd1540d0 --- /dev/null +++ b/packages/web/src/content/docs/pl/tools.mdx @@ -0,0 +1,379 @@ +--- +title: Narzędzia +description: Zarządzaj narzędziami, z których może korzystać LLM. +--- + +Narzędzia umożliwiają LLM wykonywanie działań w bazie kodu. OpenCode posiada zestaw wbudowanych narzędzi, ale możesz go rozszerzyć o [narzędzia niestandardowe](/docs/custom-tools) lub [serwery MCP](/docs/mcp-servers). + +Domyślnie wszystkie narzędzia są **włączone** i nie wymagają zatwierdzenia przed uruchomieniem. Możesz kontrolować zachowanie narzędzi poprzez [uprawnienia](/docs/permissions). + +--- + +## Konfiguracja + +Użyj pola `permission` do kontrolowania zachowania narzędzia. Dla każdego narzędzia możesz zezwolić (`allow`), odmówić (`deny`) lub wymagać zatwierdzenia (`ask`). + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +Możesz także używać symboli wieloznacznych do kontrolowania wielu narzędzi jednocześnie. Na przykład, aby wymagać zatwierdzenia dla wszystkich narzędzi z serwera MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[Dowiedz się więcej](/docs/permissions) o konfigurowaniu uprawnień. + +--- + +## Wbudowane narzędzia + +Oto wszystkie wbudowane narzędzia dostępne w OpenCode. + +--- + +### bash + +Wykonuj polecenia powłoki (shell) w środowisku projektu. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +To narzędzie umożliwia LLM uruchamianie poleceń terminalowych, takich jak `npm install`, `git status` lub dowolne inne polecenie powłoki. + +--- + +### edit + +Modyfikuj istniejące pliki poprzez precyzyjne zastępowanie tekstu. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +To narzędzie umożliwia precyzyjną edycję plików poprzez zastąpienie dokładnych dopasowań tekstu. Jest to główny sposób, w jaki LLM modyfikuje kod. + +--- + +### write + +Twórz nowe pliki lub nadpisuj istniejące. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Użyj tego, aby umożliwić LLM tworzenie nowych plików. Zastąpi istniejące pliki, jeśli już istnieją. + +:::note +Narzędzie `write` jest kontrolowane przez uprawnienie `edit`, które obejmuje wszystkie modyfikacje plików (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### read + +Odczytaj zawartość pliku z bazy kodu. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +Narzędzie to odczytuje pliki i zwraca ich zawartość. Obsługuje czytanie określonych zakresów linii w przypadku dużych plików. + +--- + +### grep + +Przeszukuj zawartość plików za pomocą wyrażeń regularnych. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +Szybkie wyszukiwanie treści w całej bazie kodu. Obsługuje pełną składnię wyrażeń regularnych i filtrowanie wzorców plików. + +--- + +### glob + +Znajduj pliki na podstawie wzorców. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +Szukaj plików przy użyciu wzorców glob, takich jak `**/*.js` lub `src/**/*.ts`. Zwraca pasujące ścieżki plików posortowane według czasu modyfikacji. + +--- + +### list + +Wyświetla listę plików i katalogów w podanej ścieżce. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +To narzędzie wyświetla zawartość katalogu. Akceptuje wzorce glob do filtrowania wyników. + +--- + +### LSP (eksperymentalne) + +Interakcja ze skonfigurowanymi serwerami LSP w celu uzyskania funkcji analizy kodu, takich jak definicje, referencje, podpowiedzi (hover) i hierarchia wywołań. + +:::note +To narzędzie jest dostępne tylko wtedy, gdy `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (lub `OPENCODE_EXPERIMENTAL=true`). +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +Obsługiwane operacje obejmują `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls` i `outgoingCalls`. + +Aby skonfigurować, które serwery LSP są dostępne dla Twojego projektu, zobacz [Serwery LSP](/docs/lsp). + +--- + +### patch + +Stosuj łatki (patches) do plików. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +To narzędzie stosuje pliki różnicowe (diffs) do bazy kodu. Przydatne do stosowania zmian z różnych źródeł. + +:::note +Narzędzie `patch` jest kontrolowane przez uprawnienie `edit`, które obejmuje wszystkie modyfikacje plików (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### skill + +Załaduj [umiejętność](/docs/skills) (plik `SKILL.md`) i zwróć jej treść w rozmowie. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +Zarządzaj listami zadań (todo) podczas sesji kodowania. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +Tworzy i aktualizuje listy zadań w celu śledzenia postępu podczas złożonych operacji. LLM wykorzystuje to do organizowania zadań wieloetapowych. + +:::note +To narzędzie jest domyślnie wyłączone dla subagentów, ale można je włączyć ręcznie. [Dowiedz się więcej](/docs/agents/#permissions) +::: + +--- + +### todoread + +Odczytuj istniejące listy zadań (todo). + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +Odczytuje bieżący stan listy rzeczy do zrobienia. Używany przez LLM do śledzenia zadań oczekujących lub ukończonych. + +:::note +To narzędzie jest domyślnie wyłączone dla subagentów, ale można je włączyć ręcznie. [Dowiedz się więcej](/docs/agents/#permissions) +::: + +--- + +### webfetch + +Pobieraj treści z sieci. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +Umożliwia LLM pobieranie i odczytywanie stron internetowych. Przydatne do wyszukiwania dokumentacji lub zasobów online. + +--- + +### websearch + +Wyszukaj informacje w Internecie. + +:::note +To narzędzie jest dostępne tylko w przypadku korzystania z dostawcy OpenCode lub gdy zmienna środowiskowa `OPENCODE_ENABLE_EXA` jest ustawiona na dowolną wartość prawdziwą (np. `true` lub `1`). + +Aby włączyć przy uruchamianiu OpenCode: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +Przeszukuje Internet za pomocą Exa AI, aby znaleźć odpowiednie informacje. Przydatne do badania tematów, znajdowania bieżących wydarzeń lub zbierania informacji wykraczających poza zbiór danych treningowych. + +Nie jest wymagany żaden klucz API — narzędzie łączy się bezpośrednio z usługą MCP hostowaną przez Exa AI bez uwierzytelniania. + +:::tip +Użyj `websearch`, gdy chcesz znaleźć informacje (odkrywanie), i `webfetch`, gdy musisz pobrać treść z określonego adresu URL (pobieranie). +::: + +--- + +### question + +Zadawaj pytania użytkownikowi podczas wykonywania. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +To narzędzie umożliwia LLM zadawanie pytań użytkownikowi podczas wykonywania zadania. Jest to przydatne do: + +- Zbierania preferencji i wymagań użytkownika +- Doprecyzowania niejednoznacznych instrukcji +- Podejmowania decyzji dotyczących implementacji +- Proponowania możliwych kierunków działania + +Każde pytanie zawiera nagłówek, tekst pytania i listę opcji. Użytkownicy mogą wybierać spośród dostępnych opcji lub wpisać niestandardową odpowiedź. Jeśli pytań jest wiele, użytkownicy mogą nawigować między nimi przed przesłaniem wszystkich odpowiedzi. + +--- + +## Narzędzia niestandardowe + +Niestandardowe narzędzia pozwalają zdefiniować własne funkcje, które LLM może wywołać. Są one zdefiniowane w pliku konfiguracyjnym i mogą wykonywać dowolny kod. + +[Więcej informacji](/docs/custom-tools) o tworzeniu narzędzi niestandardowych. + +--- + +## Serwery MCP + +Serwery MCP (Model Context Protocol) umożliwiają integrację zewnętrznych narzędzi i usług. Obejmuje to dostęp do baz danych, integracje API i usługi stron trzecich. + +[Dowiedz się więcej](/docs/mcp-servers) o konfigurowaniu serwerów MCP. + +--- + +## Szczegóły techniczne + +Wewnętrznie narzędzia takie jak `grep`, `glob` i `list` używają [ripgrep](https://github.com/BurntSushi/ripgrep). Domyślnie ripgrep respektuje wzorce `.gitignore`, co oznacza, że pliki i katalogi wymienione w Twoim `.gitignore` zostaną wykluczone z wyszukiwań i list. + +--- + +### Ignorowanie plików + +Aby uwzględnić pliki, które normalnie byłyby ignorowane, utwórz plik `.ignore` w katalogu głównym projektu. Ten plik może jawnie zezwalać na określone ścieżki. + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +Na przykład ten plik `.ignore` pozwala ripgrepowi przeszukiwać katalogi `node_modules/`, `dist/` i `build/`, nawet jeśli są one wymienione w `.gitignore`. diff --git a/packages/web/src/content/docs/pl/troubleshooting.mdx b/packages/web/src/content/docs/pl/troubleshooting.mdx new file mode 100644 index 00000000000..2230cea35ce --- /dev/null +++ b/packages/web/src/content/docs/pl/troubleshooting.mdx @@ -0,0 +1,300 @@ +--- +title: Rozwiązywanie problemów +description: Typowe problemy i sposoby ich rozwiązywania. +--- + +Aby debugować problemy z opencode, zacznij od sprawdzenia dzienników i danych lokalnych przechowywanych na dysku. + +--- + +## Dzienniki + +Pliki logów są zapisywane w: + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: Naciśnij `WIN+R` i wklej `%USERPROFILE%\.local\share\opencode\log` + +Nazwy plików dziennika zawierają znaczniki czasu (np. `2025-01-09T123456.log`) i przechowywanych jest 10 ostatnich plików dziennika. + +Możesz ustawić poziom dziennika za pomocą opcji wiersza poleceń `--log-level`, aby uzyskać bardziej szczegółowe informacje debugowania. Na przykład `opencode --log-level DEBUG`. + +--- + +## Przechowywanie danych + +opencode przechowuje dane sesji i inne dane aplikacji na dysku pod adresem: + +- **macOS/Linux**: `~/.local/share/opencode/` +- **Windows**: Naciśnij `WIN+R` i wklej `%USERPROFILE%\.local\share\opencode` + +Ten katalog zawiera: + +- `auth.json` - Authentication data like API keys, OAuth tokens +- `log/` - Application logs +- `project/` — Dane specyficzne dla projektu, takie jak dane sesji i komunikatów + - Jeśli projekt znajduje się w repozytorium Git, jest on przechowywany w `.//storage/` + - If it is not a Git repo, it is stored in `./global/storage/` + +--- + +## Aplikacja desktopowa + +opencode Desktop uruchamia w tle lokalny serwer opencode (sidecar `opencode-cli`). Większość problemów jest spowodowana nieprawidłowo działającą wtyczką, uszkodzoną pamięcią podręczną lub złymi ustawieniami serwera. + +### Szybkie sprawdzenie + +- Całkowicie zakończ i uruchom ponownie aplikację. +- Jeśli aplikacja wyświetli ekran błędu, kliknij **Uruchom ponownie** i skopiuj szczegóły błędu. +- Tylko macOS: menu `OpenCode` -> **Załaduj ponownie przeglądarkę internetową** (pomaga, jeśli interfejs użytkownika jest pusty/zawieszony). + +--- + +### Wyłączanie wtyczek + +Jeśli aplikacja komputerowa ulega awarii podczas uruchamiania, zawiesza się lub zachowuje się dziwnie, zacznij od wyłączenia wtyczek. + +#### Sprawdź konfigurację globalną + +Otwórz globalny plik konfiguracyjny i poszukaj klucza `plugin`. + +- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (lub `~/.config/opencode/opencode.json`) +- **macOS/Linux** (starsze instalacje): `~/.local/share/opencode/opencode.jsonc` +- **Windows**: Naciśnij `WIN+R` i wklej `%USERPROFILE%\.config\opencode\opencode.jsonc` + +Jeśli masz skonfigurowane wtyczki, tymczasowo je wyłącz, usuwając klucz lub ustawiając go na pustą tablicę: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### Sprawdź katalogi wtyczek + +opencode może także ładować lokalne wtyczki z dysku. Tymczasowo usuń je (lub zmień nazwę folderu) i uruchom ponownie aplikację komputerową: + +- **Wtyczki globalne** + - **macOS/Linux**: `~/.config/opencode/plugins/` + - **Windows**: Naciśnij `WIN+R` i wklej `%USERPROFILE%\.config\opencode\plugins` +- **Wtyczki projektowe** (tylko jeśli używasz konfiguracji dla poszczególnych projektów) + - `/.opencode/plugins/` + +Jeśli aplikacja ponownie zacznie działać, włączaj ponownie wtyczki pojedynczo, aby dowiedzieć się, która powoduje problem. + +--- + +### Wyczyść pamięć podręczną + +Jeśli wyłączenie wtyczek nie pomoże (lub instalacja wtyczki utknęła), wyczyść pamięć podręczną, aby opencode mógł ją odbudować. + +1. Całkowicie zamknij opencode Desktop. +2. Usuń katalog pamięci podręcznej: + +- **macOS**: Finder -> `Cmd+Shift+G` -> paste `~/.cache/opencode` +- **Linux**: usuń `~/.cache/opencode` (lub uruchom `rm -rf ~/.cache/opencode`) +- **Windows**: Naciśnij `WIN+R` i wklej `%USERPROFILE%\.cache\opencode` + +3. Uruchom ponownie opencode Desktop. + +--- + +### Napraw problemy z połączeniem z serwerem + +opencode Desktop może uruchomić własny serwer lokalny (domyślnie) lub połączyć się ze skonfigurowanym adresem URL serwera. + +Jeśli zobaczysz okno dialogowe **„Połączenie nie powiodło się”** (lub aplikacja nigdy nie wychodzi poza ekran powitalny), sprawdź, czy jest niestandardowy adres URL serwera. + +#### Wyczyść domyślny adres URL serwera na komputerze + +Na ekranie głównym kliknij nazwę serwera (z kropką stanu), aby otworzyć selektor serwerów. W sekcji **Serwer domyślny** kliknij **Wyczyść**. + +#### Usuń `server.port` / `server.hostname` ze swojej konfiguracji + +Jeśli Twój `opencode.json(c)` zawiera sekcję `server`, tymczasowo usuń ją i uruchom ponownie aplikację komputerową. + +#### Sprawdź zmienne środowiskowe + +Jeśli w swoim środowisku masz ustawiony `OPENCODE_PORT`, aplikacja komputerowa spróbuje użyć tego portu dla serwera lokalnego. + +- usuń `OPENCODE_PORT` (lub wybierz wolny port) i uruchom ponownie. + +--- + +### Linux: Problemy z Wayland / X11 + +W systemie Linux, niektóre konfiguracje Wayland mogą powodować puste okna lub błędy kompozytora. + +- Jeśli korzystasz z Wayland, a aplikacja jest pusta/ ulega awarii, spróbuj uruchomić ją za pomocą `OC_ALLOW_WAYLAND=1`. +- Jeśli to pogorszy sprawę, usuń go i zamiast tego spróbuj uruchomić w sesji X11. + +--- + +### Windows: Środowisko uruchomieniowe WebView2 + +W systemie Windows opencode Desktop wymaga Microsoft Edge **WebView2 Runtime**. Jeśli aplikacja otwiera się w pustym oknie lub nie uruchamia się, zainstaluj/zaktualizuj WebView2 i spróbuj ponownie. + +--- + +### Windows: Ogólne problemy z wydajnością + +Jeśli doświadczasz niskiej wydajności, problemów z dostępem do plików lub problemów z terminalem w systemie Windows, spróbuj użyć [WSL (podsystem Windows dla systemu Linux) (./windows-wsl). WSL zapewnia środowisko Linux, które płynniej współpracuje z funkcjami opencode. + +--- + +### Brak powiadomień + +opencode Desktop pokazuje powiadomienia systemowe tylko wtedy, gdy: + +- powiadomienia są włączone dla opencode w ustawieniach systemu operacyjnego, oraz +- okno aplikacji nie jest aktywne. + +--- + +### Resetowanie pamięci aplikacji + +Jeśli aplikacja nie uruchamia się i nie możesz wyczyścić ustawień w interfejsie użytkownika, zresetuj zapisany stan aplikacji komputerowej. + +1. Zamknij całkowicie opencode Desktop. +2. Znajdź i usuń te pliki (znajdują się w katalogu danych aplikacji opencode Desktop): + +- `opencode.settings.dat` (domyślny adres URL serwera na komputerze stacjonarnym) +- `opencode.global.dat` i `opencode.workspace.*.dat` (stan interfejsu użytkownika, taki jak najnowsze serwery/projekty) + +Aby szybko znaleźć katalog: + +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (następnie wyszukaj nazwy plików powyżej) +- **Linux**: wyszukaj powyższe nazwy plików pod `~/.local/share` +- **Windows**: Naciśnij `WIN+R` -> `%APPDATA%` (następnie wyszukaj nazwy plików powyżej) + +--- + +## Uzyskiwanie pomocy + +Jeśli masz problemy z opencode: + +1. **Zgłoś problem na GitHub** + + Najlepszym sposobem zgłaszania błędów lub zgłaszania żądań funkcji jest skorzystanie z naszego repozytorium GitHub: + + [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + + Przed utworzeniem nowego problemu przeszukaj istniejące i sprawdź, czy Twój problem nie został już zgłoszony. + +2. **Dołącz do naszego Discorda** + + Aby uzyskać pomoc w czasie rzeczywistym i dyskusję społeczności, dołącz do naszego serwera Discord: + + [**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## Typowe problemy + +Oto kilka typowych problemów i sposobów ich rozwiązania. + +--- + +### opencode nie uruchamia się + +1. Sprawdź dzienniki pod kątem komunikatów o błędach +2. Spróbuj uruchomić z `--print-logs`, aby zobaczyć dane wyjściowe w terminalu +3. Upewnij się, że masz najnowszą wersję z `opencode upgrade` + +--- + +### Problemy z uwierzytelnianiem + +1. Spróbuj ponownie uwierzytelnić się za pomocą polecenia `/connect` w TUI +2. Sprawdź, czy klucze API są ważne +3. Upewnij się, że Twoja sieć umożliwia połączenia z interfejsem API dostawcy + +--- + +### Model niedostępny + +1. Sprawdź, czy dokonałeś uwierzytelnienia u dostawcy +2. Sprawdź, czy nazwa modelu w konfiguracji jest poprawna +3. Niektóre modele mogą wymagać określonego dostępu lub subskrypcji + +Jeśli napotkasz `ProviderModelNotFoundError`, najprawdopodobniej +błędnie odwołujesz się gdzieś do modelu. +Modele powinny być wskazywane w ten sposób: `/` + +Przykłady: + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +Aby dowiedzieć się, do jakich modeli masz dostęp, uruchom `opencode models` + +--- + +### ProviderInitError + +Jeśli napotkasz błąd ProviderInitError, prawdopodobnie masz nieprawidłową lub uszkodzoną konfigurację. + +Aby rozwiązać ten problem: + +1. Najpierw sprawdź, czy Twój dostawca jest prawidłowo skonfigurowany, postępując zgodnie z [przewodnikiem dostawców](/docs/providers) +2. Jeśli problem będzie się powtarzał, spróbuj wyczyścić zapisaną konfigurację: + + ```bash + rm -rf ~/.local/share/opencode + ``` + + W systemie Windows naciśnij `WIN+R` i usuń: `%USERPROFILE%\.local\share\opencode` + +3. Ponownie uwierzytelnij się u swojego dostawcy za pomocą polecenia `/connect` w TUI. + +--- + +### Błędy AI_APICallError i problemy z pakietami dostawców + +Jeśli napotkasz błędy wywołań API, może to wynikać z nieaktualnych pakietów dostawców. opencode dynamicznie instaluje pakiety dostawców (OpenAI, Anthropic, Google itp.) w razie potrzeby i przechowuje je lokalnie w pamięci podręcznej. + +Aby rozwiązać problemy z pakietem dostawcy: + +1. Wyczyść pamięć podręczną pakietu dostawcy: + + ```bash + rm -rf ~/.cache/opencode + ``` + + W systemie Windows naciśnij `WIN+R` i usuń: `%USERPROFILE%\.cache\opencode` + +2. Uruchom ponownie kod opencode, aby ponownie zainstalować najnowsze pakiety dostawców + +Zmusi to opencode do pobrania najnowszych wersji pakietów dostawców, co często rozwiązuje problemy ze zgodnością z parametrami modelu i zmianami API. + +--- + +### Kopiowanie/wklejanie nie działa na Linuxie + +Aby funkcja kopiowania/wklejania działała, użytkownicy systemu Linux muszą mieć zainstalowane jedno z następujących narzędzi schowka: + +**Dla systemów X11:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**Dla systemów Wayland:** + +```bash +apt install -y wl-clipboard +``` + +**Dla środowisk headless:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +opencode wykryje, czy używasz Waylanda i wolisz `wl-clipboard`, w przeciwnym razie spróbuje znaleźć narzędzia schowka w kolejności: `xclip` i `xsel`. diff --git a/packages/web/src/content/docs/pl/tui.mdx b/packages/web/src/content/docs/pl/tui.mdx new file mode 100644 index 00000000000..6d693eb9e65 --- /dev/null +++ b/packages/web/src/content/docs/pl/tui.mdx @@ -0,0 +1,390 @@ +--- +title: TUI +description: Korzystanie z interfejsu użytkownika terminala opencode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +opencode zapewnia interaktywny interfejs terminala lub TUI do pracy nad projektami za pomocą LLM. + +Uruchomienie opencode uruchamia TUI dla bieżącego katalogu. + +```bash +opencode +``` + +Możesz też uruchomić go dla określonego katalogu roboczego. + +```bash +opencode /path/to/project +``` + +Gdy znajdziesz się w TUI, możesz wyświetlić monit za pomocą komunikatu. + +```text +Give me a quick summary of the codebase. +``` + +--- + +## Referencje plików + +Możesz odwoływać się do plików w swoich wiadomościach, używając `@`. Spowoduje to rozmyte wyszukiwanie plików w bieżącym katalogu roboczym. + +:::tip +Możesz także użyć `@` do odwoływania się do plików w swoich wiadomościach. +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +Zawartość pliku jest automatycznie dodawana do rozmowy. + +--- + +## Polecenia Bash + +Rozpocznij wiadomość od `!`, aby uruchomić polecenie shell. + +```bash frame="none" +!ls -la +``` + +Dane wyjściowe polecenia są dodawane do konwersacji jako wynik narzędzia. + +--- + +## Komendy + +Korzystając z TUI opencode, możesz wpisać `/`, po którym następuje nazwa polecenia, aby szybko wykonać działania. Na przykład: + +```bash frame="none" +/help +``` + +Większość poleceń ma również skrót klawiszowy wykorzystujący `ctrl+x` jako klucz wiodący, gdzie `ctrl+x` jest domyślnym klawiszem wiodącym. [Dowiedz się więcej](/docs/keybinds). + +Oto wszystkie dostępne slash commands: + +--- + +### connect + +Dodaj dostawcę do opencode. Umożliwia wybór dostępnych dostawców i dodanie ich kluczy API. + +```bash frame="none" +/connect +``` + +--- + +### compact + +Kompaktuj bieżącą sesję. _Alias_: `/summarize` + +```bash frame="none" +/compact +``` + +**Keybind:** `ctrl+x c` + +--- + +### details + +Przełącz szczegóły wykonywania narzędzi. + +```bash frame="none" +/details +``` + +**Keybind:** `ctrl+x d` + +--- + +### editor + +Otwórz zewnętrzny edytor do tworzenia wiadomości. Używa edytora ustawionego w zmiennej środowiskowej `EDITOR`. [Dowiedz się więcej](#editor-setup). + +```bash frame="none" +/editor +``` + +**Keybind:** `ctrl+x e` + +--- + +### exit + +Zamknij opencode. _Aliasy_: `/quit`, `/q` + +```bash frame="none" +/exit +``` + +**Keybind:** `ctrl+x q` + +--- + +### export + +Wyeksportuj bieżącą rozmowę do Markdown i otwórz ją w domyślnym edytorze. Używa edytora ustawionego w zmiennej środowiskowej `EDITOR`. [Dowiedz się więcej](#editor-setup). + +```bash frame="none" +/export +``` + +**Keybind:** `ctrl+x x` + +--- + +### help + +Pokaż okno pomocy. + +```bash frame="none" +/help +``` + +**Keybind:** `ctrl+x h` + +--- + +### init + +Utwórz lub zaktualizuj plik `AGENTS.md`. [Dowiedz się więcej](/docs/rules). + +```bash frame="none" +/init +``` + +**Keybind:** `ctrl+x i` + +--- + +### models + +Lista dostępnych modeli. + +```bash frame="none" +/models +``` + +**Keybind:** `ctrl+x m` + +--- + +### new + +Rozpocznij nową sesję. _Alias_: `/clear` + +```bash frame="none" +/new +``` + +**Keybind:** `ctrl+x n` + +--- + +### redo + +Ponów cofniętą wcześniej wiadomość. Dostępne tylko po użyciu `/undo`. + +:::tip +Wszystkie zmiany plików również zostaną przywrócone. +::: + +Wewnętrznie używa Git do zarządzania zmianami plików. Więc Twój projekt ** musi +be a Git repository**. + +```bash frame="none" +/redo +``` + +**Keybind:** `ctrl+x r` + +--- + +### sessions + +Wyświetl listę i przełączaj się między sesjami. _Aliasy_: `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +**Keybind:** `ctrl+x l` + +--- + +### share + +Udostępnij bieżącą sesję. [Dowiedz się więcej](/docs/share). + +```bash frame="none" +/share +``` + +**Keybind:** `ctrl+x s` + +--- + +### themes + +Lista dostępnych motywów. + +```bash frame="none" +/theme +``` + +**Keybind:** `ctrl+x t` + +--- + +### thinking + +Przełącz widoczność bloków myślenia/rozumowania w rozmowie. Po włączeniu tej opcji można zobaczyć proces wnioskowania modelu w przypadku modeli obsługujących myślenie rozszerzone. + +:::note +To polecenie kontroluje jedynie, czy bloki myślowe są **wyświetlane** - nie włącza ani nie wyłącza możliwości wnioskowania modelu. Aby przełączyć rzeczywiste możliwości wnioskowania, użyj `ctrl+t` do przełączania wariantów modelu. +::: + +```bash frame="none" +/thinking +``` + +--- + +### undo + +Cofnij ostatnią wiadomość w rozmowie. Usuwa najnowszą wiadomość użytkownika, wszystkie kolejne odpowiedzi i wszelkie zmiany w plikach. + +:::tip +Wszystkie zmiany plików również zostaną cofnięte. +::: + +Wewnętrznie używa Git do zarządzania zmianami plików. Więc Twój projekt ** musi +be a Git repository**. + +```bash frame="none" +/undo +``` + +**Keybind:** `ctrl+x u` + +--- + +### unshare + +Anuluj udostępnianie bieżącej sesji. [Dowiedz się więcej](/docs/share#un-sharing). + +```bash frame="none" +/unshare +``` + +--- + +## Konfiguracja edytora + +Zarówno polecenia `/editor`, jak i `/export` korzystają z edytora określonego w zmiennej środowiskowej `EDITOR`. + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + + Aby było to trwałe, dodaj to do swojego profilu shell; + `~/.bashrc`, `~/.zshrc`, etc. + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + + Aby ustawić tę opcję na stałe, użyj opcji **Właściwości systemu** > **Środowisko + Variables**. + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + + Aby uczynić to trwałym, dodaj to do swojego profilu PowerShell. + + + + +Popularne opcje edytora: + +- `code` - Visual Studio Code +- `cursor` - Cursor +- `windsurf` - Windsurf +- `nvim` - Neovim editor +- `vim` - Vim editor +- `nano` - Nano editor +- `notepad` - Windows Notepad +- `subl` - Sublime Text + +:::note +Niektóre edytory, takie jak VS Code, należy uruchamiać z flagą `--wait`. +::: + +Niektórzy edytory potrzebują argumentów wiersza poleceń, aby działać w trybie blokowania. Flaga `--wait` blokuje proces edytora aż do jego zamknięcia. + +--- + +## Skonfiguruj + +Możesz dostosować zachowanie TUI za pomocą pliku konfiguracyjnego opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### 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`.** + +--- + +## Personalizacja + +Za pomocą palety poleceń (`ctrl+x h` lub `/help`) można dostosować różne aspekty widoku TUI. Te ustawienia są zachowywane po ponownym uruchomieniu. + +--- + +#### Wyświetlanie nazwy użytkownika + +Włącz lub wyłącz wyświetlanie Twojej nazwy użytkownika w wiadomościach na czacie. Dostęp do tego poprzez: + +- Paleta poleceń: Wyszukaj „nazwę użytkownika” lub „ukryj nazwę użytkownika” +- Ustawienie zostanie zapamiętane automatycznie i będzie pamiętane podczas sesji TUI diff --git a/packages/web/src/content/docs/pl/web.mdx b/packages/web/src/content/docs/pl/web.mdx new file mode 100644 index 00000000000..2a2ada1cf6b --- /dev/null +++ b/packages/web/src/content/docs/pl/web.mdx @@ -0,0 +1,142 @@ +--- +title: Web +description: Korzystanie z opencode w przeglądarce. +--- + +opencode może działać jako aplikacja internetowa w przeglądarce, zapewniając takie same możliwości kodowania AI bez konieczności korzystania z terminala. + +![Sieć opencode - Nowa sesja](../../../assets/web/web-homepage-new-session.png) + +## Pierwsze kroki + +Uruchom interfejs sieciowy, uruchamiając: + +```bash +opencode web +``` + +Spowoduje to uruchomienie lokalnego serwera na `127.0.0.1` z losowo dostępnym portem i automatyczne otwarcie opencode w domyślnej przeglądarce. + +:::caution +Jeśli `OPENCODE_SERVER_PASSWORD` nie jest ustawione, serwer będzie niezabezpieczony. Jest to dobre rozwiązanie do użytku lokalnego, ale powinno być ustawione na dostęp do sieci. +::: + +:::tip[Windows Users] +Aby uzyskać najlepsze wyniki, uruchom `opencode web` z [WSL](/docs/windows-wsl) zamiast programu PowerShell. Zapewnia to prawidłowy dostęp do systemu plików i integrację terminala. +::: + +--- + +## Konfiguracja + +Możesz skonfigurować serwer WWW za pomocą flag wiersza poleceń lub w [pliku konfiguracyjnym] (./config). + +### Port + +Domyślnie opencode wybiera dostępny port. Możesz określić port: + +```bash +opencode web --port 4096 +``` + +### Nazwa hosta + +Domyślnie serwer łączy się z `127.0.0.1` (tylko localhost). Aby udostępnić opencode w swojej sieci: + +```bash +opencode web --hostname 0.0.0.0 +``` + +Podczas korzystania z `0.0.0.0` opencode wyświetli zarówno adresy lokalne, jak i sieciowe: + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### Wykrywanie mDNS + +Włącz mDNS, aby Twój serwer był wykrywalny w sieci lokalnej: + +```bash +opencode web --mdns +``` + +To automatycznie ustawia nazwę hosta na `0.0.0.0` i anonsuje serwer jako `opencode.local`. + +Możesz dostosować nazwę domeny mDNS, aby uruchamiała wiele instancji w tej samej sieci: + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +Aby zezwolić na dodatkowe domeny dla CORS (przydatne w przypadku niestandardowych interfejsów): + +```bash +opencode web --cors https://example.com +``` + +### Uwierzytelnianie + +Aby chronić dostęp, ustaw hasło za pomocą zmiennej środowiskowej `OPENCODE_SERVER_PASSWORD`: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +Domyślna nazwa użytkownika to `opencode`, ale można ją zmienić za pomocą `OPENCODE_SERVER_USERNAME`. + +--- + +## Korzystanie z interfejsu internetowego + +Po uruchomieniu interfejs sieciowy zapewnia dostęp do sesji opencode. + +### Sesje + +Przeglądaj sesje i zarządzaj nimi ze strony głównej. Możesz zobaczyć aktywne sesje i rozpocząć nowe. + +![opencode Web - Aktywna sesja](../../../assets/web/web-homepage-active-session.png) + +### Stan serwera + +Kliknij „Zobacz serwery”, aby wyświetlić podłączone serwery i ich status. + +![opencode Web - See Servers](../../../assets/web/web-homepage-see-servers.png) + +--- + +## Podłączanie terminala + +Możesz podłączyć terminal TUI do działającego serwera WWW: + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +Umożliwia to jednoczesne korzystanie z interfejsu sieciowego i terminala, współdzieląc te same sesje i stan. + +--- + +## Plik konfiguracyjny + +Możesz także skonfigurować ustawienia serwera w pliku konfiguracyjnym `opencode.json`: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +Flagi wiersza poleceń mają pierwszeństwo przed ustawieniami pliku konfiguracyjnego. diff --git a/packages/web/src/content/docs/pl/windows-wsl.mdx b/packages/web/src/content/docs/pl/windows-wsl.mdx new file mode 100644 index 00000000000..85629c2e5f6 --- /dev/null +++ b/packages/web/src/content/docs/pl/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: Uruchamiaj opencode na Windows z WSL dla najlepszych efektow. +--- + +import { Steps } from "@astrojs/starlight/components" + +Chociaz opencode moze dzialac bezposrednio na Windows, dla najlepszych rezultatow zalecamy [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install). WSL zapewnia srodowisko Linuksa, ktore bardzo dobrze wspolpracuje z funkcjami opencode. + +:::tip[Dlaczego WSL?] +WSL oferuje lepsza wydajnosc systemu plikow, pelna obsluge terminala i zgodnosc z narzedziami developerskimi, na ktorych opiera sie opencode. +::: + +--- + +## Konfiguracja + + + +1. **Zainstaluj WSL** + + Jesli jeszcze tego nie zrobiles, [zainstaluj WSL](https://learn.microsoft.com/en-us/windows/wsl/install) wedlug oficjalnego przewodnika Microsoft. + +2. **Zainstaluj opencode w WSL** + + Po skonfigurowaniu WSL otworz terminal WSL i zainstaluj opencode jedna z [metod instalacji](/docs/). + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **Korzystaj z opencode przez WSL** + + Przejdz do katalogu projektu (pliki Windows sa dostepne przez `/mnt/c/`, `/mnt/d/` itd.) i uruchom opencode. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## Aplikacja desktopowa + serwer WSL + +Jesli wolisz aplikacje desktopowa opencode, ale chcesz uruchamiac serwer w WSL: + +1. **Uruchom serwer w WSL** z `--hostname 0.0.0.0`, aby zezwolic na polaczenia zewnetrzne: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **Polacz aplikacje desktopowa** z `http://localhost:4096` + +:::note +Jesli `localhost` nie dziala w Twojej konfiguracji, polacz sie przez adres IP WSL (w WSL: `hostname -I`) i uzyj `http://:4096`. +::: + +:::caution +Przy uzyciu `--hostname 0.0.0.0` ustaw `OPENCODE_SERVER_PASSWORD`, aby zabezpieczyc serwer. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## Klient web + WSL + +Dla najlepszej pracy w przegladarce na Windows: + +1. **Uruchamiaj `opencode web` w terminalu WSL**, a nie w PowerShell: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Otworz w przegladarce Windows** pod adresem `http://localhost:` (opencode wypisze URL) + +Uruchamianie `opencode web` z WSL zapewnia poprawny dostep do systemu plikow i integracje z terminalem, a nadal pozostaje dostepne z przegladarki Windows. + +--- + +## Dostep do plikow Windows + +WSL moze uzyskac dostep do wszystkich plikow Windows przez katalog `/mnt/`: + +- Dysk `C:` → `/mnt/c/` +- Dysk `D:` → `/mnt/d/` +- I tak dalej... + +Przyklad: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +Aby uzyskac najplynniejsza prace, rozwaz sklonowanie/skopiowanie repozytorium do systemu plikow WSL (np. do `~/code/`) i uruchamianie tam opencode. +::: + +--- + +## Wskazowki + +- Uruchamiaj opencode w WSL dla projektow zapisanych na dyskach Windows - dostep do plikow jest bezproblemowy +- Uzywaj [rozszerzenia WSL dla VS Code](https://code.visualstudio.com/docs/remote/wsl) razem z opencode, aby miec zintegrowany workflow +- Konfiguracja opencode i sesje sa przechowywane w srodowisku WSL pod `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/pl/zen.mdx b/packages/web/src/content/docs/pl/zen.mdx new file mode 100644 index 00000000000..6d5d8c0bd78 --- /dev/null +++ b/packages/web/src/content/docs/pl/zen.mdx @@ -0,0 +1,254 @@ +--- +title: Zen +description: Wyselekcjonowana lista modeli dostarczonych przez opencode. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen to lista przetestowanych i zweryfikowanych modeli udostępniona przez zespół opencode. + +:::note +OpenCode Zen is currently in beta. +::: + +Zen działa jak każdy inny dostawca opencode. Logujesz się do OpenCode Zen i dostajesz +Twój klucz API. Jest **całkowicie opcjonalny** i nie musisz go używać, aby z niego korzystać +opencode. + +--- + +## Tło + +Istnieje ogromna liczba modeli, ale tylko kilka z nich +działa dobrze jako agenci kodujący. Dodatkowo większość dostawców jest +skonfigurowana bardzo różnie; więc otrzymujesz zupełnie inną wydajność i jakość. + +:::tip +Przetestowaliśmy wybraną grupę modeli i dostawców, którzy dobrze współpracują z opencode. +::: + +Jeśli więc używasz modelu za pośrednictwem czegoś takiego jak OpenRouter, nigdy nie będzie to możliwe +pewien, czy otrzymujesz najlepszą wersję modelu, jaki chcesz. + +Aby to naprawić, zrobiliśmy kilka rzeczy: + +1. Przetestowaliśmy wybraną grupę modeli i rozmawialiśmy z ich zespołami o tym, jak to zrobić + najlepiej je uruchom. +2. Następnie współpracowaliśmy z kilkoma dostawcami, aby upewnić się, że są one obsługiwane + correctly. +3. Na koniec porównaliśmy kombinację modelu/dostawcy i otrzymaliśmy wynik + z listą, którą z przyjemnością polecamy. + +OpenCode Zen to brama AI, która zapewnia dostęp do tych modeli. + +--- + +## Jak to działa + +OpenCode Zen działa jak każdy inny dostawca opencode. + +1. Logujesz się do **OpenCode Zen**, dodajesz swoje rozliczenia + szczegóły i skopiuj klucz API. +2. Uruchamiasz polecenie `/connect` w TUI, wybierasz OpenCode Zen i wklejasz klucz API. +3. Uruchom `/models` w TUI, aby zobaczyć listę zalecanych przez nas modeli. + +Opłata jest pobierana za każde żądanie i możesz dodać kredyty do swojego konta. + +--- + +## Punkty końcowe + +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 | +| ------------------ | -------------------- | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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` | + +[Identyfikator modelu](/docs/config/#models) w konfiguracji opencode +używa formatu `opencode/`. Na przykład w przypadku Kodeksu GPT 5.2 zrobiłbyś to +użyj `opencode/gpt-5.2-codex` w swojej konfiguracji. + +--- + +### Modele + +Pełną listę dostępnych modeli i ich metadane możesz pobrać z: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## Cennik + +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 | +| --------------------------------- | ------- | ------- | --------------------------- | -------------------------- | +| Big Pickle | Free | Free | Free | - | +| MiniMax M2.1 Free | Free | Free | Free | - | +| MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | +| GLM 4.7 Free | Free | Free | Free | - | +| 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 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 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.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 | Free | Free | Free | - | + +Możesz zauważyć _Claude Haiku 3.5_ w swojej historii użytkowania. To jest [model niskokosztowy](/docs/config/#models), który służy do generowania tytułów sesji. + +:::note +Opłaty za karty kredytowe są przenoszone na koszt (4,4% + 0,30 USD za transakcję); nie pobieramy żadnych dodatkowych opłat. +::: + +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. + +Skontaktuj się z nami, jeśli masz jakieś pytania. + +--- + +### Automatyczne doładowanie + +Jeśli Twoje saldo spadnie poniżej 5 USD, Zen automatycznie doładuje 20 USD. + +Możesz zmienić kwotę automatycznego doładowania. Możesz także całkowicie wyłączyć automatyczne przeładowywanie. + +--- + +### Limity miesięczne + +Możesz także ustawić miesięczny limit wykorzystania dla całego obszaru roboczego i dla każdego z nich +członek Twojego zespołu. + +Załóżmy na przykład, że ustawiłeś miesięczny limit użytkowania na 20 USD, Zen nie będzie z niego korzystał +ponad 20 dolarów miesięcznie. Ale jeśli masz włączone automatyczne przeładowywanie, Zen może się skończyć +obciąży Cię kwotą wyższą niż 20 USD, jeśli saldo spadnie poniżej 5 USD. + +--- + +## Prywatność + +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. +- 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). + +--- + +## Dla zespołów + +Zen świetnie sprawdza się także w zespołach. Możesz zapraszać członków zespołu, przypisywać role, zarządzać +modele, z których korzysta Twój zespół i nie tylko. + +:::note +Obszary robocze są obecnie bezpłatne dla zespołów w ramach wersji beta. +::: + +Zarządzanie obszarem roboczym jest obecnie bezpłatne dla zespołów w ramach wersji beta. Będziemy +wkrótce udostępnimy więcej szczegółów na temat cen. + +--- + +### Role + +Możesz zapraszać członków zespołu do swojego obszaru roboczego i przypisywać role: + +- **Administrator**: Zarządzaj modelami, członkami, kluczami API i rozliczeniami +- **Członek**: Zarządzaj tylko własnymi kluczami API + +Administratorzy mogą także ustawić miesięczne limity wydatków dla każdego członka, aby utrzymać koszty pod kontrolą. + +--- + +### Dostęp do modelu + +Administratorzy mogą włączać i wyłączać określone modele w obszarze roboczym. Żądania skierowane do wyłączonego modelu zwrócą błąd. + +Jest to przydatne w przypadkach, gdy chcesz wyłączyć korzystanie z modelu, który +collects data. + +--- + +### Przynieś swój własny klucz + +Możesz używać własnych kluczy OpenAI lub Anthropic API, jednocześnie uzyskując dostęp do innych modeli w Zen. + +Kiedy używasz własnych kluczy, tokeny są rozliczane bezpośrednio przez dostawcę, a nie przez Zen. + +Na przykład Twoja organizacja może już mieć klucz do OpenAI lub Anthropic +i chcesz go używać zamiast tego, który zapewnia Zen. + +--- + +## Cele + +Stworzyliśmy OpenCode Zen, aby: + +1. **Testować** (Benchmark) najlepsze modele/dostawców dla agentów kodujących. +2. Miej dostęp do opcji **najwyższej jakości**, a nie obniżaj wydajności ani nie kieruj się do tańszych dostawców. +3. Przekaż wszelkie **obniżki cen**, sprzedając po kosztach; więc jedyną marżą jest pokrycie naszych opłat manipulacyjnych. +4. Nie **nie blokuj**, umożliwiając używanie go z dowolnym innym agentem kodującym. I zawsze pozwalaj na korzystanie z opencode dowolnego innego dostawcy. diff --git a/packages/web/src/content/docs/pt-br/acp.mdx b/packages/web/src/content/docs/pt-br/acp.mdx new file mode 100644 index 00000000000..549f6cead7f --- /dev/null +++ b/packages/web/src/content/docs/pt-br/acp.mdx @@ -0,0 +1,156 @@ +--- +title: Suporte ACP +description: Use o opencode em qualquer editor compatível com ACP. +--- + +O opencode suporta o [Agent Client Protocol](https://agentclientprotocol.com) ou (ACP), permitindo que você o utilize diretamente em editores e IDEs compatíveis. + +:::tip +Para uma lista de editores e ferramentas que suportam ACP, confira o [relatório de progresso do ACP](https://zed.dev/blog/acp-progress-report#available-now). +::: + +O ACP é um protocolo aberto que padroniza a comunicação entre editores de código e agentes de codificação de IA. + +--- + +## Configuração + +Para usar opencode via ACP, configure seu editor para executar o comando `opencode acp`. + +Este comando inicia o opencode como um subprocesso compatível com ACP que se comunica com seu editor via JSON-RPC através do stdio. + +Abaixo estão exemplos para editores populares que suportam ACP. + +--- + +### Zed + +Adicione à sua configuração do [Zed](https://zed.dev) (`~/.config/zed/settings.json`): + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +Para abri-lo, use a ação `agent: new thread` na **Paleta de Comandos**. + +Você também pode vincular um atalho de teclado editando seu `keymap.json`: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### IDEs JetBrains + +Adicione ao seu acp.json do [JetBrains IDE](https://www.jetbrains.com/) de acordo com a [documentação](https://www.jetbrains.com/help/ai-assistant/acp.html): + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +Para abri-lo, use o novo agente 'opencode' no seletor de agentes do AI Chat. + +--- + +### Avante.nvim + +Adicione à sua configuração do [Avante.nvim](https://github.com/yetone/avante.nvim): + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +Se você precisar passar variáveis de ambiente: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +Para usar opencode como um agente ACP no [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim), adicione o seguinte à sua configuração do Neovim: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +Esta configuração configura o CodeCompanion para usar opencode como o agente ACP para chat. + +Se você precisar passar variáveis de ambiente (como `OPENCODE_API_KEY`), consulte [Configurando Adaptadores: Variáveis de Ambiente](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) na documentação do CodeCompanion.nvim para detalhes completos. + +## Suporte + +O opencode funciona da mesma forma via ACP como funciona no terminal. Todos os recursos são suportados: + +:::note +Alguns comandos de barra integrados, como `/undo` e `/redo`, atualmente não são suportados. +::: + +- Ferramentas integradas (operações de arquivo, comandos de terminal, etc.) +- Ferramentas personalizadas e comandos de barra +- Servidores MCP configurados na sua configuração do opencode +- Regras específicas do projeto do `AGENTS.md` +- Formatadores e linters personalizados +- Sistema de agentes e permissões diff --git a/packages/web/src/content/docs/pt-br/agents.mdx b/packages/web/src/content/docs/pt-br/agents.mdx new file mode 100644 index 00000000000..9a831e80489 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/agents.mdx @@ -0,0 +1,747 @@ +--- +title: Agentes +description: Configure e use agentes especializados. +--- + +Agentes são assistentes de IA especializados que podem ser configurados para tarefas e fluxos de trabalho específicos. Eles permitem que você crie ferramentas focadas com prompts, modelos e acesso a ferramentas personalizados. + +:::tip +Use o agente de planejamento (plan) para analisar código e revisar sugestões sem fazer alterações no código. +::: + +Você pode alternar entre agentes durante uma sessão ou invocá-los com a menção `@`. + +--- + +## Tipos + +Existem dois tipos de agentes no opencode; agentes primários e subagentes. + +--- + +### Agentes primários + +Agentes primários são os principais assistentes com os quais você interage diretamente. Você pode alternar entre eles usando a tecla **Tab** ou sua tecla de atalho configurada `switch_agent`. Esses agentes lidam com sua conversa principal. O acesso às ferramentas é configurado por meio de permissões — por exemplo, Build tem todas as ferramentas habilitadas, enquanto Plan é restrito. + +:::tip +Você pode usar a tecla **Tab** para alternar entre agentes primários durante uma sessão. +::: + +opencode vem com dois agentes primários integrados, **Build** e **Plan**. Vamos +ver isso abaixo. + +--- + +### Subagentes + +Subagentes são assistentes especializados que agentes primários podem invocar para tarefas específicas. Você também pode invocá-los manualmente mencionando-os com **@** em suas mensagens. + +opencode vem com dois subagentes integrados, **General** e **Explore**. Vamos ver isso abaixo. + +--- + +## Integrados + +opencode vem com dois agentes primários integrados e dois subagentes integrados. + +--- + +### build + +_Modo_: `primary` + +Build é o agente primário **padrão** com todas as ferramentas habilitadas. Este é o agente padrão para trabalho de desenvolvimento onde você precisa de acesso total a operações de arquivo e comandos do sistema. + +--- + +### plan + +_Modo_: `primary` + +Um agente restrito projetado para planejamento e análise. Usamos um sistema de permissões para lhe dar mais controle e evitar alterações não intencionais. +Por padrão, todos os seguintes estão configurados para `ask`: + +- `file edits`: Todas as gravações, patches e edições +- `bash`: Todos os comandos bash + +Este agente é útil quando você deseja que o LLM analise código, sugira alterações ou crie planos sem fazer modificações reais em seu código. + +--- + +### general + +_Modo_: `subagent` + +Um agente de propósito geral para pesquisar questões complexas e executar tarefas em múltiplas etapas. Tem acesso total às ferramentas (exceto todo), portanto, pode fazer alterações em arquivos quando necessário. Use isso para executar várias unidades de trabalho em paralelo. + +--- + +### explore + +_Modo_: `subagent` + +Um agente rápido e somente leitura para explorar bases de código. Não pode modificar arquivos. Use isso quando você precisar encontrar rapidamente arquivos por padrões, pesquisar código por palavras-chave ou responder perguntas sobre a base de código. + +--- + +### compaction + +_Modo_: `primary` + +Agente de sistema oculto que compacta longos contextos em um resumo menor. Ele é executado automaticamente quando necessário e não é selecionável na interface. + +--- + +### title + +_Modo_: `primary` + +Agente de sistema oculto que gera títulos curtos para sessões. Ele é executado automaticamente e não é selecionável na interface. + +--- + +### summary + +_Modo_: `primary` + +Agente de sistema oculto que cria resumos de sessões. Ele é executado automaticamente e não é selecionável na interface. + +--- + +## Uso + +1. Para agentes primários, use a tecla **Tab** para alternar entre eles durante uma sessão. Você também pode usar sua tecla de atalho configurada `switch_agent`. + +2. Subagentes podem ser invocados: + - **Automaticamente** por agentes primários para tarefas especializadas com base em suas descrições. + - Manualmente mencionando um subagente em sua mensagem. Por exemplo. + + ```txt frame="none" + @general help me search for this function + ``` + +3. **Navegação entre sessões**: Quando subagentes criam suas próprias sessões filhas, você pode navegar entre a sessão pai e todas as sessões filhas usando: + - **\+Right** (ou sua tecla de atalho configurada `session_child_cycle`) para alternar para frente através de pai → child1 → child2 → ... → pai + - **\+Left** (ou sua tecla de atalho configurada `session_child_cycle_reverse`) para alternar para trás através de pai ← child1 ← child2 ← ... ← pai + + Isso permite que você mude perfeitamente entre a conversa principal e o trabalho especializado do subagente. + +--- + +## Configuração + +Você pode personalizar os agentes integrados ou criar os seus próprios através da configuração. Os agentes podem ser configurados de duas maneiras: + +--- + +### JSON + +Configure os agentes em seu arquivo de configuração `opencode.json`: + +```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": "Revisa código para melhores práticas e potenciais problemas", + "mode": "subagent", + "model": "anthropic/claude-sonnet-4-20250514", + "prompt": "Você é um revisor de código. Foque em segurança, performance e manutenibilidade.", + "tools": { + "write": false, + "edit": false + } + } + } +} +``` + +--- + +### Markdown + +Você também pode definir agentes usando arquivos markdown. Coloque-os em: + +- Global: `~/.config/opencode/agents/` +- Por projeto: `.opencode/agents/` + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Revisa código para qualidade e melhores práticas +mode: subagent +model: anthropic/claude-sonnet-4-20250514 +temperature: 0.1 +tools: + write: false + edit: false + bash: false +--- + +Você está no modo de revisão de código. Foque em: + +- Qualidade do código e melhores práticas +- Bugs potenciais e casos de borda +- Implicações de desempenho +- Considerações de segurança + +Forneça feedback construtivo sem fazer alterações diretas. +``` + +O nome do arquivo markdown se torna o nome do agente. Por exemplo, `review.md` cria um agente `review`. + +--- + +## Opções + +Vamos analisar essas opções de configuração em detalhes. + +--- + +### Descrição + +Use a opção `description` para fornecer uma breve descrição do que o agente faz e quando usá-lo. + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Revisa código para melhores práticas e potenciais problemas" + } + } +} +``` + +Esta é uma opção de configuração **obrigatória**. + +--- + +### Temperatura + +Controle a aleatoriedade e criatividade das respostas do LLM com a configuração `temperature`. + +Valores mais baixos tornam as respostas mais focadas e determinísticas, enquanto valores mais altos aumentam a criatividade e variabilidade. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Os valores de temperatura geralmente variam de 0.0 a 1.0: + +- **0.0-0.2**: Respostas muito focadas e determinísticas, ideais para análise de código e planejamento +- **0.3-0.5**: Respostas equilibradas com alguma criatividade, boas para tarefas de desenvolvimento gerais +- **0.6-1.0**: Respostas mais criativas e variadas, úteis para brainstorming e exploração + +```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}" + } + } +} +``` + +Se nenhuma temperatura for especificada, o opencode usa padrões específicos do modelo; tipicamente 0 para a maioria dos modelos, 0.55 para modelos Qwen. + +--- + +### Máximo de etapas + +Controle o número máximo de iterações que um agente pode realizar antes de ser forçado a responder apenas com texto. Isso permite que usuários que desejam controlar custos definam um limite nas ações do agente. + +Se isso não for definido, o agente continuará a iterar até que o modelo decida parar ou o usuário interrompa a sessão. + +```json title="opencode.json" +{ + "agent": { + "quick-thinker": { + "description": "Raciocínio rápido com iterações limitadas", + "prompt": "Você é um pensador rápido. Resolva problemas com etapas mínimas.", + "steps": 5 + } + } +} +``` + +Quando o limite é alcançado, o agente recebe um prompt especial do sistema instruindo-o a responder com um resumo de seu trabalho e tarefas recomendadas restantes. + +:::caution +O campo legado `maxSteps` está obsoleto. Use `steps` em vez disso. +::: + +--- + +### Desativar + +Defina como `true` para desativar o agente. + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### Prompt + +Especifique um arquivo de prompt do sistema personalizado para este agente com a configuração `prompt`. O arquivo de prompt deve conter instruções específicas para o propósito do agente. + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Este caminho é relativo ao local onde o arquivo de configuração está localizado. Portanto, isso funciona tanto para a configuração global do opencode quanto para a configuração específica do projeto. + +--- + +### Modelo + +Use a configuração `model` para substituir o modelo para este agente. Útil para usar diferentes modelos otimizados para diferentes tarefas. Por exemplo, um modelo mais rápido para planejamento, um modelo mais capaz para implementação. + +:::tip +Se você não especificar um modelo, os agentes primários usam o [modelo configurado globalmente](/docs/config#models) enquanto subagentes usarão o modelo do agente primário que invocou o subagente. +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +O ID do modelo em sua configuração do opencode usa o formato `provider/model-id`. Por exemplo, se você estiver usando [OpenCode Zen](/docs/zen), você usaria `opencode/gpt-5.1-codex` para GPT 5.1 Codex. + +--- + +### Ferramentas + +Controle quais ferramentas estão disponíveis neste agente com a configuração `tools`. Você pode habilitar ou desabilitar ferramentas específicas definindo-as como `true` ou `false`. + +```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 +A configuração específica do agente substitui a configuração global. +::: + +Você também pode usar curingas para controlar várias ferramentas ao mesmo tempo. Por exemplo, para desativar todas as ferramentas de um servidor MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[Saiba mais sobre ferramentas](/docs/tools). + +--- + +### Permissões + +Você pode configurar permissões para gerenciar quais ações um agente pode realizar. Atualmente, as permissões para as ferramentas `edit`, `bash` e `webfetch` podem ser configuradas para: + +- `"ask"` — Solicitar aprovação antes de executar a ferramenta +- `"allow"` — Permitir todas as operações sem aprovação +- `"deny"` — Desativar a ferramenta + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +Você pode substituir essas permissões por agente. + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +Você também pode definir permissões em agentes Markdown. + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Revisão de código sem edições +mode: subagent +permission: + edit: deny + bash: + "*": ask + "git diff": allow + "git log*": allow + "grep *": allow + webfetch: deny +--- + +Apenas analise o código e sugira alterações. +``` + +Você pode definir permissões para comandos bash específicos. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +Isso pode aceitar um padrão glob. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +E você também pode usar o curinga `*` para gerenciar permissões para todos os comandos. +Como a última regra correspondente tem precedência, coloque o curinga `*` primeiro e regras específicas depois. + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[Saiba mais sobre permissões](/docs/permissions). + +--- + +### Modo + +Controle o modo do agente com a configuração `mode`. A opção `mode` é usada para determinar como o agente pode ser usado. + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +A opção `mode` pode ser definida como `primary`, `subagent` ou `all`. Se nenhum `mode` for especificado, o padrão é `all`. + +--- + +### Oculto + +Oculte um subagente do menu de autocompletar `@` com `hidden: true`. Útil para subagentes internos que devem ser invocados apenas programaticamente por outros agentes através da ferramenta Task. + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +Isso afeta apenas a visibilidade do usuário no menu de autocompletar. Agentes ocultos ainda podem ser invocados pelo modelo através da ferramenta Task, se as permissões permitirem. + +:::note +Aplica-se apenas a agentes `mode: subagent`. +::: + +--- + +### Permissões de tarefa + +Controle quais subagentes um agente pode invocar através da ferramenta Task com `permission.task`. Usa padrões globais para correspondência flexível. + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +Quando definido como `deny`, o subagente é removido da descrição da ferramenta Task completamente, então o modelo não tentará invocá-lo. + +:::tip +As regras são avaliadas em ordem, e a **última regra correspondente vence**. No exemplo acima, `orchestrator-planner` corresponde a ambos `*` (deny) e `orchestrator-*` (allow), mas como `orchestrator-*` vem depois de `*`, o resultado é `allow`. +::: + +:::tip +Os usuários sempre podem invocar qualquer subagente diretamente através do menu de autocompletar `@`, mesmo que as permissões de tarefa do agente o neguem. +::: + +--- + +### Cor + +Personalize a aparência visual do agente na interface com a opção `color`. Isso afeta como o agente aparece na interface. + +Use uma cor hex válida (por exemplo, `#FF5733`) ou cor de tema: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +Controle a diversidade das respostas com a opção `top_p`. Alternativa à temperatura para controlar a aleatoriedade. + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +Os valores variam de 0.0 a 1.0. Valores mais baixos são mais focados, valores mais altos são mais diversos. + +--- + +### Adicional + +Quaisquer outras opções que você especificar em sua configuração de agente serão **passadas diretamente** para o provedor como opções de modelo. Isso permite que você use recursos e parâmetros específicos do provedor. + +Por exemplo, com os modelos de raciocínio da OpenAI, você pode controlar o esforço de raciocínio: + +```json title="opencode.json" {6,7} +{ + "agent": { + "deep-thinker": { + "description": "Agente que usa alto esforço de raciocínio para problemas complexos", + "model": "openai/gpt-5", + "reasoningEffort": "high", + "textVerbosity": "low" + } + } +} +``` + +Essas opções adicionais são específicas do modelo e do provedor. Verifique a documentação do seu provedor para parâmetros disponíveis. + +:::tip +Execute `opencode models` para ver uma lista dos modelos disponíveis. +::: + +--- + +## Criando agentes + +Você pode criar novos agentes usando o seguinte comando: + +```bash +opencode agent create +``` + +Este comando interativo irá: + +1. Perguntar onde salvar o agente; global ou específico do projeto. +2. Descrição do que o agente deve fazer. +3. Gerar um prompt de sistema apropriado e identificador. +4. Permitir que você selecione quais ferramentas o agente pode acessar. +5. Finalmente, criar um arquivo markdown com a configuração do agente. + +--- + +## Casos de uso + +Aqui estão alguns casos de uso comuns para diferentes agentes. + +- **Agente Build**: Trabalho de desenvolvimento completo com todas as ferramentas habilitadas +- **Agente Plan**: Análise e planejamento sem fazer alterações +- **Agente Review**: Revisão de código com acesso somente leitura e ferramentas de documentação +- **Agente Debug**: Focado em investigação com ferramentas bash e de leitura habilitadas +- **Agente Docs**: Redação de documentação com operações de arquivo, mas sem comandos do sistema + +--- + +## Exemplos + +Aqui estão alguns agentes de exemplo que você pode achar úteis. + +:::tip +Você tem um agente que gostaria de compartilhar? [Envie um PR](https://github.com/anomalyco/opencode). +::: + +--- + +### Agente de documentação + +```markdown title="~/.config/opencode/agents/docs-writer.md" +--- +description: Escreve e mantém a documentação do projeto +mode: subagent +tools: + bash: false +--- + +Você é um escritor técnico. Crie documentação clara e abrangente. + +Foque em: + +- Explicações claras +- Estrutura adequada +- Exemplos de código +- Linguagem amigável ao usuário +``` + +--- + +### Auditor de segurança + +```markdown title="~/.config/opencode/agents/security-auditor.md" +--- +description: Realiza auditorias de segurança e identifica vulnerabilidades +mode: subagent +tools: + write: false + edit: false +--- + +Você é um especialista em segurança. Foque em identificar potenciais problemas de segurança. + +Procure por: + +- Vulnerabilidades de validação de entrada +- Falhas de autenticação e autorização +- Riscos de exposição de dados +- Vulnerabilidades de dependência +- Problemas de segurança de configuração +``` diff --git a/packages/web/src/content/docs/pt-br/cli.mdx b/packages/web/src/content/docs/pt-br/cli.mdx new file mode 100644 index 00000000000..0edaaadea8a --- /dev/null +++ b/packages/web/src/content/docs/pt-br/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: Opções e comandos da CLI do opencode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +A CLI do opencode, por padrão, inicia o [TUI](/docs/tui) quando executada sem argumentos. + +```bash +opencode +``` + +Mas também aceita comandos conforme documentado nesta página. Isso permite que você interaja com o opencode programaticamente. + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +Inicie a interface de usuário do terminal do opencode. + +```bash +opencode [project] +``` + +#### Opções + +| Flag | Curto | Descrição | +| ------------ | ----- | -------------------------------------------------------------------------- | +| `--continue` | `-c` | Continue a última sessão | +| `--session` | `-s` | ID da sessão para continuar | +| `--fork` | | Criar um fork da sessão ao continuar (use com `--continue` ou `--session`) | +| `--prompt` | | Prompt a ser usado | +| `--model` | `-m` | Modelo a ser usado na forma de provider/model | +| `--agent` | | Agente a ser usado | +| `--port` | | Porta para escutar | +| `--hostname` | | Nome do host para escutar | + +--- + +## Comandos + +A CLI do opencode também possui os seguintes comandos. + +--- + +### agent + +Gerencie agentes para o opencode. + +```bash +opencode agent [command] +``` + +--- + +### attach + +Anexe um terminal a um servidor backend do opencode já em execução, iniciado via comandos `serve` ou `web`. + +```bash +opencode attach [url] +``` + +Isso permite usar o TUI com um backend opencode remoto. Por exemplo: + +```bash +# Inicie o servidor backend para acesso web/mobile +opencode web --port 4096 --hostname 0.0.0.0 + +# Em outro terminal, anexe o TUI ao backend em execução +opencode attach http://10.20.30.40:4096 +``` + +#### Opções + +| Flag | Curto | Descrição | +| ----------- | ----- | ---------------------------------------- | +| `--dir` | | Diretório de trabalho para iniciar o TUI | +| `--session` | `-s` | ID da sessão para continuar | + +--- + +#### create + +Crie um novo agente com configuração personalizada. + +```bash +opencode agent create +``` + +Este comando irá guiá-lo na criação de um novo agente com um prompt de sistema personalizado e configuração de ferramentas. + +--- + +#### list + +Liste todos os agentes disponíveis. + +```bash +opencode agent list +``` + +--- + +### auth + +Comando para gerenciar credenciais e login para provedores. + +```bash +opencode auth [command] +``` + +--- + +#### login + +O opencode é alimentado pela lista de provedores em [Models.dev](https://models.dev), então você pode usar `opencode auth login` para configurar chaves de API para qualquer provedor que você gostaria de usar. Isso é armazenado em `~/.local/share/opencode/auth.json`. + +```bash +opencode auth login +``` + +Quando o opencode é iniciado, ele carrega os provedores do arquivo de credenciais. E se houver chaves definidas em seus ambientes ou em um arquivo `.env` em seu projeto. + +--- + +#### list + +Lista todos os provedores autenticados conforme armazenado no arquivo de credenciais. + +```bash +opencode auth list +``` + +Ou a versão curta. + +```bash +opencode auth ls +``` + +--- + +#### logout + +Desconecta você de um provedor limpando-o do arquivo de credenciais. + +```bash +opencode auth logout +``` + +--- + +### github + +Gerencie o agente do GitHub para automação de repositórios. + +```bash +opencode github [command] +``` + +--- + +#### install + +Instale o agente do GitHub em seu repositório. + +```bash +opencode github install +``` + +Isso configura o fluxo de trabalho necessário do GitHub Actions e o guia pelo processo de configuração. [Saiba mais](/docs/github). + +--- + +#### run + +Execute o agente do GitHub. Isso é tipicamente usado em GitHub Actions. + +```bash +opencode github run +``` + +##### Opções + +| Flag | Descrição | +| --------- | ------------------------------------------------ | +| `--event` | Evento simulado do GitHub para executar o agente | +| `--token` | Token de acesso pessoal do GitHub | + +--- + +### mcp + +Gerencie servidores do Model Context Protocol. + +```bash +opencode mcp [command] +``` + +--- + +#### add + +Adicione um servidor MCP à sua configuração. + +```bash +opencode mcp add +``` + +Este comando irá guiá-lo na adição de um servidor MCP local ou remoto. + +--- + +#### list + +Liste todos os servidores MCP configurados e seu status de conexão. + +```bash +opencode mcp list +``` + +Ou use a versão curta. + +```bash +opencode mcp ls +``` + +--- + +#### auth + +Autentique-se com um servidor MCP habilitado para OAuth. + +```bash +opencode mcp auth [name] +``` + +Se você não fornecer um nome de servidor, será solicitado que você selecione entre os servidores disponíveis habilitados para OAuth. + +Você também pode listar servidores habilitados para OAuth e seu status de autenticação. + +```bash +opencode mcp auth list +``` + +Ou use a versão curta. + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +Remova credenciais OAuth para um servidor MCP. + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +Depure problemas de conexão OAuth para um servidor MCP. + +```bash +opencode mcp debug +``` + +--- + +### models + +Liste todos os modelos disponíveis dos provedores configurados. + +```bash +opencode models [provider] +``` + +Este comando exibe todos os modelos disponíveis entre seus provedores configurados no formato `provider/model`. + +Isso é útil para descobrir o nome exato do modelo a ser usado em [sua configuração](/docs/config/). + +Você pode opcionalmente passar um ID de provedor para filtrar modelos por esse provedor. + +```bash +opencode models anthropic +``` + +#### Opções + +| Flag | Descrição | +| ----------- | --------------------------------------------------------------------- | +| `--refresh` | Atualiza o cache de modelos a partir do models.dev | +| `--verbose` | Use uma saída de modelo mais detalhada (inclui metadados como custos) | + +Use a flag `--refresh` para atualizar a lista de modelos em cache. Isso é útil quando novos modelos foram adicionados a um provedor e você deseja vê-los no opencode. + +```bash +opencode models --refresh +``` + +--- + +### run + +Execute o opencode em modo não interativo passando um prompt diretamente. + +```bash +opencode run [message..] +``` + +Isso é útil para scripts, automação ou quando você deseja uma resposta rápida sem iniciar o TUI completo. Por exemplo. + +```bash "opencode run" +opencode run Explique o uso de context em Go +``` + +Você também pode se anexar a uma instância em execução do `opencode serve` para evitar tempos de inicialização a frio do servidor MCP em cada execução: + +```bash +# Inicie um servidor sem cabeça em um terminal +opencode serve + +# Em outro terminal, execute comandos que se anexam a ele +opencode run --attach http://localhost:4096 "Explique async/await em JavaScript" +``` + +#### Opções + +| Flag | Curto | Descrição | +| ------------ | ----- | ----------------------------------------------------------------------------- | +| `--command` | | O comando a ser executado, use mensagem para argumentos | +| `--continue` | `-c` | Continue a última sessão | +| `--session` | `-s` | ID da sessão para continuar | +| `--fork` | | Criar um fork da sessão ao continuar (use com `--continue` ou `--session`) | +| `--share` | | Compartilhe a sessão | +| `--model` | `-m` | Modelo a ser usado na forma de provider/model | +| `--agent` | | Agente a ser usado | +| `--file` | `-f` | Arquivo(s) a serem anexados à mensagem | +| `--format` | | Formato: padrão (formatado) ou json (eventos JSON brutos) | +| `--title` | | Título para a sessão (usa o prompt truncado se nenhum valor for fornecido) | +| `--attach` | | Anexe a um servidor opencode em execução (por exemplo, http://localhost:4096) | +| `--port` | | Porta para o servidor local (padrão para porta aleatória) | + +--- + +### serve + +Inicie um servidor opencode sem cabeça para acesso à API. Confira a [documentação do servidor](/docs/server) para a interface HTTP completa. + +```bash +opencode serve +``` + +Isso inicia um servidor HTTP que fornece acesso à funcionalidade do opencode sem a interface TUI. Defina `OPENCODE_SERVER_PASSWORD` para habilitar a autenticação básica HTTP (o nome de usuário padrão é `opencode`). + +#### Opções + +| Flag | Descrição | +| ------------ | ----------------------------------------------------- | +| `--port` | Porta para escutar | +| `--hostname` | Nome do host para escutar | +| `--mdns` | Habilitar descoberta mDNS | +| `--cors` | Origem(ns) de navegador adicionais para permitir CORS | + +--- + +### session + +Gerencie sessões do opencode. + +```bash +opencode session [command] +``` + +--- + +#### list + +Liste todas as sessões do opencode. + +```bash +opencode session list +``` + +##### Opções + +| Flag | Curto | Descrição | +| ------------- | ----- | ----------------------------------------- | +| `--max-count` | `-n` | Limitar às N sessões mais recentes | +| `--format` | | Formato de saída: tabela ou json (tabela) | + +--- + +### stats + +Mostre o uso de tokens e estatísticas de custo para suas sessões do opencode. + +```bash +opencode stats +``` + +#### Opções + +| Flag | Descrição | +| ----------- | ---------------------------------------------------------------------------------------------------- | +| `--days` | Mostre estatísticas dos últimos N dias (todo o tempo) | +| `--tools` | Número de ferramentas a serem mostradas (todas) | +| `--models` | Mostre a divisão do uso de modelos (oculto por padrão). Passe um número para mostrar os N principais | +| `--project` | Filtrar por projeto (todos os projetos, string vazia: projeto atual) | + +--- + +### export + +Exporte dados da sessão como JSON. + +```bash +opencode export [sessionID] +``` + +Se você não fornecer um ID de sessão, será solicitado que você selecione entre as sessões disponíveis. + +--- + +### import + +Importe dados da sessão de um arquivo JSON ou URL de compartilhamento do opencode. + +```bash +opencode import +``` + +Você pode importar de um arquivo local ou de uma URL de compartilhamento do opencode. + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +Inicie um servidor opencode sem cabeça com uma interface web. + +```bash +opencode web +``` + +Isso inicia um servidor HTTP e abre um navegador para acessar o opencode através de uma interface web. Defina `OPENCODE_SERVER_PASSWORD` para habilitar a autenticação básica HTTP (o nome de usuário padrão é `opencode`). + +#### Opções + +| Flag | Descrição | +| ------------ | ----------------------------------------------------- | +| `--port` | Porta para escutar | +| `--hostname` | Nome do host para escutar | +| `--mdns` | Habilitar descoberta mDNS | +| `--cors` | Origem(ns) de navegador adicionais para permitir CORS | + +--- + +### acp + +Inicie um servidor ACP (Agent Client Protocol). + +```bash +opencode acp +``` + +Este comando inicia um servidor ACP que se comunica via stdin/stdout usando nd-JSON. + +#### Opções + +| Flag | Descrição | +| ------------ | ------------------------- | +| `--cwd` | Diretório de trabalho | +| `--port` | Porta para escutar | +| `--hostname` | Nome do host para escutar | + +--- + +### uninstall + +Desinstale o opencode e remova todos os arquivos relacionados. + +```bash +opencode uninstall +``` + +#### Opções + +| Flag | Curto | Descrição | +| --------------- | ----- | ---------------------------------------- | +| `--keep-config` | `-c` | Manter arquivos de configuração | +| `--keep-data` | `-d` | Manter dados de sessão e snapshots | +| `--dry-run` | | Mostrar o que seria removido sem remover | +| `--force` | `-f` | Pular prompts de confirmação | + +--- + +### upgrade + +Atualiza o opencode para a versão mais recente ou uma versão específica. + +```bash +opencode upgrade [target] +``` + +Para atualizar para a versão mais recente. + +```bash +opencode upgrade +``` + +Para atualizar para uma versão específica. + +```bash +opencode upgrade v0.1.48 +``` + +#### Opções + +| Flag | Curto | Descrição | +| ---------- | ----- | ---------------------------------------------------------------- | +| `--method` | `-m` | O método de instalação que foi usado; curl, npm, pnpm, bun, brew | + +--- + +## Opções Globais + +A CLI do opencode aceita as seguintes flags globais. + +| Flag | Curto | Descrição | +| -------------- | ----- | --------------------------------------- | +| `--help` | `-h` | Exibir ajuda | +| `--version` | `-v` | Imprimir número da versão | +| `--print-logs` | | Imprimir logs no stderr | +| `--log-level` | | Nível de log (DEBUG, INFO, WARN, ERROR) | + +--- + +## Variáveis de ambiente + +O opencode pode ser configurado usando variáveis de ambiente. + +| Variável | Tipo | Descrição | +| ------------------------------------- | ------- | --------------------------------------------------------------------- | +| `OPENCODE_AUTO_SHARE` | boolean | Compartilhar sessões automaticamente | +| `OPENCODE_GIT_BASH_PATH` | string | Caminho para o executável do Git Bash no Windows | +| `OPENCODE_CONFIG` | string | Caminho para o arquivo de configuração | +| `OPENCODE_CONFIG_DIR` | string | Caminho para o diretório de configuração | +| `OPENCODE_CONFIG_CONTENT` | string | Conteúdo de configuração json inline | +| `OPENCODE_DISABLE_AUTOUPDATE` | boolean | Desabilitar verificações de atualização automática | +| `OPENCODE_DISABLE_PRUNE` | boolean | Desabilitar a poda de dados antigos | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | Desabilitar atualizações automáticas do título do terminal | +| `OPENCODE_PERMISSION` | string | Configuração de permissões json inline | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | Desabilitar plugins padrão | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | Desabilitar downloads automáticos do servidor LSP | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | Habilitar modelos experimentais | +| `OPENCODE_DISABLE_AUTOCOMPACT` | boolean | Desabilitar compactação automática de contexto | +| `OPENCODE_DISABLE_CLAUDE_CODE` | boolean | Desabilitar leitura de `.claude` (prompt + habilidades) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | Desabilitar leitura de `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | Desabilitar carregamento de `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | boolean | Desabilitar busca de modelos de fontes remotas | +| `OPENCODE_FAKE_VCS` | string | Provedor VCS falso para fins de teste | +| `OPENCODE_DISABLE_FILETIME_CHECK` | boolean | Desabilitar verificação de tempo de arquivo para otimização | +| `OPENCODE_CLIENT` | string | Identificador do cliente (padrão é `cli`) | +| `OPENCODE_ENABLE_EXA` | boolean | Habilitar ferramentas de busca web Exa | +| `OPENCODE_SERVER_PASSWORD` | string | Habilitar autenticação básica para `serve`/`web` | +| `OPENCODE_SERVER_USERNAME` | string | Substituir nome de usuário de autenticação básica (padrão `opencode`) | +| `OPENCODE_MODELS_URL` | string | URL personalizada para buscar configuração de modelos | + +--- + +### Experimental + +Essas variáveis de ambiente habilitam recursos experimentais que podem mudar ou ser removidos. + +| Variável | Tipo | Descrição | +| ----------------------------------------------- | ------- | --------------------------------------------------------- | +| `OPENCODE_EXPERIMENTAL` | boolean | Habilitar todos os recursos experimentais | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | Habilitar descoberta de ícones | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | Desabilitar cópia ao selecionar no TUI | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number | Tempo limite padrão para comandos bash em ms | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | number | Máximo de tokens de saída para respostas LLM | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolean | Habilitar monitoramento de arquivos para todo o diretório | +| `OPENCODE_EXPERIMENTAL_OXFMT` | boolean | Habilitar formatador oxfmt | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolean | Habilitar ferramenta LSP experimental | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | Desabilitar monitoramento de arquivos | +| `OPENCODE_EXPERIMENTAL_EXA` | boolean | Habilitar recursos experimentais do Exa | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolean | Habilitar verificação de tipo LSP experimental | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolean | Habilitar recursos experimentais de markdown | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolean | Habilitar modo de plano | diff --git a/packages/web/src/content/docs/pt-br/commands.mdx b/packages/web/src/content/docs/pt-br/commands.mdx new file mode 100644 index 00000000000..b4a8a306d8d --- /dev/null +++ b/packages/web/src/content/docs/pt-br/commands.mdx @@ -0,0 +1,322 @@ +--- +title: Comandos +description: Crie comandos personalizados para tarefas repetitivas. +--- + +Comandos personalizados permitem que você especifique um prompt que deseja executar quando esse comando for executado no TUI. + +```bash frame="none" +/my-command +``` + +Comandos personalizados são adicionais aos comandos integrados como `/init`, `/undo`, `/redo`, `/share`, `/help`. [Saiba mais](/docs/tui#commands). + +--- + +## Criando arquivos de comando + +Crie arquivos markdown no diretório `commands/` para definir comandos personalizados. + +Crie `.opencode/commands/test.md`: + +```md title=".opencode/commands/test.md" +--- +description: Execute testes com cobertura +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Execute a suíte de testes completa com relatório de cobertura e mostre quaisquer falhas. +Concentre-se nos testes com falha e sugira correções. +``` + +O frontmatter define as propriedades do comando. O conteúdo se torna o template. + +Use o comando digitando `/` seguido pelo nome do comando. + +```bash frame="none" +"/test" +``` + +--- + +## Configuração + +Você pode adicionar comandos personalizados através da configuração do opencode ou criando arquivos markdown no diretório `commands/`. + +--- + +### JSON + +Use a opção `command` na sua [configuração](/docs/config) do opencode: + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // Isso se torna o nome do comando + "test": { + // Este é o prompt que será enviado ao LLM + "template": "Execute a suíte de testes completa com relatório de cobertura e mostre quaisquer falhas.\nConcentre-se nos testes com falha e sugira correções.", + // Isso é exibido como a descrição no TUI + "description": "Execute testes com cobertura", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Agora você pode executar este comando no TUI: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +Você também pode definir comandos usando arquivos markdown. Coloque-os em: + +- Global: `~/.config/opencode/commands/` +- Por projeto: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Execute testes com cobertura +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Execute a suíte de testes completa com relatório de cobertura e mostre quaisquer falhas. +Concentre-se nos testes com falha e sugira correções. +``` + +O nome do arquivo markdown se torna o nome do comando. Por exemplo, `test.md` permite que você execute: + +```bash frame="none" +/test +``` + +--- + +## Configuração do prompt + +Os prompts para os comandos personalizados suportam vários espaços reservados e sintaxes especiais. + +--- + +### Argumentos + +Passe argumentos para os comandos usando o espaço reservado `$ARGUMENTS`. + +```md title=".opencode/commands/component.md" +--- +description: Crie um novo componente +--- + +Crie um novo componente React chamado $ARGUMENTS com suporte a TypeScript. +Inclua tipagem adequada e estrutura básica. +``` + +Execute o comando com argumentos: + +```bash frame="none" +/component Button +``` + +E `$ARGUMENTS` será substituído por `Button`. + +Você também pode acessar argumentos individuais usando parâmetros posicionais: + +- `$1` - Primeiro argumento +- `$2` - Segundo argumento +- `$3` - Terceiro argumento +- E assim por diante... + +Por exemplo: + +```md title=".opencode/commands/create-file.md" +--- +description: Crie um novo arquivo com conteúdo +--- + +Crie um arquivo chamado $1 no diretório $2 +com o seguinte conteúdo: $3 +``` + +Execute o comando: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +Isso substitui: + +- `$1` por `config.json` +- `$2` por `src` +- `$3` por `{ "key": "value" }` + +--- + +### Saída do shell + +Use _!`command`_ para injetar a saída do [comando bash](/docs/tui#bash-commands) no seu prompt. + +Por exemplo, para criar um comando personalizado que analisa a cobertura de testes: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analise cobertura de testes +--- + +Aqui estão os resultados atuais dos testes: +!`npm test` + +Com base nesses resultados, sugira melhorias para aumentar a cobertura. +``` + +Ou para revisar alterações recentes: + +```md title=".opencode/commands/review-changes.md" +--- +description: Revise alterações recentes +--- + +Commits recentes do git: +!`git log --oneline -10` + +Revise essas alterações e sugira quaisquer melhorias. +``` + +Os comandos são executados no diretório raiz do seu projeto e sua saída se torna parte do prompt. + +--- + +### Referências de arquivo + +Inclua arquivos no seu comando usando `@` seguido pelo nome do arquivo. + +```md title=".opencode/commands/review-component.md" +--- +description: Revise componente +--- + +Revise o componente em @src/components/Button.tsx. +Verifique problemas de desempenho e sugira melhorias. +``` + +O conteúdo do arquivo é incluído automaticamente no prompt. + +--- + +## Opções + +Vamos analisar as opções de configuração em detalhes. + +--- + +### Template + +A opção `template` define o prompt que será enviado ao LLM quando o comando for executado. + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Execute a suíte de testes completa com relatório de cobertura e mostre quaisquer falhas.\nConcentre-se nos testes com falha e sugira correções." + } + } +} +``` + +Esta é uma opção de configuração **obrigatória**. + +--- + +### Descrição + +Use a opção `description` para fornecer uma breve descrição do que o comando faz. + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Execute testes com cobertura" + } + } +} +``` + +Isso é exibido como a descrição no TUI quando você digita o comando. + +--- + +### Agente + +Use a configuração `agent` para especificar opcionalmente qual [agente](/docs/agents) deve executar este comando. +Se este for um [subagente](/docs/agents/#subagents), o comando acionará uma invocação de subagente por padrão. +Para desativar esse comportamento, defina `subtask` como `false`. + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +Esta é uma opção de configuração **opcional**. Se não especificado, o padrão é o seu agente atual. + +--- + +### Subtarefa + +Use o booleano `subtask` para forçar o comando a acionar uma invocação de [subagente](/docs/agents/#subagents). +Isso é útil se você quiser que o comando não polua seu contexto principal e **forçará** o agente a agir como um subagente, +mesmo que `mode` esteja definido como `primary` na configuração do [agente](/docs/agents). + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +Esta é uma opção de configuração **opcional**. + +--- + +### Modelo + +Use a configuração `model` para substituir o modelo padrão para este comando. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Esta é uma opção de configuração **opcional**. + +--- + +## Integrados + +opencode inclui vários comandos integrados como `/init`, `/undo`, `/redo`, `/share`, `/help`; [saiba mais](/docs/tui#commands). + +:::note +Comandos personalizados podem substituir comandos integrados. +::: + +Se você definir um comando personalizado com o mesmo nome, ele substituirá o comando integrado. diff --git a/packages/web/src/content/docs/pt-br/config.mdx b/packages/web/src/content/docs/pt-br/config.mdx new file mode 100644 index 00000000000..405c5379456 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/config.mdx @@ -0,0 +1,681 @@ +--- +title: Configuração +description: Usando a configuração JSON do opencode. +--- + +Você pode configurar o opencode usando um arquivo de configuração JSON. + +--- + +## Formato + +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, +} +``` + +--- + +## Locais + +Você pode colocar sua configuração em alguns locais diferentes e eles têm uma +ordem de precedência diferente. + +:::note +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. + +--- + +### Ordem de precedência + +As fontes de configuração são carregadas nesta ordem (fontes posteriores substituem as anteriores): + +1. **Configuração remota** (de `.well-known/opencode`) - padrões organizacionais +2. **Configuração global** (`~/.config/opencode/opencode.json`) - preferências do usuário +3. **Configuração personalizada** (`OPENCODE_CONFIG` var de ambiente) - substituições personalizadas +4. **Configuração do projeto** (`opencode.json` no projeto) - configurações específicas do projeto +5. **Diretórios `.opencode`** - agentes, comandos, plugins +6. **Configuração inline** (`OPENCODE_CONFIG_CONTENT` var de ambiente) - substituições em tempo de execução + +Isso significa que as configurações do projeto podem substituir os padrões globais, e as configurações globais podem substituir os padrões organizacionais remotos. + +:::note +Os diretórios `.opencode` e `~/.config/opencode` usam **nomes no plural** para subdiretórios: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/`, e `themes/`. Nomes no singular (por exemplo, `agent/`) também são suportados para compatibilidade retroativa. +::: + +--- + +### Remoto + +As organizações podem fornecer configuração padrão através do endpoint `.well-known/opencode`. Isso é buscado automaticamente quando você se autentica com um provedor que o suporta. + +A configuração remota é carregada primeiro, servindo como a camada base. Todas as outras fontes de configuração (global, projeto) podem substituir esses padrões. + +Por exemplo, se sua organização fornece servidores MCP que estão desativados por padrão: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +Você pode habilitar servidores específicos em sua configuração local: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### 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. + +A configuração global substitui os padrões organizacionais remotos. + +--- + +### Por projeto + +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. + +:::tip +Coloque a configuração específica do projeto na raiz do seu projeto. +::: + +Quando o opencode é iniciado, ele procura um arquivo de configuração no diretório atual ou sobe até o diretório Git mais próximo. + +Isso também é seguro para ser verificado no Git e usa o mesmo esquema que o global. + +--- + +### Caminho personalizado + +Especifique um caminho de arquivo de configuração personalizado usando a variável de ambiente `OPENCODE_CONFIG`. + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +A configuração personalizada é carregada entre as configurações globais e do projeto na ordem de precedência. + +--- + +### Diretório personalizado + +Especifique um diretório de configuração personalizado usando a variável de ambiente `OPENCODE_CONFIG_DIR`. Este diretório será pesquisado por agentes, comandos, modos e plugins, assim como o diretório padrão `.opencode`, e deve seguir a mesma estrutura. + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +O diretório personalizado é carregado após a configuração global e os diretórios `.opencode`, então ele **pode substituir** suas configurações. + +--- + +## Esquema + +O arquivo de configuração tem um esquema que está definido em [**`opencode.ai/config.json`**](https://opencode.ai/config.json). + +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`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +Opções disponíveis: + +- `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. + +[Saiba mais sobre o uso do TUI aqui](/docs/tui). + +--- + +### Servidor + +Você pode configurar as configurações do servidor para os comandos `opencode serve` e `opencode web` através da opção `server`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +Opções disponíveis: + +- `port` - Porta para escutar. +- `hostname` - Nome do host para escutar. Quando `mdns` está habilitado e nenhum nome de host está definido, o padrão é `0.0.0.0`. +- `mdns` - Habilitar descoberta de serviço mDNS. Isso permite que outros dispositivos na rede descubram seu servidor opencode. +- `mdnsDomain` - Nome de domínio personalizado para o serviço mDNS. O padrão é `opencode.local`. Útil para executar várias instâncias na mesma rede. +- `cors` - Origens adicionais a serem permitidas para CORS ao usar o servidor HTTP de um cliente baseado em navegador. Os valores devem ser origens completas (esquema + host + porta opcional), por exemplo, `https://app.example.com`. + +[Saiba mais sobre o servidor aqui](/docs/server). + +--- + +### Ferramentas + +Você pode gerenciar as ferramentas que um LLM pode usar através da opção `tools`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[Saiba mais sobre ferramentas aqui](/docs/tools). + +--- + +### Modelos + +Você pode configurar os provedores e modelos que deseja usar em sua configuração do opencode através das opções `provider`, `model` e `small_model`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +A opção `small_model` configura um modelo separado para tarefas leves, como geração de títulos. Por padrão, o opencode tenta usar um modelo mais barato se um estiver disponível do seu provedor, caso contrário, ele recua para seu modelo principal. + +As opções do provedor podem incluir `timeout` e `setCacheKey`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` - Tempo limite da solicitação em milissegundos (padrão: 300000). Defina como `false` para desabilitar. +- `setCacheKey` - Garantir que uma chave de cache seja sempre definida para o provedor designado. + +Você também pode configurar [modelos locais](/docs/models#local). [Saiba mais](/docs/models). + +--- + +#### Opções Específicas do Provedor + +Alguns provedores suportam opções de configuração adicionais além das configurações genéricas `timeout` e `apiKey`. + +##### Amazon Bedrock + +Amazon Bedrock suporta configuração específica da AWS: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` - Região AWS para Bedrock (padrão para `AWS_REGION` var de ambiente ou `us-east-1`) +- `profile` - Perfil nomeado da AWS em `~/.aws/credentials` (padrão para `AWS_PROFILE` var de ambiente) +- `endpoint` - URL de endpoint personalizada para endpoints VPC. Este é um alias para a opção genérica `baseURL` usando terminologia específica da AWS. Se ambos forem especificados, `endpoint` tem precedência. + +:::note +Tokens Bearer (`AWS_BEARER_TOKEN_BEDROCK` ou `/connect`) têm precedência sobre a autenticação baseada em perfil. Veja [precedência de autenticação](/docs/providers#authentication-precedence) para detalhes. +::: + +[Saiba mais sobre a configuração do Amazon Bedrock](/docs/providers#amazon-bedrock). + +--- + +### Temas + +Você pode configurar o tema que deseja usar em sua configuração do opencode através da opção `theme`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[Saiba mais aqui](/docs/themes). + +--- + +### Agentes + +Você pode configurar agentes especializados para tarefas específicas através da opção `agent`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Revisa código para melhores práticas e potenciais problemas", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "Você é um revisor de código. Foque em segurança, performance e manutenibilidade.", + "tools": { + // Desabilitar ferramentas de modificação de arquivo para agente de apenas revisão + "write": false, + "edit": false, + }, + }, + }, +} +``` + +Você também pode definir agentes usando arquivos markdown em `~/.config/opencode/agents/` ou `.opencode/agents/`. [Saiba mais aqui](/docs/agents). + +--- + +### Agente padrão + +Você pode definir o agente padrão usando a opção `default_agent`. Isso determina qual agente é usado quando nenhum é explicitamente especificado. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +O agente padrão deve ser um agente primário (não um subagente). Isso pode ser um agente embutido como `"build"` ou `"plan"`, ou um [agente personalizado](/docs/agents) que você definiu. Se o agente especificado não existir ou for um subagente, o opencode recuará para `"build"` com um aviso. + +Essa configuração se aplica a todas as interfaces: TUI, CLI (`opencode run`), aplicativo desktop e GitHub Action. + +--- + +### Compartilhamento + +Você pode configurar o recurso [share](/docs/share) através da opção `share`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +Isso aceita: + +- `"manual"` - Permitir compartilhamento manual via comandos (padrão) +- `"auto"` - Compartilhar novas conversas automaticamente +- `"disabled"` - Desabilitar compartilhamento completamente + +Por padrão, o compartilhamento é definido para o modo manual, onde você precisa compartilhar explicitamente as conversas usando o comando `/share`. + +--- + +### Comandos + +Você pode configurar comandos personalizados para tarefas repetitivas através da opção `command`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Execute a suíte de testes completa com relatório de cobertura e mostre quaisquer falhas.\nConcentre-se nos testes com falha e sugira correções.", + "description": "Execute testes com cobertura", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Crie um novo componente React chamado $ARGUMENTS com suporte a TypeScript.\nInclua tipagem adequada e estrutura básica.", + "description": "Crie um novo componente", + }, + }, +} +``` + +Você também pode definir comandos usando arquivos markdown em `~/.config/opencode/commands/` ou `.opencode/commands/`. [Saiba mais aqui](/docs/commands). + +--- + +### Atalhos de teclado + +Você pode personalizar seus atalhos de teclado através da opção `keybinds`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[Saiba mais aqui](/docs/keybinds). + +--- + +### Atualização automática + +O opencode fará o download automaticamente de quaisquer novas atualizações quando for iniciado. Você pode desabilitar isso com a opção `autoupdate`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +Se você não quiser atualizações, mas deseja ser notificado quando uma nova versão estiver disponível, defina `autoupdate` como `"notify"`. +Observe que isso só funciona se não foi instalado usando um gerenciador de pacotes como o Homebrew. + +--- + +### Formatadores + +Você pode configurar formatadores de código através da opção `formatter`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[Saiba mais sobre formatadores aqui](/docs/formatters). + +--- + +### Permissões + +Por padrão, o opencode **permite todas as operações** sem exigir aprovação explícita. Você pode mudar isso usando a opção `permission`. + +Por exemplo, para garantir que as ferramentas `edit` e `bash` exijam aprovação do usuário: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[Saiba mais sobre permissões aqui](/docs/permissions). + +--- + +### Compactação + +Você pode controlar o comportamento de compactação de contexto através da opção `compaction`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `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`). + +--- + +### Observador + +Você pode configurar padrões de ignorar do observador de arquivos através da opção `watcher`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +Os padrões seguem a sintaxe glob. Use isso para excluir diretórios barulhentos da observação de arquivos. + +--- + +### Servidores MCP + +Você pode configurar servidores MCP que deseja usar através da opção `mcp`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[Saiba mais aqui](/docs/mcp-servers). + +--- + +### Plugins + +[Plugins](/docs/plugins) estendem o opencode com ferramentas, hooks e integrações personalizadas. + +Coloque arquivos de plugin em `.opencode/plugins/` ou `~/.config/opencode/plugins/`. Você também pode carregar plugins do npm através da opção `plugin`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[Saiba mais aqui](/docs/plugins). + +--- + +### Instruções + +Você pode configurar as instruções para o modelo que está usando através da opção `instructions`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Isso aceita um array de caminhos e padrões glob para arquivos de instrução. [Saiba mais sobre regras aqui](/docs/rules). + +--- + +### Provedores desabilitados + +Você pode desabilitar provedores que são carregados automaticamente através da opção `disabled_providers`. Isso é útil quando você deseja impedir que certos provedores sejam carregados, mesmo que suas credenciais estejam disponíveis. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +A opção `disabled_providers` tem prioridade sobre `enabled_providers`. +::: + +A opção `disabled_providers` aceita um array de IDs de provedores. Quando um provedor é desabilitado: + +- Ele não será carregado, mesmo que variáveis de ambiente estejam definidas. +- Ele não será carregado, mesmo que chaves de API estejam configuradas através do comando `/connect`. +- Os modelos do provedor não aparecerão na lista de seleção de modelos. + +--- + +### Provedores habilitados + +Você pode especificar uma lista de permissão de provedores através da opção `enabled_providers`. Quando definida, apenas os provedores especificados serão habilitados e todos os outros serão ignorados. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +Isso é útil quando você deseja restringir o opencode para usar apenas provedores específicos, em vez de desabilitá-los um a um. + +:::note +A opção `disabled_providers` tem prioridade sobre `enabled_providers`. +::: + +Se um provedor aparecer em `enabled_providers` e `disabled_providers`, a `disabled_providers` tem prioridade para compatibilidade retroativa. + +--- + +### Experimental + +A chave `experimental` contém opções que estão em desenvolvimento ativo. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +Opções experimentais não são estáveis. Elas podem mudar ou ser removidas sem aviso prévio. +::: + +--- + +## Variáveis + +Você pode usar substituição de variáveis em seus arquivos de configuração para referenciar variáveis de ambiente e conteúdos de arquivos. + +--- + +### Variáveis de ambiente + +Use `{env:VARIABLE_NAME}` para substituir variáveis de ambiente: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +Se a variável de ambiente não estiver definida, ela será substituída por uma string vazia. + +--- + +### Arquivos + +Use `{file:path/to/file}` para substituir o conteúdo de um arquivo: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +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: + +- Manter dados sensíveis, como chaves de API, em arquivos separados. +- Incluir grandes arquivos de instrução sem sobrecarregar sua configuração. +- Compartilhar trechos de configuração comuns entre vários arquivos de configuração. diff --git a/packages/web/src/content/docs/pt-br/custom-tools.mdx b/packages/web/src/content/docs/pt-br/custom-tools.mdx new file mode 100644 index 00000000000..43749200f86 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: Ferramentas Personalizadas +description: Crie ferramentas que o LLM pode chamar no opencode. +--- + +Ferramentas personalizadas são funções que você cria e que o LLM pode chamar durante as conversas. Elas funcionam junto com as [ferramentas integradas](/docs/tools) do opencode, como `read`, `write` e `bash`. + +--- + +## Criando uma ferramenta + +As ferramentas são definidas como arquivos **TypeScript** ou **JavaScript**. No entanto, a definição da ferramenta pode invocar scripts escritos em **qualquer linguagem** — TypeScript ou JavaScript é usado apenas para a definição da ferramenta em si. + +--- + +### Localização + +Elas podem ser definidas: + +- Localmente, colocando-as no diretório `.opencode/tools/` do seu projeto. +- Ou globalmente, colocando-as em `~/.config/opencode/tools/`. + +--- + +### Estrutura + +A maneira mais fácil de criar ferramentas é usando o helper `tool()`, que fornece segurança de tipo e validação. + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Consultar o banco de dados do projeto", + args: { + query: tool.schema.string().describe("Consulta SQL para executar"), + }, + async execute(args) { + // Sua lógica de banco de dados aqui + return `Consulta executada: ${args.query}` + }, +}) +``` + +O **nome do arquivo** se torna o **nome da ferramenta**. O acima cria uma ferramenta `database`. + +--- + +#### Múltiplas ferramentas por arquivo + +Você também pode exportar várias ferramentas de um único arquivo. Cada exportação se torna **uma ferramenta separada** com o nome **`_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Adicionar dois números", + args: { + a: tool.schema.number().describe("Primeiro número"), + b: tool.schema.number().describe("Segundo número"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiplicar dois números", + args: { + a: tool.schema.number().describe("Primeiro número"), + b: tool.schema.number().describe("Segundo número"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +Isso cria duas ferramentas: `math_add` e `math_multiply`. + +--- + +### Argumentos + +Você pode usar `tool.schema`, que é apenas [Zod](https://zod.dev), para definir tipos de argumentos. + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("Consulta SQL para executar") +} +``` + +Você também pode importar [Zod](https://zod.dev) diretamente e retornar um objeto simples: + +```ts {6} +import { z } from "zod" + +export default { + description: "Descrição da ferramenta", + args: { + param: z.string().describe("Descrição do parâmetro"), + }, + async execute(args, context) { + // Implementação da ferramenta + return "result" + }, +} +``` + +--- + +### Contexto + +As ferramentas recebem contexto sobre a sessão atual: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Obter informações do projeto", + args: {}, + async execute(args, context) { + // Acessar informações de contexto + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +Use `context.directory` para o diretório de trabalho da sessão. +Use `context.worktree` para a raiz do worktree do git. + +--- + +## Exemplos + +### Escrevendo uma ferramenta em Python + +Você pode escrever suas ferramentas em qualquer linguagem que desejar. Aqui está um exemplo que adiciona dois números usando Python. + +Primeiro, crie a ferramenta como um script Python: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +Em seguida, crie a definição da ferramenta que a invoca: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Adicionar dois números usando Python", + args: { + a: tool.schema.number().describe("Primeiro número"), + b: tool.schema.number().describe("Segundo número"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +Aqui estamos usando o utilitário [`Bun.$`](https://bun.com/docs/runtime/shell) para executar o script Python. diff --git a/packages/web/src/content/docs/pt-br/ecosystem.mdx b/packages/web/src/content/docs/pt-br/ecosystem.mdx new file mode 100644 index 00000000000..ac5d3544411 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: Ecossistema +description: Projetos e integrações construídos com o opencode. +--- + +Uma coleção de projetos da comunidade construídos sobre o opencode. + +:::note +Quer adicionar seu projeto relacionado ao opencode a esta lista? Envie um PR. +::: + +Você também pode conferir [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) e [opencode.cafe](https://opencode.cafe), uma comunidade que agrega o ecossistema e a comunidade. + +--- + +## Plugins + +| Nome | Descrição | +| --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | Execute automaticamente sessões do opencode em sandboxes isoladas do Daytona com sincronização git e pré-visualizações ao vivo | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | Injete automaticamente cabeçalhos de sessão Helicone para agrupamento de requisições | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | Auto-injetar tipos TypeScript/Svelte em leituras de arquivos com ferramentas de busca | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | Use sua assinatura ChatGPT Plus/Pro em vez de créditos de API | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | Use seu plano Gemini existente em vez de cobrança de API | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | Use os modelos gratuitos do Antigravity em vez de cobrança de API | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Isolamento de devcontainer multi-branch com clones rasos e portas atribuídas automaticamente | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Plugin Google Antigravity OAuth, com suporte para Google Search e manuseio de API mais robusto | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Otimize o uso de tokens podando saídas de ferramentas obsoletas | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Adicione suporte nativo de pesquisa na web para provedores suportados com estilo fundamentado no Google | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Permite que agentes de IA executem processos em segundo plano em um PTY, enviando entrada interativa para eles. | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Instruções para comandos de shell não interativos - evita travamentos de operações dependentes de TTY | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Acompanhe o uso do opencode com Wakatime | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Limpe tabelas markdown produzidas por LLMs | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | Edição de código 10x mais rápida com a API Morph Fast Apply e marcadores de edição preguiçosos | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Agentes em segundo plano, ferramentas LSP/AST/MCP pré-construídas, agentes curados, compatível com Claude Code | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | Notificações de desktop e alertas sonoros para sessões do opencode | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Notificações de desktop e alertas sonoros para eventos de permissão, conclusão e erro | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | Nomeação automática de sessões Zellij com suporte de IA com base no contexto do opencode | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Permite que agentes do opencode carreguem prompts sob demanda com descoberta e injeção de habilidades | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Memória persistente entre sessões usando Supermemory | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Revisão de plano interativa com anotação visual e compartilhamento privado/offline | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Estenda opencode /commands em um poderoso sistema de orquestração com controle de fluxo granular | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | Agende trabalhos recorrentes usando launchd (Mac) ou systemd (Linux) com sintaxe cron | +| [micode](https://github.com/vtemian/micode) | Fluxo de trabalho Estruturado Brainstorm → Planejar → Implementar com continuidade de sessão | +| [octto](https://github.com/vtemian/octto) | UI interativa do navegador para brainstorming de IA com formulários de múltiplas perguntas | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | Agentes em segundo plano estilo Claude Code com delegação assíncrona e persistência de contexto | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | Notificações nativas do OS para opencode – saiba quando as tarefas são concluídas | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | Conjunto de orquestração multi-agente – 16 componentes, uma instalação | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | Worktrees git sem atrito para opencode | + +--- + +## Projetos + +| Nome | Descrição | +| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- | +| [kimaki](https://github.com/remorses/kimaki) | Bot do Discord para controlar sessões do opencode, construído sobre o SDK | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Plugin Neovim para prompts cientes do editor, construído sobre a API | +| [portal](https://github.com/hosenur/portal) | UI web mobile-first para opencode sobre Tailscale/VPN | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | Template para construir plugins do opencode | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Frontend Neovim para opencode - um agente de codificação IA baseado em terminal | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Provedor Vercel AI SDK para usar opencode via @opencode-ai/sdk | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | Aplicativo Web / Desktop e Extensão do VS Code para opencode | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Plugin Obsidian que incorpora opencode na UI do Obsidian | +| [OpenWork](https://github.com/different-ai/openwork) | Uma alternativa de código aberto ao Claude Cowork, alimentada pelo opencode | +| [ocx](https://github.com/kdcokenny/ocx) | Gerenciador de extensões opencode com perfis portáteis e isolados. | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | Aplicativo Desktop, Web, Mobile e Cliente Remoto para opencode | + +--- + +## Agentes + +| Nome | Descrição | +| ----------------------------------------------------------------- | ----------------------------------------------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | Agentes e comandos de IA modulares para desenvolvimento estruturado | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | Configurações, prompts, agentes e plugins para fluxos de trabalho aprimorados | diff --git a/packages/web/src/content/docs/pt-br/enterprise.mdx b/packages/web/src/content/docs/pt-br/enterprise.mdx new file mode 100644 index 00000000000..3a649dc0772 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/enterprise.mdx @@ -0,0 +1,166 @@ +--- +title: Empresa +description: Usando o opencode com segurança em sua organização. +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +O opencode Enterprise é para organizações que desejam garantir que seu código e dados nunca deixem sua infraestrutura. Isso pode ser feito usando uma configuração centralizada que se integra ao seu SSO e gateway de IA interno. + +:::note +O opencode não armazena nenhum de seus códigos ou dados de contexto. +::: + +Para começar com o opencode Enterprise: + +1. Faça um teste internamente com sua equipe. +2. **Entre em contato conosco** para discutir opções de preços e implementação. + +--- + +## Teste + +O opencode é de código aberto e não armazena nenhum de seus códigos ou dados de contexto, então seus desenvolvedores podem simplesmente [começar](/docs/) e realizar um teste. + +--- + +### Manipulação de dados + +**O opencode não armazena seu código ou dados de contexto.** Todo o processamento acontece localmente ou através de chamadas diretas de API para seu provedor de IA. + +Isso significa que, enquanto você estiver usando um provedor em quem confia, ou um gateway de IA interno, você pode usar o opencode com segurança. + +A única ressalva aqui é o recurso opcional `/share`. + +--- + +#### Compartilhando conversas + +Se um usuário habilitar o recurso `/share`, a conversa e os dados associados a ela são enviados para o serviço que usamos para hospedar essas páginas de compartilhamento em opencode.ai. + +Os dados são atualmente servidos através da rede de borda do nosso CDN e são armazenados em cache na borda perto de seus usuários. + +Recomendamos que você desative isso para seu teste. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[Saiba mais sobre compartilhamento](/docs/share). + +--- + +### Propriedade do código + +**Você possui todo o código produzido pelo opencode.** Não há restrições de licenciamento ou reivindicações de propriedade. + +--- + +## Preços + +Usamos um modelo por assento para o opencode Enterprise. Se você tiver seu próprio gateway LLM, não cobramos pelos tokens usados. Para mais detalhes sobre preços e opções de implementação, **entre em contato conosco**. + +--- + +## Implantação + +Uma vez que você tenha concluído seu teste e esteja pronto para usar o opencode em sua organização, você pode **entrar em contato conosco** para discutir preços e opções de implementação. + +--- + +### Configuração Central + +Podemos configurar o opencode para usar uma única configuração central para toda a sua organização. + +Essa configuração centralizada pode se integrar ao seu provedor de SSO e garante que todos os usuários acessem apenas seu gateway de IA interno. + +--- + +### Integração SSO + +Através da configuração central, o opencode pode se integrar ao provedor de SSO de sua organização para autenticação. + +Isso permite que o opencode obtenha credenciais para seu gateway de IA interno através do seu sistema de gerenciamento de identidade existente. + +--- + +### Gateway de IA Interno + +Com a configuração central, o opencode também pode ser configurado para usar apenas seu gateway de IA interno. + +Você também pode desativar todos os outros provedores de IA, garantindo que todas as solicitações passem pela infraestrutura aprovada de sua organização. + +--- + +### Auto-hospedagem + +Embora recomendemos desativar as páginas de compartilhamento para garantir que seus dados nunca deixem sua organização, também podemos ajudá-lo a auto-hospedá-las em sua infraestrutura. + +Isso está atualmente em nosso roadmap. Se você estiver interessado, **nos avise**. + +--- + +## FAQ + +

+O que é o opencode Enterprise? + +O opencode Enterprise é para organizações que desejam garantir que seu código e dados nunca deixem sua infraestrutura. Isso pode ser feito usando uma configuração centralizada que se integra ao seu SSO e gateway de IA interno. + +
+ +
+Como posso começar com o opencode Enterprise? + +Basta começar com um teste interno com sua equipe. O opencode, por padrão, não armazena seu código ou dados de contexto, facilitando o início. + +Depois, **entre em contato conosco** para discutir opções de preços e implementação. + +
+ +
+Como funciona a precificação empresarial? + +Oferecemos preços empresariais por assento. Se você tiver seu próprio gateway LLM, não cobramos pelos tokens usados. Para mais detalhes, **entre em contato conosco** para um orçamento personalizado com base nas necessidades de sua organização. + +
+ +
+Meus dados estão seguros com o opencode Enterprise? + +Sim. O opencode não armazena seu código ou dados de contexto. Todo o processamento acontece localmente ou através de chamadas diretas de API para seu provedor de IA. Com a configuração central e a integração SSO, seus dados permanecem seguros dentro da infraestrutura de sua organização. + +
+ +
+Podemos usar nosso próprio registro NPM privado? + +O opencode suporta registros npm privados através do suporte nativo do arquivo `.npmrc` do Bun. Se sua organização usa um registro privado, como JFrog Artifactory, Nexus ou similar, certifique-se de que os desenvolvedores estejam autenticados antes de executar o opencode. + +Para configurar a autenticação com seu registro privado: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +Isso cria `~/.npmrc` com os detalhes de autenticação. O opencode irá automaticamente +capturar isso. + +:::caution +Você deve estar logado no registro privado antes de executar o opencode. +::: + +Alternativamente, você pode configurar manualmente um arquivo `.npmrc`: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +Os desenvolvedores devem estar logados no registro privado antes de executar o opencode para garantir que os pacotes possam ser instalados a partir do seu registro empresarial. + +
diff --git a/packages/web/src/content/docs/pt-br/formatters.mdx b/packages/web/src/content/docs/pt-br/formatters.mdx new file mode 100644 index 00000000000..3037e7b65b1 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: Formatadores +description: O opencode usa formatadores específicos de linguagem. +--- + +O opencode formata automaticamente arquivos após serem escritos ou editados usando formatadores específicos de linguagem. Isso garante que o código gerado siga os estilos de código do seu projeto. + +--- + +## Integrados + +O opencode vem com vários formatadores integrados para linguagens e frameworks populares. Abaixo está uma lista dos formatadores, extensões de arquivo suportadas e comandos ou opções de configuração necessárias. + +| Formatador | Extensões | Requisitos | +| -------------------- | ------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- | +| gofmt | .go | Comando `gofmt` disponível | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | Comando `mix` disponível | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, e [mais](https://prettier.io/docs/en/index.html) | Dependência `prettier` em `package.json` | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, e [mais](https://biomejs.dev/) | Arquivo de configuração `biome.json(c)` | +| zig | .zig, .zon | Comando `zig` disponível | +| clang-format | .c, .cpp, .h, .hpp, .ino, e [mais](https://clang.llvm.org/docs/ClangFormat.html) | Arquivo de configuração `.clang-format` | +| ktlint | .kt, .kts | Comando `ktlint` disponível | +| ruff | .py, .pyi | Comando `ruff` disponível com configuração | +| rustfmt | .rs | Comando `rustfmt` disponível | +| cargofmt | .rs | Comando `cargo fmt` disponível | +| uv | .py, .pyi | Comando `uv` disponível | +| rubocop | .rb, .rake, .gemspec, .ru | Comando `rubocop` disponível | +| standardrb | .rb, .rake, .gemspec, .ru | Comando `standardrb` disponível | +| htmlbeautifier | .erb, .html.erb | Comando `htmlbeautifier` disponível | +| air | .R | Comando `air` disponível | +| dart | .dart | Comando `dart` disponível | +| ocamlformat | .ml, .mli | Comando `ocamlformat` disponível e arquivo de configuração `.ocamlformat` | +| terraform | .tf, .tfvars | Comando `terraform` disponível | +| gleam | .gleam | Comando `gleam` disponível | +| nixfmt | .nix | Comando `nixfmt` disponível | +| shfmt | .sh, .bash | Comando `shfmt` disponível | +| pint | .php | Dependência `laravel/pint` em `composer.json` | +| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | Dependência `oxfmt` em `package.json` e uma [variável de ambiente experimental](/docs/cli/#experimental) | +| ormolu | .hs | Comando `ormolu` disponível | + +Portanto, se seu projeto tiver `prettier` em seu `package.json`, o opencode o usará automaticamente. + +--- + +## Como funciona + +Quando o opencode escreve ou edita um arquivo, ele: + +1. Verifica a extensão do arquivo em relação a todos os formatadores habilitados. +2. Executa o comando do formatador apropriado no arquivo. +3. Aplica as alterações de formatação automaticamente. + +Esse processo acontece em segundo plano, garantindo que seus estilos de código sejam mantidos sem etapas manuais. + +--- + +## Configuração + +Você pode personalizar os formatadores através da seção `formatter` em sua configuração do opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +Cada configuração de formatador suporta o seguinte: + +| Propriedade | Tipo | Descrição | +| ------------- | -------- | ---------------------------------------------------------------- | +| `disabled` | boolean | Defina como `true` para desabilitar o formatador | +| `command` | string[] | O comando a ser executado para formatação | +| `environment` | object | Variáveis de ambiente a serem definidas ao executar o formatador | +| `extensions` | string[] | Extensões de arquivo que este formatador deve tratar | + +Vamos ver alguns exemplos. + +--- + +### Desabilitando formatadores + +Para desabilitar **todos** os formatadores globalmente, defina `formatter` como `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +Para desabilitar um **formatador específico**, defina `disabled` como `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### Formatadores personalizados + +Você pode substituir os formatadores integrados ou adicionar novos especificando o comando, variáveis de ambiente e extensões de arquivo: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +O **placeholder `$FILE`** no comando será substituído pelo caminho do arquivo que está sendo formatado. diff --git a/packages/web/src/content/docs/pt-br/github.mdx b/packages/web/src/content/docs/pt-br/github.mdx new file mode 100644 index 00000000000..c2e53ca77ea --- /dev/null +++ b/packages/web/src/content/docs/pt-br/github.mdx @@ -0,0 +1,321 @@ +--- +title: GitHub +description: Use o opencode em problemas e pull-requests do GitHub. +--- + +O opencode integra-se ao seu fluxo de trabalho do GitHub. Mencione `/opencode` ou `/oc` em seu comentário, e o opencode executará tarefas dentro do seu runner do GitHub Actions. + +--- + +## Recursos + +- **Triagem de problemas**: Peça ao opencode para analisar um problema e explicá-lo para você. +- **Corrigir e implementar**: Peça ao opencode para corrigir um problema ou implementar um recurso. E ele trabalhará em um novo branch e enviará um PR com todas as alterações. +- **Seguro**: O opencode é executado dentro dos runners do seu GitHub. + +--- + +## Instalação + +Execute o seguinte comando em um projeto que está em um repositório do GitHub: + +```bash +opencode github install +``` + +Isso o guiará pela instalação do aplicativo GitHub, criação do fluxo de trabalho e configuração de segredos. + +--- + +### Configuração Manual + +Ou você pode configurá-lo manualmente. + +1. **Instale o aplicativo GitHub** + + Acesse [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). Certifique-se de que está instalado no repositório de destino. + +2. **Adicione o fluxo de trabalho** + + Adicione o seguinte arquivo de fluxo de trabalho em `.github/workflows/opencode.yml` no seu repositório. Certifique-se de definir o `model` apropriado e as chaves de API necessárias em `env`. + + ```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx + ``` + +3. **Armazene as chaves de API em segredos** + + Nas **configurações** da sua organização ou projeto, expanda **Segredos e variáveis** à esquerda e selecione **Ações**. E adicione as chaves de API necessárias. + +--- + +## Configuração + +- `model`: O modelo a ser usado com o opencode. Tem o formato de `provider/model`. Isso é **obrigatório**. +- `agent`: O agente a ser usado. Deve ser um agente primário. Retorna ao `default_agent` da configuração ou `"build"` se não encontrado. +- `share`: Se deve compartilhar a sessão do opencode. O padrão é **true** para repositórios públicos. +- `prompt`: Prompt personalizado opcional para substituir o comportamento padrão. Use isso para personalizar como o opencode processa solicitações. +- `token`: Token de acesso do GitHub opcional para realizar operações como criar comentários, confirmar alterações e abrir pull requests. Por padrão, o opencode usa o token de acesso da instalação do aplicativo GitHub opencode, então commits, comentários e pull requests aparecem como se fossem da aplicação. + + Alternativamente, você pode usar o [`GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) embutido do runner do GitHub Action sem instalar o aplicativo GitHub opencode. Apenas certifique-se de conceder as permissões necessárias em seu fluxo de trabalho: + + ```yaml + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + ``` + + Você também pode usar um [token de acesso pessoal](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) se preferir. + +--- + +## Eventos Suportados + +O opencode pode ser acionado pelos seguintes eventos do GitHub: + +| Tipo de Evento | Acionado Por | Detalhes | +| ----------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| `issue_comment` | Comentário em um problema ou PR | Mencione `/opencode` ou `/oc` em seu comentário. O opencode lê o contexto e pode criar branches, abrir PRs ou responder. | +| `pull_request_review_comment` | Comentário em linhas de código específicas em um PR | Mencione `/opencode` ou `/oc` enquanto revisa o código. O opencode recebe o caminho do arquivo, números das linhas e contexto do diff. | +| `issues` | Problema aberto ou editado | Aciona automaticamente o opencode quando problemas são criados ou modificados. Requer entrada de `prompt`. | +| `pull_request` | PR aberto ou atualizado | Aciona automaticamente o opencode quando PRs são abertos, sincronizados ou reabertos. Útil para revisões automatizadas. | +| `schedule` | Cron baseado em agendamento | Execute o opencode em um cronograma. Requer entrada de `prompt`. A saída vai para logs e PRs (sem problema para comentar). | +| `workflow_dispatch` | Acionamento manual pela interface do GitHub | Acione o opencode sob demanda através da aba Ações. Requer entrada de `prompt`. A saída vai para logs e PRs. | + +### Exemplo de Agendamento + +Execute o opencode em um cronograma para realizar tarefas automatizadas: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Revise a base de código para quaisquer comentários TODO e crie um resumo. + Se encontrar problemas que valham a pena resolver, abra um issue para rastreá-los. +``` + +Para eventos agendados, a entrada `prompt` é **obrigatória** uma vez que não há comentário para extrair instruções. Fluxos de trabalho agendados são executados sem um contexto de usuário para verificação de permissões, então o fluxo de trabalho deve conceder `contents: write` e `pull-requests: write` se você espera que o opencode crie branches ou PRs. + +--- + +### Exemplo de Pull Request + +Revise automaticamente PRs quando forem abertos ou atualizados: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Revise este pull request: + - Verifique problemas de qualidade de código + - Procure por potenciais bugs + - Sugira melhorias +``` + +Para eventos de `pull_request`, se nenhum `prompt` for fornecido, o opencode padrão será revisar o pull request. + +--- + +### Exemplo de Triagem de Problemas + +Triagem automática de novos problemas. Este exemplo filtra contas com mais de 30 dias para reduzir spam: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Revise este issue. Se houver uma correção clara ou docs relevantes: + - Forneça links de documentação + - Adicione orientação sobre tratamento de erros para exemplos de código + Caso contrário, não comente. +``` + +Para eventos de `issues`, a entrada `prompt` é **obrigatória** uma vez que não há comentário para extrair instruções. + +--- + +## Prompts Personalizados + +Substitua o prompt padrão para personalizar o comportamento do opencode para seu fluxo de trabalho. + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Revise este pull request: + - Verifique problemas de qualidade de código + - Procure por potenciais bugs + - Sugira melhorias +``` + +Isso é útil para impor critérios de revisão específicos, padrões de codificação ou áreas de foco relevantes para seu projeto. + +--- + +## Exemplos + +Aqui estão alguns exemplos de como você pode usar o opencode no GitHub. + +- **Explicar um problema** + + Adicione este comentário em um problema do GitHub. + + ``` + /opencode explain this issue + ``` + + O opencode lerá toda a conversa, incluindo todos os comentários, e responderá com uma explicação clara. + +- **Corrigir um problema** + + Em um problema do GitHub, diga: + + ``` + /opencode fix this + ``` + + E o opencode criará um novo branch, implementará as alterações e abrirá um PR com as mudanças. + +- **Revisar PRs e fazer alterações** + + Deixe o seguinte comentário em um PR do GitHub. + + ``` + Delete the attachment from S3 when the note is removed /oc + ``` + + O opencode implementará a alteração solicitada e a confirmará no mesmo PR. + +- **Revisar linhas de código específicas** + + Deixe um comentário diretamente nas linhas de código na aba "Files" do PR. O opencode detecta automaticamente o arquivo, os números das linhas e o contexto do diff para fornecer respostas precisas. + + ``` + [Comentário em linhas específicas na aba Files] + /oc add error handling here + ``` + + Ao comentar sobre linhas específicas, o opencode recebe: + - O arquivo exato sendo revisado + - As linhas específicas de código + - O contexto do diff ao redor + - Informações sobre números de linha + + Isso permite solicitações mais direcionadas sem precisar especificar caminhos de arquivos ou números de linhas manualmente. diff --git a/packages/web/src/content/docs/pt-br/gitlab.mdx b/packages/web/src/content/docs/pt-br/gitlab.mdx new file mode 100644 index 00000000000..dc48aa57cac --- /dev/null +++ b/packages/web/src/content/docs/pt-br/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: Use o opencode em problemas e solicitações de mesclagem do GitLab. +--- + +O opencode se integra ao seu fluxo de trabalho do GitLab através do seu pipeline CI/CD do GitLab ou com o GitLab Duo. + +Em ambos os casos, o opencode será executado em seus runners do GitLab. + +--- + +## GitLab CI + +O opencode funciona em um pipeline regular do GitLab. Você pode integrá-lo a um pipeline como um [componente CI](https://docs.gitlab.com/ee/ci/components/) + +Aqui estamos usando um componente CI/CD criado pela comunidade para opencode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### Recursos + +- **Use configuração personalizada por trabalho**: Configure o opencode com um diretório de configuração personalizado, por exemplo `./config/#custom-directory` para habilitar ou desabilitar funcionalidades por invocação do opencode. +- **Configuração mínima**: O componente CI configura o opencode em segundo plano, você só precisa criar a configuração do opencode e o prompt inicial. +- **Flexível**: O componente CI suporta várias entradas para personalizar seu comportamento. + +--- + +### Configuração + +1. Armazene seu JSON de autenticação do opencode como variáveis de ambiente do tipo File em **Configurações** > **CI/CD** > **Variáveis**. Certifique-se de marcá-las como "Mascaradas e ocultas". +2. Adicione o seguinte ao seu arquivo `.gitlab-ci.yml`. + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # O nome da variável para seu JSON de autenticação do OpenCode + command: optional-custom-command + message: "Seu prompt aqui" + ``` + +Para mais entradas e casos de uso [consulte a documentação](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) deste componente. + +--- + +## GitLab Duo + +O opencode se integra ao seu fluxo de trabalho do GitLab. +Mencione `@opencode` em um comentário, e o opencode executará tarefas dentro do seu pipeline CI do GitLab. + +--- + +### Recursos + +- **Triagem de problemas**: Peça ao opencode para analisar um problema e explicá-lo para você. +- **Corrigir e implementar**: Peça ao opencode para corrigir um problema ou implementar uma funcionalidade. + Ele criará um novo branch e abrirá uma solicitação de mesclagem com as alterações. +- **Seguro**: O opencode é executado em seus runners do GitLab. + +--- + +### Configuração + +O opencode é executado em seu pipeline CI/CD do GitLab, aqui está o que você precisará para configurá-lo: + +:::tip +Consulte a [**documentação do GitLab**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) para instruções atualizadas. +::: + +1. Configure seu ambiente GitLab +2. Configure CI/CD +3. Obtenha uma chave de API do provedor de modelo de IA +4. Crie uma conta de serviço +5. Configure variáveis de CI/CD +6. Crie um arquivo de configuração de fluxo, aqui está um exemplo: + +
+ + Configuração de fluxo + + ```yaml + image: node:22-slim + commands: + - echo "Instalando opencode" + - npm install --global opencode-ai + - echo "Instalando glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configurando glab" + - echo $GITLAB_HOST + - echo "Criando configuração de auth do OpenCode" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configurando git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testando glab" + - glab issue list + - echo "Executando OpenCode" + - | + opencode run " + Você é um assistente de IA ajudando com operações do GitLab. + + Contexto: $AI_FLOW_CONTEXT + Tarefa: $AI_FLOW_INPUT + Evento: $AI_FLOW_EVENT + + Por favor, execute a tarefa solicitada usando as ferramentas disponíveis do GitLab. + Seja minucioso em sua análise e forneça explicações claras. + + + Por favor, use a CLI glab para acessar dados do GitLab. A CLI glab já foi autenticada. Você pode executar os comandos correspondentes. + + Se for solicitado a resumir um MR ou problema ou solicitado a fornecer mais informações, poste uma nota de volta no MR/Problema para que o usuário possa ver. + Você não precisa commitar ou enviar alterações, isso será feito automaticamente com base nas alterações de arquivo que você fizer. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Verificando alterações no git e enviando se existirem" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Alterações git detectadas, adicionando e enviando..." + git add . + if git diff --cached --quiet; then + echo "Nenhuma alteração preparada para commit" + else + echo "Commitando alterações para o branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Enviando alterações para $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Alterações enviadas com sucesso" + fi + else + echo "Nenhuma alteração git detectada, pulando envio" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +Você pode consultar a [documentação dos agentes da CLI do GitLab](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) para instruções detalhadas. + +--- + +### Exemplos + +Aqui estão alguns exemplos de como você pode usar o opencode no GitLab. + +:::tip +Você pode configurar para usar uma frase de gatilho diferente de `@opencode`. +::: + +- **Explicar um problema** + + Adicione este comentário em um problema do GitLab. + + ``` + @opencode explain this issue + ``` + + O opencode lerá o problema e responderá com uma explicação clara. + +- **Corrigir um problema** + + Em um problema do GitLab, diga: + + ``` + @opencode fix this + ``` + + O opencode criará um novo branch, implementará as alterações e abrirá uma solicitação de mesclagem com as alterações. + +- **Revisar solicitações de mesclagem** + + Deixe o seguinte comentário em uma solicitação de mesclagem do GitLab. + + ``` + @opencode review this merge request + ``` + + O opencode revisará a solicitação de mesclagem e fornecerá feedback. diff --git a/packages/web/src/content/docs/pt-br/ide.mdx b/packages/web/src/content/docs/pt-br/ide.mdx new file mode 100644 index 00000000000..cb773c991ab --- /dev/null +++ b/packages/web/src/content/docs/pt-br/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: A extensão opencode para VS Code, Cursor e outros IDEs +--- + +O opencode integra-se com VS Code, Cursor ou qualquer IDE que suporte um terminal. Basta executar `opencode` no terminal para começar. + +--- + +## Uso + +- **Lançamento Rápido**: Use `Cmd+Esc` (Mac) ou `Ctrl+Esc` (Windows/Linux) para abrir o opencode em uma visualização de terminal dividido, ou focar em uma sessão de terminal existente se uma já estiver em execução. +- **Nova Sessão**: Use `Cmd+Shift+Esc` (Mac) ou `Ctrl+Shift+Esc` (Windows/Linux) para iniciar uma nova sessão de terminal opencode, mesmo que uma já esteja aberta. Você também pode clicar no botão opencode na interface. +- **Consciência de Contexto**: Compartilhe automaticamente sua seleção ou aba atual com o opencode. +- **Atalhos de Referência de Arquivo**: Use `Cmd+Option+K` (Mac) ou `Alt+Ctrl+K` (Linux/Windows) para inserir referências de arquivo. Por exemplo, `@File#L37-42`. + +--- + +## Instalação + +Para instalar o opencode no VS Code e forks populares como Cursor, Windsurf, VSCodium: + +1. Abra o VS Code +2. Abra o terminal integrado +3. Execute `opencode` - a extensão será instalada automaticamente + +Se, por outro lado, você quiser usar seu próprio IDE ao executar `/editor` ou `/export` a partir do TUI, você precisará definir `export EDITOR="code --wait"`. [Saiba mais](/docs/tui/#editor-setup). + +--- + +### Instalação Manual + +Procure por **opencode** no Marketplace de Extensões e clique em **Instalar**. + +--- + +### Solução de Problemas + +Se a extensão falhar ao instalar automaticamente: + +- Certifique-se de que você está executando `opencode` no terminal integrado. +- Confirme se a CLI para seu IDE está instalado: + - Para VS Code: comando `code` + - Para Cursor: comando `cursor` + - Para Windsurf: comando `windsurf` + - Para VSCodium: comando `codium` + - Se não, execute `Cmd+Shift+P` (Mac) ou `Ctrl+Shift+P` (Windows/Linux) e procure por "Shell Command: Install 'code' command in PATH" (ou o equivalente para seu IDE) +- Certifique-se de que o VS Code tem permissão para instalar extensões diff --git a/packages/web/src/content/docs/pt-br/index.mdx b/packages/web/src/content/docs/pt-br/index.mdx new file mode 100644 index 00000000000..acbf12f2aa1 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/index.mdx @@ -0,0 +1,343 @@ +--- +title: Introdução +description: Comece a usar o opencode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**opencode**](/) é um agente de codificação de IA de código aberto. Está disponível como uma interface baseada em terminal, aplicativo desktop ou extensão de IDE. + +![opencode TUI com o tema opencode](../../../assets/lander/screenshot.png) + +Vamos começar. + +--- + +#### Pré-requisitos + +Para usar o opencode no seu terminal, você precisará de: + +1. Um emulador de terminal moderno como: + - [WezTerm](https://wezterm.org), multiplataforma + - [Alacritty](https://alacritty.org), multiplataforma + - [Ghostty](https://ghostty.org), Linux e macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux e macOS + +2. Chaves de API para os provedores de LLM que você deseja usar. + +--- + +## Instalação + +A maneira mais fácil de instalar o opencode é através do script de instalação. + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +Você também pode instalá-lo com os seguintes comandos: + +- **Usando Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **Usando Homebrew no macOS e Linux** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > Recomendamos usar o tap do opencode para as versões mais atualizadas. A fórmula oficial `brew install opencode` é mantida pela equipe do Homebrew e é atualizada com menos frequência. + +- **Usando Paru no Arch Linux** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[Recomendado: Use WSL] +Para a melhor experiência no Windows, recomendamos usar o [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Ele oferece melhor desempenho e total compatibilidade com os recursos do opencode. +::: + +- **Usando Chocolatey** + + ```bash + choco install opencode + ``` + +- **Usando Scoop** + + ```bash + scoop install opencode + ``` + +- **Usando NPM** + + ```bash + npm install -g opencode-ai + ``` + +- **Usando Mise** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **Usando Docker** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +O suporte para instalar o opencode no Windows usando Bun está atualmente em andamento. + +Você também pode baixar o binário na seção [Releases](https://github.com/anomalyco/opencode/releases). + +--- + +## Configuração + +Com o opencode, você pode usar qualquer provedor de LLM configurando suas chaves de API. + +Se você é novo no uso de provedores de LLM, recomendamos usar o [OpenCode Zen](/docs/zen). +É uma lista selecionada de modelos que foram testados e verificados pela equipe do opencode. + +1. Execute o comando `/connect` no TUI, selecione opencode e acesse [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. Faça login, adicione seus dados de cobrança e copie sua chave de API. + +3. Cole sua chave de API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +Alternativamente, você pode selecionar um dos outros provedores. [Saiba mais](/docs/providers#directory). + +--- + +## Inicialização + +Agora que você configurou um provedor, pode navegar até um projeto no qual deseja trabalhar. + +```bash +cd /path/to/project +``` + +E execute o opencode. + +```bash +opencode +``` + +Em seguida, inicialize o opencode para o projeto executando o seguinte comando. + +```bash frame="none" +/init +``` + +Isso fará com que o opencode analise seu projeto e crie um arquivo `AGENTS.md` na raiz do projeto. + +:::tip +Você deve commitar o arquivo `AGENTS.md` do seu projeto no Git. +::: + +Isso ajuda o opencode a entender a estrutura do projeto e os padrões de codificação utilizados. + +--- + +## Uso + +Agora você está pronto para usar o opencode para trabalhar em seu projeto. Sinta-se à vontade para perguntar qualquer coisa! + +Se você é novo no uso de um agente de codificação de IA, aqui estão alguns exemplos que podem ajudar. + +--- + +### Fazendo perguntas + +Você pode pedir ao opencode para explicar a base de código para você. + +:::tip +Use a tecla `@` para buscar arquivos no projeto. +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +Isso é útil se houver uma parte da base de código na qual você não trabalhou. + +--- + +### Adicionando recursos + +Você pode pedir ao opencode para adicionar novos recursos ao seu projeto. Embora primeiro recomendemos pedir para ele criar um plano. + +1. **Criar um plano** + + O opencode tem um _Modo de Plano_ que desabilita sua capacidade de fazer alterações e, em vez disso, sugere _como_ implementará o recurso. + + Mude para ele usando a tecla **Tab**. Você verá um indicador para isso no canto inferior direito. + + ```bash frame="none" title="Switch to Plan mode" + + ``` + + Agora vamos descrever o que queremos que ele faça. + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + Você quer dar ao opencode detalhes suficientes para entender o que você deseja. Ajuda conversar com ele como se você estivesse falando com um desenvolvedor júnior da sua equipe. + + :::tip + Dê ao opencode bastante contexto e exemplos para ajudá-lo a entender o que você deseja. + ::: + +2. **Iterar sobre o plano** + + Uma vez que ele lhe der um plano, você pode dar feedback ou adicionar mais detalhes. + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + + :::tip + Arraste e solte imagens no terminal para adicioná-las ao prompt. + ::: + + O opencode pode escanear qualquer imagem que você fornecer e adicioná-la ao prompt. Você pode fazer isso arrastando e soltando uma imagem no terminal. + +3. **Construir o recurso** + + Uma vez que você se sinta confortável com o plano, volte para o _Modo de Construção_ pressionando a tecla **Tab** novamente. + + ```bash frame="none" + + ``` + + E peça para ele fazer as alterações. + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### Fazendo alterações + +Para alterações mais simples, você pode pedir ao opencode para construí-las diretamente sem precisar revisar o plano primeiro. + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +Você quer ter certeza de fornecer uma boa quantidade de detalhes para que o opencode faça as alterações corretas. + +--- + +### Desfazendo alterações + +Vamos supor que você peça ao opencode para fazer algumas alterações. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Mas você percebe que não era isso que você queria. Você **pode desfazer** as alterações usando o comando `/undo`. + +```bash frame="none" +/undo +``` + +O opencode agora reverterá as alterações que você fez e mostrará sua mensagem original novamente. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +A partir daqui, você pode ajustar o prompt e pedir ao opencode para tentar novamente. + +:::tip +Você pode executar `/undo` várias vezes para desfazer várias alterações. +::: + +Ou você **pode refazer** as alterações usando o comando `/redo`. + +```bash frame="none" +/redo +``` + +--- + +## Compartilhamento + +As conversas que você tem com o opencode podem ser [compartilhadas com sua equipe](/docs/share). + +```bash frame="none" +/share +``` + +Isso criará um link para a conversa atual e o copiará para sua área de transferência. + +:::note +As conversas não são compartilhadas por padrão. +::: + +Aqui está uma [conversa de exemplo](https://opencode.ai/s/4XP1fce5) com o opencode. + +--- + +## Personalização + +E é isso! Agora você é um profissional em usar o opencode. + +Para torná-lo seu, recomendamos [escolher um tema](/docs/themes), [personalizar os atalhos de teclado](/docs/keybinds), [configurar formatadores de código](/docs/formatters), [criar comandos personalizados](/docs/commands) ou brincar com a [configuração do opencode](/docs/config). diff --git a/packages/web/src/content/docs/pt-br/keybinds.mdx b/packages/web/src/content/docs/pt-br/keybinds.mdx new file mode 100644 index 00000000000..b4da4471aa5 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/keybinds.mdx @@ -0,0 +1,192 @@ +--- +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. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## Tecla líder + +O opencode usa uma tecla `leader` para a maioria dos atalhos de teclado. Isso evita conflitos no seu terminal. + +Por padrão, `ctrl+x` é a tecla líder e a maioria das ações requer que você primeiro pressione a tecla líder e depois o atalho. Por exemplo, para iniciar uma nova sessão, você primeiro pressiona `ctrl+x` e depois pressiona `n`. + +Você não precisa usar uma tecla líder para seus atalhos, mas recomendamos que o faça. + +--- + +## Desativar atalho + +Você pode desativar um atalho adicionando a tecla à sua configuração com um valor de "none". + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## Atalhos do prompt do desktop + +O prompt de entrada do aplicativo desktop opencode suporta atalhos comuns de estilo Readline/Emacs para edição de texto. Estes são embutidos e atualmente não são configuráveis via `opencode.json`. + +| Atalho | Ação | +| -------- | ------------------------------------------------ | +| `ctrl+a` | Mover para o início da linha atual | +| `ctrl+e` | Mover para o final da linha atual | +| `ctrl+b` | Mover o cursor uma posição para trás | +| `ctrl+f` | Mover o cursor uma posição para frente | +| `alt+b` | Mover o cursor uma palavra para trás | +| `alt+f` | Mover o cursor uma palavra para frente | +| `ctrl+d` | Deletar o caractere sob o cursor | +| `ctrl+k` | Matar até o final da linha | +| `ctrl+u` | Matar até o início da linha | +| `ctrl+w` | Matar a palavra anterior | +| `alt+d` | Matar a próxima palavra | +| `ctrl+t` | Transpor caracteres | +| `ctrl+g` | Cancelar popovers / abortar resposta em execução | + +--- + +## Shift+Enter + +Alguns terminais não enviam teclas modificadoras com Enter por padrão. Você pode precisar configurar seu terminal para enviar `Shift+Enter` como uma sequência de escape. + +### Windows Terminal + +Abra seu `settings.json` em: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +Adicione isso ao array `actions` de nível raiz: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Adicione isso ao array `keybindings` de nível raiz: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Salve o arquivo e reinicie o Windows Terminal ou abra uma nova aba. diff --git a/packages/web/src/content/docs/pt-br/lsp.mdx b/packages/web/src/content/docs/pt-br/lsp.mdx new file mode 100644 index 00000000000..6baf1813b34 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: Servidores LSP +description: O opencode integra-se aos seus servidores LSP. +--- + +O opencode integra-se ao seu Protocolo de Servidor de Linguagem (LSP) para ajudar o LLM a interagir com sua base de código. Ele usa diagnósticos para fornecer feedback ao LLM. + +--- + +## Integrados + +O opencode vem com vários servidores LSP integrados para linguagens populares: + +| Servidor LSP | Extensões | Requisitos | +| ------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| astro | .astro | Instala automaticamente para projetos Astro | +| bash | .sh, .bash, .zsh, .ksh | Instala automaticamente bash-language-server | +| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | Instala automaticamente para projetos C/C++ | +| csharp | .cs | `.NET SDK` instalado | +| clojure-lsp | .clj, .cljs, .cljc, .edn | Comando `clojure-lsp` disponível | +| dart | .dart | Comando `dart` disponível | +| deno | .ts, .tsx, .js, .jsx, .mjs | Comando `deno` disponível (detecta automaticamente deno.json/deno.jsonc) | +| elixir-ls | .ex, .exs | Comando `elixir` disponível | +| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | Dependência `eslint` no projeto | +| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` instalado | +| gleam | .gleam | Comando `gleam` disponível | +| gopls | .go | Comando `go` disponível | +| hls | .hs, .lhs | Comando `haskell-language-server-wrapper` disponível | +| jdtls | .java | `Java SDK (version 21+)` instalado | +| kotlin-ls | .kt, .kts | Instala automaticamente para projetos Kotlin | +| lua-ls | .lua | Instala automaticamente para projetos Lua | +| nixd | .nix | Comando `nixd` disponível | +| ocaml-lsp | .ml, .mli | Comando `ocamllsp` disponível | +| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | Dependência `oxlint` no projeto | +| php intelephense | .php | Instala automaticamente para projetos PHP | +| prisma | .prisma | Comando `prisma` disponível | +| pyright | .py, .pyi | Dependência `pyright` instalada | +| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | Comandos `ruby` e `gem` disponíveis | +| rust | .rs | Comando `rust-analyzer` disponível | +| sourcekit-lsp | .swift, .objc, .objcpp | `swift` instalado (`xcode` no macOS) | +| svelte | .svelte | Instala automaticamente para projetos Svelte | +| terraform | .tf, .tfvars | Instala automaticamente a partir de lançamentos do GitHub | +| tinymist | .typ, .typc | Instala automaticamente a partir de lançamentos do GitHub | +| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | Dependência `typescript` no projeto | +| vue | .vue | Instala automaticamente para projetos Vue | +| yaml-ls | .yaml, .yml | Instala automaticamente o servidor yaml-language-server da Red Hat | +| zls | .zig, .zon | Comando `zig` disponível | + +Os servidores LSP são habilitados automaticamente quando uma das extensões de arquivo acima é detectada e os requisitos são atendidos. + +:::note +Você pode desabilitar os downloads automáticos do servidor LSP definindo a variável de ambiente `OPENCODE_DISABLE_LSP_DOWNLOAD` como `true`. +::: + +--- + +## Como Funciona + +Quando o opencode abre um arquivo, ele: + +1. Verifica a extensão do arquivo em relação a todos os servidores LSP habilitados. +2. Inicia o servidor LSP apropriado se não estiver em execução. + +--- + +## Configuração + +Você pode personalizar os servidores LSP através da seção `lsp` na sua configuração do opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +Cada servidor LSP suporta o seguinte: + +| Propriedade | Tipo | Descrição | +| ---------------- | -------- | ------------------------------------------------------------- | +| `disabled` | boolean | Defina como `true` para desabilitar o servidor LSP | +| `command` | string[] | O comando para iniciar o servidor LSP | +| `extensions` | string[] | Extensões de arquivo que este servidor LSP deve manipular | +| `env` | object | Variáveis de ambiente a serem definidas ao iniciar o servidor | +| `initialization` | object | Opções de inicialização a serem enviadas ao servidor LSP | + +Vamos ver alguns exemplos. + +--- + +### Variáveis de ambiente + +Use a propriedade `env` para definir variáveis de ambiente ao iniciar o servidor LSP: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### Opções de inicialização + +Use a propriedade `initialization` para passar opções de inicialização ao servidor LSP. Estas são configurações específicas do servidor enviadas durante a solicitação `initialize` do LSP: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +As opções de inicialização variam de acordo com o servidor LSP. Verifique a documentação do seu servidor LSP para opções disponíveis. +::: + +--- + +### Desabilitando servidores LSP + +Para desabilitar **todos** os servidores LSP globalmente, defina `lsp` como `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +Para desabilitar um servidor LSP **específico**, defina `disabled` como `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### Servidores LSP personalizados + +Você pode adicionar servidores LSP personalizados especificando o comando e as extensões de arquivo: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## Informações Adicionais + +### PHP Intelephense + +PHP Intelephense oferece recursos premium através de uma chave de licença. Você pode fornecer uma chave de licença colocando (apenas) a chave em um arquivo de texto em: + +- No macOS/Linux: `$HOME/intelephense/license.txt` +- No Windows: `%USERPROFILE%/intelephense/license.txt` + +O arquivo deve conter apenas a chave de licença sem conteúdo adicional. diff --git a/packages/web/src/content/docs/pt-br/mcp-servers.mdx b/packages/web/src/content/docs/pt-br/mcp-servers.mdx new file mode 100644 index 00000000000..a4d6c1bfbc2 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/mcp-servers.mdx @@ -0,0 +1,511 @@ +--- +title: Servidores MCP +description: Adicione ferramentas MCP locais e remotas. +--- + +Você pode adicionar ferramentas externas ao opencode usando o _Model Context Protocol_, ou MCP. O opencode suporta servidores locais e remotos. + +Uma vez adicionadas, as ferramentas MCP estão automaticamente disponíveis para o LLM juntamente com as ferramentas integradas. + +--- + +#### Avisos + +Quando você usa um servidor MCP, ele adiciona ao contexto. Isso pode rapidamente se acumular se você tiver muitas ferramentas. Portanto, recomendamos ter cuidado com quais servidores MCP você usa. + +:::tip +Os servidores MCP adicionam ao seu contexto, então você deve ter cuidado com quais você habilita. +::: + +Certos servidores MCP, como o servidor MCP do GitHub, tendem a adicionar muitos tokens e podem facilmente exceder o limite de contexto. + +--- + +## Habilitando + +Você pode definir servidores MCP em sua [Configuração do opencode](https://opencode.ai/docs/config/) sob `mcp`. Adicione cada MCP com um nome único. Você pode se referir a esse MCP pelo nome ao solicitar ao LLM. + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +Você também pode desabilitar um servidor definindo `enabled` como `false`. Isso é útil se você quiser desabilitar temporariamente um servidor sem removê-lo de sua configuração. + +--- + +### Substituindo padrões remotos + +As organizações podem fornecer servidores MCP padrão através de seu endpoint `.well-known/opencode`. Esses servidores podem estar desabilitados por padrão, permitindo que os usuários optem pelos que precisam. + +Para habilitar um servidor específico da configuração remota da sua organização, adicione-o à sua configuração local com `enabled: true`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +Os valores da sua configuração local substituem os padrões remotos. Veja [precedência de configuração](/docs/config#precedence-order) para mais detalhes. + +--- + +## Local + +Adicione servidores MCP locais usando `type` como `"local"` dentro do objeto 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", + }, + }, + }, +} +``` + +O comando é como o servidor MCP local é iniciado. Você também pode passar uma lista de variáveis de ambiente. + +Por exemplo, aqui está como você pode adicionar o servidor MCP de teste [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything). + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "mcp_everything": { + "type": "local", + "command": ["npx", "-y", "@modelcontextprotocol/server-everything"], + }, + }, +} +``` + +E para usá-lo, posso adicionar `use the mcp_everything tool` aos meus prompts. + +```txt "mcp_everything" +use the mcp_everything tool to add the number 3 and 4 +``` + +--- + +#### Opções + +Aqui estão todas as opções para configurar um servidor MCP local. + +| Opção | Tipo | Requerido | Descrição | +| ------------- | ------- | --------- | ----------------------------------------------------------------------------------------- | +| `type` | String | S | Tipo de conexão do servidor MCP, deve ser `"local"`. | +| `command` | Array | S | Comando e argumentos para executar o servidor MCP. | +| `environment` | Object | | Variáveis de ambiente a serem definidas ao executar o servidor. | +| `enabled` | Boolean | | Habilitar ou desabilitar o servidor MCP na inicialização. | +| `timeout` | Number | | Tempo limite em ms para buscar ferramentas do servidor MCP. O padrão é 5000 (5 segundos). | + +--- + +## Remoto + +Adicione servidores MCP remotos definindo `type` como `"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" + } + } + } +} +``` + +O `url` é a URL do servidor MCP remoto e com a opção `headers` você pode passar uma lista de cabeçalhos. + +--- + +#### Opções + +| Opção | Tipo | Requerido | Descrição | +| --------- | ------- | --------- | ----------------------------------------------------------------------------------------- | +| `type` | String | S | Tipo de conexão do servidor MCP, deve ser `"remote"`. | +| `url` | String | S | URL do servidor MCP remoto. | +| `enabled` | Boolean | | Habilitar ou desabilitar o servidor MCP na inicialização. | +| `headers` | Object | | Cabeçalhos a serem enviados com a solicitação. | +| `oauth` | Object | | Configuração de autenticação OAuth. Veja a seção [OAuth](#oauth) abaixo. | +| `timeout` | Number | | Tempo limite em ms para buscar ferramentas do servidor MCP. O padrão é 5000 (5 segundos). | + +--- + +## OAuth + +O opencode lida automaticamente com a autenticação OAuth para servidores MCP remotos. Quando um servidor requer autenticação, o opencode irá: + +1. Detectar a resposta 401 e iniciar o fluxo OAuth +2. Usar **Registro Dinâmico de Cliente (RFC 7591)** se suportado pelo servidor +3. Armazenar tokens de forma segura para futuras solicitações + +--- + +### Automático + +Para a maioria dos servidores MCP habilitados para OAuth, nenhuma configuração especial é necessária. Basta configurar o servidor remoto: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "my-oauth-server": { + "type": "remote", + "url": "https://mcp.example.com/mcp" + } + } +} +``` + +Se o servidor requer autenticação, o opencode solicitará que você se autentique quando tentar usá-lo pela primeira vez. Se não, você pode [iniciar manualmente o fluxo](#authenticating) com `opencode mcp auth `. + +--- + +### Pré-registrado + +Se você tiver credenciais de cliente do provedor do servidor MCP, pode configurá-las: + +```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" + } + } + } +} +``` + +--- + +### Autenticação + +Você pode iniciar manualmente a autenticação ou gerenciar credenciais. + +Autentique-se com um servidor MCP específico: + +```bash +opencode mcp auth my-oauth-server +``` + +Liste todos os servidores MCP e seu status de autenticação: + +```bash +opencode mcp list +``` + +Remova credenciais armazenadas: + +```bash +opencode mcp logout my-oauth-server +``` + +O comando `mcp auth` abrirá seu navegador para autorização. Após você autorizar, o opencode armazenará os tokens de forma segura em `~/.local/share/opencode/mcp-auth.json`. + +--- + +#### Desabilitando OAuth + +Se você quiser desabilitar o OAuth automático para um servidor (por exemplo, para servidores que usam chaves de API em vez disso), defina `oauth` como `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}" + } + } + } +} +``` + +--- + +#### Opções de OAuth + +| Opção | Tipo | Descrição | +| -------------- | --------------- | ----------------------------------------------------------------------------------------- | +| `oauth` | Object \| false | Objeto de configuração OAuth, ou `false` para desabilitar a detecção automática de OAuth. | +| `clientId` | String | ID do cliente OAuth. Se não fornecido, o registro dinâmico do cliente será tentado. | +| `clientSecret` | String | Segredo do cliente OAuth, se necessário pelo servidor de autorização. | +| `scope` | String | Escopos OAuth a serem solicitados durante a autorização. | + +#### Depuração + +Se um servidor MCP remoto estiver falhando na autenticação, você pode diagnosticar problemas com: + +```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 +``` + +O comando `mcp debug` mostra o status de autenticação atual, testa a conectividade HTTP e tenta o fluxo de descoberta OAuth. + +--- + +## Gerenciamento + +Seus MCPs estão disponíveis como ferramentas no opencode, juntamente com ferramentas integradas. Portanto, você pode gerenciá-los através da configuração do opencode como qualquer outra ferramenta. + +--- + +### Global + +Isso significa que você pode habilitá-los ou desabilitá-los globalmente. + +```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 + } +} +``` + +Também podemos usar um padrão glob para desabilitar todos os MCPs correspondentes. + +```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 + } +} +``` + +Aqui estamos usando o padrão glob `my-mcp*` para desabilitar todos os MCPs. + +--- + +### Por agente + +Se você tiver um grande número de servidores MCP, pode querer habilitá-los apenas por agente e desabilitá-los globalmente. Para fazer isso: + +1. Desabilite-o como uma ferramenta globalmente. +2. Em sua [configuração de agente](/docs/agents#tools), habilite o servidor MCP como uma ferramenta. + +```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 + } + } + } +} +``` + +--- + +#### Padrões glob + +O padrão glob usa padrões simples de regex globbing: + +- `*` corresponde a zero ou mais de qualquer caractere (por exemplo, `"my-mcp*"` corresponde a `my-mcp_search`, `my-mcp_list`, etc.) +- `?` corresponde exatamente a um caractere +- Todos os outros caracteres correspondem literalmente + +:::note +As ferramentas do servidor MCP são registradas com o nome do servidor como prefixo, então para desabilitar todas as ferramentas de um servidor, simplesmente use: + +``` +"mymcpservername_*": false +``` + +::: + +--- + +## Exemplos + +Abaixo estão exemplos de alguns servidores MCP comuns. Você pode enviar um PR se quiser documentar outros servidores. + +--- + +### Sentry + +Adicione o [servidor MCP Sentry](https://mcp.sentry.dev) para interagir com seus projetos e problemas do Sentry. + +```json title="opencode.json" {4-8} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "sentry": { + "type": "remote", + "url": "https://mcp.sentry.dev/mcp", + "oauth": {} + } + } +} +``` + +Após adicionar a configuração, autentique-se com o Sentry: + +```bash +opencode mcp auth sentry +``` + +Isso abrirá uma janela do navegador para completar o fluxo OAuth e conectar o opencode à sua conta do Sentry. + +Uma vez autenticado, você pode usar ferramentas do Sentry em seus prompts para consultar problemas, projetos e dados de erro. + +```txt "use sentry" +Show me the latest unresolved issues in my project. use sentry +``` + +--- + +### Context7 + +Adicione o [servidor MCP Context7](https://github.com/upstash/context7) para pesquisar através de documentos. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "context7": { + "type": "remote", + "url": "https://mcp.context7.com/mcp" + } + } +} +``` + +Se você se inscreveu para uma conta gratuita, pode usar sua chave de API e obter limites de taxa mais altos. + +```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}" + } + } + } +} +``` + +Aqui estamos assumindo que você tem a variável de ambiente `CONTEXT7_API_KEY` definida. + +Adicione `use context7` aos seus prompts para usar o servidor MCP Context7. + +```txt "use context7" +Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 +``` + +Alternativamente, você pode adicionar algo assim ao seu [AGENTS.md](/docs/rules/). + +```md title="AGENTS.md" +When you need to search docs, use `context7` tools. +``` + +--- + +### Grep by Vercel + +Adicione o [Grep by Vercel](https://grep.app) servidor MCP para pesquisar através de trechos de código no GitHub. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "gh_grep": { + "type": "remote", + "url": "https://mcp.grep.app" + } + } +} +``` + +Como nomeamos nosso servidor MCP como `gh_grep`, você pode adicionar `use the gh_grep tool` aos seus prompts para fazer o agente usá-lo. + +```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 +``` + +Alternativamente, você pode adicionar algo assim ao seu [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/pt-br/models.mdx b/packages/web/src/content/docs/pt-br/models.mdx new file mode 100644 index 00000000000..3711bf1102e --- /dev/null +++ b/packages/web/src/content/docs/pt-br/models.mdx @@ -0,0 +1,222 @@ +--- +title: Modelos +description: Configurando um provedor e modelo LLM. +--- + +O opencode usa o [AI SDK](https://ai-sdk.dev/) e [Models.dev](https://models.dev) para suportar **75+ provedores LLM** e suporta a execução de modelos locais. + +--- + +## Provedores + +Os provedores mais populares são pré-carregados por padrão. Se você adicionou as credenciais para um provedor através do comando `/connect`, elas estarão disponíveis quando você iniciar o opencode. + +Saiba mais sobre [provedores](/docs/providers). + +--- + +## Selecionando um modelo + +Depois de configurar seu provedor, você pode selecionar o modelo que deseja digitando: + +```bash frame="none" +/models +``` + +--- + +## Modelos recomendados + +Existem muitos modelos disponíveis, com novos modelos sendo lançados toda semana. + +:::tip +Considere usar um dos modelos que recomendamos. +::: + +No entanto, há apenas alguns deles que são bons tanto em gerar código quanto em chamar ferramentas. + +Aqui estão vários modelos que funcionam bem com o opencode, em nenhuma ordem específica. (Esta não é uma lista exaustiva nem necessariamente atualizada): + +- GPT 5.2 +- GPT 5.1 Codex +- Claude Opus 4.5 +- Claude Sonnet 4.5 +- Minimax M2.1 +- Gemini 3 Pro + +--- + +## Definindo um padrão + +Para definir um desses como o modelo padrão, você pode definir a chave `model` na sua configuração do opencode. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +Aqui, o ID completo é `provider_id/model_id`. Por exemplo, se você estiver usando [OpenCode Zen](/docs/zen), você usaria `opencode/gpt-5.1-codex` para GPT 5.1 Codex. + +Se você configurou um [provedor personalizado](/docs/providers#custom), o `provider_id` é a chave da parte `provider` da sua configuração, e o `model_id` é a chave de `provider.models`. + +--- + +## Configurando modelos + +Você pode configurar globalmente as opções de um modelo através da configuração. + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +Aqui estamos configurando as configurações globais para dois modelos integrados: `gpt-5` quando acessado via o provedor `openai`, e `claude-sonnet-4-20250514` quando acessado via o provedor `anthropic`. +Os nomes dos provedores e modelos integrados podem ser encontrados em [Models.dev](https://models.dev). + +Você também pode configurar essas opções para quaisquer agentes que estiver usando. A configuração do agente substitui quaisquer opções globais aqui. [Saiba mais](/docs/agents/#additional). + +Você também pode definir variantes personalizadas que estendem as integradas. As variantes permitem que você configure diferentes configurações para o mesmo modelo sem criar entradas duplicadas: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## Variantes + +Muitos modelos suportam várias variantes com diferentes configurações. O opencode vem com variantes padrão integradas para provedores populares. + +### Variantes integradas + +O opencode vem com variantes padrão para muitos provedores: + +**Anthropic**: + +- `high` - Orçamento de pensamento alto (padrão) +- `max` - Orçamento de pensamento máximo + +**OpenAI**: + +Varia por modelo, mas aproximadamente: + +- `none` - Sem raciocínio +- `minimal` - Esforço de raciocínio mínimo +- `low` - Baixo esforço de raciocínio +- `medium` - Esforço de raciocínio médio +- `high` - Alto esforço de raciocínio +- `xhigh` - Esforço de raciocínio extra alto + +**Google**: + +- `low` - Orçamento de esforço/token mais baixo +- `high` - Orçamento de esforço/token mais alto + +:::tip +Esta lista não é abrangente. Muitos outros provedores também têm padrões integrados. +::: + +### Variantes personalizadas + +Você pode substituir variantes existentes ou adicionar as suas: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### Ciclo de variantes + +Use a tecla de atalho `variant_cycle` para alternar rapidamente entre variantes. [Saiba mais](/docs/keybinds). + +--- + +## Carregando modelos + +Quando o opencode é iniciado, ele verifica modelos na seguinte ordem de prioridade: + +1. A flag de linha de comando `--model` ou `-m`. O formato é o mesmo que no arquivo de configuração: `provider_id/model_id`. + +2. A lista de modelos na configuração do opencode. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + + O formato aqui é `provider/model`. + +3. O último modelo usado. + +4. O primeiro modelo usando uma prioridade interna. diff --git a/packages/web/src/content/docs/pt-br/modes.mdx b/packages/web/src/content/docs/pt-br/modes.mdx new file mode 100644 index 00000000000..62a7f947af2 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/modes.mdx @@ -0,0 +1,328 @@ +--- +title: Modos +description: Modos diferentes para diferentes casos de uso. +--- + +:::caution +Os modos agora são configurados através da opção `agent` na configuração do opencode. A opção `mode` agora está obsoleta. [Saiba mais](/docs/agents). +::: + +Os modos no opencode permitem que você personalize o comportamento, as ferramentas e os prompts para diferentes casos de uso. + +Ele vem com dois modos integrados: **build** e **plan**. Você pode personalizar esses ou configurar os seus próprios através da configuração do opencode. + +Você pode alternar entre os modos durante uma sessão ou configurá-los no seu arquivo de configuração. + +--- + +## Integrados + +O opencode vem com dois modos integrados. + +--- + +### build + +Build é o modo **padrão** com todas as ferramentas habilitadas. Este é o modo padrão para trabalho de desenvolvimento onde você precisa de acesso total a operações de arquivos e comandos do sistema. + +--- + +### plan + +Um modo restrito projetado para planejamento e análise. No modo plan, as seguintes ferramentas estão desativadas por padrão: + +- `write` - Não pode criar novos arquivos +- `edit` - Não pode modificar arquivos existentes, exceto para arquivos localizados em `.opencode/plans/*.md` para detalhar o plano em si +- `patch` - Não pode aplicar patches +- `bash` - Não pode executar comandos de shell + +Este modo é útil quando você deseja que a IA analise o código, sugira alterações ou crie planos sem fazer modificações reais em sua base de código. + +--- + +## Alternando + +Você pode alternar entre modos durante uma sessão usando a tecla _Tab_. Ou sua tecla de atalho configurada `switch_mode`. + +Veja também: [Formatadores](/docs/formatters) para informações sobre configuração de formatação de código. + +--- + +## Configuração + +Você pode personalizar os modos integrados ou criar os seus próprios através da configuração. Os modos podem ser configurados de duas maneiras: + +### Configuração JSON + +Configure os modos no seu arquivo de configuração `opencode.json`: + +```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 + } + } + } +} +``` + +### Configuração Markdown + +Você também pode definir modos usando arquivos markdown. Coloque-os em: + +- Global: `~/.config/opencode/modes/` +- Projeto: `.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. +``` + +O nome do arquivo markdown se torna o nome do modo (por exemplo, `review.md` cria um modo `review`). + +Vamos analisar essas opções de configuração em detalhes. + +--- + +### Modelo + +Use a configuração `model` para substituir o modelo padrão para este modo. Útil para usar diferentes modelos otimizados para diferentes tarefas. Por exemplo, um modelo mais rápido para planejamento, um modelo mais capaz para implementação. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### Temperatura + +Controle a aleatoriedade e a criatividade das respostas da IA com a configuração `temperature`. Valores mais baixos tornam as respostas mais focadas e determinísticas, enquanto valores mais altos aumentam a criatividade e a variabilidade. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Os valores de temperatura geralmente variam de 0.0 a 1.0: + +- **0.0-0.2**: Respostas muito focadas e determinísticas, ideais para análise de código e planejamento +- **0.3-0.5**: Respostas equilibradas com alguma criatividade, boas para tarefas de desenvolvimento geral +- **0.6-1.0**: Respostas mais criativas e variadas, úteis para brainstorming e exploração + +```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}" + } + } +} +``` + +Se nenhuma temperatura for especificada, o opencode usa padrões específicos do modelo (geralmente 0 para a maioria dos modelos, 0.55 para modelos Qwen). + +--- + +### Prompt + +Especifique um arquivo de prompt do sistema personalizado para este modo com a configuração `prompt`. O arquivo de prompt deve conter instruções específicas para o propósito do modo. + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Este caminho é relativo a onde o arquivo de configuração está localizado. Portanto, isso funciona tanto para a configuração global do opencode quanto para a configuração específica do projeto. + +--- + +### Ferramentas + +Controle quais ferramentas estão disponíveis neste modo com a configuração `tools`. Você pode habilitar ou desabilitar ferramentas específicas definindo-as como `true` ou `false`. + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +Se nenhuma ferramenta for especificada, todas as ferramentas estão habilitadas por padrão. + +--- + +#### Ferramentas disponíveis + +Aqui estão todas as ferramentas que podem ser controladas através da configuração do modo. + +| Ferramenta | Descrição | +| ----------- | ------------------------------- | +| `bash` | Executar comandos de shell | +| `edit` | Modificar arquivos existentes | +| `write` | Criar novos arquivos | +| `read` | Ler conteúdos de arquivos | +| `grep` | Pesquisar conteúdos de arquivos | +| `glob` | Encontrar arquivos por padrão | +| `list` | Listar conteúdos de diretório | +| `patch` | Aplicar patches a arquivos | +| `todowrite` | Gerenciar listas de tarefas | +| `todoread` | Ler listas de tarefas | +| `webfetch` | Buscar conteúdo da web | + +--- + +## Modos personalizados + +Você pode criar seus próprios modos personalizados adicionando-os à configuração. Aqui estão exemplos usando ambas as abordagens: + +### Usando configuração JSON + +```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 + } + } + } +} +``` + +### Usando arquivos markdown + +Crie arquivos de modo em `.opencode/modes/` para modos específicos do projeto ou `~/.config/opencode/modes/` para modos globais: + +```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 +``` + +--- + +### Casos de uso + +Aqui estão alguns casos de uso comuns para diferentes modos. + +- **Modo Build**: Trabalho de desenvolvimento completo com todas as ferramentas habilitadas +- **Modo Plan**: Análise e planejamento sem fazer alterações +- **Modo Review**: Revisão de código com acesso somente leitura e ferramentas de documentação +- **Modo Debug**: Focado em investigação com ferramentas bash e de leitura habilitadas +- **Modo Docs**: Redação de documentação com operações de arquivo, mas sem comandos do sistema + +Você também pode descobrir que diferentes modelos são bons para diferentes casos de uso. diff --git a/packages/web/src/content/docs/pt-br/network.mdx b/packages/web/src/content/docs/pt-br/network.mdx new file mode 100644 index 00000000000..1e13f258c6a --- /dev/null +++ b/packages/web/src/content/docs/pt-br/network.mdx @@ -0,0 +1,57 @@ +--- +title: Rede +description: Configure proxies e certificados personalizados. +--- + +O opencode suporta variáveis de ambiente de proxy padrão e certificados personalizados para ambientes de rede corporativa. + +--- + +## Proxy + +O opencode respeita variáveis de ambiente de proxy padrão. + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +O TUI se comunica com um servidor HTTP local. Você deve ignorar o proxy para essa conexão para evitar loops de roteamento. +::: + +Você pode configurar a porta e o nome do host do servidor usando [flags da CLI](/docs/cli#run). + +--- + +### Autenticação + +Se o seu proxy requer autenticação básica, inclua as credenciais na URL. + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +Evite codificar senhas. Use variáveis de ambiente ou armazenamento seguro de credenciais. +::: + +Para proxies que requerem autenticação avançada como NTLM ou Kerberos, considere usar um LLM Gateway que suporte seu método de autenticação. + +--- + +## Certificados personalizados + +Se sua empresa usa CAs personalizadas para conexões HTTPS, configure o opencode para confiá-las. + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +Isso funciona tanto para conexões de proxy quanto para acesso direto à API. diff --git a/packages/web/src/content/docs/pt-br/permissions.mdx b/packages/web/src/content/docs/pt-br/permissions.mdx new file mode 100644 index 00000000000..a815e731345 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: Permissões +description: Controle quais ações requerem aprovação para serem executadas. +--- + +O opencode usa a configuração `permission` para decidir se uma determinada ação deve ser executada automaticamente, solicitar sua aprovação ou ser bloqueada. + +A partir da versão `v1.1.1`, a configuração booleana legada `tools` foi descontinuada e mesclada na `permission`. A antiga configuração `tools` ainda é suportada para compatibilidade retroativa. + +--- + +## Ações + +Cada regra de permissão se resolve em uma das seguintes opções: + +- `"allow"` — executar sem aprovação +- `"ask"` — solicitar aprovação +- `"deny"` — bloquear a ação + +--- + +## Configuração + +Você pode definir permissões globalmente (com `*`), e substituir ferramentas específicas. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +Você também pode definir todas as permissões de uma vez: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## Regras Granulares (Sintaxe de Objeto) + +Para a maioria das permissões, você pode usar um objeto para aplicar diferentes ações com base na entrada da ferramenta. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +As regras são avaliadas por correspondência de padrão, com a **última regra correspondente vencendo**. Um padrão comum é colocar a regra de captura `"*"` primeiro, e regras mais específicas depois. + +### Coringas + +Os padrões de permissão usam correspondência simples de coringas: + +- `*` corresponde a zero ou mais de qualquer caractere +- `?` corresponde exatamente a um caractere +- Todos os outros caracteres correspondem literalmente + +### Expansão do Diretório Home + +Você pode usar `~` ou `$HOME` no início de um padrão para referenciar seu diretório home. Isso é particularmente útil para regras de [`external_directory`](#external-directories). + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### Diretórios Externos + +Use `external_directory` para permitir chamadas de ferramentas que tocam em caminhos fora do diretório de trabalho onde o opencode foi iniciado. Isso se aplica a qualquer ferramenta que aceite um caminho como entrada (por exemplo, `read`, `edit`, `list`, `glob`, `grep` e muitos comandos `bash`). + +A expansão do home (como `~/...`) afeta apenas como um padrão é escrito. Não torna um caminho externo parte do espaço de trabalho atual, então caminhos fora do diretório de trabalho ainda devem ser permitidos via `external_directory`. + +Por exemplo, isso permite acesso a tudo sob `~/projects/personal/`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +Qualquer diretório permitido aqui herda os mesmos padrões do espaço de trabalho atual. Como [`read` padrão é `allow`](#defaults), leituras também são permitidas para entradas sob `external_directory`, a menos que sejam substituídas. Adicione regras explícitas quando uma ferramenta deve ser restrita nesses caminhos, como bloquear edições enquanto mantém leituras: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +Mantenha a lista focada em caminhos confiáveis e adicione regras adicionais de permissão ou negação conforme necessário para outras ferramentas (por exemplo, `bash`). + +--- + +## Permissões Disponíveis + +As permissões do opencode são indexadas pelo nome da ferramenta, além de alguns guardas de segurança: + +- `read` — leitura de um arquivo (corresponde ao caminho do arquivo) +- `edit` — todas as modificações de arquivo (cobre `edit`, `write`, `patch`, `multiedit`) +- `glob` — globbing de arquivos (corresponde ao padrão glob) +- `grep` — busca de conteúdo (corresponde ao padrão regex) +- `list` — listagem de arquivos em um diretório (corresponde ao caminho do diretório) +- `bash` — execução de comandos de shell (corresponde a comandos analisados como `git status --porcelain`) +- `task` — lançamento de subagentes (corresponde ao tipo de subagente) +- `skill` — carregamento de uma habilidade (corresponde ao nome da habilidade) +- `lsp` — execução de consultas LSP (atualmente não granular) +- `todoread`, `todowrite` — leitura/atualização da lista de tarefas +- `webfetch` — busca de uma URL (corresponde à URL) +- `websearch`, `codesearch` — busca na web/código (corresponde à consulta) +- `external_directory` — acionado quando uma ferramenta toca em caminhos fora do diretório de trabalho do projeto +- `doom_loop` — acionado quando a mesma chamada de ferramenta se repete 3 vezes com entrada idêntica + +--- + +## Padrões + +Se você não especificar nada, o opencode começa com padrões permissivos: + +- A maioria das permissões padrão é `"allow"`. +- `doom_loop` e `external_directory` padrão é `"ask"`. +- `read` é `"allow"`, mas arquivos `.env` são negados por padrão: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## O que “Ask” Faz + +Quando o opencode solicita aprovação, a interface oferece três resultados: + +- `once` — aprovar apenas esta solicitação +- `always` — aprovar futuras solicitações que correspondam aos padrões sugeridos (para o restante da sessão atual do opencode) +- `reject` — negar a solicitação + +O conjunto de padrões que `always` aprovaria é fornecido pela ferramenta (por exemplo, aprovações de bash normalmente incluem um prefixo de comando seguro como `git status*`). + +--- + +## Agentes + +Você pode substituir permissões por agente. As permissões do agente são mescladas com a configuração global, e as regras do agente têm precedência. [Saiba mais](/docs/agents#permissions) sobre permissões de agentes. + +:::note +Consulte a seção [Regras Granulares (Sintaxe de Objeto)](#granular-rules-object-syntax) acima para exemplos mais detalhados de correspondência de padrões. +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +Você também pode configurar permissões de agentes em Markdown: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +Use correspondência de padrões para comandos com argumentos. `"grep *"` permite `grep pattern file.txt`, enquanto `"grep"` sozinho o bloquearia. Comandos como `git status` funcionam para o comportamento padrão, mas requerem permissão explícita (como `"git status *"`) quando argumentos são passados. +::: diff --git a/packages/web/src/content/docs/pt-br/plugins.mdx b/packages/web/src/content/docs/pt-br/plugins.mdx new file mode 100644 index 00000000000..bcf8f379bc3 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/plugins.mdx @@ -0,0 +1,384 @@ +--- +title: Plugins +description: Escreva seus próprios plugins para estender o opencode. +--- + +Plugins permitem que você estenda o opencode conectando-se a vários eventos e personalizando o comportamento. Você pode criar plugins para adicionar novos recursos, integrar-se a serviços externos ou modificar o comportamento padrão do opencode. + +Para exemplos, confira os [plugins](/docs/ecosystem#plugins) criados pela comunidade. + +--- + +## Usando um plugin + +Existem duas maneiras de carregar plugins. + +--- + +### De arquivos locais + +Coloque arquivos JavaScript ou TypeScript no diretório de plugins. + +- `.opencode/plugins/` - Plugins em nível de projeto +- `~/.config/opencode/plugins/` - Plugins globais + +Os arquivos nesses diretórios são carregados automaticamente na inicialização. + +--- + +### Do npm + +Especifique pacotes npm no seu arquivo de configuração. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +Pacotes npm regulares e escopados são suportados. + +Navegue pelos plugins disponíveis no [ecossistema](/docs/ecosystem#plugins). + +--- + +### Como os plugins são instalados + +**Plugins npm** são instalados automaticamente usando Bun na inicialização. Pacotes e suas dependências são armazenados em cache em `~/.cache/opencode/node_modules/`. + +**Plugins locais** são carregados diretamente do diretório de plugins. Para usar pacotes externos, você deve criar um `package.json` dentro do seu diretório de configuração (veja [Dependências](#dependencies)), ou publicar o plugin no npm e [adicioná-lo à sua configuração](/docs/config#plugins). + +--- + +### Ordem de carregamento + +Os plugins são carregados de todas as fontes e todos os hooks são executados em sequência. A ordem de carregamento é: + +1. Configuração global (`~/.config/opencode/opencode.json`) +2. Configuração do projeto (`opencode.json`) +3. Diretório de plugins global (`~/.config/opencode/plugins/`) +4. Diretório de plugins do projeto (`.opencode/plugins/`) + +Pacotes npm duplicados com o mesmo nome e versão são carregados uma vez. No entanto, um plugin local e um plugin npm com nomes semelhantes são carregados separadamente. + +--- + +## Criando um plugin + +Um plugin é um **módulo JavaScript/TypeScript** que exporta uma ou mais funções de plugin. Cada função recebe um objeto de contexto e retorna um objeto de hooks. + +--- + +### Dependências + +Plugins locais e ferramentas personalizadas podem usar pacotes npm externos. Adicione um `package.json` ao seu diretório de configuração com as dependências necessárias. + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +O opencode executa `bun install` na inicialização para instalar esses pacotes. Seus plugins e ferramentas podem então importá-los. + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### Estrutura básica + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +A função do plugin recebe: + +- `project`: As informações do projeto atual. +- `directory`: O diretório de trabalho atual. +- `worktree`: O caminho do worktree do git. +- `client`: Um cliente SDK do opencode para interagir com a AI. +- `$`: A [API shell](https://bun.com/docs/runtime/shell) do Bun para executar comandos. + +--- + +### Suporte a TypeScript + +Para plugins TypeScript, você pode importar tipos do pacote de plugin: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### Eventos + +Plugins podem se inscrever em eventos como visto abaixo na seção Exemplos. Aqui está uma lista dos diferentes eventos disponíveis. + +#### Eventos de Comando + +- `command.executed` + +#### Eventos de Arquivo + +- `file.edited` +- `file.watcher.updated` + +#### Eventos de Instalação + +- `installation.updated` + +#### Eventos LSP + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### Eventos de Mensagem + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### Eventos de Permissão + +- `permission.asked` +- `permission.replied` + +#### Eventos de Servidor + +- `server.connected` + +#### Eventos de Sessão + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### Eventos de Todo + +- `todo.updated` + +#### Eventos de Shell + +- `shell.env` + +#### Eventos de Ferramenta + +- `tool.execute.after` +- `tool.execute.before` + +#### Eventos TUI + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## Exemplos + +Aqui estão alguns exemplos de plugins que você pode usar para estender o opencode. + +--- + +### Enviando notificações + +Envie notificações quando certos eventos ocorrerem: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +Estamos usando `osascript` para executar AppleScript no macOS. Aqui estamos usando para enviar notificações. + +:::note +Se você estiver usando o aplicativo desktop opencode, ele pode enviar notificações do sistema automaticamente quando uma resposta estiver pronta ou quando ocorrer um erro na sessão. +::: + +--- + +### Proteção .env + +Impeça o opencode de ler arquivos `.env`: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### Injetando variáveis de ambiente + +Injete variáveis de ambiente em todas as execuções de shell (ferramentas de AI e terminais de usuário): + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### Ferramentas personalizadas + +Plugins também podem adicionar ferramentas personalizadas ao opencode: + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +O helper `tool` cria uma ferramenta personalizada que o opencode pode chamar. Ele aceita uma função de esquema Zod e retorna uma definição de ferramenta com: + +- `description`: O que a ferramenta faz +- `args`: Esquema Zod para os argumentos da ferramenta +- `execute`: Função que é executada quando a ferramenta é chamada + +Suas ferramentas personalizadas estarão disponíveis para o opencode junto com as ferramentas integradas. + +--- + +### Registro + +Use `client.app.log()` em vez de `console.log` para registro estruturado: + +```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" }, + }, + }) +} +``` + +Níveis: `debug`, `info`, `warn`, `error`. Veja a [documentação do SDK](https://opencode.ai/docs/sdk) para detalhes. + +--- + +### Hooks de compactação + +Personalize o contexto incluído quando uma sessão é compactada: + +```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 +`) + }, + } +} +``` + +O hook `experimental.session.compacting` é acionado antes que o LLM gere um resumo de continuação. Use-o para injetar contexto específico de domínio que o prompt de compactação padrão poderia perder. + +Você também pode substituir o prompt de compactação completamente definindo `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. +` + }, + } +} +``` + +Quando `output.prompt` é definido, ele substitui completamente o prompt de compactação padrão. O array `output.context` é ignorado neste caso. diff --git a/packages/web/src/content/docs/pt-br/providers.mdx b/packages/web/src/content/docs/pt-br/providers.mdx new file mode 100644 index 00000000000..43f2e385f13 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/providers.mdx @@ -0,0 +1,1898 @@ +--- +title: Provedores +description: Usando qualquer provedor LLM no opencode. +--- + +import config from "../../../../config.mjs" +export const console = config.console + +opencode usa o [AI SDK](https://ai-sdk.dev/) e [Models.dev](https://models.dev) para suportar **75+ provedores LLM** e suporta a execução de modelos locais. + +Para adicionar um provedor, você precisa: + +1. Adicionar as chaves da API para o provedor usando o comando `/connect`. +2. Configurar o provedor na sua configuração do opencode. + +--- + +### Credenciais + +Quando você adiciona as chaves da API de um provedor com o comando `/connect`, elas são armazenadas em `~/.local/share/opencode/auth.json`. + +--- + +### Configuração + +Você pode personalizar os provedores através da seção `provider` na sua configuração do opencode. + +--- + +#### URL Base + +Você pode personalizar a URL base para qualquer provedor definindo a opção `baseURL`. Isso é útil ao usar serviços de proxy ou endpoints personalizados. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen é uma lista de modelos fornecidos pela equipe do opencode que foram testados e verificados para funcionar bem com o opencode. [Saiba mais](/docs/zen). + +:::tip +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). + + ```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. + +--- + +## Diretório + +Vamos olhar alguns dos provedores em detalhes. Se você gostaria de adicionar um provedor à lista, sinta-se à vontade para abrir um PR. + +:::note +Não vê um provedor aqui? Envie um PR. +::: + +--- + +### 302.AI + +1. Acesse o [console 302.AI](https://302.ai/), crie uma conta e gere uma chave da API. + +2. Execute o comando `/connect` e procure por **302.AI**. + + ```txt + /connect + ``` + +3. Insira sua chave da API 302.AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo. + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +Para usar o Amazon Bedrock com o opencode: + +1. Acesse o **Catálogo de Modelos** no console do Amazon Bedrock e solicite acesso aos modelos que você deseja. + + :::tip + Você precisa ter acesso ao modelo que deseja no Amazon Bedrock. + ::: + +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: + + ```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode + ``` + + Ou adicione-as ao seu perfil bash: + + ```bash title="~/.bash_profile" + export AWS_PROFILE=my-dev-profile + export AWS_REGION=us-east-1 + ``` + + #### Arquivo de Configuração (Recomendado) + + Para configuração específica do projeto ou persistente, use `opencode.json`: + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile" + } + } + } + } + ``` + + **Opções disponíveis:** + - `region` - Região da AWS (ex: `us-east-1`, `eu-west-1`) + - `profile` - Perfil nomeado da AWS em `~/.aws/credentials` + - `endpoint` - URL de endpoint personalizada para endpoints VPC (alias para a opção genérica `baseURL`) + + :::tip + 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: + + ```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 + 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: + 1. **Bearer Token** - variável de ambiente `AWS_BEARER_TOKEN_BEDROCK` ou token do comando `/connect` + 2. **Cadeia de Credenciais da AWS** - Perfil, chaves de acesso, credenciais compartilhadas, funções IAM, Tokens de Identidade da Web (EKS IRSA), metadados da instância + + :::note + Quando um token bearer é definido (via `/connect` ou `AWS_BEARER_TOKEN_BEDROCK`), ele tem precedência sobre todos os métodos de credenciais da AWS, incluindo perfis configurados. + ::: + +3. Execute o comando `/models` para selecionar o modelo que você deseja. + + ```txt + /models + ``` + +:::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: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. Depois de se inscrever, execute o comando `/connect` e selecione Anthropic. + + ```txt + /connect + ``` + +2. Aqui você pode selecionar a opção **Claude Pro/Max** e isso abrirá seu navegador e pedirá para você se autenticar. + + ```txt + ┌ Selecione o método de autenticação + │ + │ Claude Pro/Max + │ Criar uma chave de API + │ Inserir manualmente a chave de API + └ + ``` + +3. Agora todos os modelos da Anthropic devem estar disponíveis quando você usar o comando `/models`. + + ```txt + /models + ``` + +:::info +Usar sua assinatura Claude Pro/Max no opencode não é oficialmente suportado pela [Anthropic](https://anthropic.com). +::: + +##### Usando chaves da API + +Você também pode selecionar **Criar uma chave de API** se não tiver uma assinatura Pro/Max. Isso também abrirá seu navegador e pedirá que você faça login na Anthropic e lhe dará um código que você pode colar no seu terminal. + +Ou, se você já tiver uma chave da API, pode selecionar **Inserir manualmente a chave de API** e colá-la no seu terminal. + +--- + +### Azure OpenAI + +:::note +Se você encontrar erros "Desculpe, mas não posso ajudar com esse pedido", tente mudar o filtro de conteúdo de **DefaultV2** para **Default** em seu recurso Azure. +::: + +1. Acesse o [portal Azure](https://portal.azure.com/) e crie um recurso **Azure OpenAI**. Você precisará: + - **Nome do recurso**: Isso se torna parte do seu endpoint da API (`https://RESOURCE_NAME.openai.azure.com/`) + - **Chave da API**: Seja `KEY 1` ou `KEY 2` do seu recurso + +2. Vá para [Azure AI Foundry](https://ai.azure.com/) e implante um modelo. + + :::note + O nome da implantação deve corresponder ao nome do modelo para que o opencode funcione corretamente. + ::: + +3. Execute o comando `/connect` e procure por **Azure**. + + ```txt + /connect + ``` + +4. Insira sua chave da API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Defina o nome do seu recurso como uma variável de ambiente: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + Ou adicione ao seu perfil bash: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. Execute o comando `/models` para selecionar seu modelo implantado. + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. Acesse o [portal Azure](https://portal.azure.com/) e crie um recurso **Azure OpenAI**. Você precisará: + - **Nome do recurso**: Isso se torna parte do seu endpoint da API (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) + - **Chave da API**: Seja `KEY 1` ou `KEY 2` do seu recurso + +2. Vá para [Azure AI Foundry](https://ai.azure.com/) e implante um modelo. + + :::note + O nome da implantação deve corresponder ao nome do modelo para que o opencode funcione corretamente. + ::: + +3. Execute o comando `/connect` e procure por **Azure Cognitive Services**. + + ```txt + /connect + ``` + +4. Insira sua chave da API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Defina o nome do seu recurso como uma variável de ambiente: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + Ou adicione ao seu perfil bash: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. Execute o comando `/models` para selecionar seu modelo implantado. + + ```txt + /models + ``` + +--- + +### Baseten + +1. Acesse o [Baseten](https://app.baseten.co/), crie uma conta e gere uma chave da API. + +2. Execute o comando `/connect` e procure por **Baseten**. + + ```txt + /connect + ``` + +3. Insira sua chave da API Baseten. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo. + + ```txt + /models + ``` + +--- + +### Cerebras + +1. Acesse o [console Cerebras](https://inference.cerebras.ai/), crie uma conta e gere uma chave da API. + +2. Execute o comando `/connect` e procure por **Cerebras**. + + ```txt + /connect + ``` + +3. Insira sua chave da API Cerebras. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo como _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +O Cloudflare AI Gateway permite que você acesse modelos do OpenAI, Anthropic, Workers AI e mais através de um endpoint unificado. Com [Faturamento Unificado](https://developers.cloudflare.com/ai-gateway/features/unified-billing/), você não precisa de chaves de API separadas para cada provedor. + +1. Acesse o [painel do Cloudflare](https://dash.cloudflare.com/), navegue até **AI** > **AI Gateway** e crie um novo gateway. + +2. Defina seu ID de Conta e ID de Gateway como variáveis de ambiente. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. Execute o comando `/connect` e procure por **Cloudflare AI Gateway**. + + ```txt + /connect + ``` + +4. Insira seu token da API do Cloudflare. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + Ou defina como uma variável de ambiente. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. Execute o comando `/models` para selecionar um modelo. + + ```txt + /models + ``` + + Você também pode adicionar modelos através da sua configuração do opencode. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +### Cortecs + +1. Acesse o [console Cortecs](https://cortecs.ai/), crie uma conta e gere uma chave da API. + +2. Execute o comando `/connect` e procure por **Cortecs**. + + ```txt + /connect + ``` + +3. Insira sua chave da API Cortecs. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo como _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. Acesse o [console DeepSeek](https://platform.deepseek.com/), crie uma conta e clique em **Criar nova chave da API**. + +2. Execute o comando `/connect` e procure por **DeepSeek**. + + ```txt + /connect + ``` + +3. Insira sua chave da API DeepSeek. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo DeepSeek como _DeepSeek Reasoner_. + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. Acesse o [painel Deep Infra](https://deepinfra.com/dash), crie uma conta e gere uma chave da API. + +2. Execute o comando `/connect` e procure por **Deep Infra**. + + ```txt + /connect + ``` + +3. Insira sua chave da API Deep Infra. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo. + + ```txt + /models + ``` + +--- + +### Firmware + +1. Acesse o [painel Firmware](https://app.firmware.ai/signup), crie uma conta e gere uma chave da API. + +2. Execute o comando `/connect` e procure por **Firmware**. + + ```txt + /connect + ``` + +3. Insira sua chave da API Firmware. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo. + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. Acesse o [console Fireworks AI](https://app.fireworks.ai/), crie uma conta e clique em **Criar Chave da API**. + +2. Execute o comando `/connect` e procure por **Fireworks AI**. + + ```txt + /connect + ``` + +3. Insira sua chave da API Fireworks AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo como _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo fornece um chat agente com suporte a ferramentas nativas através do proxy da Anthropic do GitLab. + +1. Execute o comando `/connect` e selecione GitLab. + + ```txt + /connect + ``` + +2. Escolha seu método de autenticação: + + ```txt + ┌ Selecione o método de autenticação + │ + │ OAuth (Recomendado) + │ Token de Acesso Pessoal + └ + ``` + + #### Usando OAuth (Recomendado) + + Selecione **OAuth** e seu navegador abrirá para autorização. + + #### Usando Token de Acesso Pessoal + 1. Vá para [Configurações do Usuário do GitLab > Tokens de Acesso](https://gitlab.com/-/user_settings/personal_access_tokens) + 2. Clique em **Adicionar novo token** + 3. Nome: `OpenCode`, Escopos: `api` + 4. Copie o token (começa com `glpat-`) + 5. Insira-o no terminal + +3. Execute o comando `/models` para ver os modelos disponíveis. + + ```txt + /models + ``` + + Três modelos baseados em Claude estão disponíveis: + - **duo-chat-haiku-4-5** (Padrão) - Respostas rápidas para tarefas rápidas + - **duo-chat-sonnet-4-5** - Desempenho equilibrado para a maioria dos fluxos de trabalho + - **duo-chat-opus-4-5** - Mais capaz para análises complexas + +:::note +Você também pode especificar a variável de ambiente 'GITLAB_TOKEN' se não quiser +armazenar o token no armazenamento de autenticação do opencode. +::: + +##### GitLab Auto-Hospedado + +:::note[nota de conformidade] +opencode usa um pequeno modelo para algumas tarefas de AI, como gerar o título da sessão. +Ele está configurado para usar gpt-5-nano por padrão, hospedado pela Zen. Para bloquear o opencode +para usar apenas sua própria instância hospedada do GitLab, adicione o seguinte ao seu +arquivo `opencode.json`. Também é recomendado desativar o compartilhamento de sessões. + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +Para instâncias do GitLab auto-hospedadas: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +Se sua instância executar um AI Gateway personalizado: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +Ou adicione ao seu perfil bash: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +Seu administrador do GitLab deve habilitar o seguinte: + +1. [Duo Agent Platform](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) para o usuário, grupo ou instância +2. Flags de recurso (via console Rails): + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: + +##### OAuth para instâncias auto-hospedadas + +Para fazer o OAuth funcionar para sua instância auto-hospedada, você precisa criar +um novo aplicativo (Configurações → Aplicativos) com a +URL de callback `http://127.0.0.1:8080/callback` e os seguintes escopos: + +- api (Acessar a API em seu nome) +- read_user (Ler suas informações pessoais) +- read_repository (Permite acesso somente leitura ao repositório) + +Em seguida, exponha o ID do aplicativo como variável de ambiente: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +Mais documentação na página [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth). + +##### Configuração + +Personalize através do `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### Ferramentas da API do GitLab (Opcional, mas altamente recomendado) + +Para acessar ferramentas do GitLab (merge requests, issues, pipelines, CI/CD, etc.): + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +Este plugin fornece capacidades abrangentes de gerenciamento de repositório do GitLab, incluindo revisões de MR, rastreamento de issues, monitoramento de pipelines e mais. + +--- + +### GitHub Copilot + +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. + + ```txt + /connect + ``` + +2. Navegue até [github.com/login/device](https://github.com/login/device) e insira o código. + + ```txt + ┌ Login com GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Digite o código: 8F43-6FCF + │ + └ Aguardando autorização... + ``` + +3. Agora execute o comando `/models` para selecionar o modelo que você deseja. + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +Para usar o Google Vertex AI com o opencode: + +1. Acesse o **Model Garden** no Console do Google Cloud e verifique os + modelos disponíveis na sua região. + + :::note + Você precisa ter um projeto do Google Cloud com a API Vertex AI habilitada. + ::: + +2. Defina as variáveis de ambiente necessárias: + - `GOOGLE_CLOUD_PROJECT`: Seu ID do projeto do Google Cloud + - `VERTEX_LOCATION` (opcional): A região para o Vertex AI (padrão é `global`) + - Autenticação (escolha uma): + - `GOOGLE_APPLICATION_CREDENTIALS`: Caminho para seu arquivo de chave JSON da conta de serviço + - Autentique usando o CLI gcloud: `gcloud auth application-default login` + + Defina-as ao executar o opencode. + + ```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode + ``` + + Ou adicione-as ao seu perfil bash. + + ```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 +A região `global` melhora a disponibilidade e reduz erros sem custo adicional. Use endpoints regionais (ex: `us-central1`) para requisitos de residência de dados. [Saiba mais](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. Execute o comando `/models` para selecionar o modelo que você deseja. + + ```txt + /models + ``` + +--- + +### Groq + +1. Acesse o [console Groq](https://console.groq.com/), clique em **Criar Chave da API** e copie a chave. + +2. Execute o comando `/connect` e procure por Groq. + + ```txt + /connect + ``` + +3. Insira a chave da API para o provedor. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar o que você deseja. + + ```txt + /models + ``` + +--- + +### Hugging Face + +[Provedores de Inferência Hugging Face](https://huggingface.co/docs/inference-providers) fornecem acesso a modelos abertos suportados por mais de 17 provedores. + +1. Acesse [configurações do Hugging Face](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained) para criar um token com permissão para fazer chamadas para Provedores de Inferência. + +2. Execute o comando `/connect` e procure por **Hugging Face**. + + ```txt + /connect + ``` + +3. Insira seu token do Hugging Face. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo como _Kimi-K2-Instruct_ ou _GLM-4.6_. + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) é uma plataforma de observabilidade LLM que fornece registro, monitoramento e análises para suas aplicações de AI. O Helicone AI Gateway roteia suas solicitações para o provedor apropriado automaticamente com base no modelo. + +1. Acesse [Helicone](https://helicone.ai), crie uma conta e gere uma chave da API a partir do seu painel. + +2. Execute o comando `/connect` e procure por **Helicone**. + + ```txt + /connect + ``` + +3. Insira sua chave da API Helicone. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo. + + ```txt + /models + ``` + +Para mais provedores e recursos avançados como cache e limitação de taxa, consulte a [documentação do Helicone](https://docs.helicone.ai). + +#### Configurações Opcionais + +Caso você veja um recurso ou modelo do Helicone que não está configurado automaticamente através do opencode, você sempre pode configurá-lo você mesmo. + +Aqui está o [Diretório de Modelos do Helicone](https://helicone.ai/models), você precisará disso para pegar os IDs dos modelos que deseja adicionar. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### Cabeçalhos Personalizados + +Helicone suporta cabeçalhos personalizados para recursos como cache, rastreamento de usuários e gerenciamento de sessões. Adicione-os à sua configuração do provedor usando `options.headers`: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### Rastreamento de Sessões + +O recurso [Sessões](https://docs.helicone.ai/features/sessions) do Helicone permite que você agrupe solicitações LLM relacionadas. Use o plugin [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) para registrar automaticamente cada conversa do opencode como uma sessão no Helicone. + +```bash +npm install -g opencode-helicone-session +``` + +Adicione-o à sua configuração. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +O plugin injeta os cabeçalhos `Helicone-Session-Id` e `Helicone-Session-Name` em suas solicitações. Na página de Sessões do Helicone, você verá cada conversa do opencode listada como uma sessão separada. + +##### Cabeçalhos Comuns do Helicone + +| Cabeçalho | Descrição | +| -------------------------- | --------------------------------------------------------------------------- | +| `Helicone-Cache-Enabled` | Habilitar cache de resposta (`true`/`false`) | +| `Helicone-User-Id` | Rastrear métricas por usuário | +| `Helicone-Property-[Name]` | Adicionar propriedades personalizadas (ex: `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | Associar solicitações com versões de prompt | + +Consulte o [Diretório de Cabeçalhos do Helicone](https://docs.helicone.ai/helicone-headers/header-directory) para todos os cabeçalhos disponíveis. + +--- + +### llama.cpp + +Você pode configurar o opencode para usar modelos locais através da utilidade llama-server do [llama.cpp](https://github.com/ggml-org/llama.cpp) + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +Neste exemplo: + +- `llama.cpp` é o ID do provedor personalizado. Isso pode ser qualquer string que você quiser. +- `npm` especifica o pacote a ser usado para este provedor. Aqui, `@ai-sdk/openai-compatible` é usado para qualquer API compatível com OpenAI. +- `name` é o nome exibido para o provedor na interface do usuário. +- `options.baseURL` é o endpoint para o servidor local. +- `models` é um mapa de IDs de modelos para suas configurações. O nome do modelo será exibido na lista de seleção de modelos. + +--- + +### IO.NET + +IO.NET oferece 17 modelos otimizados para vários casos de uso: + +1. Acesse o [console IO.NET](https://ai.io.net/), crie uma conta e gere uma chave da API. + +2. Execute o comando `/connect` e procure por **IO.NET**. + + ```txt + /connect + ``` + +3. Insira sua chave da API IO.NET. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo. + + ```txt + /models + ``` + +--- + +### LM Studio + +Você pode configurar o opencode para usar modelos locais através do LM Studio. + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +Neste exemplo: + +- `lmstudio` é o ID do provedor personalizado. Isso pode ser qualquer string que você quiser. +- `npm` especifica o pacote a ser usado para este provedor. Aqui, `@ai-sdk/openai-compatible` é usado para qualquer API compatível com OpenAI. +- `name` é o nome exibido para o provedor na interface do usuário. +- `options.baseURL` é o endpoint para o servidor local. +- `models` é um mapa de IDs de modelos para suas configurações. O nome do modelo será exibido na lista de seleção de modelos. + +--- + +### Moonshot AI + +Para usar Kimi K2 do Moonshot AI: + +1. Acesse o [console Moonshot AI](https://platform.moonshot.ai/console), crie uma conta e clique em **Criar chave da API**. + +2. Execute o comando `/connect` e procure por **Moonshot AI**. + + ```txt + /connect + ``` + +3. Insira sua chave da API Moonshot. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar _Kimi K2_. + + ```txt + /models + ``` + +--- + +### MiniMax + +1. Acesse o [MiniMax API Console](https://platform.minimax.io/login), crie uma conta e gere uma chave da API. + +2. Execute o comando `/connect` e procure por **MiniMax**. + + ```txt + /connect + ``` + +3. Insira sua chave da API MiniMax. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo como _M2.1_. + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. Acesse o [console Nebius Token Factory](https://tokenfactory.nebius.com/), crie uma conta e clique em **Adicionar Chave**. + +2. Execute o comando `/connect` e procure por **Nebius Token Factory**. + + ```txt + /connect + ``` + +3. Insira sua chave da API Nebius Token Factory. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo como _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Ollama + +Você pode configurar o opencode para usar modelos locais através do Ollama. + +:::tip +Ollama pode se configurar automaticamente para o opencode. Consulte a [documentação de integração do Ollama](https://docs.ollama.com/integrations/opencode) para detalhes. +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +Neste exemplo: + +- `ollama` é o ID do provedor personalizado. Isso pode ser qualquer string que você quiser. +- `npm` especifica o pacote a ser usado para este provedor. Aqui, `@ai-sdk/openai-compatible` é usado para qualquer API compatível com OpenAI. +- `name` é o nome exibido para o provedor na interface do usuário. +- `options.baseURL` é o endpoint para o servidor local. +- `models` é um mapa de IDs de modelos para suas configurações. O nome do modelo será exibido na lista de seleção de modelos. + +:::tip +Se chamadas de ferramentas não estiverem funcionando, tente aumentar `num_ctx` no Ollama. Comece em torno de 16k - 32k. +::: + +--- + +### Ollama Cloud + +Para usar o Ollama Cloud com o opencode: + +1. Acesse [https://ollama.com/](https://ollama.com/) e faça login ou crie uma conta. + +2. Navegue até **Configurações** > **Chaves** e clique em **Adicionar Chave da API** para gerar uma nova chave da API. + +3. Copie a chave da API para uso no opencode. + +4. Execute o comando `/connect` e procure por **Ollama Cloud**. + + ```txt + /connect + ``` + +5. Insira sua chave da API do Ollama Cloud. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **Importante**: Antes de usar modelos em nuvem no opencode, você deve puxar as informações do modelo localmente: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. Execute o comando `/models` para selecionar seu modelo do Ollama Cloud. + + ```txt + /models + ``` + +--- + +### OpenAI + +Recomendamos se inscrever para [ChatGPT Plus ou Pro](https://chatgpt.com/pricing). + +1. Depois de se inscrever, execute o comando `/connect` e selecione OpenAI. + + ```txt + /connect + ``` + +2. Aqui você pode selecionar a opção **ChatGPT Plus/Pro** e isso abrirá seu navegador e pedirá para você se autenticar. + + ```txt + ┌ Selecione o método de autenticação + │ + │ ChatGPT Plus/Pro + │ Inserir manualmente a chave de API + └ + ``` + +3. Agora todos os modelos da OpenAI devem estar disponíveis quando você usar o comando `/models`. + + ```txt + /models + ``` + +##### Usando chaves da API + +Se você já tiver uma chave da API, pode selecionar **Inserir chave da API manualmente** e colá-la no seu terminal. + +--- + +### OpenCode Zen + +OpenCode Zen é uma lista de modelos testados e verificados fornecidos pela equipe do opencode. [Saiba mais](/docs/zen). + +1. Faça login em **OpenCode Zen** e clique em **Criar Chave da API**. + +2. Execute o comando `/connect` e procure por **OpenCode Zen**. + + ```txt + /connect + ``` + +3. Insira sua chave da API do opencode. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo como _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### OpenRouter + +1. Acesse o [painel OpenRouter](https://openrouter.ai/settings/keys), clique em **Criar Chave da API** e copie a chave. + +2. Execute o comando `/connect` e procure por OpenRouter. + + ```txt + /connect + ``` + +3. Insira a chave da API para o provedor. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Muitos modelos do OpenRouter são pré-carregados por padrão, execute o comando `/models` para selecionar o que você deseja. + + ```txt + /models + ``` + + Você também pode adicionar modelos adicionais através da sua configuração do opencode. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +5. Você também pode personalizá-los através da sua configuração do opencode. Aqui está um exemplo de especificar um provedor + + ```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 fornece acesso a mais de 40 modelos do OpenAI, Anthropic, Google, Amazon, Meta, Mistral e AI21 através de uma plataforma unificada. + +1. Vá para seu [SAP BTP Cockpit](https://account.hana.ondemand.com/), navegue até sua instância de serviço SAP AI Core e crie uma chave de serviço. + + :::tip + A chave de serviço é um objeto JSON contendo `clientid`, `clientsecret`, `url` e `serviceurls.AI_API_URL`. Você pode encontrar sua instância do AI Core em **Serviços** > **Instâncias e Assinaturas** no BTP Cockpit. + ::: + +2. Execute o comando `/connect` e procure por **SAP AI Core**. + + ```txt + /connect + ``` + +3. Insira seu JSON da chave de serviço. + + ```txt + ┌ Service key + │ + │ + └ enter + ``` + + Ou defina a variável de ambiente `AICORE_SERVICE_KEY`: + + ```bash + AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode + ``` + + Ou adicione ao seu perfil bash: + + ```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' + ``` + +4. Opcionalmente, defina o ID de implantação e o grupo de recursos: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + Essas configurações são opcionais e devem ser configuradas de acordo com sua configuração do SAP AI Core. + ::: + +5. Execute o comando `/models` para selecionar entre mais de 40 modelos disponíveis. + + ```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**. + +2. Execute o comando `/connect` e procure por **OVHcloud AI Endpoints**. + + ```txt + /connect + ``` + +3. Insira sua chave da API OVHcloud AI Endpoints. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo como _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Scaleway + +Para usar [APIs Generativas Scaleway](https://www.scaleway.com/en/docs/generative-apis/) com o opencode: + +1. Acesse as [configurações de IAM do Scaleway Console](https://console.scaleway.com/iam/api-keys) para gerar uma nova chave da API. + +2. Execute o comando `/connect` e procure por **Scaleway**. + + ```txt + /connect + ``` + +3. Insira sua chave da API Scaleway. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo como _devstral-2-123b-instruct-2512_ ou _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Together AI + +1. Acesse o [console Together AI](https://api.together.ai), crie uma conta e clique em **Adicionar Chave**. + +2. Execute o comando `/connect` e procure por **Together AI**. + + ```txt + /connect + ``` + +3. Insira sua chave da API Together AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo como _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Venice AI + +1. Acesse o [console Venice AI](https://venice.ai), crie uma conta e gere uma chave da API. + +2. Execute o comando `/connect` e procure por **Venice AI**. + + ```txt + /connect + ``` + +3. Insira sua chave da API Venice AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo como _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + +### Vercel AI Gateway + +O Vercel AI Gateway permite que você acesse modelos do OpenAI, Anthropic, Google, xAI e mais através de um endpoint unificado. Os modelos são oferecidos pelo preço de tabela, sem markup. + +1. Acesse o [painel Vercel](https://vercel.com/), navegue até a aba **AI Gateway** e clique em **Chaves da API** para criar uma nova chave da API. + +2. Execute o comando `/connect` e procure por **Vercel AI Gateway**. + + ```txt + /connect + ``` + +3. Insira sua chave da API do Vercel AI Gateway. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo. + + ```txt + /models + ``` + +Você também pode personalizar modelos através da sua configuração do opencode. Aqui está um exemplo de especificar a ordem de roteamento do provedor. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "vercel": { + "models": { + "anthropic/claude-sonnet-4": { + "options": { + "order": ["anthropic", "vertex"] + } + } + } + } + } +} +``` + +Algumas opções de roteamento úteis: + +| Opção | Descrição | +| ------------------- | -------------------------------------------------------------- | +| `order` | Sequência de provedores a serem tentados | +| `only` | Restringir a provedores específicos | +| `zeroDataRetention` | Usar apenas provedores com políticas de retenção de dados zero | + +--- + +### xAI + +1. Acesse o [console xAI](https://console.x.ai/), crie uma conta e gere uma chave da API. + +2. Execute o comando `/connect` e procure por **xAI**. + + ```txt + /connect + ``` + +3. Insira sua chave da API xAI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo como _Grok Beta_. + + ```txt + /models + ``` + +--- + +### Z.AI + +1. Acesse o [console da API Z.AI](https://z.ai/manage-apikey/apikey-list), crie uma conta e clique em **Criar uma nova chave da API**. + +2. Execute o comando `/connect` e procure por **Z.AI**. + + ```txt + /connect + ``` + + Se você estiver inscrito no **GLM Coding Plan**, selecione **Z.AI Coding Plan**. + +3. Insira sua chave da API Z.AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar um modelo como _GLM-4.7_. + + ```txt + /models + ``` + +--- + +### ZenMux + +1. Acesse o [painel ZenMux](https://zenmux.ai/settings/keys), clique em **Criar Chave da API** e copie a chave. + +2. Execute o comando `/connect` e procure por ZenMux. + + ```txt + /connect + ``` + +3. Insira a chave da API para o provedor. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Muitos modelos ZenMux são pré-carregados por padrão, execute o comando `/models` para selecionar o que você deseja. + + ```txt + /models + ``` + + Você também pode adicionar modelos adicionais através da sua configuração do opencode. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "zenmux": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +--- + +## Provedor personalizado + +Para adicionar qualquer provedor **compatível com OpenAI** que não esteja listado no comando `/connect`: + +:::tip +Você pode usar qualquer provedor compatível com OpenAI com o opencode. A maioria dos provedores de AI modernos oferece APIs compatíveis com OpenAI. +::: + +1. Execute o comando `/connect` e role para baixo até **Outro**. + + ```bash + $ /connect + + ┌ 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-... + └ + ``` + +2. Insira um ID exclusivo para o provedor. + + ```bash + $ /connect + + ┌ 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-... + └ + ``` + + :::note + Escolha um ID memorável, você usará isso no seu arquivo de configuração. + ::: + +3. Insira sua chave da API para o provedor. + + ```bash + $ /connect + + ┌ 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-... + └ + ``` + +4. Crie ou atualize seu arquivo `opencode.json` no diretório do seu projeto: + + ```json title="opencode.json" ""myprovider"" {5-15} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "myprovider": { + "npm": "@ai-sdk/openai-compatible", + "name": "Nome de Exibição do Meu Provedor de IA", + "options": { + "baseURL": "https://api.myprovider.com/v1" + }, + "models": { + "my-model-name": { + "name": "Nome de Exibição do Meu Modelo" + } + } + } + } + } + } + } + ``` + + Aqui estão as opções de configuração: + - **npm**: Pacote do SDK de AI a ser usado, `@ai-sdk/openai-compatible` para provedores compatíveis com OpenAI + - **name**: Nome de exibição na interface do usuário. + - **models**: Modelos disponíveis. + - **options.baseURL**: URL do endpoint da API. + - **options.apiKey**: Defina opcionalmente a chave da API, se não estiver usando autenticação. + - **options.headers**: Defina opcionalmente cabeçalhos personalizados. + + Mais sobre as opções avançadas no exemplo abaixo. + +5. Execute o comando `/models` e seu provedor e modelos personalizados aparecerão na lista de seleção. + +--- + +##### Exemplo + +Aqui está um exemplo definindo as opções `apiKey`, `headers` e `limit` do modelo. + +```json title="opencode.json" {9,11,17-20} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "myprovider": { + "npm": "@ai-sdk/openai-compatible", + "name": "Nome de Exibição do Meu Provedor de IA", + "options": { + "baseURL": "https://api.myprovider.com/v1", + "apiKey": "{env:ANTHROPIC_API_KEY}", + "headers": { + "Authorization": "Bearer custom-token" + } + }, + "models": { + "my-model-name": { + "name": "Nome de Exibição do Meu Modelo", + "limit": { + "context": 200000, + "output": 65536 + } + } + } + } + } + }, + "models": { + "my-model-name": { + "name": "Nome de Exibição do Meu Modelo", + "limit": { + "context": 200000, + "output": 65536 + } + } + } + } + } +} +``` + +Detalhes da configuração: + +- **apiKey**: Definido usando a sintaxe de variável `env`, [saiba mais](/docs/config#env-vars). +- **headers**: Cabeçalhos personalizados enviados com cada solicitação. +- **limit.context**: Máximo de tokens de entrada que o modelo aceita. +- **limit.output**: Máximo de tokens que o modelo pode gerar. + +Os campos `limit` permitem que o opencode entenda quanto contexto você tem disponível. Provedores padrão puxam isso automaticamente do models.dev. + +--- + +## Solução de Problemas + +Se você estiver tendo problemas para configurar um provedor, verifique o seguinte: + +1. **Verifique a configuração de autenticação**: Execute `opencode auth list` para ver se as credenciais + para o provedor estão adicionadas à sua configuração. + + Isso não se aplica a provedores como Amazon Bedrock, que dependem de variáveis de ambiente para sua autenticação. + +2. Para provedores personalizados, verifique a configuração do opencode e: + - Certifique-se de que o ID do provedor usado no comando `/connect` corresponda ao ID na sua configuração do opencode. + - O pacote npm correto está sendo usado para o provedor. Por exemplo, use `@ai-sdk/cerebras` para Cerebras. E para todos os outros provedores compatíveis com OpenAI, use `@ai-sdk/openai-compatible`. + - Verifique se o endpoint da API correto está sendo usado no campo `options.baseURL`. diff --git a/packages/web/src/content/docs/pt-br/rules.mdx b/packages/web/src/content/docs/pt-br/rules.mdx new file mode 100644 index 00000000000..3b0a1eda20e --- /dev/null +++ b/packages/web/src/content/docs/pt-br/rules.mdx @@ -0,0 +1,180 @@ +--- +title: Regras +description: Defina instruções personalizadas para opencode. +--- + +Você pode fornecer instruções personalizadas para opencode criando um arquivo `AGENTS.md`. Isso é semelhante às regras do Cursor. Ele contém instruções que serão incluídas no contexto do LLM para personalizar seu comportamento para o seu projeto específico. + +--- + +## Inicializar + +Para criar um novo arquivo `AGENTS.md`, você pode executar o comando `/init` no opencode. + +:::tip +Você deve commitar o arquivo `AGENTS.md` do seu projeto no Git. +::: + +Isso irá escanear seu projeto e todo o seu conteúdo para entender do que se trata o projeto e gerar um arquivo `AGENTS.md` com isso. Isso ajuda o opencode a navegar melhor pelo projeto. + +Se você já tiver um arquivo `AGENTS.md` existente, isso tentará adicionar a ele. + +--- + +## Exemplo + +Você também pode criar este arquivo manualmente. Aqui está um exemplo de algumas coisas que você pode colocar em um arquivo `AGENTS.md`. + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +Estamos adicionando instruções específicas do projeto aqui e isso será compartilhado entre sua equipe. + +--- + +## Tipos + +O opencode também suporta a leitura do arquivo `AGENTS.md` de múltiplos locais. E isso serve a diferentes propósitos. + +### Projeto + +Coloque um `AGENTS.md` na raiz do seu projeto para regras específicas do projeto. Essas regras se aplicam apenas quando você está trabalhando neste diretório ou em seus subdiretórios. + +### Global + +Você também pode ter regras globais em um arquivo `~/.config/opencode/AGENTS.md`. Isso é aplicado em todas as sessões do opencode. + +Como isso não é commitado no Git ou compartilhado com sua equipe, recomendamos usar isso para especificar quaisquer regras pessoais que o LLM deve seguir. + +### Compatibilidade com Claude Code + +Para usuários migrando do Claude Code, o opencode suporta as convenções de arquivo do Claude Code como alternativas: + +- **Regras do projeto**: `CLAUDE.md` no diretório do seu projeto (usado se não existir `AGENTS.md`) +- **Regras globais**: `~/.claude/CLAUDE.md` (usado se não existir `~/.config/opencode/AGENTS.md`) +- **Habilidades**: `~/.claude/skills/` — veja [Habilidades do Agente](/docs/skills/) para detalhes + +Para desabilitar a compatibilidade com Claude Code, defina uma dessas variáveis de ambiente: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## Precedência + +Quando o opencode inicia, ele procura arquivos de regras nesta ordem: + +1. **Arquivos locais** percorrendo a partir do diretório atual (`AGENTS.md`, `CLAUDE.md`) +2. **Arquivo global** em `~/.config/opencode/AGENTS.md` +3. **Arquivo Claude Code** em `~/.claude/CLAUDE.md` (a menos que desabilitado) + +O primeiro arquivo correspondente vence em cada categoria. Por exemplo, se você tiver tanto `AGENTS.md` quanto `CLAUDE.md`, apenas `AGENTS.md` é usado. Da mesma forma, `~/.config/opencode/AGENTS.md` tem precedência sobre `~/.claude/CLAUDE.md`. + +--- + +## Instruções Personalizadas + +Você pode especificar arquivos de instrução personalizados no seu `opencode.json` ou no global `~/.config/opencode/opencode.json`. Isso permite que você e sua equipe reutilizem regras existentes em vez de ter que duplicá-las no AGENTS.md. + +Exemplo: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Você também pode usar URLs remotas para carregar instruções da web. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +Instruções remotas são buscadas com um tempo limite de 5 segundos. + +Todos os arquivos de instrução são combinados com seus arquivos `AGENTS.md`. + +--- + +## Referenciando Arquivos Externos + +Embora o opencode não analise automaticamente referências de arquivos em `AGENTS.md`, você pode alcançar funcionalidade semelhante de duas maneiras: + +### Usando opencode.json + +A abordagem recomendada é usar o campo `instructions` em `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### Instruções Manuais em AGENTS.md + +Você pode ensinar o opencode a ler arquivos externos fornecendo instruções explícitas em seu `AGENTS.md`. Aqui está um exemplo prático: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +Essa abordagem permite que você: + +- Crie arquivos de regras modulares e reutilizáveis +- Compartilhe regras entre projetos via symlinks ou submódulos do git +- Mantenha o AGENTS.md conciso enquanto referencia diretrizes detalhadas +- Garanta que o opencode carregue arquivos apenas quando necessário para a tarefa específica + +:::tip +Para monorepos ou projetos com padrões compartilhados, usar `opencode.json` com padrões glob (como `packages/*/AGENTS.md`) é mais sustentável do que instruções manuais. +::: diff --git a/packages/web/src/content/docs/pt-br/sdk.mdx b/packages/web/src/content/docs/pt-br/sdk.mdx new file mode 100644 index 00000000000..672b852f6be --- /dev/null +++ b/packages/web/src/content/docs/pt-br/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: Cliente JS seguro em tipos para o servidor opencode. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +O SDK JS/TS do opencode fornece um cliente seguro em tipos para interagir com o servidor. +Use-o para construir integrações e controlar o opencode programaticamente. + +[Saiba mais](/docs/server) sobre como o servidor funciona. Para exemplos, confira os [projetos](/docs/ecosystem#projects) construídos pela comunidade. + +--- + +## Instalar + +Instale o SDK a partir do npm: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## Criar cliente + +Crie uma instância do opencode: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +Isso inicia tanto um servidor quanto um cliente. + +#### Opções + +| Opção | Tipo | Descrição | Padrão | +| ---------- | ------------- | ------------------------------------------ | ----------- | +| `hostname` | `string` | Nome do host do servidor | `127.0.0.1` | +| `port` | `number` | Porta do servidor | `4096` | +| `signal` | `AbortSignal` | Sinal de abortar para cancelamento | `undefined` | +| `timeout` | `number` | Tempo limite em ms para iniciar o servidor | `5000` | +| `config` | `Config` | Objeto de configuração | `{}` | + +--- + +## Configuração + +Você pode passar um objeto de configuração para personalizar o comportamento. A instância ainda pega seu `opencode.json`, mas você pode substituir ou adicionar configuração inline: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## Apenas cliente + +Se você já tem uma instância do opencode em execução, pode criar uma instância de cliente para se conectar a ela: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### Opções + +| Opção | Tipo | Descrição | Padrão | +| --------------- | ---------- | ------------------------------------- | ----------------------- | +| `baseUrl` | `string` | URL do servidor | `http://localhost:4096` | +| `fetch` | `function` | Implementação de fetch personalizada | `globalThis.fetch` | +| `parseAs` | `string` | Método de análise da resposta | `auto` | +| `responseStyle` | `string` | Estilo de retorno: `data` ou `fields` | `fields` | +| `throwOnError` | `boolean` | Lançar erros em vez de retornar | `false` | + +--- + +## Tipos + +O SDK inclui definições TypeScript para todos os tipos da API. Importe-os diretamente: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +Todos os tipos são gerados a partir da especificação OpenAPI do servidor e estão disponíveis no arquivo de tipos. + +--- + +## Erros + +O SDK pode lançar erros que você pode capturar e tratar: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## APIs + +O SDK expõe todas as APIs do servidor através de um cliente seguro em tipos. + +--- + +### Global + +| Método | Descrição | Resposta | +| ----------------- | -------------------------------------- | ------------------------------------ | +| `global.health()` | Verificar a saúde e versão do servidor | `{ healthy: true, version: string }` | + +--- + +#### Exemplos + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### App + +| Método | Descrição | Resposta | +| -------------- | ----------------------------------- | ------------------------------------------- | +| `app.log()` | Escrever uma entrada de log | `boolean` | +| `app.agents()` | Listar todos os agentes disponíveis | Agent[] | + +--- + +#### Exemplos + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### Projeto + +| Método | Descrição | Resposta | +| ------------------- | ------------------------ | --------------------------------------------- | +| `project.list()` | Listar todos os projetos | Project[] | +| `project.current()` | Obter projeto atual | Project | + +--- + +#### Exemplos + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### Caminho + +| Método | Descrição | Resposta | +| ------------ | ------------------- | ---------------------------------------- | +| `path.get()` | Obter caminho atual | Path | + +--- + +#### Exemplos + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### Configuração + +| Método | Descrição | Resposta | +| -------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | Obter informações de configuração | Config | +| `config.providers()` | Listar provedores e modelos padrão | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### Exemplos + +```javascript +const config = await client.config.get() + +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` | + +--- + +#### Exemplos + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### Arquivos + +| Método | Descrição | Resposta | +| ------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------- | +| `find.text({ query })` | Pesquisar texto em arquivos | Array de objetos de correspondência com `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `find.files({ query })` | Encontrar arquivos e diretórios por nome | `string[]` (caminhos) | +| `find.symbols({ query })` | Encontrar símbolos no workspace | Symbol[] | +| `file.read({ query })` | Ler um arquivo | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | Obter status para arquivos rastreados | File[] | + +`find.files` suporta alguns campos de consulta opcionais: + +- `type`: `"file"` ou `"directory"` +- `directory`: substituir a raiz do projeto para a pesquisa +- `limit`: resultados máximos (1–200) + +--- + +#### Exemplos + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| Método | Descrição | Resposta | +| ------------------------------ | -------------------------- | --------- | +| `tui.appendPrompt({ body })` | Adicionar texto ao prompt | `boolean` | +| `tui.openHelp()` | Abrir o diálogo de ajuda | `boolean` | +| `tui.openSessions()` | Abrir o seletor de sessões | `boolean` | +| `tui.openThemes()` | Abrir o seletor de temas | `boolean` | +| `tui.openModels()` | Abrir o seletor de modelos | `boolean` | +| `tui.submitPrompt()` | Enviar o prompt atual | `boolean` | +| `tui.clearPrompt()` | Limpar o prompt | `boolean` | +| `tui.executeCommand({ body })` | Executar um comando | `boolean` | +| `tui.showToast({ body })` | Mostrar notificação toast | `boolean` | + +--- + +#### Exemplos + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### Autenticação + +| Método | Descrição | Resposta | +| ------------------- | ----------------------------------- | --------- | +| `auth.set({ ... })` | Definir credenciais de autenticação | `boolean` | + +--- + +#### Exemplos + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### Eventos + +| Método | Descrição | Resposta | +| ------------------- | --------------------------------------- | --------------------------------------- | +| `event.subscribe()` | Fluxo de eventos enviados pelo servidor | Fluxo de eventos enviados pelo servidor | + +--- + +#### Exemplos + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/pt-br/server.mdx b/packages/web/src/content/docs/pt-br/server.mdx new file mode 100644 index 00000000000..6d2e9eb3861 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/server.mdx @@ -0,0 +1,284 @@ +--- +title: Servidor +description: Interaja com o servidor opencode via HTTP. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +O comando `opencode serve` executa um servidor HTTP sem cabeça que expõe um endpoint OpenAPI que um cliente opencode pode usar. + +--- + +### Uso + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### Opções + +| Flag | Descrição | Padrão | +| --------------- | ------------------------------------------------- | ---------------- | +| `--port` | Porta para escutar | `4096` | +| `--hostname` | Nome do host para escutar | `127.0.0.1` | +| `--mdns` | Habilitar descoberta mDNS | `false` | +| `--mdns-domain` | Nome de domínio personalizado para o serviço mDNS | `opencode.local` | +| `--cors` | Origens adicionais de navegador a permitir | `[]` | + +`--cors` pode ser passado várias vezes: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### Autenticação + +Defina `OPENCODE_SERVER_PASSWORD` para proteger o servidor com autenticação básica HTTP. O nome de usuário padrão é `opencode`, ou defina `OPENCODE_SERVER_USERNAME` para substituí-lo. Isso se aplica tanto ao `opencode serve` quanto ao `opencode web`. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### Como funciona + +Quando você executa `opencode`, ele inicia um TUI e um servidor. Onde o TUI é o cliente que se comunica com o servidor. O servidor expõe um endpoint de especificação OpenAPI 3.1. Este endpoint também é usado para gerar um [SDK](/docs/sdk). + +:::tip +Use o servidor opencode para interagir com o opencode programaticamente. +::: + +Essa arquitetura permite que o opencode suporte múltiplos clientes e permite que você interaja com o opencode programaticamente. + +Você pode executar `opencode serve` para iniciar um servidor autônomo. Se você tiver o TUI do opencode em execução, `opencode serve` iniciará um novo servidor. + +--- + +#### Conectar a um servidor existente + +Quando você inicia o TUI, ele atribui aleatoriamente uma porta e um nome de host. Você pode passar os [flags](/docs/cli) `--hostname` e `--port`. Em seguida, use isso para se conectar ao seu servidor. + +O endpoint [`/tui`](#tui) pode ser usado para controlar o TUI através do servidor. Por exemplo, você pode preencher ou executar um prompt. Essa configuração é usada pelos plugins do opencode [IDE](/docs/ide). + +--- + +## Especificação + +O servidor publica uma especificação OpenAPI 3.1 que pode ser visualizada em: + +``` +http://:/doc +``` + +Por exemplo, `http://localhost:4096/doc`. Use a especificação para gerar clientes ou inspecionar tipos de requisição e resposta. Ou visualize em um explorador Swagger. + +--- + +## APIs + +O servidor opencode expõe as seguintes APIs. + +--- + +### Global + +| Método | Caminho | Descrição | Resposta | +| ------ | ---------------- | --------------------------------- | ------------------------------------ | +| `GET` | `/global/health` | Obter saúde e versão do servidor | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | Obter eventos globais (fluxo SSE) | Fluxo de eventos | + +--- + +### Projeto + +| Método | Caminho | Descrição | Resposta | +| ------ | ------------------ | ------------------------ | --------------------------------------------- | +| `GET` | `/project` | Listar todos os projetos | Project[] | +| `GET` | `/project/current` | Obter o projeto atual | Project | + +--- + +### Caminho & VCS + +| Método | Caminho | Descrição | Resposta | +| ------ | ------- | --------------------------------------------- | ------------------------------------------- | +| `GET` | `/path` | Obter o caminho atual | Path | +| `GET` | `/vcs` | Obter informações do VCS para o projeto atual | VcsInfo | + +--- + +### Instância + +| Método | Caminho | Descrição | Resposta | +| ------ | ------------------- | --------------------------- | --------- | +| `POST` | `/instance/dispose` | Descartar a instância atual | `boolean` | + +--- + +### Configuração + +| Método | Caminho | Descrição | Resposta | +| ------- | ------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------- | +| `GET` | `/config` | Obter informações de configuração | Config | +| `PATCH` | `/config` | Atualizar configuração | Config | +| `GET` | `/config/providers` | Listar provedores e modelos padrão | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +### Provedor + +| Método | Caminho | Descrição | Resposta | +| ------ | -------------------------------- | ------------------------------------------- | ----------------------------------------------------------------------------------- | +| `GET` | `/provider` | Listar todos os provedores | `{ all: `Provider[]`, default: {...}, connected: string[] }` | +| `GET` | `/provider/auth` | Obter métodos de autenticação do provedor | `{ [providerID: string]: `ProviderAuthMethod[]` }` | +| `POST` | `/provider/{id}/oauth/authorize` | Autorizar um provedor usando OAuth | ProviderAuthAuthorization | +| `POST` | `/provider/{id}/oauth/callback` | Lidar com o callback OAuth para um provedor | `boolean` | + +--- + +### Sessões + +| Método | Caminho | Descrição | Notas | +| -------- | ---------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------- | +| `GET` | `/session` | Listar todas as sessões | Retorna Session[] | +| `POST` | `/session` | Criar uma nova sessão | corpo: `{ parentID?, title? }`, retorna Session | +| `GET` | `/session/status` | Obter status da sessão para todas as sessões | Retorna `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | Obter detalhes da sessão | Retorna Session | +| `DELETE` | `/session/:id` | Deletar uma sessão e todos os seus dados | Retorna `boolean` | +| `PATCH` | `/session/:id` | Atualizar propriedades da sessão | corpo: `{ title? }`, retorna Session | +| `GET` | `/session/:id/children` | Obter as sessões filhas de uma sessão | Retorna Session[] | +| `GET` | `/session/:id/todo` | Obter a lista de tarefas para uma sessão | Retorna Todo[] | +| `POST` | `/session/:id/init` | Analisar o app e criar `AGENTS.md` | corpo: `{ messageID, providerID, modelID }`, retorna `boolean` | +| `POST` | `/session/:id/fork` | Fazer um fork de uma sessão existente em uma mensagem | corpo: `{ messageID? }`, retorna Session | +| `POST` | `/session/:id/abort` | Abortar uma sessão em execução | Retorna `boolean` | +| `POST` | `/session/:id/share` | Compartilhar uma sessão | Retorna Session | +| `DELETE` | `/session/:id/share` | Descompartilhar uma sessão | Retorna Session | +| `GET` | `/session/:id/diff` | Obter a diferença para esta sessão | query: `messageID?`, retorna FileDiff[] | +| `POST` | `/session/:id/summarize` | Resumir a sessão | corpo: `{ providerID, modelID }`, retorna `boolean` | +| `POST` | `/session/:id/revert` | Reverter uma mensagem | corpo: `{ messageID, partID? }`, retorna `boolean` | +| `POST` | `/session/:id/unrevert` | Restaurar todas as mensagens revertidas | Retorna `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | Responder a um pedido de permissão | corpo: `{ response, remember? }`, retorna `boolean` | + +--- + +### Mensagens + +| Método | Caminho | Descrição | Notas | +| ------ | --------------------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `GET` | `/session/:id/message` | Listar mensagens em uma sessão | query: `limit?`, retorna `{ info: `Message`, parts: `Part[]`}[]` | +| `POST` | `/session/:id/message` | Enviar uma mensagem e aguardar resposta | corpo: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, retorna `{ info: `Message`, parts: `Part[]`}` | +| `GET` | `/session/:id/message/:messageID` | Obter detalhes da mensagem | Retorna `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/prompt_async` | Enviar uma mensagem assíncrona (sem espera) | corpo: igual a `/session/:id/message`, retorna `204 No Content` | +| `POST` | `/session/:id/command` | Executar um comando de barra | corpo: `{ messageID?, agent?, model?, command, arguments }`, retorna `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/shell` | Executar um comando shell | corpo: `{ agent, model?, command }`, retorna `{ info: `Message`, parts: `Part[]`}` | + +--- + +### Comandos + +| Método | Caminho | Descrição | Resposta | +| ------ | ---------- | ------------------------ | --------------------------------------------- | +| `GET` | `/command` | Listar todos os comandos | Command[] | + +--- + +### Arquivos + +| Método | Caminho | Descrição | Resposta | +| ------ | ------------------------ | ---------------------------------------- | ------------------------------------------------------------------------------------------------------- | +| `GET` | `/find?pattern=` | Pesquisar texto em arquivos | Array de objetos de correspondência com `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `GET` | `/find/file?query=` | Encontrar arquivos e diretórios por nome | `string[]` (caminhos) | +| `GET` | `/find/symbol?query=` | Encontrar símbolos do workspace | Symbol[] | +| `GET` | `/file?path=` | Listar arquivos e diretórios | FileNode[] | +| `GET` | `/file/content?path=

` | Ler um arquivo | FileContent | +| `GET` | `/file/status` | Obter status para arquivos rastreados | File[] | + +#### Parâmetros de consulta `/find/file` + +- `query` (obrigatório) — string de pesquisa (correspondência difusa) +- `type` (opcional) — limitar resultados a `"file"` ou `"directory"` +- `directory` (opcional) — substituir a raiz do projeto para a pesquisa +- `limit` (opcional) — resultados máximos (1–200) +- `dirs` (opcional) — flag legada (`"false"` retorna apenas arquivos) + +--- + +### Ferramentas (Experimental) + +| Método | Caminho | Descrição | Resposta | +| ------ | ------------------------------------------- | --------------------------------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | Listar todos os IDs de ferramentas | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | Listar ferramentas com esquemas JSON para um modelo | ToolList | + +--- + +### LSP, Formatadores & MCP + +| Método | Caminho | Descrição | Resposta | +| ------ | ------------ | ------------------------------------ | -------------------------------------------------------- | +| `GET` | `/lsp` | Obter status do servidor LSP | LSPStatus[] | +| `GET` | `/formatter` | Obter status do formatador | FormatterStatus[] | +| `GET` | `/mcp` | Obter status do servidor MCP | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | Adicionar servidor MCP dinamicamente | corpo: `{ name, config }`, retorna objeto de status MCP | + +--- + +### Agentes + +| Método | Caminho | Descrição | Resposta | +| ------ | -------- | ----------------------------------- | ------------------------------------------- | +| `GET` | `/agent` | Listar todos os agentes disponíveis | Agent[] | + +--- + +### Registro + +| Método | Caminho | Descrição | Resposta | +| ------ | ------- | --------------------------------------------------------------------- | --------- | +| `POST` | `/log` | Escrever entrada de log. Corpo: `{ service, level, message, extra? }` | `boolean` | + +--- + +### TUI + +| Método | Caminho | Descrição | Resposta | +| ------ | ----------------------- | ---------------------------------------------- | ---------------------------- | +| `POST` | `/tui/append-prompt` | Anexar texto ao prompt | `boolean` | +| `POST` | `/tui/open-help` | Abrir o diálogo de ajuda | `boolean` | +| `POST` | `/tui/open-sessions` | Abrir o seletor de sessões | `boolean` | +| `POST` | `/tui/open-themes` | Abrir o seletor de temas | `boolean` | +| `POST` | `/tui/open-models` | Abrir o seletor de modelos | `boolean` | +| `POST` | `/tui/submit-prompt` | Enviar o prompt atual | `boolean` | +| `POST` | `/tui/clear-prompt` | Limpar o prompt | `boolean` | +| `POST` | `/tui/execute-command` | Executar um comando (`{ command }`) | `boolean` | +| `POST` | `/tui/show-toast` | Mostrar toast (`{ title?, message, variant }`) | `boolean` | +| `GET` | `/tui/control/next` | Aguardar o próximo pedido de controle | Objeto de pedido de controle | +| `POST` | `/tui/control/response` | Responder a um pedido de controle (`{ body }`) | `boolean` | + +--- + +### Auth + +| Método | Caminho | Descrição | Resposta | +| ------ | ----------- | ------------------------------------------------------------------------------------- | --------- | +| `PUT` | `/auth/:id` | Definir credenciais de autenticação. O corpo deve corresponder ao esquema do provedor | `boolean` | + +--- + +### Eventos + +| Método | Caminho | Descrição | Resposta | +| ------ | -------- | ------------------------------------------------------------------------------------------------------ | --------------------------------------- | +| `GET` | `/event` | Fluxo de eventos enviados pelo servidor. O primeiro evento é `server.connected`, depois eventos de bus | Fluxo de eventos enviados pelo servidor | + +--- + +### Docs + +| Método | Caminho | Descrição | Resposta | +| ------ | ------- | ------------------------- | --------------------------------------- | +| `GET` | `/doc` | Especificação OpenAPI 3.1 | Página HTML com a especificação OpenAPI | diff --git a/packages/web/src/content/docs/pt-br/share.mdx b/packages/web/src/content/docs/pt-br/share.mdx new file mode 100644 index 00000000000..5aa0439d068 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/share.mdx @@ -0,0 +1,127 @@ +--- +title: Compartilhar +description: Compartilhe suas conversas do opencode. +--- + +O recurso de compartilhamento do opencode permite que você crie links públicos para suas conversas do opencode, para que você possa colaborar com colegas de equipe ou obter ajuda de outros. + +:::note +Conversas compartilhadas são acessíveis publicamente para qualquer pessoa com o link. +::: + +--- + +## Como funciona + +Quando você compartilha uma conversa, o opencode: + +1. Cria uma URL pública única para sua sessão +2. Sincroniza seu histórico de conversas com nossos servidores +3. Torna a conversa acessível através do link compartilhável — `opncd.ai/s/` + +--- + +## Compartilhamento + +O opencode suporta três modos de compartilhamento que controlam como as conversas são compartilhadas: + +--- + +### Manual (padrão) + +Por padrão, o opencode usa o modo de compartilhamento manual. As sessões não são compartilhadas automaticamente, mas você pode compartilhá-las manualmente usando o comando `/share`: + +``` +/share +``` + +Isso gerará uma URL única que será copiada para sua área de transferência. + +Para definir explicitamente o modo manual em seu [arquivo de configuração](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### Compartilhamento automático + +Você pode habilitar o compartilhamento automático para todas as novas conversas definindo a opção `share` como `"auto"` em seu [arquivo de configuração](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +Com o compartilhamento automático habilitado, cada nova conversa será compartilhada automaticamente e um link será gerado. + +--- + +### Desativado + +Você pode desativar o compartilhamento completamente definindo a opção `share` como `"disabled"` em seu [arquivo de configuração](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +Para impor isso em sua equipe para um determinado projeto, adicione-o ao `opencode.json` em seu projeto e faça o check-in no Git. + +--- + +## Cancelar compartilhamento + +Para parar de compartilhar uma conversa e removê-la do acesso público: + +``` +/unshare +``` + +Isso removerá o link de compartilhamento e excluirá os dados relacionados à conversa. + +--- + +## Privacidade + +Há algumas coisas a serem lembradas ao compartilhar uma conversa. + +--- + +### Retenção de dados + +Conversas compartilhadas permanecem acessíveis até que você as descompartilhe explicitamente. Isso inclui: + +- Histórico completo da conversa +- Todas as mensagens e respostas +- Metadados da sessão + +--- + +### Recomendações + +- Compartilhe apenas conversas que não contenham informações sensíveis. +- Revise o conteúdo da conversa antes de compartilhar. +- Descompartilhe conversas quando a colaboração estiver completa. +- Evite compartilhar conversas com código proprietário ou dados confidenciais. +- Para projetos sensíveis, desative o compartilhamento completamente. + +--- + +## Para empresas + +Para implantações empresariais, o recurso de compartilhamento pode ser: + +- **Desativado** completamente para conformidade de segurança +- **Restrito** a usuários autenticados apenas através de SSO +- **Auto-hospedado** em sua própria infraestrutura + +[Saiba mais](/docs/enterprise) sobre como usar o opencode em sua organização. diff --git a/packages/web/src/content/docs/pt-br/skills.mdx b/packages/web/src/content/docs/pt-br/skills.mdx new file mode 100644 index 00000000000..23a4497ed8b --- /dev/null +++ b/packages/web/src/content/docs/pt-br/skills.mdx @@ -0,0 +1,222 @@ +--- +title: "Habilidades do Agente" +description: "Defina comportamentos reutilizáveis via definições de SKILL.md" +--- + +As habilidades do agente permitem que o opencode descubra instruções reutilizáveis do seu repositório ou diretório pessoal. +As habilidades são carregadas sob demanda através da ferramenta nativa `skill`—os agentes veem as habilidades disponíveis e podem carregar o conteúdo completo quando necessário. + +--- + +## Colocar arquivos + +Crie uma pasta por nome de habilidade e coloque um `SKILL.md` dentro dela. +O opencode pesquisa nesses locais: + +- Configuração do projeto: `.opencode/skills//SKILL.md` +- Configuração global: `~/.config/opencode/skills//SKILL.md` +- Projeto compatível com Claude: `.claude/skills//SKILL.md` +- Global compatível com Claude: `~/.claude/skills//SKILL.md` +- Projeto compatível com agente: `.agents/skills//SKILL.md` +- Global compatível com agente: `~/.agents/skills//SKILL.md` + +--- + +## Entender a descoberta + +Para caminhos locais do projeto, o opencode sobe a partir do seu diretório de trabalho atual até alcançar a árvore de trabalho do git. +Ele carrega qualquer `skills/*/SKILL.md` correspondente em `.opencode/` e qualquer `.claude/skills/*/SKILL.md` ou `.agents/skills/*/SKILL.md` ao longo do caminho. + +As definições globais também são carregadas de `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md` e `~/.agents/skills/*/SKILL.md`. + +--- + +## Escrever frontmatter + +Cada `SKILL.md` deve começar com frontmatter YAML. +Somente estes campos são reconhecidos: + +- `name` (obrigatório) +- `description` (obrigatório) +- `license` (opcional) +- `compatibility` (opcional) +- `metadata` (opcional, mapa de string para string) + +Campos de frontmatter desconhecidos são ignorados. + +--- + +## Validar nomes + +`name` deve: + +- Ter de 1 a 64 caracteres +- Ser alfanumérico em minúsculas com separadores de hífen simples +- Não começar ou terminar com `-` +- Não conter `--` consecutivos +- Combinar com o nome do diretório que contém `SKILL.md` + +Regex equivalente: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## Seguir regras de comprimento + +`description` deve ter de 1 a 1024 caracteres. +Mantenha-a específica o suficiente para que o agente escolha corretamente. + +--- + +## Usar um exemplo + +Crie `.opencode/skills/git-release/SKILL.md` assim: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## Reconhecer descrição da ferramenta + +O opencode lista as habilidades disponíveis na descrição da ferramenta `skill`. +Cada entrada inclui o nome e a descrição da habilidade: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +O agente carrega uma habilidade chamando a ferramenta: + +``` +skill({ name: "git-release" }) +``` + +--- + +## Configurar permissões + +Controle quais habilidades os agentes podem acessar usando permissões baseadas em padrões em `opencode.json`: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| Permissão | Comportamento | +| --------- | --------------------------------------------------- | +| `allow` | Habilidade carrega imediatamente | +| `deny` | Habilidade oculta do agente, acesso rejeitado | +| `ask` | Usuário solicitado para aprovação antes de carregar | + +Padrões suportam curingas: `internal-*` corresponde a `internal-docs`, `internal-tools`, etc. + +--- + +## Substituir por agente + +Dê a agentes específicos permissões diferentes das configurações globais padrão. + +**Para agentes personalizados** (no frontmatter do agente): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**Para agentes embutidos** (em `opencode.json`): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## Desativar a ferramenta de habilidades + +Desative completamente as habilidades para agentes que não devem usá-las: + +**Para agentes personalizados**: + +```yaml +--- +tools: + skill: false +--- +``` + +**Para agentes embutidos**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +Quando desativado, a seção `` é omitida completamente. + +--- + +## Solucionar problemas de carregamento + +Se uma habilidade não aparecer: + +1. Verifique se `SKILL.md` está escrito em letras maiúsculas +2. Verifique se o frontmatter inclui `name` e `description` +3. Certifique-se de que os nomes das habilidades sejam únicos em todos os locais +4. Verifique as permissões—habilidades com `deny` estão ocultas dos agentes diff --git a/packages/web/src/content/docs/pt-br/themes.mdx b/packages/web/src/content/docs/pt-br/themes.mdx new file mode 100644 index 00000000000..a1a5083cb86 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/themes.mdx @@ -0,0 +1,369 @@ +--- +title: Temas +description: Selecione um tema embutido ou defina o seu próprio. +--- + +Com o opencode, você pode selecionar um dos vários temas embutidos, usar um tema que se adapta ao tema do seu terminal ou definir seu próprio tema personalizado. + +Por padrão, o opencode usa nosso próprio tema `opencode`. + +--- + +## Requisitos do terminal + +Para que os temas sejam exibidos corretamente com sua paleta de cores completa, seu terminal deve suportar **truecolor** (cor de 24 bits). A maioria dos terminais modernos suporta isso por padrão, mas você pode precisar habilitar: + +- **Verificar suporte**: Execute `echo $COLORTERM` - deve retornar `truecolor` ou `24bit` +- **Habilitar truecolor**: Defina a variável de ambiente `COLORTERM=truecolor` no seu perfil de shell +- **Compatibilidade do terminal**: Certifique-se de que seu emulador de terminal suporta cores de 24 bits (a maioria dos terminais modernos, como iTerm2, Alacritty, Kitty, Windows Terminal e versões recentes do GNOME Terminal, suportam) + +Sem suporte a truecolor, os temas podem aparecer com precisão de cor reduzida ou voltar para a aproximação de 256 cores mais próxima. + +--- + +## Temas embutidos + +O opencode vem com vários temas embutidos. + +| Nome | Descrição | +| ---------------------- | --------------------------------------------------------------------------- | +| `system` | Adapta-se à cor de fundo do seu terminal | +| `tokyonight` | Baseado no tema [Tokyonight](https://github.com/folke/tokyonight.nvim) | +| `everforest` | Baseado no tema [Everforest](https://github.com/sainnhe/everforest) | +| `ayu` | Baseado no tema escuro [Ayu](https://github.com/ayu-theme) | +| `catppuccin` | Baseado no tema [Catppuccin](https://github.com/catppuccin) | +| `catppuccin-macchiato` | Baseado no tema [Catppuccin](https://github.com/catppuccin) | +| `gruvbox` | Baseado no tema [Gruvbox](https://github.com/morhetz/gruvbox) | +| `kanagawa` | Baseado no tema [Kanagawa](https://github.com/rebelot/kanagawa.nvim) | +| `nord` | Baseado no tema [Nord](https://github.com/nordtheme/nord) | +| `matrix` | Tema verde estilo hacker sobre fundo preto | +| `one-dark` | Baseado no tema escuro [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) | + +E mais, estamos constantemente adicionando novos temas. + +--- + +## Tema do sistema + +O tema `system` é projetado para se adaptar automaticamente ao esquema de cores do seu terminal. Ao contrário dos temas tradicionais que usam cores fixas, o tema _system_: + +- **Gera escala de cinza**: Cria uma escala de cinza personalizada com base na cor de fundo do seu terminal, garantindo contraste ideal. +- **Usa cores ANSI**: Aproveita as cores ANSI padrão (0-15) para destaque de sintaxe e elementos da interface, que respeitam a paleta de cores do seu terminal. +- **Preserva padrões do terminal**: Usa `none` para cores de texto e fundo para manter a aparência nativa do seu terminal. + +O tema do sistema é para usuários que: + +- Querem que o opencode corresponda à aparência do seu terminal +- Usam esquemas de cores de terminal personalizados +- Preferem uma aparência consistente em todos os aplicativos de terminal + +--- + +## 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). + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## Temas personalizados + +O opencode suporta um sistema de temas flexível baseado em JSON que permite aos usuários criar e personalizar temas facilmente. + +--- + +### Hierarquia + +Os temas são carregados de vários diretórios na seguinte ordem, onde diretórios posteriores substituem os anteriores: + +1. **Temas embutidos** - Estes estão incorporados no binário +2. **Diretório de configuração do usuário** - Definido em `~/.config/opencode/themes/*.json` ou `$XDG_CONFIG_HOME/opencode/themes/*.json` +3. **Diretório raiz do projeto** - Definido em `/.opencode/themes/*.json` +4. **Diretório de trabalho atual** - Definido em `./.opencode/themes/*.json` + +Se vários diretórios contiverem um tema com o mesmo nome, o tema do diretório com maior prioridade será usado. + +--- + +### Criando um tema + +Para criar um tema personalizado, crie um arquivo JSON em um dos diretórios de tema. + +Para temas de usuário: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +E para temas específicos do projeto. + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### Formato JSON + +Os temas usam um formato JSON flexível com suporte para: + +- **Cores Hex**: `"#ffffff"` +- **Cores ANSI**: `3` (0-255) +- **Referências de cor**: `"primary"` ou definições personalizadas +- **Variantes escuras/claras**: `{"dark": "#000", "light": "#fff"}` +- **Sem cor**: `"none"` - Usa a cor padrão do terminal ou transparente + +--- + +### Definições de cor + +A seção `defs` é opcional e permite que você defina cores reutilizáveis que podem ser referenciadas no tema. + +--- + +### Padrões do terminal + +O valor especial `"none"` pode ser usado para qualquer cor para herdar a cor padrão do terminal. Isso é particularmente útil para criar temas que se misturam perfeitamente com o esquema de cores do seu terminal: + +- `"text": "none"` - Usa a cor de primeiro plano padrão do terminal +- `"background": "none"` - Usa a cor de fundo padrão do terminal + +--- + +### Exemplo + +Aqui está um exemplo de um tema personalizado: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/pt-br/tools.mdx b/packages/web/src/content/docs/pt-br/tools.mdx new file mode 100644 index 00000000000..53f96248582 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/tools.mdx @@ -0,0 +1,379 @@ +--- +title: Ferramentas +description: Gerencie as ferramentas que um LLM pode usar. +--- + +As ferramentas permitem que o LLM execute ações em sua base de código. O opencode vem com um conjunto de ferramentas integradas, mas você pode estendê-lo com [ferramentas personalizadas](/docs/custom-tools) ou [servidores MCP](/docs/mcp-servers). + +Por padrão, todas as ferramentas estão **ativadas** e não precisam de permissão para serem executadas. Você pode controlar o comportamento das ferramentas através de [permissões](/docs/permissions). + +--- + +## Configuração + +Use o campo `permission` para controlar o comportamento das ferramentas. Você pode permitir, negar ou exigir aprovação para cada ferramenta. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +Você também pode usar curingas para controlar várias ferramentas ao mesmo tempo. Por exemplo, para exigir aprovação para todas as ferramentas de um servidor MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[Saiba mais](/docs/permissions) sobre como configurar permissões. + +--- + +## Integradas + +Aqui estão todas as ferramentas integradas disponíveis no opencode. + +--- + +### bash + +Execute comandos de shell no ambiente do seu projeto. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +Esta ferramenta permite que o LLM execute comandos de terminal como `npm install`, `git status` ou qualquer outro comando de shell. + +--- + +### edit + +Modifique arquivos existentes usando substituições de string exatas. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Esta ferramenta realiza edições precisas em arquivos substituindo correspondências de texto exatas. É a principal forma como o LLM modifica o código. + +--- + +### write + +Crie novos arquivos ou sobrescreva os existentes. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Use isso para permitir que o LLM crie novos arquivos. Ele sobrescreverá arquivos existentes se já existirem. + +:::note +A ferramenta `write` é controlada pela permissão `edit`, que cobre todas as modificações de arquivos (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### read + +Leia o conteúdo dos arquivos da sua base de código. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +Esta ferramenta lê arquivos e retorna seus conteúdos. Suporta a leitura de intervalos de linhas específicos para arquivos grandes. + +--- + +### grep + +Pesquise o conteúdo dos arquivos usando expressões regulares. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +Busca rápida de conteúdo em sua base de código. Suporta a sintaxe completa de regex e filtragem de padrões de arquivos. + +--- + +### glob + +Encontre arquivos por correspondência de padrões. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +Pesquise arquivos usando padrões glob como `**/*.js` ou `src/**/*.ts`. Retorna caminhos de arquivos correspondentes ordenados por tempo de modificação. + +--- + +### list + +Liste arquivos e diretórios em um determinado caminho. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +Esta ferramenta lista o conteúdo do diretório. Aceita padrões glob para filtrar resultados. + +--- + +### lsp (experimental) + +Interaja com seus servidores LSP configurados para obter recursos de inteligência de código, como definições, referências, informações de hover e hierarquia de chamadas. + +:::note +Esta ferramenta está disponível apenas quando `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (ou `OPENCODE_EXPERIMENTAL=true`). +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +As operações suportadas incluem `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls` e `outgoingCalls`. + +Para configurar quais servidores LSP estão disponíveis para seu projeto, veja [Servidores LSP](/docs/lsp). + +--- + +### patch + +Aplique patches a arquivos. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Esta ferramenta aplica arquivos de patch à sua base de código. Útil para aplicar diffs e patches de várias fontes. + +:::note +A ferramenta `patch` é controlada pela permissão `edit`, que cobre todas as modificações de arquivos (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### skill + +Carregue uma [skill](/docs/skills) (um arquivo `SKILL.md`) e retorne seu conteúdo na conversa. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +Gerencie listas de tarefas durante sessões de codificação. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +Cria e atualiza listas de tarefas para acompanhar o progresso durante operações complexas. O LLM usa isso para organizar tarefas de múltiplas etapas. + +:::note +Esta ferramenta está desativada para subagentes por padrão, mas você pode ativá-la manualmente. [Saiba mais](/docs/agents/#permissions) +::: + +--- + +### todoread + +Leia listas de tarefas existentes. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +Lê o estado atual da lista de tarefas. Usado pelo LLM para acompanhar quais tarefas estão pendentes ou concluídas. + +:::note +Esta ferramenta está desativada para subagentes por padrão, mas você pode ativá-la manualmente. [Saiba mais](/docs/agents/#permissions) +::: + +--- + +### webfetch + +Busque conteúdo da web. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +Permite que o LLM busque e leia páginas da web. Útil para consultar documentação ou pesquisar recursos online. + +--- + +### websearch + +Pesquise na web por informações. + +:::note +Esta ferramenta está disponível apenas ao usar o provedor opencode ou quando a variável de ambiente `OPENCODE_ENABLE_EXA` está definida como qualquer valor verdadeiro (por exemplo, `true` ou `1`). + +Para habilitar ao iniciar o opencode: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +Realiza buscas na web usando Exa AI para encontrar informações relevantes online. Útil para pesquisar tópicos, encontrar eventos atuais ou reunir informações além do limite de dados de treinamento. + +Nenhuma chave de API é necessária — a ferramenta se conecta diretamente ao serviço MCP hospedado da Exa AI sem autenticação. + +:::tip +Use `websearch` quando precisar encontrar informações (descoberta) e `webfetch` quando precisar recuperar conteúdo de uma URL específica (recuperação). +::: + +--- + +### question + +Faça perguntas ao usuário durante a execução. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +Esta ferramenta permite que o LLM faça perguntas ao usuário durante uma tarefa. É útil para: + +- Coletar preferências ou requisitos do usuário +- Esclarecer instruções ambíguas +- Obter decisões sobre escolhas de implementação +- Oferecer opções sobre qual direção seguir + +Cada pergunta inclui um cabeçalho, o texto da pergunta e uma lista de opções. Os usuários podem selecionar entre as opções fornecidas ou digitar uma resposta personalizada. Quando há várias perguntas, os usuários podem navegar entre elas antes de enviar todas as respostas. + +--- + +## Ferramentas personalizadas + +Ferramentas personalizadas permitem que você defina suas próprias funções que o LLM pode chamar. Estas são definidas em seu arquivo de configuração e podem executar código arbitrário. + +[Saiba mais](/docs/custom-tools) sobre como criar ferramentas personalizadas. + +--- + +## Servidores MCP + +Servidores MCP (Model Context Protocol) permitem que você integre ferramentas e serviços externos. Isso inclui acesso a bancos de dados, integrações de API e serviços de terceiros. + +[Saiba mais](/docs/mcp-servers) sobre como configurar servidores MCP. + +--- + +## Internos + +Internamente, ferramentas como `grep`, `glob` e `list` usam [ripgrep](https://github.com/BurntSushi/ripgrep) por trás dos panos. Por padrão, o ripgrep respeita padrões `.gitignore`, o que significa que arquivos e diretórios listados em seu `.gitignore` serão excluídos de buscas e listagens. + +--- + +### Padrões de ignorar + +Para incluir arquivos que normalmente seriam ignorados, crie um arquivo `.ignore` na raiz do seu projeto. Este arquivo pode permitir explicitamente certos caminhos. + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +Por exemplo, este arquivo `.ignore` permite que o ripgrep busque dentro dos diretórios `node_modules/`, `dist/` e `build/`, mesmo que estejam listados em `.gitignore`. diff --git a/packages/web/src/content/docs/pt-br/troubleshooting.mdx b/packages/web/src/content/docs/pt-br/troubleshooting.mdx new file mode 100644 index 00000000000..aa70e80fef8 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/troubleshooting.mdx @@ -0,0 +1,299 @@ +--- +title: Solução de Problemas +description: Problemas comuns e como resolvê-los. +--- + +Para depurar problemas com o opencode, comece verificando os logs e os dados locais que ele armazena no disco. + +--- + +## Logs + +Os arquivos de log são gravados em: + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: Pressione `WIN+R` e cole `%USERPROFILE%\.local\share\opencode\log` + +Os arquivos de log são nomeados com timestamps (por exemplo, `2025-01-09T123456.log`) e os 10 arquivos de log mais recentes são mantidos. + +Você pode definir o nível de log com a opção de linha de comando `--log-level` para obter informações de depuração mais detalhadas. Por exemplo, `opencode --log-level DEBUG`. + +--- + +## Armazenamento + +O opencode armazena dados de sessão e outros dados do aplicativo no disco em: + +- **macOS/Linux**: `~/.local/share/opencode/` +- **Windows**: Pressione `WIN+R` e cole `%USERPROFILE%\.local\share\opencode` + +Este diretório contém: + +- `auth.json` - Dados de autenticação como chaves de API, tokens OAuth +- `log/` - Logs do aplicativo +- `project/` - Dados específicos do projeto, como dados de sessão e mensagens + - Se o projeto estiver dentro de um repositório Git, ele é armazenado em `.//storage/` + - Se não for um repositório Git, ele é armazenado em `./global/storage/` + +--- + +## Aplicativo de Desktop + +O opencode Desktop executa um servidor opencode local (o sidecar `opencode-cli`) em segundo plano. A maioria dos problemas é causada por um plugin com mau funcionamento, um cache corrompido ou uma configuração de servidor incorreta. + +### Verificações rápidas + +- Saia completamente do aplicativo e reinicie-o. +- Se o aplicativo mostrar uma tela de erro, clique em **Reiniciar** e copie os detalhes do erro. +- Apenas macOS: menu `OpenCode` -> **Recarregar Webview** (ajuda se a interface estiver em branco/congelada). + +--- + +### Desativando plugins + +Se o aplicativo de desktop estiver travando ao iniciar, pendurado ou se comportando de maneira estranha, comece desativando os plugins. + +#### Verificando a configuração global + +Abra seu arquivo de configuração global e procure uma chave `plugin`. + +- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (ou `~/.config/opencode/opencode.json`) +- **macOS/Linux** (instalações mais antigas): `~/.local/share/opencode/opencode.jsonc` +- **Windows**: Pressione `WIN+R` e cole `%USERPROFILE%\.config\opencode\opencode.jsonc` + +Se você tiver plugins configurados, desative-os temporariamente removendo a chave ou definindo-a como um array vazio: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### Verificando os diretórios de plugins + +O opencode também pode carregar plugins locais do disco. Mova-os temporariamente para fora do caminho (ou renomeie a pasta) e reinicie o aplicativo de desktop: + +- **Plugins globais** + - **macOS/Linux**: `~/.config/opencode/plugins/` + - **Windows**: Pressione `WIN+R` e cole `%USERPROFILE%\.config\opencode\plugins` +- **Plugins de projeto** (apenas se você usar configuração por projeto) + - `/.opencode/plugins/` + +Se o aplicativo voltar a funcionar, reative os plugins um por um para descobrir qual está causando o problema. + +--- + +### Limpando o cache + +Se desativar plugins não ajudar (ou se a instalação de um plugin estiver travada), limpe o cache para que o opencode possa reconstruí-lo. + +1. Saia completamente do opencode Desktop. +2. Exclua o diretório de cache: + +- **macOS**: Finder -> `Cmd+Shift+G` -> cole `~/.cache/opencode` +- **Linux**: exclua `~/.cache/opencode` (ou execute `rm -rf ~/.cache/opencode`) +- **Windows**: Pressione `WIN+R` e cole `%USERPROFILE%\.cache\opencode` + +3. Reinicie o opencode Desktop. + +--- + +### Corrigindo problemas de conexão com o servidor + +O opencode Desktop pode iniciar seu próprio servidor local (padrão) ou conectar-se a uma URL de servidor que você configurou. + +Se você ver um diálogo **"Conexão Falhou"** (ou o aplicativo nunca passa da tela de inicialização), verifique se há uma URL de servidor personalizada. + +#### Limpando a URL do servidor padrão do desktop + +Na tela inicial, clique no nome do servidor (com o ponto de status) para abrir o seletor de Servidor. Na seção **Servidor padrão**, clique em **Limpar**. + +#### Removendo `server.port` / `server.hostname` da sua configuração + +Se seu `opencode.json(c)` contiver uma seção `server`, remova-a temporariamente e reinicie o aplicativo de desktop. + +#### Verificando as variáveis de ambiente + +Se você tiver `OPENCODE_PORT` definido em seu ambiente, o aplicativo de desktop tentará usar essa porta para o servidor local. + +- Desfaça `OPENCODE_PORT` (ou escolha uma porta livre) e reinicie. + +--- + +### Linux: Problemas com Wayland / X11 + +No Linux, algumas configurações do Wayland podem causar janelas em branco ou erros de compositor. + +- Se você estiver no Wayland e o aplicativo estiver em branco/travando, tente iniciar com `OC_ALLOW_WAYLAND=1`. +- Se isso piorar as coisas, remova e tente iniciar sob uma sessão X11. + +--- + +### Windows: Runtime do WebView2 + +No Windows, o opencode Desktop requer o **WebView2 Runtime** do Microsoft Edge. Se o aplicativo abrir em uma janela em branco ou não iniciar, instale/atualize o WebView2 e tente novamente. + +--- + +### Windows: Problemas gerais de desempenho + +Se você estiver enfrentando desempenho lento, problemas de acesso a arquivos ou problemas no terminal no Windows, tente usar [WSL (Windows Subsystem for Linux)](/docs/windows-wsl). O WSL fornece um ambiente Linux que funciona de forma mais integrada com os recursos do opencode. + +--- + +### Notificações não aparecendo + +O opencode Desktop só mostra notificações do sistema quando: + +- as notificações estão habilitadas para o opencode nas configurações do seu sistema operacional, e +- a janela do aplicativo não está focada. + +--- + +### Redefinindo o armazenamento do aplicativo de desktop (último recurso) + +Se o aplicativo não iniciar e você não conseguir limpar as configurações pela interface, redefina o estado salvo do aplicativo de desktop. + +1. Saia do opencode Desktop. +2. Encontre e exclua estes arquivos (eles estão no diretório de dados do aplicativo opencode Desktop): + +- `opencode.settings.dat` (URL do servidor padrão do desktop) +- `opencode.global.dat` e `opencode.workspace.*.dat` (estado da interface como servidores/projetos recentes) + +Para encontrar o diretório rapidamente: + +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (depois pesquise pelos nomes dos arquivos acima) +- **Linux**: pesquise em `~/.local/share` pelos nomes dos arquivos acima +- **Windows**: Pressione `WIN+R` -> `%APPDATA%` (depois pesquise pelos nomes dos arquivos acima) + +--- + +## Obtendo ajuda + +Se você estiver enfrentando problemas com o opencode: + +1. **Relatar problemas no GitHub** + + A melhor maneira de relatar bugs ou solicitar recursos é através do nosso repositório no GitHub: + + [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + + Antes de criar um novo problema, pesquise problemas existentes para ver se seu problema já foi relatado. + +2. **Junte-se ao nosso Discord** + + Para ajuda em tempo real e discussão da comunidade, junte-se ao nosso servidor Discord: + + [**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## Problemas comuns + +Aqui estão alguns problemas comuns e como resolvê-los. + +--- + +### O opencode não inicia + +1. Verifique os logs em busca de mensagens de erro +2. Tente executar com `--print-logs` para ver a saída no terminal +3. Certifique-se de que você tem a versão mais recente com `opencode upgrade` + +--- + +### Problemas de autenticação + +1. Tente reautenticar com o comando `/connect` na TUI +2. Verifique se suas chaves de API são válidas +3. Certifique-se de que sua rede permite conexões com a API do provedor + +--- + +### Modelo não disponível + +1. Verifique se você se autenticou com o provedor +2. Verifique se o nome do modelo em sua configuração está correto +3. Alguns modelos podem exigir acesso ou assinaturas específicas + +Se você encontrar `ProviderModelNotFoundError`, é mais provável que você esteja referenciando um modelo incorretamente em algum lugar. +Os modelos devem ser referenciados assim: `/` + +Exemplos: + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +Para descobrir quais modelos você tem acesso, execute `opencode models` + +--- + +### ProviderInitError + +Se você encontrar um ProviderInitError, provavelmente você tem uma configuração inválida ou corrompida. + +Para resolver isso: + +1. Primeiro, verifique se seu provedor está configurado corretamente seguindo o [guia de provedores](/docs/providers) +2. Se o problema persistir, tente limpar sua configuração armazenada: + + ```bash + rm -rf ~/.local/share/opencode + ``` + + No Windows, pressione `WIN+R` e exclua: `%USERPROFILE%\.local\share\opencode` + +3. Reautentique-se com seu provedor usando o comando `/connect` na TUI. + +--- + +### AI_APICallError e problemas com pacotes de provedores + +Se você encontrar erros de chamada de API, isso pode ser devido a pacotes de provedores desatualizados. O opencode instala dinamicamente pacotes de provedores (OpenAI, Anthropic, Google, etc.) conforme necessário e os armazena em cache localmente. + +Para resolver problemas com pacotes de provedores: + +1. Limpe o cache do pacote de provedores: + + ```bash + rm -rf ~/.cache/opencode + ``` + + No Windows, pressione `WIN+R` e exclua: `%USERPROFILE%\.cache\opencode` + +2. Reinicie o opencode para reinstalar os pacotes de provedores mais recentes + +Isso forçará o opencode a baixar as versões mais recentes dos pacotes de provedores, o que muitas vezes resolve problemas de compatibilidade com parâmetros de modelo e alterações na API. + +--- + +### Copiar/colar não funciona no Linux + +Usuários do Linux precisam ter um dos seguintes utilitários de área de transferência instalados para que a funcionalidade de copiar/colar funcione: + +**Para sistemas X11:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**Para sistemas Wayland:** + +```bash +apt install -y wl-clipboard +``` + +**Para ambientes sem cabeça:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +O opencode detectará se você está usando Wayland e preferirá `wl-clipboard`, caso contrário, tentará encontrar ferramentas de área de transferência na ordem: `xclip` e `xsel`. diff --git a/packages/web/src/content/docs/pt-br/tui.mdx b/packages/web/src/content/docs/pt-br/tui.mdx new file mode 100644 index 00000000000..17b9c7de0b3 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/tui.mdx @@ -0,0 +1,387 @@ +--- +title: TUI +description: Usando a interface de usuário de terminal opencode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +O opencode fornece uma interface de terminal interativa ou TUI para trabalhar em seus projetos com um LLM. + +Executar opencode inicia o TUI para o diretório atual. + +```bash +opencode +``` + +Ou você pode iniciá-lo para um diretório de trabalho específico. + +```bash +opencode /path/to/project +``` + +Uma vez que você esteja no TUI, você pode solicitar com uma mensagem. + +```text +Faça um resumo rápido da base de código. +``` + +--- + +## Referências de arquivos + +Você pode referenciar arquivos em suas mensagens usando `@`. Isso faz uma busca difusa de arquivos no diretório de trabalho atual. + +:::tip +Você também pode usar `@` para referenciar arquivos em suas mensagens. +::: + +```text "@packages/functions/src/api/index.ts" +Como a autenticação é tratada em @packages/functions/src/api/index.ts? +``` + +O conteúdo do arquivo é adicionado à conversa automaticamente. + +--- + +## Comandos Bash + +Comece uma mensagem com `!` para executar um comando de shell. + +```bash frame="none" +!ls -la +``` + +A saída do comando é adicionada à conversa como um resultado de ferramenta. + +--- + +## Comandos + +Ao usar o TUI do opencode, você pode digitar `/` seguido pelo nome de um comando para executar ações rapidamente. Por exemplo: + +```bash frame="none" +/help +``` + +A maioria dos comandos também possui atalhos usando `ctrl+x` como a tecla líder, onde `ctrl+x` é a tecla líder padrão. [Saiba mais](/docs/keybinds). + +Aqui estão todos os comandos de barra disponíveis: + +--- + +### connect + +Adicione um provedor ao opencode. Permite que você selecione entre os provedores disponíveis e adicione suas chaves de API. + +```bash frame="none" +/connect +``` + +--- + +### compact + +Compacte a sessão atual. _Alias_: `/summarize` + +```bash frame="none" +/compact +``` + +**Atalho:** `ctrl+x c` + +--- + +### details + +Alternar detalhes da execução da ferramenta. + +```bash frame="none" +/details +``` + +**Atalho:** `ctrl+x d` + +--- + +### editor + +Abra um editor externo para compor mensagens. Usa o editor definido na sua variável de ambiente `EDITOR`. [Saiba mais](#editor-setup). + +```bash frame="none" +/editor +``` + +**Atalho:** `ctrl+x e` + +--- + +### exit + +Saia do opencode. _Aliases_: `/quit`, `/q` + +```bash frame="none" +/exit +``` + +**Atalho:** `ctrl+x q` + +--- + +### export + +Exporte a conversa atual para Markdown e abra no seu editor padrão. Usa o editor definido na sua variável de ambiente `EDITOR`. [Saiba mais](#editor-setup). + +```bash frame="none" +/export +``` + +**Atalho:** `ctrl+x x` + +--- + +### help + +Mostre o diálogo de ajuda. + +```bash frame="none" +/help +``` + +**Atalho:** `ctrl+x h` + +--- + +### init + +Crie ou atualize o arquivo `AGENTS.md`. [Saiba mais](/docs/rules). + +```bash frame="none" +/init +``` + +**Atalho:** `ctrl+x i` + +--- + +### models + +Liste os modelos disponíveis. + +```bash frame="none" +/models +``` + +**Atalho:** `ctrl+x m` + +--- + +### new + +Inicie uma nova sessão. _Alias_: `/clear` + +```bash frame="none" +/new +``` + +**Atalho:** `ctrl+x n` + +--- + +### redo + +Refaça uma mensagem anteriormente desfeita. Disponível apenas após usar `/undo`. + +:::tip +Quaisquer alterações de arquivo também serão restauradas. +::: + +Internamente, isso usa Git para gerenciar as alterações de arquivo. Portanto, seu projeto **precisa ser um repositório Git**. + +```bash frame="none" +/redo +``` + +**Atalho:** `ctrl+x r` + +--- + +### sessions + +Liste e alterne entre sessões. _Aliases_: `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +**Atalho:** `ctrl+x l` + +--- + +### share + +Compartilhe a sessão atual. [Saiba mais](/docs/share). + +```bash frame="none" +/share +``` + +**Atalho:** `ctrl+x s` + +--- + +### themes + +Liste os temas disponíveis. + +```bash frame="none" +/theme +``` + +**Atalho:** `ctrl+x t` + +--- + +### thinking + +Alternar a visibilidade dos blocos de pensamento/razão na conversa. Quando ativado, você pode ver o processo de raciocínio do modelo para modelos que suportam pensamento estendido. + +:::note +Este comando apenas controla se os blocos de pensamento são **exibidos** - não ativa ou desativa as capacidades de raciocínio do modelo. Para alternar as capacidades reais de raciocínio, use `ctrl+t` para alternar entre variantes do modelo. +::: + +```bash frame="none" +/thinking +``` + +--- + +### undo + +Desfaça a última mensagem na conversa. Remove a mensagem mais recente do usuário, todas as respostas subsequentes e quaisquer alterações de arquivo. + +:::tip +Quaisquer alterações de arquivo feitas também serão revertidas. +::: + +Internamente, isso usa Git para gerenciar as alterações de arquivo. Portanto, seu projeto **precisa ser um repositório Git**. + +```bash frame="none" +/undo +``` + +**Atalho:** `ctrl+x u` + +--- + +### unshare + +Descompartilhe a sessão atual. [Saiba mais](/docs/share#un-sharing). + +```bash frame="none" +/unshare +``` + +--- + +## Configuração do Editor + +Tanto os comandos `/editor` quanto `/export` usam o editor especificado na sua variável de ambiente `EDITOR`. + + + + ```bash + # Exemplo para nano ou vim + export EDITOR=nano + export EDITOR=vim + + # Para editores GUI, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # inclua --wait + export EDITOR="code --wait" + ``` + + Para torná-lo permanente, adicione isso ao seu perfil de shell; + `~/.bashrc`, `~/.zshrc`, etc. + + + + + ```bash + set EDITOR=notepad + + # Para editores GUI, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # inclua --wait + set EDITOR=code --wait + ``` + + Para torná-lo permanente, use **Propriedades do Sistema** > **Variáveis de Ambiente**. + + + + + ```powershell + $env:EDITOR = "notepad" + + # Para editores GUI, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # inclua --wait + $env:EDITOR = "code --wait" + ``` + + Para torná-lo permanente, adicione isso ao seu perfil do PowerShell. + + + + +As opções de editor populares incluem: + +- `code` - VS Code +- `cursor` - Cursor +- `windsurf` - Windsurf +- `nvim` - Editor Neovim +- `vim` - Editor Vim +- `nano` - Editor Nano +- `notepad` - Bloco de Notas do Windows +- `subl` - Sublime Text + +:::note +Alguns editores como o VS Code precisam ser iniciados com a flag `--wait`. +::: + +Alguns editores precisam de argumentos de linha de comando para rodar em modo bloqueante. A flag `--wait` faz com que o processo do editor bloqueie até ser fechado. + +--- + +## Configuração + +Você pode personalizar o comportamento do TUI através do seu arquivo de configuração do opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### 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`.** + +--- + +## Personalização + +Você pode personalizar vários aspectos da visualização do TUI usando a paleta de comandos (`ctrl+x h` ou `/help`). Essas configurações persistem entre reinicializações. + +--- + +#### Exibição do nome de usuário + +Alternar se seu nome de usuário aparece nas mensagens de chat. Acesse isso através de: + +- Paleta de comandos: Pesquise por "username" ou "hide username" +- A configuração persiste automaticamente e será lembrada entre as sessões do TUI diff --git a/packages/web/src/content/docs/pt-br/web.mdx b/packages/web/src/content/docs/pt-br/web.mdx new file mode 100644 index 00000000000..5338a4ce404 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/web.mdx @@ -0,0 +1,142 @@ +--- +title: Web +description: Usando o opencode no seu navegador. +--- + +O opencode pode ser executado como uma aplicação web no seu navegador, proporcionando a mesma poderosa experiência de codificação com IA sem precisar de um terminal. + +![opencode Web - Nova Sessão](../../../assets/web/web-homepage-new-session.png) + +## Primeiros passos + +Inicie a interface web executando: + +```bash +opencode web +``` + +Isso inicia um servidor local em `127.0.0.1` com uma porta aleatória disponível e abre automaticamente o opencode no seu navegador padrão. + +:::caution +Se `OPENCODE_SERVER_PASSWORD` não estiver definido, o servidor ficará sem segurança. Isso é aceitável para uso local, mas deve ser configurado para acesso à rede. +::: + +:::tip[Usuários do Windows] +Para a melhor experiência, execute `opencode web` a partir do [WSL](/docs/windows-wsl) em vez do PowerShell. Isso garante acesso adequado ao sistema de arquivos e integração com o terminal. +::: + +--- + +## Configuração + +Você pode configurar o servidor web usando flags de linha de comando ou no seu [arquivo de configuração](/docs/config). + +### Porta + +Por padrão, o opencode escolhe uma porta disponível. Você pode especificar uma porta: + +```bash +opencode web --port 4096 +``` + +### Nome do Host + +Por padrão, o servidor se vincula a `127.0.0.1` (apenas localhost). Para tornar o opencode acessível na sua rede: + +```bash +opencode web --hostname 0.0.0.0 +``` + +Ao usar `0.0.0.0`, o opencode exibirá endereços locais e de rede: + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### Descoberta mDNS + +Ative o mDNS para tornar seu servidor descobrível na rede local: + +```bash +opencode web --mdns +``` + +Isso define automaticamente o nome do host como `0.0.0.0` e anuncia o servidor como `opencode.local`. + +Você pode personalizar o nome de domínio mDNS para executar várias instâncias na mesma rede: + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +Para permitir domínios adicionais para CORS (útil para frontends personalizados): + +```bash +opencode web --cors https://example.com +``` + +### Autenticação + +Para proteger o acesso, defina uma senha usando a variável de ambiente `OPENCODE_SERVER_PASSWORD`: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +O nome de usuário padrão é `opencode`, mas pode ser alterado com `OPENCODE_SERVER_USERNAME`. + +--- + +## Usando a Interface Web + +Uma vez iniciada, a interface web fornece acesso às suas sessões do opencode. + +### Sessões + +Visualize e gerencie suas sessões a partir da página inicial. Você pode ver sessões ativas e iniciar novas. + +![opencode Web - Sessão Ativa](../../../assets/web/web-homepage-active-session.png) + +### Status do Servidor + +Clique em "Ver Servidores" para visualizar os servidores conectados e seu status. + +![opencode Web - Ver Servidores](../../../assets/web/web-homepage-see-servers.png) + +--- + +## Anexando um Terminal + +Você pode anexar um terminal TUI a um servidor web em execução: + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +Isso permite que você use tanto a interface web quanto o terminal simultaneamente, compartilhando as mesmas sessões e estado. + +--- + +## Arquivo de Configuração + +Você também pode configurar as configurações do servidor no seu arquivo de configuração `opencode.json`: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +As flags de linha de comando têm precedência sobre as configurações do arquivo de configuração. diff --git a/packages/web/src/content/docs/pt-br/windows-wsl.mdx b/packages/web/src/content/docs/pt-br/windows-wsl.mdx new file mode 100644 index 00000000000..a4b9ac11ad0 --- /dev/null +++ b/packages/web/src/content/docs/pt-br/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: Execute o opencode no Windows com WSL para melhor experiência. +--- + +import { Steps } from "@astrojs/starlight/components" + +Embora o opencode possa rodar direto no Windows, recomendamos usar [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) para a melhor experiência. O WSL oferece um ambiente Linux que funciona de forma integrada com os recursos do opencode. + +:::tip[Por que WSL?] +O WSL oferece melhor desempenho de sistema de arquivos, suporte completo a terminal e compatibilidade com as ferramentas de desenvolvimento das quais o opencode depende. +::: + +--- + +## Configuração + + + +1. **Instale o WSL** + + Se ainda não instalou, [instale o WSL](https://learn.microsoft.com/en-us/windows/wsl/install) usando o guia oficial da Microsoft. + +2. **Instale o opencode no WSL** + + Depois de configurar o WSL, abra o terminal do WSL e instale o opencode usando um dos [métodos de instalação](/docs/). + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **Use o opencode pelo WSL** + + Vá para o diretório do seu projeto (acesse arquivos do Windows via `/mnt/c/`, `/mnt/d/` etc.) e execute o opencode. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## App desktop + servidor WSL + +Se você prefere usar o app desktop do opencode, mas quer rodar o servidor no WSL: + +1. **Inicie o servidor no WSL** com `--hostname 0.0.0.0` para permitir conexões externas: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **Conecte o app desktop** em `http://localhost:4096` + +:::note +Se `localhost` não funcionar no seu ambiente, conecte usando o IP do WSL (no WSL: `hostname -I`) e use `http://:4096`. +::: + +:::caution +Ao usar `--hostname 0.0.0.0`, defina `OPENCODE_SERVER_PASSWORD` para proteger o servidor. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## Cliente web + WSL + +Para a melhor experiência web no Windows: + +1. **Execute `opencode web` no terminal WSL** em vez do PowerShell: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Acesse pelo navegador do Windows** em `http://localhost:` (o opencode mostra a URL) + +Executar `opencode web` a partir do WSL garante acesso correto ao sistema de arquivos e integração com o terminal, continuando acessível no navegador do Windows. + +--- + +## Acessar arquivos do Windows + +O WSL pode acessar todos os arquivos do Windows pelo diretório `/mnt/`: + +- Unidade `C:` → `/mnt/c/` +- Unidade `D:` → `/mnt/d/` +- E assim por diante... + +Exemplo: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +Para uma experiência mais fluida, considere clonar/copiar seu repositório para o sistema de arquivos do WSL (por exemplo em `~/code/`) e executar o opencode por lá. +::: + +--- + +## Dicas + +- Mantenha o opencode rodando no WSL para projetos armazenados em unidades do Windows - o acesso aos arquivos fica fluido +- Use a [extensão WSL do VS Code](https://code.visualstudio.com/docs/remote/wsl) junto com o opencode para um fluxo de desenvolvimento integrado +- Sua configuração e suas sessões do opencode ficam armazenadas no ambiente WSL em `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/pt-br/zen.mdx b/packages/web/src/content/docs/pt-br/zen.mdx new file mode 100644 index 00000000000..203f0b3f9df --- /dev/null +++ b/packages/web/src/content/docs/pt-br/zen.mdx @@ -0,0 +1,236 @@ +--- +title: Zen +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. + +:::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. + +--- + +## Contexto + +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. +::: + +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. + +Para resolver isso, fizemos algumas coisas: + +1. Testamos um grupo selecionado de modelos e conversamos com suas equipes sobre como executá-los da melhor forma. +2. Trabalhamos com alguns provedores para garantir que esses modelos estivessem sendo servidos corretamente. +3. Finalmente, realizamos benchmarks da combinação modelo/provedor e elaboramos uma lista que nos sentimos bem em recomendar. + +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. + +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. +3. Execute `/models` no TUI para ver a lista de modelos que recomendamos. + +Você é cobrado por solicitação e pode adicionar créditos à sua conta. + +--- + +## Endpoints + +Você também pode acessar nossos modelos através dos seguintes endpoints da API. + +| Modelo | ID do Modelo | Endpoint | Pacote AI SDK | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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. + +--- + +### Modelos + +Você pode buscar a lista completa de modelos disponíveis e seus metadados em: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## Preços + +Nós suportamos um modelo de pagamento conforme o uso. Abaixo estão os preços **por 1M de tokens**. + +| 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.1 | $0.30 | $1.20 | $0.10 | - | +| GLM 4.7 Free | Grátis | Grátis | Grátis | - | +| 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 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 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.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 | Grátis | Grátis | Grátis | - | + +Você pode notar _Claude Haiku 3.5_ em seu histórico de uso. Este é um [modelo de baixo custo](/docs/config/#models) que é usado para gerar os títulos de suas sessões. + +:::note +As taxas de cartão de crédito são repassadas ao custo (4,4% + $0,30 por transação); não cobramos nada além disso. +::: + +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. + +Entre em contato conosco se você tiver alguma dúvida. + +--- + +### Recarga automática + +Se seu saldo cair abaixo de $5, o Zen recarregará automaticamente $20. + +Você pode alterar o valor da recarga automática. Você também pode desativar a recarga automática completamente. + +--- + +### Limites mensais + +Você também pode definir um limite de uso mensal para todo o espaço de trabalho e para cada membro de sua equipe. + +Por exemplo, digamos que você defina um limite de uso mensal de $20, o Zen não usará mais de $20 em um mês. Mas se você tiver a recarga automática ativada, o Zen pode acabar cobrando mais de $20 se seu saldo cair abaixo de $5. + +--- + +## Privacidade + +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. +- 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). + +--- + +## Para Equipes + +O Zen também funciona muito bem para equipes. Você pode convidar colegas de equipe, atribuir funções, selecionar os modelos que sua equipe usa e muito mais. + +:::note +Os espaços de trabalho estão atualmente gratuitos para equipes como parte do beta. +::: + +Gerenciar seu espaço de trabalho é atualmente gratuito para equipes como parte do beta. Em breve, compartilharemos mais detalhes sobre os preços. + +--- + +### Funções + +Você pode convidar colegas de equipe para seu espaço de trabalho e atribuir funções: + +- **Admin**: Gerenciar modelos, membros, chaves de API e cobrança +- **Membro**: Gerenciar apenas suas próprias chaves de API + +Os administradores também podem definir limites de gastos mensais para cada membro para manter os custos sob controle. + +--- + +### Acesso ao modelo + +Os administradores podem habilitar ou desabilitar modelos específicos para o espaço de trabalho. Solicitações feitas a um modelo desabilitado retornarão um erro. + +Isso é útil para casos em que você deseja desabilitar o uso de um modelo que coleta dados. + +--- + +### Traga sua própria chave + +Você pode usar suas próprias chaves de API da OpenAI ou Anthropic enquanto ainda acessa outros modelos no Zen. + +Quando você usa suas próprias chaves, os tokens são cobrados diretamente pelo provedor, não pelo Zen. + +Por exemplo, sua organização pode já ter uma chave para OpenAI ou Anthropic e você deseja usar essa em vez da que o Zen fornece. + +--- + +## Objetivos + +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. diff --git a/packages/web/src/content/docs/ru/acp.mdx b/packages/web/src/content/docs/ru/acp.mdx new file mode 100644 index 00000000000..c4a6132fe5e --- /dev/null +++ b/packages/web/src/content/docs/ru/acp.mdx @@ -0,0 +1,156 @@ +--- +title: Поддержка ACP +description: Используйте opencode в любом ACP-совместимом редакторе. +--- + +opencode поддерживает [Agent Client Protocol](https://agentclientprotocol.com) (ACP), что позволяет использовать его непосредственно в совместимых редакторах и IDE. + +:::tip +Список редакторов и инструментов, поддерживающих ACP, можно найти в [отчете о ходе работы ACP](https://zed.dev/blog/acp-progress-report#available-now). +::: + +ACP — это открытый протокол, который стандартизирует взаимодействие между редакторами кода и ИИ-агентами. + +--- + +## Настройка + +Чтобы использовать opencode через ACP, настройте свой редактор для запуска команды `opencode acp`. + +Команда запускает opencode как ACP-совместимый подпроцесс, который взаимодействует с вашим редактором через JSON-RPC через stdio. + +Ниже приведены примеры популярных редакторов, поддерживающих ACP. + +--- + +### Zed + +Добавьте в конфигурацию [Zed](https://zed.dev) (`~/.config/zed/settings.json`): + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +Чтобы открыть его, используйте действие `agent: new thread` в **Палитре команд**. + +Вы также можете привязать сочетание клавиш, отредактировав свой `keymap.json`: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### IDE JetBrains + +Добавьте в свою [JetBrains IDE](https://www.jetbrains.com/) acp.json в соответствии с [документацией](https://www.jetbrains.com/help/ai-assistant/acp.html): + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +Чтобы открыть его, используйте новый агент opencode в селекторе агентов AI Chat. + +--- + +### Avante.nvim + +Добавьте в свою конфигурацию [Avante.nvim](https://github.com/yetone/avante.nvim): + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +Если вам нужно передать переменные среды: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +Чтобы использовать opencode в качестве агента ACP в [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim), добавьте в конфигурацию Neovim следующее: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +Эта конфигурация настраивает CodeCompanion для использования opencode в качестве агента ACP для чата. + +Если вам нужно передать переменные среды (например, `OPENCODE_API_KEY`), обратитесь к разделу [Настройка адаптеров: переменные среды](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) в документации CodeCompanion.nvim для получения полной информации. + +## Поддержка + +opencode через ACP работает так же, как и в терминале. Поддерживаются все функции: + +:::note +Некоторые встроенные команды слэша, такие как `/undo` и `/redo`, в настоящее время не поддерживаются. +::: + +- Встроенные инструменты (файловые операции, команды терминала и т. д.) +- Пользовательские инструменты и команды слэша +- Серверы MCP, настроенные в вашей конфигурации opencode +- Правила для конкретного проекта из `AGENTS.md` +- Пользовательские форматтеры и линтеры +- Агенты и система разрешений diff --git a/packages/web/src/content/docs/ru/agents.mdx b/packages/web/src/content/docs/ru/agents.mdx new file mode 100644 index 00000000000..f515c15d7bf --- /dev/null +++ b/packages/web/src/content/docs/ru/agents.mdx @@ -0,0 +1,746 @@ +--- +title: Агенты +description: Настройте и используйте специализированные агенты. +--- + +Агенты — это специализированные ИИ-помощники, которых можно настроить для конкретных задач и рабочих процессов. Они позволяют создавать специализированные инструменты с настраиваемыми подсказками, моделями и доступом к инструментам. + +:::tip +Используйте агент плана для анализа кода и просмотра предложений без внесения каких-либо изменений в код. +::: + +Вы можете переключаться между агентами во время сеанса или вызывать их с помощью упоминания `@`. + +--- + +## Типы + +В opencode есть два типа агентов; Первичные агенты и субагенты. + +--- + +### Первичные агенты + +Первичные агенты — это основные помощники, с которыми вы взаимодействуете напрямую. Вы можете переключаться между ними, используя клавишу **Tab** или настроенную привязку клавиш `switch_agent`. Эти агенты ведут ваш основной разговор. Доступ к инструментам настраивается с помощью разрешений — например, при сборке все инструменты включены, а при планировании — ограничены. + +:::tip +Вы можете использовать клавишу **Tab** для переключения между основными агентами во время сеанса. +::: + +opencode поставляется с двумя встроенными основными агентами: **Build** и **Plan**. Мы рассмотрим их ниже. + +--- + +### Субагенты + +Субагенты — это специализированные помощники, которых основные агенты могут вызывать для выполнения определенных задач. Вы также можете вызвать их вручную, **@ упомянув** их в своих сообщениях. + +opencode поставляется с двумя встроенными субагентами: **General** и **Explore**. Мы рассмотрим это ниже. + +--- + +## Встроенные агенты + +opencode поставляется с двумя встроенными основными агентами и двумя встроенными субагентами. + +--- + +### Использование Build + +_Режим_: `primary` + +Build — основной агент **по умолчанию** со всеми включенными инструментами. Это стандартный агент для разработки, где вам необходим полный доступ к файловым операциям и системным командам. + +--- + +### Использование Plan + +_Режим_: `primary` + +Агент с ограниченным доступом, предназначенный для планирования и анализа. Мы используем систему разрешений, чтобы предоставить вам больше контроля и предотвратить непреднамеренные изменения. +По умолчанию для всех следующих параметров установлено значение `ask`: + +- `file edits`: Все записи, исправления и изменения. +- `bash`: все команды bash. + +Этот агент полезен, если вы хотите, чтобы LLM анализировал код, предлагал изменения или создавал планы без внесения каких-либо фактических изменений в вашу кодовую базу. + +--- + +### Использование General + +_Режим_: `subagent` + +Универсальный агент для исследования сложных вопросов и выполнения многоэтапных задач. Имеет полный доступ к инструментам (кроме задач), поэтому при необходимости может вносить изменения в файлы. Используйте это для параллельного выполнения нескольких единиц работы. + +--- + +### Использование Explore + +_Режим_: `subagent` + +Быстрый агент только для чтения для изучения кодовых баз. Невозможно изменить файлы. Используйте это, когда вам нужно быстро найти файлы по шаблонам, выполнить поиск кода по ключевым словам или ответить на вопросы о кодовой базе. + +--- + +### Использование Compact + +_Режим_: `primary` + +Скрытый системный агент, который сжимает длинный контекст в меньшее резюме. Он запускается автоматически при необходимости и не может быть выбран в пользовательском интерфейсе. + +--- + +### Использование Title + +_Режим_: `primary` + +Скрытый системный агент, генерирующий короткие заголовки сессий. Он запускается автоматически и не может быть выбран в пользовательском интерфейсе. + +--- + +### Использование Summary + +_Режим_: `primary` + +Скрытый системный агент, создающий сводки сеансов. Он запускается автоматически и не может быть выбран в пользовательском интерфейсе. + +--- + +## Использование + +1. Для основных агентов используйте клавишу **Tab** для переключения между ними во время сеанса. Вы также можете использовать настроенную привязку клавиш `switch_agent`. + +2. Субагенты могут быть вызваны: + - **Автоматически** основными агентами для выполнения специализированных задач на основе их описаний. + - Вручную, **@ упомянув** субагента в своем сообщении. Например. + + ```txt frame="none" + @general help me search for this function + ``` + +3. **Навигация между сеансами**. Когда субагенты создают свои собственные дочерние сеансы, вы можете перемещаться между родительским сеансом и всеми дочерними сеансами, используя: + - **\+Right** (или настроенная вами комбинация клавиш `session_child_cycle`) для перехода вперед через родительский элемент → дочерний элемент1 → дочерний элемент2 → ... → родительский элемент. + - **\+Left** (или настроенная вами комбинация клавиш `session_child_cycle_reverse`) для перехода назад по родительскому элементу ← дочерний элемент1 ← дочерний элемент2 ← ... ← родительский элемент + + Это позволяет плавно переключаться между основным разговором и работой специализированного субагента. + +--- + +## Настройка + +Вы можете настроить встроенные агенты или создать свои собственные посредством настройки. Агенты можно настроить двумя способами: + +--- + +### JSON + +Настройте агентов в файле конфигурации `opencode.json`: + +```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 + +Вы также можете определить агентов, используя файлы Markdown. Поместите их в: + +- Глобальный: `~/.config/opencode/agents/` +- Для каждого проекта: `.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 файла становится именем агента. Например, `review.md` создает агент `review`. + +--- + +## Параметры + +Давайте рассмотрим эти параметры конфигурации подробно. + +--- + +### Описание + +Используйте опцию `description`, чтобы предоставить краткое описание того, что делает агент и когда его использовать. + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +Это **обязательный** параметр конфигурации. + +--- + +### Температура + +Контролируйте случайность и креативность ответов LLM с помощью конфигурации `temperature`. + +Более низкие значения делают ответы более целенаправленными и детерминированными, а более высокие значения повышают креативность и вариативность. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Значения температуры обычно находятся в диапазоне от 0,0 до 1,0: + +- **0,0–0,2**: очень целенаправленные и детерминированные ответы, идеальные для анализа кода и планирования. +- **0,3–0,5**: сбалансированные ответы с некоторой креативностью, подходят для общих задач разработки. +- **0,6–1,0**: более творческие и разнообразные ответы, полезные для мозгового штурма и исследования. + +```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}" + } + } +} +``` + +Если температура не указана, opencode использует значения по умолчанию, специфичные для модели; обычно 0 для большинства моделей, 0,55 для моделей Qwen. + +--- + +### Максимальное количество шагов + +Управляйте максимальным количеством агентных итераций, которые агент может выполнить, прежде чем ему придется отвечать только текстом. Это позволяет пользователям, желающим контролировать расходы, устанавливать лимит на агентские действия. + +Если этот параметр не установлен, агент будет продолжать выполнять итерацию до тех пор, пока модель не решит остановиться или пока пользователь не прервет сеанс. + +```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 + } + } +} +``` + +При достижении лимита агент получает специальную системную подсказку с указанием в ответ краткой информации о своей работе и рекомендуемых оставшихся задачах. + +:::caution +Устаревшее поле `maxSteps` устарело. Вместо этого используйте `steps`. +::: + +--- + +### Отключение + +Установите `true`, чтобы отключить агент. + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### Промпт + +Укажите собственный файл системных приглашений для этого агента с помощью конфигурации `prompt`. Файл подсказки должен содержать инструкции, специфичные для целей агента. + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Этот путь указан относительно того, где находится файл конфигурации. Таким образом, это работает как для глобальной конфигурации opencode, так и для конфигурации конкретного проекта. + +--- + +### Модель + +Используйте конфигурацию `model`, чтобы переопределить модель этого агента. Полезно для использования разных моделей, оптимизированных под разные задачи. Например, более быстрая модель планирования и более эффективная модель реализации. + +:::tip +Если вы не укажете модель, основные агенты будут использовать глобально настроенную модель](/docs/config#models), а субагенты будут использовать модель основного агента, вызвавшего субагент. +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +Идентификатор модели в вашей конфигурации opencode использует формат `provider/model-id`. Например, если вы используете [OpenCode Zen](/docs/zen), вы должны использовать `opencode/gpt-5.1-codex` для кодекса GPT 5.1. + +--- + +### Инструменты + +Контролируйте, какие инструменты доступны в этом агенте, с помощью конфигурации `tools`. Вы можете включить или отключить определенные инструменты, установив для них значение `true` или `false`. + +```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 +Конфигурация, специфичная для агента, переопределяет глобальную конфигурацию. +::: + +Вы также можете использовать подстановочные знаки для одновременного управления несколькими инструментами. Например, чтобы отключить все инструменты с сервера MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[Подробнее об инструментах](/docs/tools). + +--- + +### Разрешения + +Вы можете настроить разрешения, чтобы управлять действиями, которые может выполнять агент. В настоящее время разрешения для инструментов `edit`, `bash` и `webfetch` можно настроить на: + +- `"ask"` — Запросить подтверждение перед запуском инструмента. +- `"allow"` — Разрешить все операции без одобрения. +- `"deny"` — отключить инструмент + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +Вы можете переопределить эти разрешения для каждого агента. + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +Вы также можете установить разрешения в агентах Markdown. + +```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. +``` + +Вы можете установить разрешения для определенных команд bash. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +Это может использовать glob pattern. + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +Вы также можете использовать подстановочный знак `*` для управления разрешениями для всех команд. +Поскольку последнее правило сопоставления имеет приоритет, сначала поместите подстановочный знак `*`, а затем конкретные правила. + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[Подробнее о разрешениях](/docs/permissions). + +--- + +### Режим + +Управляйте режимом агента с помощью конфигурации `mode`. Опция `mode` используется для определения того, как можно использовать агент. + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +Опция `mode` может быть установлена ​​на `primary`, `subagent` или `all`. Если `mode` не указан, по умолчанию используется `all`. + +--- + +### Скрытый + +Скройте субагент из меню автозаполнения `@` с помощью `hidden: true`. Полезно для внутренних субагентов, которые другие агенты должны вызывать только программно с помощью инструмента Task. + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +Это влияет только на видимость пользователя в меню автозаполнения. Скрытые агенты по-прежнему могут быть вызваны моделью с помощью инструмента «Задачи», если разрешения позволяют. + +:::note +Применяется только к агентам `mode: subagent`. +::: + +--- + +### Разрешения задач + +Управляйте тем, какие субагенты агент может вызывать с помощью инструмента задач с помощью `permission.task`. Использует шаблоны glob для гибкого сопоставления. + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +Если установлено значение `deny`, субагент полностью удаляется из описания инструмента «Задача», поэтому модель не будет пытаться его вызвать. + +:::tip +Правила оцениваются по порядку, и **побеждает последнее подходящее правило**. В приведенном выше примере `orchestrator-planner` соответствует как `*` (запретить), так и `orchestrator-*` (разрешить), но поскольку `orchestrator-*` идет после `*`, результатом будет `allow`. +::: + +:::tip +Пользователи всегда могут вызвать любой субагент напрямую через меню автозаполнения `@`, даже если разрешения задач агента запрещают это. +::: + +--- + +### Цвет + +Настройте внешний вид агента в пользовательском интерфейсе с помощью параметра `color`. Это влияет на то, как агент будет отображаться в интерфейсе. + +Используйте допустимый шестнадцатеричный цвет (например, `#FF5733`) или цвет темы: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +Управляйте разнообразием ответов с помощью опции `top_p`. Альтернатива температуре для контроля случайности. + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +Значения варьируются от 0,0 до 1,0. Низкие значения делают ответы более целенаправленными, высокие — более разнообразными. + +--- + +### Дополнительно + +Любые другие параметры, указанные вами в конфигурации вашего агента, будут **передаваться напрямую** поставщику в качестве параметров модели. Это позволяет использовать функции и параметры, специфичные для поставщика. + +Например, с помощью моделей рассуждения OpenAI вы можете контролировать усилия по рассуждению: + +```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" + } + } +} +``` + +Эти дополнительные параметры зависят от модели и поставщика. Проверьте документацию вашего провайдера на наличие доступных параметров. + +:::tip +Запустите `opencode models`, чтобы просмотреть список доступных моделей. +::: + +--- + +## Создание агентов + +Вы можете создать новых агентов, используя следующую команду: + +```bash +opencode agent create +``` + +Эта интерактивная команда: + +1. Спрашивает, где сохранить агента: глобально или в проекте. +2. Запрашивает описание того, что должен делать агент. +3. Создает соответствующий системный промпт и идентификатор. +4. Позволяет выбрать, к каким инструментам агент будет иметь доступ. +5. Наконец, создает файл Markdown с конфигурацией агента. + +--- + +## Варианты использования + +Вот несколько распространенных случаев использования различных агентов. + +- **Агент сборки**: полная работа по разработке со всеми включенными инструментами. +- **Агент планирования**: анализ и планирование без внесения изменений. +- **Агент проверки**: проверка кода с доступом только для чтения и инструментами документирования. +- **Агент отладки**: сосредоточен на исследовании с включенными инструментами bash и чтения. +- **Агент документов**: запись документации с помощью файловых операций, но без системных команд. + +--- + +## Примеры + +Вот несколько примеров агентов, которые могут оказаться вам полезными. + +:::tip +У вас есть агент, которым вы хотели бы поделиться? [Отправьте PR](https://github.com/anomalyco/opencode). +::: + +--- + +### Агент документации + +```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 +``` + +--- + +### Аудитор безопасности + +```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/ru/cli.mdx b/packages/web/src/content/docs/ru/cli.mdx new file mode 100644 index 00000000000..1a1003a63a1 --- /dev/null +++ b/packages/web/src/content/docs/ru/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: Параметры и команда opencode CLI. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +CLI opencode по умолчанию запускает [TUI](/docs/tui) при запуске без каких-либо аргументов. + +```bash +opencode +``` + +Но он также принимает команды, описанные на этой странице. Это позволяет вам программно взаимодействовать с opencode. + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +Запустите TUI opencode. + +```bash +opencode [project] +``` + +#### Флаги + +| Флаг | Короткий | Описание | +| ------------ | -------- | ----------------------------------------------------------------------------- | +| `--continue` | `-c` | Продолжить последний сеанс | +| `--session` | `-s` | Идентификатор сеанса для продолжения | +| `--fork` | | Разветвить сеанс при продолжении (используйте с `--continue` или `--session`) | +| `--prompt` | | Промпт для использования | +| `--model` | `-m` | Модель для использования в виде поставщика/модели. | +| `--agent` | | Агент для использования | +| `--port` | | Порт для прослушивания | +| `--hostname` | | Имя хоста для прослушивания | + +--- + +## Команды + +CLI opencode также имеет следующие команды. + +--- + +### agent + +Управляйте агентами для opencode. + +```bash +opencode agent [command] +``` + +--- + +### attach + +Подключите терминал к уже работающему внутреннему серверу opencode, запущенному с помощью команд `serve` или `web`. + +```bash +opencode attach [url] +``` + +Это позволяет использовать TUI с удаленным сервером opencode. Например: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### Флаги + +| Флаг | Короткий | Описание | +| ----------- | -------- | ------------------------------------ | +| `--dir` | | Рабочий каталог для запуска TUI | +| `--session` | `-s` | Идентификатор сеанса для продолжения | + +--- + +#### create + +Создайте нового агента с пользовательской конфигурацией. + +```bash +opencode agent create +``` + +Эта команда поможет вам создать новый агент с настраиваемой системной подсказкой и настройкой инструмента. + +--- + +#### list + +Перечислите всех доступных агентов. + +```bash +opencode agent list +``` + +--- + +### auth + +Команда для управления учетными данными и входом в систему для провайдеров. + +```bash +opencode auth [command] +``` + +--- + +#### login + +opencode использует список провайдеров с [Models.dev](https://models.dev), поэтому вы можете использовать `opencode auth login` для настройки ключей API для любого поставщика, которого вы хотите использовать. Это хранится в `~/.local/share/opencode/auth.json`. + +```bash +opencode auth login +``` + +Когда opencode запускается, он загружает поставщиков из файла учетных данных. И если в ваших средах определены какие-либо ключи или файл `.env` в вашем проекте. + +--- + +#### list + +Перечисляет всех проверенных поставщиков, которые хранятся в файле учетных данных. + +```bash +opencode auth list +``` + +Или короткая версия. + +```bash +opencode auth ls +``` + +--- + +#### logout + +Выключает вас из провайдера, удаляя его из файла учетных данных. + +```bash +opencode auth logout +``` + +--- + +### github + +Управляйте агентом GitHub для автоматизации репозитория. + +```bash +opencode github [command] +``` + +--- + +#### install + +Установите агент GitHub в свой репозиторий. + +```bash +opencode github install +``` + +Это настроит необходимый рабочий процесс GitHub Actions и проведет вас через процесс настройки. [Подробнее](/docs/github). + +--- + +#### run + +Запустите агент GitHub. Обычно это используется в действиях GitHub. + +```bash +opencode github run +``` + +##### Флаги + +| Флаг | Описание | +| --------- | --------------------------------------------- | +| `--event` | Имитирующее событие GitHub для запуска агента | +| `--token` | Токен личного доступа GitHub | + +--- + +### mcp + +Управляйте серверами протокола контекста модели. + +```bash +opencode mcp [command] +``` + +--- + +#### add + +Добавьте сервер MCP в свою конфигурацию. + +```bash +opencode mcp add +``` + +Эта команда поможет вам добавить локальный или удаленный сервер MCP. + +--- + +#### list + +Перечислите все настроенные серверы MCP и состояние их подключения. + +```bash +opencode mcp list +``` + +Или используйте короткую версию. + +```bash +opencode mcp ls +``` + +--- + +#### auth + +Аутентификация с помощью сервера MCP с поддержкой OAuth. + +```bash +opencode mcp auth [name] +``` + +Если вы не укажете имя сервера, вам будет предложено выбрать один из доступных серверов с поддержкой OAuth. + +Вы также можете перечислить серверы с поддержкой OAuth и их статус аутентификации. + +```bash +opencode mcp auth list +``` + +Или используйте короткую версию. + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +Удалите учетные данные OAuth для сервера MCP. + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +Отладка проблем с подключением OAuth для сервера MCP. + +```bash +opencode mcp debug +``` + +--- + +### models + +Перечислите все доступные модели от настроенных поставщиков. + +```bash +opencode models [provider] +``` + +Эта команда отображает все модели, доступные у настроенных вами поставщиков, в формате `provider/model`. + +Это полезно для определения точного названия модели, которое будет использоваться в [вашем config](/docs/config/). + +При желании вы можете передать идентификатор поставщика, чтобы фильтровать модели по этому поставщику. + +```bash +opencode models anthropic +``` + +#### Флаги + +| Флаг | Описание | +| ----------- | --------------------------------------------------------------------------------- | +| `--refresh` | Обновите кеш моделей на сайте models.dev. | +| `--verbose` | Используйте более подробный вывод модели (включая метаданные, такие как затраты). | + +Используйте флаг `--refresh` для обновления списка кэшированных моделей. Это полезно, когда к поставщику добавлены новые модели и вы хотите увидеть их в opencode. + +```bash +opencode models --refresh +``` + +--- + +### run + +Запустите opencode в неинтерактивном режиме, передав приглашение напрямую. + +```bash +opencode run [message..] +``` + +Это полезно для создания сценариев, автоматизации или когда вам нужен быстрый ответ без запуска полного TUI. Например. + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +Вы также можете подключиться к работающему экземпляру `opencode serve`, чтобы избежать холодной загрузки сервера MCP при каждом запуске: + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### Флаги + +| Флаг | Короткий | Описание | +| ------------ | -------- | -------------------------------------------------------------------------------- | +| `--command` | | Команда для запуска, используйте сообщение для аргументов | +| `--continue` | `-c` | Продолжить последний сеанс | +| `--session` | `-s` | Идентификатор сеанса для продолжения | +| `--fork` | | Разветвить сеанс при продолжении (используйте с `--continue` или `--session`) | +| `--share` | | Поделиться сеансом | +| `--model` | `-m` | Модель для использования в виде поставщика/модели. | +| `--agent` | | Агент для использования | +| `--file` | `-f` | Файл(ы) для прикрепления к сообщению | +| `--format` | | Формат: по умолчанию (отформатированный) или json (необработанные события JSON). | +| `--title` | | Название сеанса (использует усеченное приглашение, если значение не указано) | +| `--attach` | | Подключитесь к работающему серверу opencode (например, http://localhost:4096) | +| `--port` | | Порт локального сервера (по умолчанию случайный порт) | + +--- + +### serve + +Запустите автономный сервер opencode для доступа к API. Полный HTTP-интерфейс можно найти в [server docs](/docs/server). + +```bash +opencode serve +``` + +При этом запускается HTTP-сервер, который обеспечивает доступ API к функциям opencode без интерфейса TUI. Установите `OPENCODE_SERVER_PASSWORD`, чтобы включить базовую аутентификацию HTTP (имя пользователя по умолчанию — `opencode`). + +#### Флаги + +| Флаг | Описание | +| ------------ | ------------------------------------------------------------- | +| `--port` | Порт для прослушивания | +| `--hostname` | Имя хоста для прослушивания | +| `--mdns` | Включить обнаружение mDNS | +| `--cors` | Дополнительные источники браузера, позволяющие разрешить CORS | + +--- + +### session + +Управляйте сессиями opencode. + +```bash +opencode session [command] +``` + +--- + +#### list + +Перечислите все сеансы opencode. + +```bash +opencode session list +``` + +##### Флаги + +| Флаг | Короткий | Описание | +| ------------- | -------- | ----------------------------------------- | +| `--max-count` | `-n` | Ограничить N последних сеансов. | +| `--format` | | Формат вывода: таблица или json (таблица) | + +--- + +### stats + +Покажите статистику использования токенов и затрат для ваших сеансов opencode. + +```bash +opencode stats +``` + +#### Флаги + +| Флаг | Описание | +| ----------- | ---------------------------------------------------------------------------------------------------------- | +| `--days` | Показать статистику за последние N дней (все время) | +| `--tools` | Количество инструментов для отображения (все) | +| `--models` | Показать разбивку по использованию модели (по умолчанию скрыто). Передайте номер, чтобы показать верхнюю N | +| `--project` | Фильтровать по проекту (все проекты, пустая строка: текущий проект) | + +--- + +### export + +Экспортируйте данные сеанса в формате JSON. + +```bash +opencode export [sessionID] +``` + +Если вы не укажете идентификатор сеанса, вам будет предложено выбрать один из доступных сеансов. + +--- + +### import + +Импортируйте данные сеанса из файла JSON или URL-адреса общего ресурса opencode. + +```bash +opencode import +``` + +Вы можете импортировать из локального файла или URL-адреса общего ресурса opencode. + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +Запустите автономный сервер opencode с веб-интерфейсом. + +```bash +opencode web +``` + +При этом запускается HTTP-сервер и открывается веб-браузер для доступа к opencode через веб-интерфейс. Установите `OPENCODE_SERVER_PASSWORD`, чтобы включить базовую аутентификацию HTTP (имя пользователя по умолчанию — `opencode`). + +#### Флаги + +| Флаг | Описание | +| ------------ | ------------------------------------------------------------- | +| `--port` | Порт для прослушивания | +| `--hostname` | Имя хоста для прослушивания | +| `--mdns` | Включить обнаружение mDNS | +| `--cors` | Дополнительные источники браузера, позволяющие разрешить CORS | + +--- + +### acp + +Запустите сервер ACP (агент-клиентский протокол). + +```bash +opencode acp +``` + +Эта команда запускает сервер ACP, который обменивается данными через stdin/stdout с использованием nd-JSON. + +#### Флаги + +| Флаг | Описание | +| ------------ | --------------------------- | +| `--cwd` | Рабочий каталог | +| `--port` | Порт для прослушивания | +| `--hostname` | Имя хоста для прослушивания | + +--- + +### uninstall + +Удалите opencode и удалите все связанные файлы. + +```bash +opencode uninstall +``` + +#### Флаги + +| Флаг | Короткий | Описание | +| --------------- | -------- | ------------------------------------------ | +| `--keep-config` | `-c` | Сохраняйте файлы конфигурации | +| `--keep-data` | `-d` | Храните данные сеанса и снимки | +| `--dry-run` | | Покажите, что было бы удалено без удаления | +| `--force` | `-f` | Пропустить запросы подтверждения | + +--- + +### upgrade + +Обновляет opencode до последней версии или определенной версии. + +```bash +opencode upgrade [target] +``` + +Чтобы обновиться до последней версии. + +```bash +opencode upgrade +``` + +Для обновления до определенной версии. + +```bash +opencode upgrade v0.1.48 +``` + +#### Флаги + +| Флаг | Короткий | Описание | +| ---------- | -------- | --------------------------------------------------------- | +| `--method` | `-m` | Используемый метод установки: local, npm, pnpm, bun, brew | + +--- + +## Глобальные флаги + +CLI opencode принимает следующие глобальные флаги. + +| Флаг | Короткий | Описание | +| -------------- | -------- | ------------------------------------------ | +| `--help` | `-h` | Отобразить справку | +| `--version` | `-v` | Распечатать номер версии | +| `--print-logs` | | Печать журналов в stderr | +| `--log-level` | | Уровень журнала (DEBUG, INFO, WARN, ERROR) | + +--- + +## Переменные среды + +opencode можно настроить с помощью переменных среды. + +| Переменная | Тип | Описание | +| ------------------------------------- | ------------------- | -------------------------------------------------------------------------------- | +| `OPENCODE_AUTO_SHARE` | логическое значение | Автоматически делиться сеансами | +| `OPENCODE_GIT_BASH_PATH` | строка | Путь к исполняемому файлу Git Bash в Windows | +| `OPENCODE_CONFIG` | строка | Путь к файлу конфигурации | +| `OPENCODE_CONFIG_DIR` | строка | Путь к каталогу конфигурации | +| `OPENCODE_CONFIG_CONTENT` | строка | Встроенное содержимое конфигурации json | +| `OPENCODE_DISABLE_AUTOUPDATE` | логическое значение | Отключить автоматическую проверку обновлений | +| `OPENCODE_DISABLE_PRUNE` | логическое значение | Отключить удаление старых данных | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | логическое значение | Отключить автоматическое обновление заголовка терминала | +| `OPENCODE_PERMISSION` | строка | Встроенная конфигурация разрешений json | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | логическое значение | Отключить плагины по умолчанию | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | логическое значение | Отключить автоматическую загрузку LSP-сервера | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | логическое значение | Включить экспериментальные модели | +| `OPENCODE_DISABLE_AUTOCOMPACT` | логическое значение | Отключить автоматическое сжатие контекста | +| `OPENCODE_DISABLE_CLAUDE_CODE` | логическое значение | Отключить чтение из `.claude` (подсказка + навыки) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | логическое значение | Отключить чтение `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | логическое значение | Отключить загрузку `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | логическое значение | Отключить получение моделей из удаленных источников | +| `OPENCODE_FAKE_VCS` | строка | Поддельный поставщик VCS для целей тестирования | +| `OPENCODE_DISABLE_FILETIME_CHECK` | логическое значение | Отключить проверку времени файла для оптимизации | +| `OPENCODE_CLIENT` | строка | Идентификатор клиента (по умолчанию `cli`) | +| `OPENCODE_ENABLE_EXA` | логическое значение | Включить инструменты веб-поиска Exa | +| `OPENCODE_SERVER_PASSWORD` | строка | Включить базовую аутентификацию для `serve`/`web` | +| `OPENCODE_SERVER_USERNAME` | строка | Переопределить имя пользователя базовой аутентификации (по умолчанию `opencode`) | +| `OPENCODE_MODELS_URL` | строка | Пользовательский URL-адрес для получения конфигурации модели | + +--- + +### Экспериментальные функции + +Эти переменные среды позволяют использовать экспериментальные функции, которые могут быть изменены или удалены. + +| Переменная | Тип | Описание | +| ----------------------------------------------- | ------------------- | ------------------------------------------------------ | +| `OPENCODE_EXPERIMENTAL` | логическое значение | Включить все экспериментальные функции | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | логическое значение | Включить обнаружение значков | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | логическое значение | Отключить копирование при выборе в TUI | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | число | Таймаут по умолчанию для команд bash в мс | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | число | Максимальное количество токенов вывода для ответов LLM | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | логическое значение | Включить просмотр файлов для всего каталога | +| `OPENCODE_EXPERIMENTAL_OXFMT` | логическое значение | Включить форматтер oxfmt | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | логическое значение | Включить экспериментальный инструмент LSP | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | логическое значение | Отключить просмотрщик файлов | +| `OPENCODE_EXPERIMENTAL_EXA` | логическое значение | Включить экспериментальные функции Exa | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | логическое значение | Включить экспериментальную проверку типа LSP | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | логическое значение | Включить экспериментальные функции Markdown | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | логическое значение | Включить режим плана | diff --git a/packages/web/src/content/docs/ru/commands.mdx b/packages/web/src/content/docs/ru/commands.mdx new file mode 100644 index 00000000000..447ef0f0dc6 --- /dev/null +++ b/packages/web/src/content/docs/ru/commands.mdx @@ -0,0 +1,323 @@ +--- +title: Команды +description: Создавайте собственные команды для повторяющихся задач. +--- + +Пользовательские команды позволяют указать подсказку, которую вы хотите запускать при выполнении этой команды в TUI. + +```bash frame="none" +/my-command +``` + +Пользовательские команды дополняют встроенные команды, такие как `/init`, `/undo`, `/redo`, `/share`, `/help`. [Подробнее](/docs/tui#commands). + +--- + +## Создание файлов команд + +Создайте Markdown файлы в каталоге `commands/` для определения пользовательских команд. + +Создайте `.opencode/commands/test.md`: + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Фронтматтер (frontmatter) определяет свойства команды. Содержимое становится шаблоном. + +Используйте команду, набрав `/`, а затем имя команды. + +```bash frame="none" +"/test" +``` + +--- + +## Настройка + +Вы можете добавлять собственные команды через конфигурацию opencode или создав файлы Markdown в каталоге `commands/`. + +--- + +### JSON + +Используйте опцию `command` в вашем opencode [config](/docs/config): + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Теперь вы можете запустить эту команду в TUI: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +Вы также можете определять команды, используя Markdown файлы. Поместите их в: + +- Глобальный: `~/.config/opencode/commands/` +- Для каждого проекта: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Имя Markdown файла становится именем команды. Например, `test.md` позволяет +вам запустить: + +```bash frame="none" +/test +``` + +--- + +## Настройка промпта + +Подсказки для пользовательских команд поддерживают несколько специальных заполнителей и синтаксиса. + +--- + +### Аргументы + +Передавайте аргументы командам, используя заполнитель `$ARGUMENTS`. + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +Запустите команду с аргументами: + +```bash frame="none" +/component Button +``` + +И `$ARGUMENTS` будет заменен на `Button`. + +Вы также можете получить доступ к отдельным аргументам, используя позиционные параметры: + +- `$1` — первый аргумент +- `$2` — Второй аргумент +- `$3` — Третий аргумент +- И так далее... + +Например: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +Запустите команду: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +Это заменяет: + +- `$1` с `config.json` +- `$2` с `src` +- `$3` с `{ "key": "value" }` + +--- + +### Вывод shell + +Используйте _!`command`_, чтобы ввести вывод команды bash](/docs/tui#bash-commands) в приглашение. + +Например, чтобы создать пользовательскую команду, которая анализирует тестовое покрытие: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +Или просмотреть последние изменения: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +Команды выполняются в корневом каталоге вашего проекта, и их вывод становится частью приглашения. + +--- + +### Ссылки на файлы + +Включите файлы в свою команду, используя `@`, за которым следует имя файла. + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +Содержимое файла автоматически включается в приглашение. + +--- + +## Параметры + +Рассмотрим варианты конфигурации подробнее. + +--- + +### Template + +Параметр `template` определяет приглашение, которое будет отправлено в LLM при выполнении команды. + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +Это **обязательный** параметр конфигурации. + +--- + +### Описание + +Используйте опцию `description`, чтобы предоставить краткое описание того, что делает команда. + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +Это отображается в виде описания в TUI при вводе команды. + +--- + +### Агент + +Используйте конфигурацию `agent`, чтобы дополнительно указать, какой [агент](/docs/agents) должен выполнить эту команду. +Если это [subagent](/docs/agents/#subagents), команда по умолчанию инициирует вызов субагента. +Чтобы отключить это поведение, установите для `subtask` значение `false`. + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +Это **необязательный** параметр конфигурации. Если не указано, по умолчанию используется текущий агент. + +--- + +### Subtask + +Используйте логическое значение `subtask`, чтобы заставить команду инициировать вызов [subagent](/docs/agents/#subagents). +Это полезно, если вы хотите, чтобы команда не загрязняла ваш основной контекст и **заставляла** агента действовать как субагент. +даже если для `mode` установлено значение `primary` в конфигурации [agent](/docs/agents). + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +Это **необязательный** параметр конфигурации. + +--- + +### Модель + +Используйте конфигурацию `model`, чтобы переопределить модель по умолчанию для этой команды. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Это **необязательный** параметр конфигурации. + +--- + +## Встроенные команды + +opencode включает несколько встроенных команд, таких как `/init`, `/undo`, `/redo`, `/share`, `/help`; [подробнее](/docs/tui#commands). + +:::note +Пользовательские команды могут переопределять встроенные команды. +::: + +Если вы определите пользовательскую команду с тем же именем, она переопределит встроенную команду. diff --git a/packages/web/src/content/docs/ru/config.mdx b/packages/web/src/content/docs/ru/config.mdx new file mode 100644 index 00000000000..14af31cfd76 --- /dev/null +++ b/packages/web/src/content/docs/ru/config.mdx @@ -0,0 +1,681 @@ +--- +title: Конфигурация +description: Использование конфигурации opencode JSON. +--- + +Вы можете настроить opencode, используя файл конфигурации JSON. + +--- + +## Формат + +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, +} +``` + +--- + +## Расположение + +Вы можете разместить свою конфигурацию в нескольких разных местах, и у них есть +разный порядок старшинства. + +:::note +Файлы конфигурации **объединяются**, а не заменяются. +::: + +Файлы конфигурации объединяются, а не заменяются. Настройки из следующих мест конфигурации объединяются. Более поздние конфигурации переопределяют предыдущие только в случае конфликта ключей. Неконфликтные настройки из всех конфигов сохраняются. + +Например, если ваша глобальная конфигурация устанавливает `theme: "opencode"` и `autoupdate: true`, а конфигурация вашего проекта устанавливает `model: "anthropic/claude-sonnet-4-5"`, окончательная конфигурация будет включать все три параметра. + +--- + +### Порядок приоритета + +Источники конфигурации загружаются в следующем порядке (более поздние источники переопределяют более ранние): + +1. **Удаленная конфигурация** (от `.well-known/opencode`) – организационные настройки по умолчанию. +2. **Глобальная конфигурация** (`~/.config/opencode/opencode.json`) — настройки пользователя. +3. **Пользовательская конфигурация** (`OPENCODE_CONFIG` env var) – пользовательские переопределения +4. **Конфигурация проекта** (`opencode.json` в проекте) — настройки, специфичные для проекта. +5. **Каталоги `.opencode`** — агенты, команды, плагины +6. **Встроенная конфигурация** (`OPENCODE_CONFIG_CONTENT` env var) – переопределяет время выполнения + +Это означает, что конфигурации проекта могут переопределять глобальные настройки по умолчанию, а глобальные конфигурации могут переопределять настройки по умолчанию для удаленной организации. + +:::note +В каталогах `.opencode` и `~/.config/opencode` для подкаталогов используются **множественные имена**: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/` и `themes/`. Единственные имена (например, `agent/`) также поддерживаются для обратной совместимости. +::: + +--- + +### Удаленная + +Организации могут предоставить конфигурацию по умолчанию через конечную точку `.well-known/opencode`. Он извлекается автоматически при аутентификации у провайдера, который его поддерживает. + +Удаленная конфигурация загружается первой и служит базовым слоем. Все остальные источники конфигурации (глобальные, проектные) могут переопределить эти значения по умолчанию. + +Например, если ваша организация предоставляет серверы MCP, которые по умолчанию отключены: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +Вы можете включить определенные серверы в локальной конфигурации: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### Глобальная + +Поместите глобальную конфигурацию opencode в `~/.config/opencode/opencode.json`. Используйте глобальную конфигурацию для общепользовательских настроек, таких как темы, поставщики или привязки клавиш. + +Глобальная конфигурация переопределяет настройки по умолчанию для удаленной организации. + +--- + +### Проектная + +Добавьте `opencode.json` в корень вашего проекта. Конфигурация проекта имеет наивысший приоритет среди стандартных файлов конфигурации — она переопределяет как глобальные, так и удаленные конфигурации. + +:::tip +Поместите конфигурацию конкретного проекта в корень вашего проекта. +::: + +Когда opencode запускается, он ищет файл конфигурации в текущем каталоге или переходит к ближайшему каталогу Git. + +Его также можно безопасно зарегистрировать в Git, и он использует ту же схему, что и глобальная. + +--- + +### Пользовательский путь + +Укажите собственный путь к файлу конфигурации, используя переменную среды `OPENCODE_CONFIG`. + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +Пользовательская конфигурация загружается между глобальными и проектными конфигурациями в порядке приоритета. + +--- + +### Пользовательский каталог + +Укажите пользовательский каталог конфигурации, используя переменную среды `OPENCODE_CONFIG_DIR`. В этом каталоге будет выполняться поиск агентов, команд, режимов и плагинов (аналогично стандартному каталогу `.opencode`), и он должен иметь ту же структуру. + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +Пользовательский каталог загружается после каталогов global config и `.opencode`, поэтому он **может переопределить** их настройки. + +--- + +## Схема + +Файл конфигурации имеет схему, определенную в [**`opencode.ai/config.json`**](https://opencode.ai/config.json). + +Ваш редактор должен иметь возможность проверять и автозаполнять данные на основе схемы. + +--- + +### TUI + +Вы можете настроить параметры TUI с помощью опции `tui`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +Доступные варианты: + +- `scroll_acceleration.enabled` — включить ускорение прокрутки в стиле MacOS. **Имеет приоритет над `scroll_speed`.** +- `scroll_speed` — пользовательский множитель скорости прокрутки (по умолчанию: `3`, минимум: `1`). Игнорируется, если `scroll_acceleration.enabled` равен `true`. +- `diff_style` — управление рендерингом различий. `"auto"` адаптируется к ширине terminal, `"stacked"` всегда отображает один столбец. + +[Подробнее об использовании TUI можно узнать здесь](/docs/tui). + +--- + +### Сервер + +Вы можете настроить параметры сервера для команд `opencode serve` и `opencode web` с помощью опции `server`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +Доступные варианты: + +- `port` — порт для прослушивания. +- `hostname` — имя хоста для прослушивания. Если `mdns` включен и имя хоста не задано, по умолчанию используется `0.0.0.0`. +- `mdns` — включить обнаружение службы mDNS. Это позволит другим устройствам в сети обнаружить ваш сервер opencode. +- `mdnsDomain` — собственное доменное имя для службы mDNS. По умолчанию `opencode.local`. Полезно для запуска нескольких экземпляров в одной сети. +- `cors` — дополнительные источники, позволяющие использовать CORS при использовании HTTP-сервера из браузерного клиента. Значения должны быть полными источниками (схема + хост + дополнительный порт), например `https://app.example.com`. + +[Подробнее о сервере можно узнать здесь](/docs/server). + +--- + +### Инструменты + +Вы можете управлять инструментами, которые LLM может использовать, с помощью опции `tools`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[Подробнее об инструментах можно узнать здесь](/docs/tools). + +--- + +### models + +Вы можете настроить поставщиков и модели, которые хотите использовать в своей конфигурации opencode, с помощью параметров `provider`, `model` и `small_model`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +Опция `small_model` настраивает отдельную модель для облегченных задач, таких как создание заголовков. По умолчанию opencode пытается использовать более дешевую модель, если она доступна у вашего провайдера, в противном случае он возвращается к вашей основной модели. + +Опции провайдера могут включать `timeout` и `setCacheKey`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` — таймаут запроса в миллисекундах (по умолчанию: 300000). Установите `false` для отключения. +- `setCacheKey` — убедитесь, что ключ кэша всегда установлен для назначенного поставщика. + +Вы также можете настроить [локальные модели](/docs/models#local). [Подробнее ](/docs/models). + +--- + +#### Параметры, зависящие от поставщика + +Некоторые поставщики поддерживают дополнительные параметры конфигурации помимо общих настроек `timeout` и `apiKey`. + +##### Amazon + +Amazon Bedrock поддерживает конфигурацию, специфичную для AWS: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` — регион AWS для Bedrock (по умолчанию переменная среды `AWS_REGION` или `us-east-1`) +- `profile` — именованный профиль AWS из `~/.aws/credentials` (по умолчанию переменная окружения `AWS_PROFILE`) +- `endpoint` — URL-адрес пользовательской конечной точки для конечных точек VPC. Это псевдоним общего параметра `baseURL`, использующий терминологию, специфичную для AWS. Если указаны оба параметра, `endpoint` имеет приоритет. + +:::note +Токены носителя (`AWS_BEARER_TOKEN_BEDROCK` или `/connect`) имеют приоритет над аутентификацией на основе профиля. Подробности см. в [приоритет аутентификации](/docs/providers#authentication-precedence). +::: + +[Подробнее о конфигурации Amazon Bedrock](/docs/providers#amazon-bedrock). + +--- + +### theme + +Вы можете настроить тему, которую хотите использовать, в конфигурации opencode с помощью опции `theme`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[Подробнее здесь](/docs/themes). + +--- + +### agent + +Вы можете настроить специализированные агенты для конкретных задач с помощью опции `agent`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +Вы также можете определить агентов, используя файлы Markdown в `~/.config/opencode/agents/` или `.opencode/agents/`. [Подробнее здесь](/docs/agents). + +--- + +### default_agent + +Вы можете установить агента по умолчанию, используя опцию `default_agent`. Это определяет, какой агент используется, если ни один из них не указан явно. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +Агент по умолчанию должен быть основным агентом (а не субагентом). Это может быть встроенный агент, например `"build"` или `"plan"`, или [пользовательский агент](/docs/agents), который вы определили. Если указанный агент не существует или является субагентом, opencode вернется к `"build"` с предупреждением. + +Этот параметр применяется ко всем интерфейсам: TUI, CLI (`opencode run`), настольному приложению и действию GitHub. + +--- + +### share + +Функцию [share](/docs/share) можно настроить с помощью опции `share`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +Принимает значения: + +- `"manual"` — разрешить общий доступ вручную с помощью команд (по умолчанию). +- `"auto"` — автоматически делиться новыми беседами. +- `"disabled"` — полностью отключить общий доступ + +По умолчанию общий доступ установлен в ручной режим, в котором вам необходимо явно делиться разговорами с помощью команды `/share`. + +--- + +### Команды + +Вы можете настроить собственные команды для повторяющихся задач с помощью опции `command`. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +Вы также можете определять команды, используя файлы Markdown в `~/.config/opencode/commands/` или `.opencode/commands/`. [Подробнее здесь](/docs/commands). + +--- + +### Сочетания клавиш + +Вы можете настроить привязки клавиш с помощью опции `keybinds`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[Подробнее здесь](/docs/keybinds). + +--- + +### Автообновление + +opencode автоматически загрузит все новые обновления при запуске. Вы можете отключить это с помощью опции `autoupdate`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +Если вы не хотите получать обновления, но хотите получать уведомления о появлении новой версии, установите для `autoupdate` значение `"notify"`. +Обратите внимание, что это работает только в том случае, если оно было установлено без использования менеджера пакетов, такого как Homebrew. + +--- + +### Форматтеры + +Вы можете настроить форматировщики кода с помощью опции `formatter`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[Подробнее о форматтерах можно узнать здесь](/docs/formatters). + +--- + +### permission + +По умолчанию opencode **разрешает все операции**, не требуя явного разрешения. Вы можете изменить это, используя опцию `permission`. + +Например, чтобы гарантировать, что инструменты `edit` и `bash` требуют одобрения пользователя: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[Подробнее о разрешениях можно узнать здесь](/docs/permissions). + +--- + +### compaction + +Вы можете управлять поведением сжатия контекста с помощью опции `compaction`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto` — автоматически сжимать сеанс при заполнении контекста (по умолчанию: `true`). +- `prune` — удалить старые выходные данные инструмента для сохранения токенов (по умолчанию: `true`). + +--- + +### watcher + +Вы можете настроить шаблоны игнорирования средства отслеживания файлов с помощью опции `watcher`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +Шаблоны соответствуют синтаксису glob. Используйте это, чтобы исключить зашумленные каталоги из просмотра файлов. + +--- + +### mcp + +Вы можете настроить серверы MCP, которые хотите использовать, с помощью опции `mcp`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[Подробнее здесь](/docs/mcp-servers). + +--- + +### Плагины + +[Плагины](/docs/plugins) расширяют opencode с помощью пользовательских инструментов, перехватчиков и интеграций. + +Поместите файлы плагина в `.opencode/plugins/` или `~/.config/opencode/plugins/`. Вы также можете загружать плагины из npm с помощью опции `plugin`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[Подробнее здесь](/docs/plugins). + +--- + +### instructions + +Вы можете настроить инструкции для используемой вами модели с помощью опции `instructions`. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Для этого требуется массив путей и шаблонов glob для файлов инструкций. [Подробнее о правилах читайте здесь](/docs/rules). + +--- + +### disabled_providers + +Вы можете отключить поставщиков, которые загружаются автоматически, с помощью опции `disabled_providers`. Это полезно, если вы хотите запретить загрузку определенных поставщиков, даже если их учетные данные доступны. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +`disabled_providers` имеет приоритет над `enabled_providers`. +::: + +Опция `disabled_providers` принимает массив идентификаторов поставщиков. Когда провайдер отключен: + +- Он не будет загружен, даже если установлены переменные среды. +- Он не будет загружен, даже если ключи API настроены с помощью команды `/connect`. +- Модели поставщика не появятся в списке выбора моделей. + +--- + +### enabled_providers + +Вы можете указать белый список поставщиков с помощью опции `enabled_providers`. Если этот параметр установлен, будут включены только указанные поставщики, а все остальные будут игнорироваться. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +Это полезно, если вы хотите ограничить opencode использованием только определенных поставщиков, а не отключать их по одному. + +:::note +`disabled_providers` имеет приоритет над `enabled_providers`. +::: + +Если поставщик указан как в `enabled_providers`, так и в `disabled_providers`, `disabled_providers` имеет приоритет для обратной совместимости. + +--- + +### Экспериментальные возможности + +Ключ `experimental` содержит параметры, находящиеся в активной разработке. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +Экспериментальные варианты не стабильны. Они могут быть изменены или удалены без предварительного уведомления. +::: + +--- + +## Переменные + +Вы можете использовать подстановку переменных в файлах конфигурации для ссылки на переменные среды и содержимое файлов. + +--- + +### Переменные окружения + +Используйте `{env:VARIABLE_NAME}` для замены переменных среды: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +Если переменная среды не установлена, она будет заменена пустой строкой. + +--- + +### Файлы + +Используйте `{file:path/to/file}` для замены содержимого файла: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +Пути к файлам могут быть: + +- Относительно каталога файла конфигурации +- Или абсолютные пути, начинающиеся с `/` или `~`. + +Они полезны для: + +- Хранение конфиденциальных данных, таких как ключи API, в отдельных файлах. +- Включая большие файлы инструкций, не загромождая вашу конфигурацию. +- Совместное использование общих фрагментов конфигурации в нескольких файлах конфигурации. diff --git a/packages/web/src/content/docs/ru/custom-tools.mdx b/packages/web/src/content/docs/ru/custom-tools.mdx new file mode 100644 index 00000000000..c487ee99585 --- /dev/null +++ b/packages/web/src/content/docs/ru/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: Пользовательские инструменты +description: Создавайте инструменты, которые LLM может вызывать в opencode. +--- + +Пользовательские инструменты — это создаваемые вами функции, которые LLM может вызывать во время разговоров. Они работают вместе со [встроенными инструментами ](/docs/tools) opencode, такими как `read`, `write` и `bash`. + +--- + +## Создание инструмента + +Инструменты определяются как файлы **TypeScript** или **JavaScript**. Однако определение инструмента может вызывать сценарии, написанные на **любом языке** — TypeScript или JavaScript используются только для самого определения инструмента. + +--- + +### Расположение + +Их можно определить: + +- Локально, поместив их в каталог `.opencode/tools/` вашего проекта. +- Или глобально, поместив их в `~/.config/opencode/tools/`. + +--- + +### Структура + +Самый простой способ создания инструментов — использовать помощник `tool()`, который обеспечивает безопасность типов и проверку. + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +**имя файла** становится **именем инструмента**. Вышеупомянутое создает инструмент `database`. + +--- + +#### Несколько инструментов в файле + +Вы также можете экспортировать несколько инструментов из одного файла. Каждый экспорт становится **отдельным инструментом** с именем **`_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +При этом создаются два инструмента: `math_add` и `math_multiply`. + +--- + +### Аргументы + +Вы можете использовать `tool.schema`, то есть просто [Zod](https://zod.dev), для определения типов аргументов. + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +Вы также можете импортировать [Zod](https://zod.dev) напрямую и вернуть простой объект: + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### Контекст + +Инструменты получают контекст текущего сеанса: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +Используйте `context.directory` для рабочего каталога сеанса. +Используйте `context.worktree` для корня рабочего дерева git. + +--- + +## Примеры + +### Инструмент на Python + +Вы можете писать свои инструменты на любом языке, который захотите. Вот пример сложения двух чисел с использованием Python. + +Сначала создайте инструмент как скрипт Python: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +Затем создайте определение инструмента, которое его вызывает: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +Здесь мы используем утилиту [`Bun.$`](https://bun.com/docs/runtime/shell) для запуска скрипта Python. diff --git a/packages/web/src/content/docs/ru/ecosystem.mdx b/packages/web/src/content/docs/ru/ecosystem.mdx new file mode 100644 index 00000000000..a278043611a --- /dev/null +++ b/packages/web/src/content/docs/ru/ecosystem.mdx @@ -0,0 +1,75 @@ +--- +title: Экосистема +description: Проекты и интеграции, созданные с помощью opencode. +--- + +Коллекция проектов сообщества, построенных на opencode. + +:::note +Хотите добавить свой проект, связанный с opencode, в этот список? Разместите PR. +::: + +Вы также можете посетить [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) и [opencode.cafe](https://opencode.cafe) — хаб, объединяющий экосистему и сообщество. + +--- + +## Плагины + +| Имя | Описание | +| --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | Автоматически запускайте сеансы opencode в изолированных песочницах Daytona с синхронизацией git и предварительным просмотром в реальном времени. | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | Автоматически внедрять заголовки сеансов Helicone для группировки запросов. | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | Автоматическое внедрение типов TypeScript/Svelte в файлы, считываемые с помощью инструментов поиска. | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | Используйте подписку ChatGPT Plus/Pro вместо кредитов API. | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | Используйте существующий план Gemini вместо выставления счетов через API. | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | Используйте бесплатные модели Antigravity вместо выставления счетов через API. | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Многоветвевая изоляция контейнеров разработки с мелкими клонами и автоматическим назначением портов. | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Плагин Google Antigravity OAuth с поддержкой поиска Google и более надежной обработкой API. | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Оптимизируйте использование токенов за счет сокращения выходных данных устаревших инструментов. | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Добавьте встроенную поддержку веб-поиска для поддерживаемых поставщиков в стиле Google. | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Позволяет агентам ИИ запускать фоновые процессы в PTY и отправлять им интерактивные данные. | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Инструкции для неинтерактивных shell-команд — предотвращают зависания из-за операций, зависящих от TTY. | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Отслеживайте использование opencode с помощью Wakatime | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Очистка таблиц Markdown, созданных LLM | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | Редактирование кода в 10 раз быстрее с помощью API Morph Fast Apply и маркеров отложенного редактирования. | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Фоновые агенты, встроенные инструменты LSP/AST/MCP, курируемые агенты, совместимость с Claude Code | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | Уведомления на рабочем столе и звуковые оповещения для сеансов opencode | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Уведомления на рабочем столе и звуковые оповещения о разрешениях, завершении и событиях ошибок. | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | Автоматическое именование сеансов Zellij на основе искусственного интеллекта на основе контекста opencode. | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Разрешить агентам opencode отложенную загрузку подсказок по требованию с обнаружением и внедрением навыков. | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Постоянная память между сеансами с использованием Supermemory | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Интерактивный обзор плана с визуальными аннотациями и возможностью совместного использования в частном или автономном режиме. | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Расширьте opencode/команды до мощной системы оркестровки с детальным управлением потоком данных. | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | Планируйте повторяющиеся задания с помощью launchd (Mac) или systemd (Linux) с синтаксисом cron. | +| [micode](https://github.com/vtemian/micode) | Структурированный мозговой штурм → План → Реализация рабочего процесса с непрерывностью сеанса | +| [octto](https://github.com/vtemian/octto) | Интерактивный пользовательский интерфейс браузера для мозгового штурма с помощью искусственного интеллекта с формами из нескольких вопросов | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | Фоновые агенты в стиле Claude Code с асинхронным делегированием и сохранением контекста. | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | Встроенные уведомления ОС для opencode — узнайте, когда задачи завершены | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | Комплексный пакет многоагентной оркестровки — 16 компонентов, одна установка | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | Рабочие деревья git с нулевым трением для opencode | + +--- + +## Проекты + +| Имя | Описание | +| ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Плагин Neovim для подсказок с поддержкой редактора, созданный на основе API | +| [portal](https://github.com/hosenur/portal) | Мобильный веб-интерфейс для opencode через Tailscale/VPN | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | Шаблон для создания плагинов opencode | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Интерфейс Neovim для opencode — агент кодирования искусственного интеллекта на базе terminal | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Поставщик Vercel AI SDK для использования opencode через @opencode-ai/sdk | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | Веб-приложение или настольное приложение и расширение VS Code для opencode | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Плагин Obsidian, встраивающий opencode в пользовательский интерфейс Obsidian. | +| [OpenWork](https://github.com/different-ai/openwork) | Альтернатива Claude Cowork с открытым исходным кодом на базе opencode. | +| [ocx](https://github.com/kdcokenny/ocx) | Менеджер расширений opencode с переносимыми изолированными профилями. | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | Настольное, веб-, мобильное и удаленное клиентское приложение для opencode | + +--- + +## Агенты + +| Имя | Описание | +| ----------------------------------------------------------------- | -------------------------------------------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | Модульные ИИ-агенты и команды для структурированной разработки | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | Конфигурации, подсказки, агенты и плагины для улучшения рабочих процессов. | diff --git a/packages/web/src/content/docs/ru/enterprise.mdx b/packages/web/src/content/docs/ru/enterprise.mdx new file mode 100644 index 00000000000..d5932e0e0c8 --- /dev/null +++ b/packages/web/src/content/docs/ru/enterprise.mdx @@ -0,0 +1,168 @@ +--- +title: Корпоративное использование +description: Безопасное использование opencode в вашей организации. +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +opencode Enterprise предназначен для организаций, которые хотят быть уверены, что их код и данные никогда не покинут инфраструктуру. Это можно сделать с помощью централизованной конфигурации, которая интегрируется с вашим единым входом и внутренним шлюзом AI. + +:::note +opencode не хранит ваш код или контекстные данные. +::: + +Чтобы начать работу с opencode Enterprise: + +1. Проведите испытание внутри своей команды. +2. **Свяжитесь с нами**, чтобы обсудить цены и варианты внедрения. + +--- + +## Пробная версия + +opencode имеет открытый исходный код и не хранит ваш код или контекстные данные, поэтому ваши разработчики могут просто [приступить к работе](/docs/) и провести пробную версию. + +--- + +### Обработка данных + +**opencode не хранит ваш код или контекстные данные.** Вся обработка происходит локально или посредством прямых вызовов API к вашему провайдеру ИИ. + +Это означает, что пока вы используете поставщика, которому доверяете, или внутреннего +Шлюз AI позволяет безопасно использовать opencode. + +Единственное предостережение — это дополнительная функция `/share`. + +--- + +#### Обмен беседами + +Если пользователь включает функцию `/share`, разговор и связанные с ним данные отправляются в службу, которую мы используем для размещения этих общих страниц на opencode.ai. + +В настоящее время данные передаются через периферийную сеть нашей CDN и кэшируются на периферии рядом с вашими пользователями. + +Мы рекомендуем вам отключить эту функцию для пробной версии. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[Подробнее о совместном использовании](/docs/share). + +--- + +### Владение кодом + +**Вы являетесь владельцем всего кода, созданного opencode.** Никаких лицензионных ограничений или претензий на право собственности нет. + +--- + +## Цены + +Мы используем модель «на рабочее место» для opencode Enterprise. Если у вас есть собственный шлюз LLM, мы не взимаем плату за используемые токены. Для получения более подробной информации о ценах и вариантах реализации **свяжитесь с нами**. + +--- + +## Развертывание + +После завершения пробной версии и готовности использовать opencode на +вашей организации, вы можете **связаться с нами**, чтобы обсудить +цены и варианты реализации. + +--- + +### Центральная конфигурация + +Мы можем настроить opencode для использования единой центральной конфигурации для всей вашей организации. + +Эта централизованная конфигурация может интегрироваться с вашим поставщиком единого входа и гарантирует всем пользователям доступ только к вашему внутреннему шлюзу AI. + +--- + +### Интеграция SSO + +Через центральную конфигурацию opencode может интегрироваться с провайдером единого входа вашей организации для аутентификации. + +Это позволяет opencode получать учетные данные для вашего внутреннего шлюза AI через существующую систему управления идентификацией. + +--- + +### Внутренний шлюз AI + +Благодаря центральной конфигурации opencode также можно настроить на использование только вашего внутреннего шлюза AI. + +Вы также можете отключить всех других поставщиков ИИ, гарантируя, что все запросы будут проходить через утвержденную инфраструктуру вашей организации. + +--- + +### Самостоятельный хостинг + +Хотя мы рекомендуем отключить страницы общего доступа, чтобы гарантировать, что ваши данные никогда не покинут вашу организацию, мы также можем помочь вам самостоятельно разместить их в вашей инфраструктуре. + +В настоящее время это находится в нашей дорожной карте. Если вы заинтересованы, **дайте нам знать**. + +--- + +## Часто задаваемые вопросы + +

+Что такое opencode Enterprise? + +opencode Enterprise предназначен для организаций, которые хотят быть уверены, что их код и данные никогда не покинут инфраструктуру. Это можно сделать с помощью централизованной конфигурации, которая интегрируется с вашим единым входом и внутренним шлюзом AI. + +
+ +
+Как начать работу с opencode Enterprise? + +Просто начните с внутреннего испытания со своей командой. opencode по умолчанию не сохраняет ваш код или контекстные данные, что упрощает начало работы. + +Затем **свяжитесь с нами**, чтобы обсудить цены и варианты внедрения. + +
+ +
+Как работает корпоративное ценообразование? + +Мы предлагаем корпоративные цены за рабочее место. Если у вас есть собственный шлюз LLM, мы не взимаем плату за используемые токены. Для получения более подробной информации **свяжитесь с нами**, чтобы получить индивидуальное предложение, соответствующее потребностям вашей организации. + +
+ +
+Защищены ли мои данные с помощью opencode Enterprise? + +Да. opencode не хранит ваш код или контекстные данные. Вся обработка происходит локально или посредством прямых вызовов API вашего провайдера ИИ. Благодаря централизованной настройке и интеграции единого входа ваши данные остаются в безопасности в инфраструктуре вашей организации. + +
+ +
+Можем ли мы использовать собственный частный реестр NPM? + +opencode поддерживает частные реестры npm посредством встроенной поддержки файлов `.npmrc` Bun. Если ваша организация использует частный реестр, такой как JFrog Artifactory, Nexus или аналогичный, убедитесь, что разработчики прошли аутентификацию перед запуском opencode. + +Чтобы настроить аутентификацию с помощью вашего частного реестра: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +При этом создается `~/.npmrc` с данными аутентификации. opencode автоматически подхватит его. + +:::caution +Перед запуском opencode вы должны войти в частный реестр. +::: + +Альтернативно вы можете вручную настроить файл `.npmrc`: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +Разработчики должны войти в частный реестр перед запуском opencode, чтобы гарантировать возможность установки пакетов из корпоративного реестра. + +
diff --git a/packages/web/src/content/docs/ru/formatters.mdx b/packages/web/src/content/docs/ru/formatters.mdx new file mode 100644 index 00000000000..8712e39c63c --- /dev/null +++ b/packages/web/src/content/docs/ru/formatters.mdx @@ -0,0 +1,118 @@ +--- +title: Форматтеры +description: opencode использует средства форматирования, специфичные для языка. +--- + +opencode автоматически форматирует файлы после их записи или редактирования с использованием средств форматирования для конкретного языка. Это гарантирует, что создаваемый код будет соответствовать стилям кода вашего проекта. + +--- + +## Встроенные + +opencode поставляется с несколькими встроенными форматировщиками для популярных языков и платформ. Ниже приведен список форматтеров, поддерживаемых расширений файлов, а также необходимых команд или параметров конфигурации. + +| Formatter | Расширения | Требования | +| -------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | +| gofmt | .go | Доступна команда `gofmt` | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | Доступна команда `mix` | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml и [подробнее](https://prettier.io/docs/en/index.html) | Зависимость `prettier` в `package.json` | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml и [подробнее](https://biomejs.dev/) | Конфигурационный файл `biome.json(c)` | +| zig | .zig, .zon | Доступна команда `zig` | +| clang-format | .c, .cpp, .h, .hpp, .ino и [подробнее](https://clang.llvm.org/docs/ClangFormat.html) | Конфигурационный файл `.clang-format` | +| ktlint | .kt, .kts | Доступна команда `ktlint` | +| ruff | .py, .pyi | Команда `ruff` доступна в конфигурации | +| rustfmt | .rs | Доступна команда `rustfmt` | +| cargofmt | .rs | Доступна команда `cargo fmt` | +| uv | .py, .pyi | Доступна команда `uv` | +| rubocop | .rb, .rake, .gemspec, .ru | Доступна команда `rubocop` | +| standardrb | .rb, .rake, .gemspec, .ru | Доступна команда `standardrb` | +| htmlbeautifier | .erb, .html.erb | Доступна команда `htmlbeautifier` | +| air | .R | Доступна команда `air` | +| dart | .dart | Доступна команда `dart` | +| ocamlformat | .ml, .mli | Доступна команда `ocamlformat` и файл конфигурации `.ocamlformat`. | +| terraform | .tf, .tfvars | Доступна команда `terraform` | +| gleam | .gleam | Доступна команда `gleam` | +| nixfmt | .nix | Доступна команда `nixfmt` | +| shfmt | .sh, .bash | Доступна команда `shfmt` | +| pint | .php | Зависимость `laravel/pint` в `composer.json` | +| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | Зависимость `oxfmt` в `package.json` и [экспериментальный флаг переменной окружения](/docs/cli/#experimental) | +| ormolu | .hs | Доступна команда `ormolu` | + +Поэтому, если ваш проект имеет `prettier` в вашем `package.json`, opencode автоматически будет использовать его. + +--- + +## Настройка + +Вы можете настроить форматтеры через раздел `formatter` в конфигурации opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +Каждая конфигурация форматтера поддерживает следующее: + +| Свойство | Тип | Описание | +| ------------- | -------- | ----------------------------------------------------------------------------------- | +| `disabled` | boolean | Установите для этого параметра значение `true`, чтобы отключить форматтер. | +| `command` | string[] | Команда для форматирования | +| `environment` | объект | Переменные среды, которые необходимо установить при запуске средства форматирования | +| `extensions` | string[] | Расширения файлов, которые должен обрабатывать этот форматтер | + +Давайте посмотрим на несколько примеров. + +--- + +### Отключение форматтеров + +Чтобы глобально отключить **все** средства форматирования, установите для `formatter` значение `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +Чтобы отключить **конкретный** форматтер, установите для `disabled` значение `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### Пользовательские форматтеры + +Вы можете переопределить встроенные средства форматирования или добавить новые, указав команду, переменные среды и расширения файлов: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +Заполнитель **`$FILE`** в команде будет заменен путем к форматируемому файлу. diff --git a/packages/web/src/content/docs/ru/github.mdx b/packages/web/src/content/docs/ru/github.mdx new file mode 100644 index 00000000000..131d4f66ddf --- /dev/null +++ b/packages/web/src/content/docs/ru/github.mdx @@ -0,0 +1,321 @@ +--- +title: GitHub +description: Используйте opencode в задачах и пул-реквестах GitHub. +--- + +opencode интегрируется с вашим рабочим процессом GitHub. Упомяните `/opencode` или `/oc` в своем комментарии, и opencode выполнит задачи в вашем средстве выполнения действий GitHub. + +--- + +## Возможности + +- **Триаж задач (Issue Triage)**. Попросите opencode разобраться в проблеме и объяснить ее вам. +- **Исправление и реализация**. Попросите opencode исправить проблему или реализовать функцию. Он будет работать в новой ветке и создаст PR со всеми изменениями. +- **Безопасность**: opencode запускается внутри ваших GitHub Runners. + +--- + +## Установка + +Запустите следующую команду в проекте, который находится в репозитории GitHub: + +```bash +opencode github install +``` + +Это поможет вам установить приложение GitHub, создать рабочий процесс и настроить secrets (секреты). + +--- + +### Ручная настройка + +Или вы можете настроить его вручную. + +1. **Установите приложение GitHub** + + Перейдите на [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). Убедитесь, что он установлен в целевом репозитории. + +2. **Добавьте рабочий процесс** + + Добавьте следующий файл рабочего процесса в `.github/workflows/opencode.yml` в своем репозитории. Обязательно установите соответствующий `model` и необходимые ключи API в `env`. + + ```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx + ``` + +3. **Храните ключи API в секрете** + + В **настройках** вашей организации или проекта разверните **Секреты и переменные** слева и выберите **Действия**. И добавьте необходимые ключи API. + +--- + +## Настройка + +- `model`: модель для использования с opencode. Принимает формат `provider/model`. Это **обязательно**. +- `agent`: используемый агент. Должен быть основным агентом. Возвращается к `default_agent` из конфигурации или к `"build"`, если не найден. +- `share`: следует ли предоставлять общий доступ к сеансу opencode. По умолчанию **true** для общедоступных репозиториев. +- `prompt`: дополнительный настраиваемый запрос для переопределения поведения по умолчанию. Используйте это, чтобы настроить обработку запросов opencode. +- `token`: дополнительный токен доступа GitHub для выполнения таких операций, как создание комментариев, фиксация изменений и открытие запросов на включение. По умолчанию opencode использует токен доступа к установке из приложения opencode GitHub, поэтому фиксации, комментарии и запросы на включение отображаются как исходящие из приложения. + + Кроме того, вы можете использовать [встроенный `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) средства запуска действий GitHub без установки приложения opencode GitHub. Просто не забудьте предоставить необходимые разрешения в вашем рабочем процессе: + + ```yaml + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + ``` + + Вы также можете использовать [токены личного доступа](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT), если предпочитаете. + +--- + +## Поддерживаемые события + +opencode может быть запущен следующими событиями GitHub: + +| Тип события | Инициировано | Подробности | +| ----------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| `issue_comment` | Комментарий к проблеме или PR | Упомяните `/opencode` или `/oc` в своем комментарии. opencode считывает контекст и может создавать ветки, открывать PR или отвечать. | +| `pull_request_review_comment` | Комментируйте конкретные строки кода в PR. | Упоминайте `/opencode` или `/oc` при просмотре кода. opencode получает путь к файлу, номера строк и контекст сравнения. | +| `issues` | Issue открыт или изменен | Автоматически запускать opencode при создании или изменении проблем. Требуется ввод `prompt`. | +| `pull_request` | PR открыт или обновлен | Автоматически запускать opencode при открытии, синхронизации или повторном открытии PR. Полезно для автоматических обзоров. | +| `schedule` | Расписание на основе Cron | Запускайте opencode по расписанию. Требуется ввод `prompt`. Вывод поступает в журналы и PR (комментариев нет). | +| `workflow_dispatch` | Ручной триггер из пользовательского интерфейса GitHub | Запускайте opencode по требованию на вкладке «Действия». Требуется ввод `prompt`. Вывод идет в логи и PR. | + +### Пример: Расписание + +Запускайте opencode по расписанию для выполнения автоматизированных задач: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +Для запланированных событий вход `prompt` **обязателен**, поскольку нет комментария, из которого можно было бы извлечь инструкции. Запланированные рабочие процессы выполняются без пользовательского контекста для проверки разрешений, поэтому рабочий процесс должен предоставлять `contents: write` и `pull-requests: write`, если вы ожидаете, что opencode будет создавать ветки или PR. + +--- + +### Пример: Pull Request + +Автоматически просматривать PR при их открытии или обновлении: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Если для событий `pull_request` не указан `prompt`, opencode по умолчанию проверяет запрос на включение. + +--- + +### Пример: Сортировка Issue + +Автоматически сортируйте новые проблемы. В этом примере фильтруется аккаунты, созданные более 30 дней назад, чтобы уменьшить количество спама: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +Для событий `issues` вход `prompt` **обязателен**, поскольку нет комментария, из которого можно было бы извлечь инструкции. + +--- + +## Пользовательские промпты + +Переопределите приглашение по умолчанию, чтобы настроить поведение opencode для вашего рабочего процесса. + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Это полезно для обеспечения соблюдения конкретных критериев проверки, стандартов кодирования или приоритетных областей, имеющих отношение к вашему проекту. + +--- + +## Примеры + +Вот несколько примеров того, как вы можете использовать opencode в GitHub. + +- **Объяснение проблемы** + + Добавьте этот комментарий в выпуск GitHub. + + ``` + /opencode explain this issue + ``` + + opencode прочитает всю ветку, включая все комментарии, и ответит с четким объяснением. + +- **Исправление проблемы** + + В выпуске GitHub скажите: + + ``` + /opencode fix this + ``` + + А opencode создаст новую ветку, внедрит изменения и откроет PR с изменениями. + +- **Проверка Pull Request и внесение изменений** + + Оставьте следующий комментарий к PR на GitHub. + + ``` + Delete the attachment from S3 when the note is removed /oc + ``` + + opencode внедрит запрошенное изменение и зафиксирует его в том же PR. + +- **Проверка отдельных строк кода** + + Оставляйте комментарии непосредственно к строкам кода на вкладке «Файлы» PR. opencode автоматически определяет файл, номера строк и контекст различий, чтобы предоставить точные ответы. + + ``` + [Comment on specific lines in Files tab] + /oc add error handling here + ``` + + При комментировании определенных строк opencode получает: + - Точный файл, который просматривается + - Конкретные строки кода + - Окружающий контекст различий + - Информация о номере строки + + Это позволяет выполнять более целевые запросы без необходимости вручную указывать пути к файлам или номера строк. diff --git a/packages/web/src/content/docs/ru/gitlab.mdx b/packages/web/src/content/docs/ru/gitlab.mdx new file mode 100644 index 00000000000..ad56e998bc7 --- /dev/null +++ b/packages/web/src/content/docs/ru/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: Используйте opencode в задачах GitLab и мерж-реквестах. +--- + +opencode интегрируется с вашим рабочим процессом GitLab через конвейер GitLab CI/CD или с GitLab Duo. + +В обоих случаях opencode будет работать на ваших программах GitLab. + +--- + +## GitLab + +opencode работает в обычном конвейере GitLab. Вы можете встроить его в конвейер как [CI-компонент](https://docs.gitlab.com/ee/ci/components/) + +Здесь мы используем созданный сообществом компонент CI/CD для opencode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### Функции + +- **Использовать пользовательскую конфигурацию для каждого задания**. Настройте opencode с помощью пользовательского каталога конфигурации, например `./config/#custom-directory`, чтобы включать или отключать функциональность для каждого вызова opencode. +- **Минимальная настройка**: компонент CI настраивает opencode в фоновом режиме, вам нужно только создать конфигурацию opencode и начальное приглашение. +- **Гибкость**: компонент CI поддерживает несколько входных данных для настройки его поведения. + +--- + +### Настройка + +1. Сохраните JSON аутентификации opencode как переменные среды CI типа файла в разделе **Настройки** > **CI/CD** > **Переменные**. Обязательно пометьте их как «Замаскированные и скрытые». +2. Добавьте следующее в файл `.gitlab-ci.yml`. + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +Дополнительные сведения и варианты использования см. в документации ](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) для этого компонента. + +--- + +## GitLab Duo + +opencode интегрируется с вашим рабочим процессом GitLab. +Упомяните `@opencode` в комментарии, и opencode выполнит задачи в вашем конвейере GitLab CI. + +--- + +### Функции + +- **Триаж задач (Issue Triage)**. Попросите opencode разобраться в проблеме и объяснить ее вам. +- **Исправление и реализация**. Попросите opencode исправить проблему или реализовать функцию. + Он создаст новую ветку и создаст мерж-реквест с изменениями. +- **Безопасность**: opencode работает на ваших программах GitLab. + +--- + +### Настройка + +opencode работает в вашем конвейере GitLab CI/CD. Вот что вам понадобится для его настройки: + +:::tip +Ознакомьтесь с [**документацией GitLab**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) для получения актуальных инструкций. +::: + +1. Настройте свою среду GitLab +2. Настройка CI/CD +3. Получите ключ API поставщика моделей ИИ +4. Создать учетную запись службы +5. Настройка переменных CI/CD +6. Создайте файл конфигурации потока, вот пример: + +
+ + Конфигурация потока + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +Подробные инструкции можно найти в [GitLab CLI agents docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/). + +--- + +### Примеры + +Вот несколько примеров того, как вы можете использовать opencode в GitLab. + +:::tip +Вы можете настроить использование триггерной фразы, отличной от `@opencode`. +::: + +- **Объяснение проблемы** + + Добавьте этот комментарий в issue GitLab. + + ``` + @opencode explain this issue + ``` + + opencode прочитает проблему и ответит с четким объяснением. + +- **Исправление проблемы** + + В issue GitLab напишите: + + ``` + @opencode fix this + ``` + + opencode создаст новую ветку, внедрит изменения и откроет мерж-реквест с изменениями. + +- **Проверка Merge Request** + + Оставьте следующий комментарий к мерж-реквесту GitLab. + + ``` + @opencode review this merge request + ``` + + opencode рассмотрит мерж-реквест и предоставит отзыв. diff --git a/packages/web/src/content/docs/ru/ide.mdx b/packages/web/src/content/docs/ru/ide.mdx new file mode 100644 index 00000000000..8691767e3d4 --- /dev/null +++ b/packages/web/src/content/docs/ru/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: Расширение opencode для VS Code, Cursor и других IDE. +--- + +opencode интегрируется с VS Code, Cursor или любой IDE, поддерживающей терминал. Просто запустите `opencode` в терминале, чтобы начать. + +--- + +## Использование + +- **Быстрый запуск**: используйте `Cmd+Esc` (Mac) или `Ctrl+Esc` (Windows/Linux), чтобы открыть opencode в разделенном представлении терминала, или сфокусируйтесь на существующем сеансе терминала, если он уже запущен. +- **Новый сеанс**: используйте `Cmd+Shift+Esc` (Mac) или `Ctrl+Shift+Esc` (Windows/Linux), чтобы начать новый сеанс терминала opencode, даже если он уже открыт. Вы также можете нажать кнопку opencode в пользовательском интерфейсе. +- **Осведомленность о контексте**: автоматически делитесь своим текущим выбором или вкладкой с помощью opencode. +- **Шорткаты ссылок на файлы**: Используйте `Cmd+Option+K` (Mac) или `Alt+Ctrl+K` (Linux/Windows) для вставки ссылок на файлы. Например, `@File#L37-42`. + +--- + +## Установка + +Чтобы установить opencode на VS Code и популярные форки, такие как Cursor, Windsurf, VSCodium: + +1. Откройте VS Code +2. Откройте встроенный терминал +3. Запустите `opencode` — расширение установится автоматически. + +С другой стороны, если вы хотите использовать собственную IDE при запуске `/editor` или `/export` из TUI, вам необходимо установить `export EDITOR="code --wait"`. [Подробнее](/docs/tui/#editor-setup). + +--- + +### Ручная установка + +Найдите **opencode** в магазине расширений и нажмите **Установить**. + +--- + +### Устранение неполадок + +Если расширение не устанавливается автоматически: + +- Убедитесь, что вы используете `opencode` во встроенном терминале. +- Убедитесь, что CLI для вашей IDE установлен: + - Для Code: команда `code`. + - Для Cursor: команда `cursor`. + - Для Windsurf: команда `windsurf`. + - Для VSCodium: команда `codium`. + - Если нет, запустите `Cmd+Shift+P` (Mac) или `Ctrl+Shift+P` (Windows/Linux) и найдите "Shell Command: Install 'code' command in PATH" (или эквивалент для вашей IDE). +- Убедитесь, что у VS Code есть разрешение на установку расширений. diff --git a/packages/web/src/content/docs/ru/index.mdx b/packages/web/src/content/docs/ru/index.mdx new file mode 100644 index 00000000000..b4a115250f4 --- /dev/null +++ b/packages/web/src/content/docs/ru/index.mdx @@ -0,0 +1,358 @@ +--- +title: Введение +description: Начните работу с opencode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**opencode**](/) — это агент кодирования искусственного интеллекта с открытым исходным кодом. Он доступен в виде интерфейса на базе терминала, настольного приложения или расширения IDE. + +![opencode TUI с темой opencode](../../../assets/lander/screenshot.png) + +Давайте начнем. + +--- + +#### Системные требования + +Чтобы использовать opencode в вашем терминале, вам понадобится: + +1. Современный эмулятор терминала, например: + - [WezTerm](https://wezterm.org), кроссплатформенный + - [Alacritty](https://alacritty.org), кроссплатформенный + - [Ghostty](https://ghostty.org), Linux и macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux и macOS + +2. Ключи API для поставщиков LLM, которых вы хотите использовать. + +--- + +## Установка + +Самый простой способ установить opencode — через сценарий установки. + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +Вы также можете установить его с помощью следующих команд: + +- **Использование Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **Использование Homebrew в macOS и Linux** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > Мы рекомендуем использовать tap opencode для получения самых последних версий. Официальная формула `brew install opencode` поддерживается командой Homebrew и обновляется реже. + +- **Использование Paru в Arch Linux** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[Рекомендуется: используйте WSL] +Для наилучшей работы в Windows мы рекомендуем использовать [Подсистема Windows для Linux (WSL)](/docs/windows-wsl). Он обеспечивает лучшую производительность и полную совместимость с функциями opencode. +::: + +- **Используя Chocolatey** + + ```bash + choco install opencode + ``` + +- **Использование Scoop** + + ```bash + scoop install opencode + ``` + +- **Использование NPM** + + ```bash + npm install -g opencode-ai + ``` + +- **Использование Mise** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **Использование Docker** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +В настоящее время добавляется поддержка установки opencode в Windows с помощью Bun. + +Вы также можете получить двоичный файл из файла [Releases](https://github.com/anomalyco/opencode/releases). + +--- + +## Настроить + +С opencode вы можете использовать любого поставщика LLM, настроив его ключи API. + +Если вы новичок в использовании поставщиков LLM, мы рекомендуем использовать [OpenCode Zen](/docs/zen). +Это тщательно подобранный список моделей, протестированных и проверенных opencode. +команда. + +1. Запустите команду `/connect` в TUI, выберите opencode и перейдите по адресу [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. Войдите в систему, добавьте свои платежные данные и скопируйте ключ API. + +3. Вставьте свой ключ API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +Альтернативно вы можете выбрать одного из других поставщиков. [Подробнее](/docs/providers#directory). + +--- + +## Инициализация + +Теперь, когда вы настроили поставщика, вы можете перейти к проекту, который +над которым вы хотите работать. + +```bash +cd /path/to/project +``` + +И запустите opencode. + +```bash +opencode +``` + +Затем инициализируйте opencode для проекта, выполнив следующую команду. + +```bash frame="none" +/init +``` + +Это позволит opencode проанализировать ваш проект и создать файл `AGENTS.md` в +корень проекта. + +:::tip +Вам следует зафиксировать файл `AGENTS.md` вашего проекта в Git. +::: + +Это помогает opencode понять структуру проекта и шаблоны кодирования. +использовал. + +--- + +## Использование + +Теперь вы готовы использовать opencode для работы над своим проектом. Не стесняйтесь спрашивать о чем угодно! + +Если вы новичок в использовании агента кодирования ИИ, вот несколько примеров, которые могут вам помочь. +помощь. + +--- + +### Задавайте вопросы + +Вы можете попросить opencode объяснить вам кодовую базу. + +:::tip +Используйте ключ `@` для нечеткого поиска файлов в проекте. +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +Это полезно, если есть часть кодовой базы, над которой вы не работали. + +--- + +### Добавление функций + +Вы можете попросить opencode добавить новые функции в ваш проект. Хотя мы сначала рекомендуем попросить его создать план. + +1. **Составьте план** + + opencode имеет _режим планирования_, который отключает возможность вносить изменения и + вместо этого предложите _как_ реализовать эту функцию. + + Переключитесь на него с помощью клавиши **Tab**. Вы увидите индикатор этого в правом нижнем углу. + + ```bash frame="none" title="Switch to Plan mode" + + ``` + + Теперь давайте опишем, что мы хотим от него. + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + Вы хотите предоставить opencode достаточно подробностей, чтобы понять, чего вы хотите. Это помогает + поговорить с ним так, как будто вы разговариваете с младшим разработчиком в своей команде. + + :::tip + Дайте opencode много контекста и примеров, чтобы помочь ему понять, что вы + хотеть. + ::: + +2. **Итерация плана** + + Как только он предоставит вам план, вы можете оставить ему отзыв или добавить более подробную информацию. + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + + :::tip + Перетащите изображения в терминал, чтобы добавить их в подсказку. + ::: + + opencode может сканировать любые изображения, которые вы ему предоставляете, и добавлять их в командную строку. Ты можешь + сделайте это, перетащив изображение в терминал. + +3. **Создайте функцию** + + Как только вы почувствуете себя комфортно с планом, вернитесь в _режим сборки_, + снова нажав клавишу **Tab**. + + ```bash frame="none" + + ``` + + И попросить его внести изменения. + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### Внесение изменений + +Для более простых изменений вы можете попросить opencode создать его напрямую. +без необходимости предварительного рассмотрения плана. + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +Вы хотите убедиться, что вы предоставляете достаточно деталей, чтобы opencode сделал правильный выбор. +изменения. + +--- + +### Отмена изменений + +Допустим, вы просите opencode внести некоторые изменения. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Но ты понимаешь, что это не то, чего ты хотел. Вы **можете отменить** изменения +с помощью команды `/undo`. + +```bash frame="none" +/undo +``` + +opencode теперь отменит внесенные вами изменения и покажет исходное сообщение. +снова. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +Отсюда вы можете настроить подсказку и попросить opencode повторить попытку. + +:::tip +Вы можете запустить `/undo` несколько раз, чтобы отменить несколько изменений. +::: + +Или вы **можете повторить** изменения с помощью команды `/redo`. + +```bash frame="none" +/redo +``` + +--- + +## Общий доступ + +Разговоры, которые вы ведете с opencode, можно [поделиться с вашим +команда](/docs/share). + +```bash frame="none" +/share +``` + +Это создаст ссылку на текущий разговор и скопирует ее в буфер обмена. + +:::note +По умолчанию общий доступ к беседам не предоставляется. +::: + +Вот [пример диалога](https://opencode.ai/s/4XP1fce5) с opencode. + +--- + +## Настроить + +И все! Теперь вы профессионал в использовании opencode. + +Чтобы создать свою собственную, мы рекомендуем [выбрать тему](/docs/themes), [настроить привязки клавиш](/docs/keybinds), [настроить средства форматирования кода](/docs/formatters), [создать собственные команды](/docs/commands) или поиграться с файлом [opencode config](/docs/config). diff --git a/packages/web/src/content/docs/ru/keybinds.mdx b/packages/web/src/content/docs/ru/keybinds.mdx new file mode 100644 index 00000000000..67d191ea2ca --- /dev/null +++ b/packages/web/src/content/docs/ru/keybinds.mdx @@ -0,0 +1,192 @@ +--- +title: Сочетания клавиш +description: Настройте свои сочетания клавиш. +--- + +opencode имеет список сочетаний клавиш, которые вы можете настроить через конфигурацию opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## Клавиша Leader + +opencode использует клавишу `leader` для большинства сочетаний клавиш. Это позволяет избежать конфликтов в вашем терминале. + +По умолчанию `ctrl+x` является клавишей leader, и для большинства действий требуется сначала нажать клавишу leader, а затем сочетание клавиш. Например, чтобы начать новый сеанс, сначала нажмите `ctrl+x`, а затем нажмите `n`. + +Вам не обязательно использовать клавишу leader для привязок клавиш, но мы рекомендуем это сделать. + +--- + +## Отключение привязки клавиш + +Вы можете отключить привязку клавиш, добавив ключ в свою конфигурацию со значением «none». + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## Шорткаты в Desktop-приложении + +Ввод приглашения настольного приложения opencode поддерживает распространенные сочетания клавиш в стиле Readline/Emacs для редактирования текста. Они встроены и в настоящее время не настраиваются через `opencode.json`. + +| Ярлык | Действие | +| -------- | ---------------------------------------------------- | +| `ctrl+a` | Перейти к началу текущей строки | +| `ctrl+e` | Перейти к концу текущей строки | +| `ctrl+b` | Переместить курсор на один символ назад | +| `ctrl+f` | Переместить курсор на один символ вперед | +| `alt+b` | Переместить курсор на одно слово назад | +| `alt+f` | Переместить курсор вперед на одно слово | +| `ctrl+d` | Удалить символ под курсором | +| `ctrl+k` | Удалить до конца строки | +| `ctrl+u` | Удалить до начала строки | +| `ctrl+w` | Удалить предыдущее слово | +| `alt+d` | Удалить следующее слово | +| `ctrl+t` | Поменять местами символы | +| `ctrl+g` | Отменить всплывающие окна/прервать выполнение ответа | + +--- + +## Shift+Enter + +Некоторые терминалы по умолчанию не отправляют клавиши-модификаторы с Enter. Возможно, вам придется настроить терминал на отправку `Shift+Enter` в качестве escape-последовательности. + +### Windows Terminal + +Откройте свой `settings.json` по адресу: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +Добавьте это в массив `actions` корневого уровня: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Добавьте это в массив `keybindings` корневого уровня: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Сохраните файл и перезапустите Windows Terminal или откройте новую вкладку. diff --git a/packages/web/src/content/docs/ru/lsp.mdx b/packages/web/src/content/docs/ru/lsp.mdx new file mode 100644 index 00000000000..0b63c9ea3bd --- /dev/null +++ b/packages/web/src/content/docs/ru/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: LSP-серверы +description: opencode интегрируется с вашими серверами LSP. +--- + +opencode интегрируется с вашим протоколом языкового сервера (LSP), чтобы помочь LLM взаимодействовать с вашей кодовой базой. Он использует диагностику для предоставления обратной связи LLM. + +--- + +## Встроенные + +opencode поставляется с несколькими встроенными LSP-серверами для популярных языков: + +| LSP Server | Extensions | Requirements | +| ------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| 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+)` установлен | +| 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-language-server | +| zls | .zig, .zon | `zig` команда доступна | + +Серверы LSP автоматически включаются при обнаружении одного из указанных выше расширений файлов и выполнении требований. + +:::note +Вы можете отключить автоматическую загрузку LSP-сервера, установив для переменной среды `OPENCODE_DISABLE_LSP_DOWNLOAD` значение `true`. +::: + +--- + +## Как это работает + +Когда opencode открывает файл, он: + +1. Проверяет расширение файла на всех включенных серверах LSP. +2. Запускает соответствующий сервер LSP, если он еще не запущен. + +--- + +## Настройка + +Вы можете настроить серверы LSP через раздел `lsp` в конфигурации opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +Каждый LSP-сервер поддерживает следующее: + +| Свойство | Тип | Описание | +| ---------------- | -------- | --------------------------------------------------------------------------- | +| `disabled` | boolean | Установите для этого параметра значение `true`, чтобы отключить сервер LSP. | +| `command` | string[] | Команда запуска LSP-сервера | +| `extensions` | string[] | Расширения файлов, которые должен обрабатывать этот сервер LSP | +| `env` | object | Переменные среды, которые нужно установить при запуске сервера | +| `initialization` | object | Параметры инициализации для отправки на сервер LSP | + +Давайте посмотрим на несколько примеров. + +--- + +### Переменные среды + +Используйте свойство `env` для установки переменных среды при запуске сервера LSP: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### Параметры инициализации + +Используйте свойство `initialization` для передачи параметров инициализации на LSP-сервер. Это настройки, специфичные для сервера, отправляемые во время запроса LSP `initialize`: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +Параметры инициализации зависят от сервера LSP. Проверьте документацию вашего LSP-сервера на наличие доступных опций. +::: + +--- + +### Отключение LSP-серверов + +Чтобы отключить **все** LSP-серверы глобально, установите для `lsp` значение `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +Чтобы отключить **конкретный** LSP-сервер, установите для `disabled` значение `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### Пользовательские LSP-серверы + +Вы можете добавить собственные LSP-серверы, указав команду и расширения файлов: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## Дополнительная информация + +### PHP Intelephense + +PHP Intelephense предлагает дополнительные функции через лицензионный ключ. Вы можете предоставить лицензионный ключ, поместив (только) ключ в текстовый файл по адресу: + +- В macOS/Linux: `$HOME/intelephense/license.txt` +- В Windows: `%USERPROFILE%/intelephense/license.txt` + +Файл должен содержать только лицензионный ключ без какого-либо дополнительного содержимого. diff --git a/packages/web/src/content/docs/ru/mcp-servers.mdx b/packages/web/src/content/docs/ru/mcp-servers.mdx new file mode 100644 index 00000000000..da88f413f9d --- /dev/null +++ b/packages/web/src/content/docs/ru/mcp-servers.mdx @@ -0,0 +1,511 @@ +--- +title: MCP-серверы +description: Добавьте локальные и удаленные инструменты MCP. +--- + +Вы можете добавить внешние инструменты в opencode, используя _Model Context Protocol_ или MCP. opencode поддерживает как локальные, так и удаленные серверы. + +После добавления инструменты MCP автоматически становятся доступными для LLM наряду со встроенными инструментами. + +--- + +#### Предостережения + +Когда вы используете сервер MCP, он добавляет контекст. Это может быстро сложиться, если у вас много инструментов. Поэтому мы рекомендуем быть осторожными с тем, какие серверы MCP вы используете. + +:::tip +Серверы MCP добавляются к вашему контексту, поэтому будьте осторожны с тем, какие из них вы включаете. +::: + +Некоторые серверы MCP, такие как сервер MCP GitHub, имеют тенденцию добавлять много токенов и могут легко превысить ограничение контекста. + +--- + +## Включение + +Вы можете определить серверы MCP в своем [opencode Config](https://opencode.ai/docs/config/) в разделе `mcp`. Добавьте каждому MCP уникальное имя. Вы можете обратиться к этому MCP по имени при запросе LLM. + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +Вы также можете отключить сервер, установив для `enabled` значение `false`. Это полезно, если вы хотите временно отключить сервер, не удаляя его из конфигурации. + +--- + +### Переопределение удаленных настроек по умолчанию + +Организации могут предоставлять серверы MCP по умолчанию через свою конечную точку `.well-known/opencode`. Эти серверы могут быть отключены по умолчанию, что позволяет пользователям выбирать те, которые им нужны. + +Чтобы включить определенный сервер из удаленной конфигурации вашей организации, добавьте его в локальную конфигурацию с помощью `enabled: true`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +Значения вашей локальной конфигурации переопределяют удаленные значения по умолчанию. Дополнительную информацию см. в [приоритете конфигурации](/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` | Строка | Да | Тип подключения к серверу MCP должен быть `"local"`. | +| `command` | Массив | Да | Команда и аргументы для запуска сервера MCP. | +| `environment` | Объект | | Переменные среды, которые необходимо установить при запуске сервера. | +| `enabled` | логическое значение | | Включите или отключите сервер MCP при запуске. | +| `timeout` | Число | | Тайм-аут в мс для получения инструментов с сервера MCP. По умолчанию 5000 (5 секунд). | + +--- + +## Удаленные + +Добавьте удаленные серверы MCP, установив для `type` значение `"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" + } + } + } +} +``` + +`url` — это URL-адрес удаленного сервера MCP, а с помощью параметра `headers` вы можете передать список заголовков. + +--- + +#### Параметры + +| Вариант | Тип | Обязательный | Описание | +| --------- | ------------------- | ------------ | ------------------------------------------------------------------------------------- | +| `type` | Строка | Да | Тип подключения к серверу MCP должен быть `"remote"`. | +| `url` | Строка | Да | URL-адрес удаленного сервера MCP. | +| `enabled` | логическое значение | | Включите или отключите сервер MCP при запуске. | +| `headers` | Объект | | Заголовки для отправки с запросом. | +| `oauth` | Объект | | Конфигурация аутентификации OAuth. См. раздел [OAuth](#oauth) ниже. | +| `timeout` | Число | | Тайм-аут в мс для получения инструментов с сервера MCP. По умолчанию 5000 (5 секунд). | + +--- + +## OAuth + +opencode автоматически обрабатывает аутентификацию OAuth для удаленных серверов MCP. Когда серверу требуется аутентификация, opencode: + +1. Обнаружьте ответ 401 и инициируйте поток OAuth. +2. Используйте **Динамическую регистрацию клиента (RFC 7591)**, если это поддерживается сервером. +3. Надежно храните токены для будущих запросов + +--- + +### Автоматически + +Для большинства серверов MCP с поддержкой OAuth не требуется никакой специальной настройки. Просто настройте удаленный сервер: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "my-oauth-server": { + "type": "remote", + "url": "https://mcp.example.com/mcp" + } + } +} +``` + +Если сервер требует аутентификации, opencode предложит вам пройти аутентификацию при первой попытке его использования. Если нет, вы можете [вручную запустить поток ](#authenticating) с помощью `opencode mcp auth `. + +--- + +### Предварительная регистрация + +Если у вас есть учетные данные клиента от поставщика сервера 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 + +Если вы хотите отключить автоматический OAuth для сервера (например, для серверов, которые вместо этого используют ключи API), установите для `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 или `false`, чтобы отключить автообнаружение OAuth. | +| `clientId` | String | OAuth client ID. Если не указан, будет выполнена динамическая регистрация клиента. | +| `clientSecret` | String | OAuth client secret, если этого требует сервер авторизации. | +| `scope` | String | OAuth scopes для запроса во время авторизации. | + +#### Отладка + +Если удаленный сервер 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, как и любым другим инструментом. + +--- + +### Глобально + +Это означает, что вы можете включать или отключать их глобально. + +```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 + } +} +``` + +Мы также можем использовать шаблон glob, чтобы отключить все соответствующие 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. В вашей [конфигурации агента](/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 + } + } + } +} +``` + +--- + +#### Glob-шаблоны + +Шаблон glob использует простые шаблоны подстановки регулярных выражений: + +- `*` соответствует нулю или более любого символа (например, `"my-mcp*"` соответствует `my-mcp_search`, `my-mcp_list` и т. д.). +- `?` соответствует ровно одному символу. +- Все остальные символы совпадают буквально + +:::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](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`. + +Добавьте `use context7` в запросы на использование сервера Context7 MCP. + +```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 + +Добавьте сервер MCP [Grep от Vercel](https://grep.app) для поиска по фрагментам кода на GitHub. + +```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/ru/models.mdx b/packages/web/src/content/docs/ru/models.mdx new file mode 100644 index 00000000000..a23a02f6a57 --- /dev/null +++ b/packages/web/src/content/docs/ru/models.mdx @@ -0,0 +1,223 @@ +--- +title: Модели +description: Настройка поставщика и модели LLM. +--- + +opencode использует [AI SDK](https://ai-sdk.dev/) и [Models.dev](https://models.dev) для поддержки **более 75 поставщиков LLM** и поддерживает запуск локальных моделей. + +--- + +## Провайдеры + +Большинство популярных провайдеров предварительно загружены по умолчанию. Если вы добавили учетные данные для поставщика с помощью команды `/connect`, они будут доступны при запуске opencode. + +Узнайте больше о [providers](/docs/providers). + +--- + +## Выберите модель + +После того, как вы настроили своего провайдера, вы можете выбрать нужную модель, введя: + +```bash frame="none" +/models +``` + +--- + +## Рекомендуемые модели + +Моделей очень много, новые выходят каждую неделю. + +:::tip +Рассмотрите возможность использования одной из моделей, которые мы рекомендуем. +::: + +Однако лишь немногие из них хороши как в генерации кода, так и в вызове инструментов. + +Вот несколько моделей, которые хорошо работают с opencode (в произвольном порядке). (Это не исчерпывающий список и не обязательно актуальный): + +- GPT 5.2 +- Кодекс GPT 5.1 +- Claude Opus 4.5 +- Claude Sonnet 4.5 +- MiniMax M2.1 +- Gemini 3 Pro + +--- + +## Установить значение по умолчанию + +Чтобы установить одну из них в качестве модели по умолчанию, вы можете установить ключ `model` в вашем +Конфигурация opencode. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +Здесь полный идентификатор `provider_id/model_id`. Например, если вы используете [OpenCode Zen](/docs/zen), вы должны использовать `opencode/gpt-5.1-codex` для кодекса GPT 5.1. + +Если вы настроили [пользовательский поставщик](/docs/providers#custom), `provider_id` — это ключ из части `provider` вашей конфигурации, а `model_id` — это ключ из `provider.models`. + +--- + +## Настройка моделей + +Вы можете глобально настроить параметры модели через файл config. + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +Здесь мы настраиваем глобальные параметры для двух встроенных моделей: `gpt-5` при доступе через поставщика `openai` и `claude-sonnet-4-20250514` при доступе через поставщика `anthropic`. +Названия встроенных поставщиков и моделей можно найти на сайте [Models.dev](https://models.dev). + +Вы также можете настроить эти параметры для любых используемых вами агентов. Конфигурация агента переопределяет любые глобальные параметры здесь. [Подробнее](/docs/agents/#additional). + +Вы также можете определить собственные варианты, расширяющие встроенные. Варианты позволяют настраивать разные параметры для одной и той же модели без создания повторяющихся записей: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## Варианты + +Многие модели поддерживают несколько вариантов с разными конфигурациями. opencode поставляется со встроенными вариантами по умолчанию для популярных провайдеров. + +### Встроенные варианты + +opencode поставляется с вариантами по умолчанию для многих провайдеров: + +**Anthropic**: + +- `high` — Бюджет рассуждений: высокий (по умолчанию) +- `max` — Максимальный бюджет рассуждений + +**OpenAI**: + +Зависит от модели, но примерно: + +- `none` — Без рассуждений. +- `minimal` — Минимальные усилия для рассуждений +- `low` — Низкие усилия для рассуждений. +- `medium` — Средние усилия для рассуждений. +- `high` — Высокие усилия для рассуждений. +- `xhigh` — Сверхвысокие усилия для рассуждений. + +**Google**: + +- `low` – меньший бюджет усилий/токенов. +- `high` — более высокий бюджет усилий/токенов + +:::tip +Этот список не является исчерпывающим. Многие другие провайдеры также имеют встроенные настройки по умолчанию. +::: + +### Пользовательские варианты + +Вы можете переопределить существующие варианты или добавить свои собственные: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### Переключение вариантов + +Используйте сочетание клавиш `variant_cycle` для быстрого переключения между вариантами. [Подробнее ](/docs/keybinds). + +--- + +## Загрузка моделей + +Когда opencode запускается, он проверяет модели в следующем порядке приоритета: + +1. CLI-флаг `--model` или `-m`. Формат тот же, что и в файле конфигурации: `provider_id/model_id`. + +2. Список моделей в конфигурации opencode. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + + Здесь используется формат `provider/model`. + +3. Последняя использованная модель. + +4. Первая модель, использующая внутренний приоритет. diff --git a/packages/web/src/content/docs/ru/modes.mdx b/packages/web/src/content/docs/ru/modes.mdx new file mode 100644 index 00000000000..c412d784267 --- /dev/null +++ b/packages/web/src/content/docs/ru/modes.mdx @@ -0,0 +1,331 @@ +--- +title: Режимы +description: Различные режимы для разных случаев использования. +--- + +:::caution +Режимы теперь настраиваются с помощью опции `agent` в конфигурации opencode. +Опция `mode` устарела. [Подробнее ](/docs/agents). +::: + +Режимы в opencode позволяют настраивать поведение, инструменты и подсказки для различных вариантов использования. + +Он имеет два встроенных режима: **сборка** и **планирование**. Вы можете настроить +эти или настройте свои собственные через конфигурацию opencode. + +Вы можете переключаться между режимами во время сеанса или настраивать их в своем файле конфигурации. + +--- + +## Встроенный + +opencode имеет два встроенных режима. + +--- + +### Build + +Build — это режим **по умолчанию** со всеми включенными инструментами. Это стандартный режим разработки, в котором вам необходим полный доступ к файловым операциям и системным командам. + +--- + +### Plan + +Ограниченный режим, предназначенный для планирования и анализа. В режиме Plan по умолчанию отключены следующие инструменты: + +- `write` – невозможно создавать новые файлы. +- `edit` – невозможно изменить существующие файлы, за исключением файлов, расположенных по адресу `.opencode/plans/*.md`, для детализации самого плана. +- `patch` – невозможно применить исправления. +- `bash` — невозможно выполнить shell-команды. + +Этот режим полезен, если вы хотите, чтобы ИИ анализировал код, предлагал изменения или создавал планы без внесения каких-либо фактических изменений в вашу кодовую базу. + +--- + +## Переключение + +Переключаться между режимами можно во время сеанса с помощью клавиши _Tab_. Или настроенную вами привязку клавиш `switch_mode`. + +См. также: [Formatters](/docs/formatters) для получения информации о конфигурации форматирования кода. + +--- + +## Настроить + +Вы можете настроить встроенные режимы или создать свои собственные посредством настройки. Режимы можно настроить двумя способами: + +### Конфигурация JSON + +Настройте режимы в файле конфигурации `opencode.json`: + +```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 + +Вы также можете определить режимы, используя файлы Markdown. Поместите их в: + +- Глобальный: `~/.config/opencode/modes/` +- Проект: `.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. +``` + +Имя Markdown файла становится именем режима (например, `review.md` создает режим `review`). + +Давайте рассмотрим эти параметры конфигурации подробно. + +--- + +### Модель + +Используйте конфигурацию `model`, чтобы переопределить модель по умолчанию для этого режима. Полезно для использования разных моделей, оптимизированных под разные задачи. Например, более быстрая модель планирования и более эффективная модель реализации. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### Температура + +Управляйте случайностью и креативностью ответов ИИ с помощью конфигурации `temperature`. Более низкие значения делают ответы более целенаправленными и детерминированными, а более высокие значения повышают креативность и вариативность. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Значения температуры обычно находятся в диапазоне от 0,0 до 1,0: + +- **0,0–0,2**: очень целенаправленные и детерминированные ответы, идеальные для анализа кода и планирования. +- **0,3–0,5**: сбалансированные ответы с некоторой креативностью, подходят для общих задач развития. +- **0,6–1,0**: более творческие и разнообразные ответы, полезные для мозгового штурма и исследования. + +```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}" + } + } +} +``` + +Если температура не указана, opencode использует значения по умолчанию для конкретной модели (обычно 0 для большинства моделей, 0,55 для моделей Qwen). + +--- + +### Промпт + +Укажите собственный файл системных подсказок для этого режима с помощью конфигурации `prompt`. Файл подсказки должен содержать инструкции, специфичные для целей режима. + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Этот путь указан относительно того, где находится файл конфигурации. Так что это работает для +как глобальная конфигурация opencode, так и конфигурация конкретного проекта. + +--- + +### Инструменты + +Контролируйте, какие инструменты доступны в этом режиме, с помощью конфигурации `tools`. Вы можете включить или отключить определенные инструменты, установив для них значение `true` или `false`. + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +Если инструменты не указаны, все инструменты включены по умолчанию. + +--- + +#### Доступные инструменты + +Вот всеми инструментами можно управлять через конфигурацию режима. + +| Инструмент | Описание | +| ----------- | ----------------------- | +| `bash` | Execute shell commands | +| `edit` | Modify existing files | +| `write` | Create new files | +| `read` | Read file contents | +| `grep` | Search file contents | +| `glob` | Find files by pattern | +| `list` | List directory contents | +| `patch` | Apply patches to files | +| `todowrite` | Manage todo lists | +| `todoread` | Read todo lists | +| `webfetch` | Fetch web content | + +--- + +## Пользовательские режимы + +Вы можете создавать свои собственные режимы, добавляя их в конфигурацию. Вот примеры использования обоих подходов: + +### Использование конфигурации JSON + +```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 + } + } + } +} +``` + +### Использование файлов Markdown + +Создайте файлы режимов в `.opencode/modes/` для режимов, специфичных для проекта, или в `~/.config/opencode/modes/` для глобальных режимов: + +```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 +``` + +--- + +### Варианты использования + +Вот несколько распространенных случаев использования различных режимов. + +- **Режим сборки**: полная работа по разработке со всеми включенными инструментами. +- **Режим планирования**: анализ и планирование без внесения изменений. +- **Режим проверки**: проверка кода с доступом только для чтения и инструментами документирования. +- **Режим отладки**: сосредоточен на исследовании с включенными инструментами bash и чтения. +- **Режим документации**: запись документации с использованием файловых операций, но без системных команд. + +Вы также можете обнаружить, что разные модели подходят для разных случаев использования. diff --git a/packages/web/src/content/docs/ru/network.mdx b/packages/web/src/content/docs/ru/network.mdx new file mode 100644 index 00000000000..b80c847899c --- /dev/null +++ b/packages/web/src/content/docs/ru/network.mdx @@ -0,0 +1,57 @@ +--- +title: Сеть +description: Настройте прокси и пользовательские сертификаты. +--- + +opencode поддерживает стандартные переменные среды прокси-сервера и пользовательские сертификаты для сетевых сред предприятия. + +--- + +## Прокси + +opencode учитывает стандартные переменные среды прокси. + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +TUI взаимодействует с локальным HTTP-сервером. Вы должны обойти прокси-сервер для этого соединения, чтобы избежать петель маршрутизации. +::: + +Вы можете настроить порт и имя хоста сервера, используя [CLI flags](/docs/cli#run). + +--- + +### Аутентификация + +Если ваш прокси-сервер требует базовой аутентификации, включите учетные данные в URL-адрес. + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +Избегайте жесткого кодирования паролей. Используйте переменные среды или безопасное хранилище учетных данных. +::: + +Для прокси-серверов, требующих расширенной аутентификации, например NTLM или Kerberos, рассмотрите возможность использования шлюза LLM, поддерживающего ваш метод аутентификации. + +--- + +## Пользовательские сертификаты + +Если ваше предприятие использует собственные центры сертификации для HTTPS-соединений, настройте opencode, чтобы доверять им. + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +Это работает как для прокси-соединений, так и для прямого доступа к API. diff --git a/packages/web/src/content/docs/ru/permissions.mdx b/packages/web/src/content/docs/ru/permissions.mdx new file mode 100644 index 00000000000..efbacc8b5f2 --- /dev/null +++ b/packages/web/src/content/docs/ru/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: Разрешения +description: Контролируйте, какие действия требуют одобрения для выполнения. +--- + +opencode использует конфигурацию `permission`, чтобы решить, должно ли данное действие выполняться автоматически, запрашивать вас или блокироваться. + +Начиная с `v1.1.1`, устаревшая логическая конфигурация `tools` устарела и была объединена с `permission`. Старая конфигурация `tools` по-прежнему поддерживается для обеспечения обратной совместимости. + +--- + +## Действия + +Каждое правило разрешения разрешается в одно из: + +- `"allow"` — запуск без одобрения +- `"ask"` — запрос на одобрение +- `"deny"` — заблокировать действие + +--- + +## Конфигурация + +Вы можете устанавливать разрешения глобально (с помощью `*`) и переопределять определенные инструменты. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +Вы также можете установить все разрешения одновременно: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## Детальные правила (синтаксис объекта) + +Для большинства разрешений вы можете использовать объект для применения различных действий на основе входных данных инструмента. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +Правила оцениваются по шаблону, при этом **выигрывает последнее совпадающее правило**. Обычно сначала ставится универсальное правило `"*"`, а после него — более конкретные правила. + +### Подстановочные знаки + +В шаблонах разрешений используется простое сопоставление с подстановочными знаками: + +- `*` соответствует нулю или более любого символа. +- `?` соответствует ровно одному символу +- Все остальные символы совпадают буквально + +### Расширение домашнего каталога + +Вы можете использовать `~` или `$HOME` в начале шаблона для ссылки на ваш домашний каталог. Это особенно полезно для правил [`external_directory`](#external-directories). + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### Внешние каталоги + +Используйте `external_directory`, чтобы разрешить вызовы инструментов, затрагивающие пути за пределами рабочего каталога, в котором был запущен opencode. Это применимо к любому инструменту, который принимает путь в качестве входных данных (например, `read`, `edit`, `list`, `glob`, `grep` и многие команды `bash`). + +Расширение дома (например, `~/...`) влияет только на запись шаблона. Он не делает внешний путь частью текущего рабочего пространства, поэтому пути за пределами рабочего каталога все равно должны быть разрешены через `external_directory`. + +Например, это позволяет получить доступ ко всему, что находится под `~/projects/personal/`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +Любой каталог, разрешенный здесь, наследует те же настройки по умолчанию, что и текущая рабочая область. Поскольку для [`read` по умолчанию установлено значение `allow`](#defaults), чтение также разрешено для записей под `external_directory`, если оно не переопределено. Добавьте явные правила, когда инструмент должен быть ограничен в этих путях, например, блокировать редактирование при сохранении чтения: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +Держите список сосредоточенным на доверенных путях и добавляйте дополнительные правила разрешения или запрета по мере необходимости для других инструментов (например, `bash`). + +--- + +## Доступные разрешения + +Разрешения opencode привязаны к имени инструмента, а также к нескольким мерам безопасности: + +- `read` — чтение файла (соответствует пути к файлу) +- `edit` — все модификации файлов (охватывает `edit`, `write`, `patch`, `multiedit`) +- `glob` — подстановка файла (соответствует шаблону подстановки) +- `grep` — поиск по контенту (соответствует шаблону регулярного выражения) +- `list` — список файлов в каталоге (соответствует пути к каталогу) +- `bash` — запуск shell-команд (соответствует проанализированным командам, например `git status --porcelain`) +- `task` — запуск субагентов (соответствует типу субагента) +- `skill` — загрузка навыка (соответствует названию навыка) +- `lsp` — выполнение запросов LSP (в настоящее время не детализированных) +- `todoread`, `todowrite` — чтение/обновление списка дел. +- `webfetch` — получение URL-адреса (соответствует URL-адресу) +- `websearch`, `codesearch` — поиск в сети/коде (соответствует запросу) +- `external_directory` — срабатывает, когда инструмент касается путей за пределами рабочего каталога проекта. +- `doom_loop` — срабатывает, когда один и тот же вызов инструмента повторяется 3 раза с одинаковым вводом. + +--- + +## По умолчанию + +Если вы ничего не укажете, opencode запустится с разрешенных значений по умолчанию: + +- Большинство разрешений по умолчанию имеют значение `"allow"`. +- `doom_loop` и `external_directory` по умолчанию равны `"ask"`. +- `read` — это `"allow"`, но файлы `.env` по умолчанию запрещены: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## Что означает «ask» + +Когда opencode запрашивает одобрение, пользовательский интерфейс предлагает три результата: + +- `once` — утвердить только этот запрос +- `always` — одобрять будущие запросы, соответствующие предложенным шаблонам (до конца текущего сеанса opencode). +- `reject` — отклонить запрос + +Набор шаблонов, которые одобрит `always`, предоставляется инструментом (например, разрешения bash обычно включают в белый список безопасный префикс команды, такой как `git status*`). + +--- + +## Агенты + +Вы можете переопределить разрешения для каждого агента. Разрешения агента объединяются с глобальной конфигурацией, и правила агента имеют приоритет. [Подробнее](/docs/agents#permissions) о разрешениях агента. + +:::note +Более подробные примеры сопоставления с образцом см. в разделе [Детальные правила (синтаксис объекта)](#granular-rules-object-syntax) выше. +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +Вы также можете настроить разрешения агента в Markdown: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +Используйте сопоставление с образцом для команд с аргументами. `"grep *"` разрешает `grep pattern file.txt`, а сам `"grep"` блокирует его. Такие команды, как `git status`, работают по умолчанию, но требуют явного разрешения (например, `"git status *"`) при передаче аргументов. +::: diff --git a/packages/web/src/content/docs/ru/plugins.mdx b/packages/web/src/content/docs/ru/plugins.mdx new file mode 100644 index 00000000000..1d7ffb339be --- /dev/null +++ b/packages/web/src/content/docs/ru/plugins.mdx @@ -0,0 +1,385 @@ +--- +title: Плагины +description: Напишите свои собственные плагины для расширения opencode. +--- + +Плагины позволяют расширять opencode, подключаясь к различным событиям и настраивая поведение. Вы можете создавать плагины для добавления новых функций, интеграции с внешними сервисами или изменения поведения opencode по умолчанию. + +Для примера ознакомьтесь с [plugins](/docs/ecosystem#plugins), созданными сообществом. + +--- + +## Используйте плагин + +Есть два способа загрузки плагинов. + +--- + +### Из локальных файлов + +Поместите файлы JavaScript или TypeScript в каталог плагина. + +- `.opencode/plugins/` – плагины уровня проекта. +- `~/.config/opencode/plugins/` — глобальные плагины + +Файлы в этих каталогах автоматически загружаются при запуске. + +--- + +### Из npm + +Укажите пакеты npm в файле конфигурации. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +Поддерживаются как обычные, так и ограниченные пакеты npm. + +Просмотрите доступные плагины в папке [ecosystem](/docs/ecosystem#plugins). + +--- + +### Как устанавливаются плагины + +**Плагины npm** устанавливаются автоматически с помощью Bun при запуске. Пакеты и их зависимости кэшируются в `~/.cache/opencode/node_modules/`. + +**Локальные плагины** загружаются непосредственно из каталога плагинов. Чтобы использовать внешние пакеты, вы должны создать `package.json` в своем каталоге конфигурации (см. [Зависимости](#dependencies)) или опубликовать плагин в npm и [добавить его в свой config](/docs/config#plugins). + +--- + +### Порядок загрузки + +Плагины загружаются из всех источников, и все хуки запускаются последовательно. Порядок загрузки следующий: + +1. Глобальная конфигурация (`~/.config/opencode/opencode.json`) +2. Конфигурация проекта (`opencode.json`) +3. Глобальный каталог плагинов (`~/.config/opencode/plugins/`) +4. Каталог плагинов проекта (`.opencode/plugins/`) + +Дубликаты пакетов npm с тем же именем и версией загружаются один раз. Однако локальный плагин и плагин npm со схожими именами загружаются отдельно. + +--- + +## Создать плагин + +Плагин — это **модуль JavaScript/TypeScript**, который экспортирует один или несколько плагинов. +функции. Каждая функция получает объект контекста и возвращает объект перехватчика. + +--- + +### Зависимости + +Локальные плагины и специальные инструменты могут использовать внешние пакеты npm. Добавьте `package.json` в каталог конфигурации с необходимыми вам зависимостями. + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +opencode запускает `bun install` при запуске для их установки. Затем ваши плагины и инструменты смогут импортировать их. + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### Базовая структура + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +Функция плагина получает: + +- `project`: Текущая информация о проекте. +- `directory`: текущий рабочий каталог. +- `worktree`: путь к рабочему дереву git. +- `client`: клиент SDK с открытым кодом для взаимодействия с ИИ. +- `$`: [Bun shell API](https://bun.com/docs/runtime/shell) для выполнения команд. + +--- + +### Поддержка TypeScript + +Для плагинов TypeScript вы можете импортировать типы из пакета плагина: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### События + +Плагины могут подписываться на события, как показано ниже в разделе «Примеры». Вот список различных доступных событий. + +#### Командные события + +- `command.executed` + +#### События файла + +- `file.edited` +- `file.watcher.updated` + +#### События установки + +- `installation.updated` + +#### События LSP + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### События сообщений + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### События разрешения + +- `permission.asked` +- `permission.replied` + +#### События сервера + +- `server.connected` + +#### События сессии + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### События + +- `todo.updated` + +#### События shell + +- `shell.env` + +#### События инструмента + +- `tool.execute.after` +- `tool.execute.before` + +#### Мероприятия TUI + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## Примеры + +Вот несколько примеров плагинов, которые вы можете использовать для расширения opencode. + +--- + +### Отправлять уведомления + +Отправляйте уведомления при возникновении определенных событий: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +Мы используем `osascript` для запуска AppleScript на macOS. Здесь мы используем его для отправки уведомлений. + +:::note +Если вы используете настольное приложение opencode, оно может автоматически отправлять системные уведомления, когда ответ готов или когда возникает ошибка сеанса. +::: + +--- + +### Защита .env + +Запретите открытому коду читать файлы `.env`: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### Внедрение переменных среды + +Внедряйте переменные среды во все shell-процессы выполнения (инструменты искусственного интеллекта и пользовательские terminal): + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### Пользовательские инструменты + +Плагины также могут добавлять в opencode собственные инструменты: + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +Помощник `tool` создает собственный инструмент, который может вызывать opencode. Он принимает функцию схемы Zod и возвращает определение инструмента: + +- `description`: Что делает инструмент +- `args`: схема Zod для аргументов инструмента. +- `execute`: функция, которая запускается при вызове инструмента. + +Ваши пользовательские инструменты будут доступны для открытия кода наряду со встроенными инструментами. + +--- + +### Ведение журнала + +Используйте `client.app.log()` вместо `console.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` в этом случае игнорируется. diff --git a/packages/web/src/content/docs/ru/providers.mdx b/packages/web/src/content/docs/ru/providers.mdx new file mode 100644 index 00000000000..5984c89f43b --- /dev/null +++ b/packages/web/src/content/docs/ru/providers.mdx @@ -0,0 +1,1888 @@ +--- +title: Провайдеры +description: Использование любого провайдера LLM в opencode. +--- + +import config from "../../../../config.mjs" +export const console = config.console + +opencode использует [AI SDK](https://ai-sdk.dev/) и [Models.dev](https://models.dev) для поддержки **более 75 поставщиков LLM** и поддерживает запуск локальных моделей. + +Чтобы добавить провайдера, вам необходимо: + +1. Добавьте ключи API для провайдера с помощью команды `/connect`. +2. Настройте провайдера в вашей конфигурации opencode. + +--- + +### Учетные данные + +Когда вы добавляете ключи API провайдера с помощью команды `/connect`, они сохраняются +в `~/.local/share/opencode/auth.json`. + +--- + +### Настройка + +Вы можете настроить поставщиков через раздел `provider` в вашем opencode. +конфиг. + +--- + +#### Базовый URL + +Вы можете настроить базовый URL-адрес для любого провайдера, установив параметр `baseURL`. Это полезно при использовании прокси-сервисов или пользовательских конечных точек. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen — это список моделей, предоставленный командой opencode, которые были +протестировано и проверено на хорошую работу с opencode. [Подробнее](/docs/zen). + +:::tip +Если вы новичок, мы рекомендуем начать с OpenCode Zen. +::: + +1. Запустите команду `/connect` в TUI, выберите opencode и перейдите по адресу [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. Войдите в систему, добавьте свои платежные данные и скопируйте ключ API. + +3. Вставьте свой ключ API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите `/models` в TUI, чтобы просмотреть список рекомендуемых нами моделей. + + ```txt + /models + ``` + +Он работает как любой другой поставщик в opencode и его использование совершенно необязательно. + +--- + +## Каталог + +Рассмотрим некоторых провайдеров подробнее. Если вы хотите добавить провайдера в список, смело открывайте PR. + +:::note +Не видите здесь провайдера? Откройте PR. +::: + +--- + +### 302.AI + +1. Перейдите в консоль 302.AI](https://302.ai/), создайте учетную запись и сгенерируйте ключ API. + +2. Запустите команду `/connect` и найдите **302.AI**. + + ```txt + /connect + ``` + +3. Введите свой ключ API 302.AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать модель. + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +Чтобы использовать Amazon Bedrock с opencode: + +1. Перейдите в **Каталог моделей** в консоли Amazon Bedrock и запросите + доступ к нужным моделям. + + :::tip + Вам необходимо иметь доступ к нужной модели в Amazon Bedrock. + ::: + +2. **Настройте аутентификацию** одним из следующих способов: + + #### Переменные среды (быстрый старт) + + Установите одну из этих переменных среды при запуске opencode: + + ```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode + ``` + + Или добавьте их в свой профиль bash: + + ```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" + } + } + } + } + ``` + + **Доступные варианты:** + - `region` – регион AWS (например, `us-east-1`, `eu-west-1`). + - `profile` – именованный профиль AWS из `~/.aws/credentials`. + - `endpoint` — URL-адрес пользовательской конечной точки для конечных точек VPC (псевдоним для общей опции `baseURL`). + + :::tip + Параметры файла конфигурации имеют приоритет над переменными среды. + ::: + + #### Дополнительно: конечные точки VPC + + Если вы используете конечные точки VPC для Bedrock: + + ```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`, использующий терминологию, специфичную для AWS. Если указаны и `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`**: создание долгосрочных ключей API из консоли Amazon Bedrock. + - **`AWS_WEB_IDENTITY_TOKEN_FILE`/`AWS_ROLE_ARN`**: для EKS IRSA (роли IAM для учетных записей служб) или других сред Kubernetes с федерацией OIDC. Эти переменные среды автоматически вводятся Kubernetes при использовании аннотаций учетной записи службы. + + #### Приоритет аутентификации + + Amazon Bedrock использует следующий приоритет аутентификации: + 1. **Токен носителя** — переменная среды `AWS_BEARER_TOKEN_BEDROCK` или токен из команды `/connect`. + 2. **Цепочка учетных данных AWS** — профиль, ключи доступа, общие учетные данные, роли IAM, токены веб-идентификации (EKS IRSA), метаданные экземпляра. + + :::note + Когда токен-носитель установлен (через `/connect` или `AWS_BEARER_TOKEN_BEDROCK`), он имеет приоритет над всеми методами учетных данных AWS, включая настроенные профили. + ::: + +3. Запустите команду `/models`, чтобы выбрать нужную модель. + + ```txt + /models + ``` + +:::note +Для пользовательских профилей вывода используйте имя модели и поставщика в ключе и задайте для свойства `id` значение arn. Это обеспечивает правильное кэширование: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. После регистрации введите команду `/connect` и выберите Anthropic. + + ```txt + /connect + ``` + +2. Здесь вы можете выбрать опцию **Claude Pro/Max**, и ваш браузер откроется. + и попросите вас пройти аутентификацию. + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. Теперь все модели Anthropic должны быть доступны при использовании команды `/models`. + + ```txt + /models + ``` + +:::info +Использование вашей подписки Claude Pro/Max в opencode официально не поддерживается [Anthropic](https://anthropic.com). +::: + +##### Использование ключей API + +Вы также можете выбрать **Создать ключ API**, если у вас нет подписки Pro/Max. Он также откроет ваш браузер и попросит вас войти в Anthropic и предоставит вам код, который вы можете вставить в свой терминал. + +Или, если у вас уже есть ключ API, вы можете выбрать **Ввести ключ API вручную** и вставить его в свой терминал. + +--- + +### Azure OpenAI + +:::note +Если вы столкнулись с ошибками «Извините, но я не могу помочь с этим запросом», попробуйте изменить фильтр содержимого с **DefaultV2** на **Default** в своем ресурсе Azure. +::: + +1. Перейдите на [портал Azure](https://portal.azure.com/) и создайте ресурс **Azure OpenAI**. Вам понадобится: + - **Имя ресурса**: оно становится частью вашей конечной точки API (`https://RESOURCE_NAME.openai.azure.com/`). + - **Ключ API**: `KEY 1` или `KEY 2` из вашего ресурса. + +2. Перейдите в [Azure AI Foundry](https://ai.azure.com/) и разверните модель. + + :::примечание + Для правильной работы opencode имя развертывания должно совпадать с именем модели. + ::: + +3. Запустите команду `/connect` и найдите **Azure**. + + ```txt + /connect + ``` + +4. Введите свой ключ API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Задайте имя ресурса как переменную среды: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + Или добавьте его в свой профиль bash: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. Запустите команду `/models`, чтобы выбрать развернутую модель. + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. Перейдите на [портал Azure](https://portal.azure.com/) и создайте ресурс **Azure OpenAI**. Вам понадобится: + - **Имя ресурса**: оно становится частью вашей конечной точки API (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`). + - **Ключ API**: `KEY 1` или `KEY 2` из вашего ресурса. + +2. Перейдите в [Azure AI Foundry](https://ai.azure.com/) и разверните модель. + + :::примечание + Для правильной работы opencode имя развертывания должно совпадать с именем модели. + ::: + +3. Запустите команду `/connect` и найдите **Azure Cognitive Services**. + + ```txt + /connect + ``` + +4. Введите свой ключ API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Задайте имя ресурса как переменную среды: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + Или добавьте его в свой профиль bash: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. Запустите команду `/models`, чтобы выбрать развернутую модель. + + ```txt + /models + ``` + +--- + +### Baseten + +1. Перейдите в [Baseten](https://app.baseten.co/), создайте учетную запись и сгенерируйте ключ API. + +2. Запустите команду `/connect` и найдите **Baseten**. + + ```txt + /connect + ``` + +3. Введите свой ключ API Baseten. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать модель. + + ```txt + /models + ``` + +--- + +### Cerebras + +1. Перейдите в [консоль Cerebras](https://inference.cerebras.ai/), создайте учетную запись и сгенерируйте ключ API. + +2. Запустите команду `/connect` и найдите **Cerebras**. + + ```txt + /connect + ``` + +3. Введите свой ключ API Cerebras. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать такую ​​модель, как _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +Cloudflare AI Gateway позволяет вам получать доступ к моделям OpenAI, Anthropic, Workers AI и т. д. через единую конечную точку. Благодаря [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) вам не нужны отдельные ключи API для каждого провайдера. + +1. Перейдите на [панель управления Cloudflare](https://dash.cloudflare.com/), выберите **AI** > **AI Gateway** и создайте новый шлюз. + +2. Установите идентификатор своей учетной записи и идентификатор шлюза в качестве переменных среды. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. Запустите команду `/connect` и найдите **Cloudflare AI Gateway**. + + ```txt + /connect + ``` + +4. Введите свой токен API Cloudflare. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + Или установите его как переменную среды. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. Запустите команду `/models`, чтобы выбрать модель. + + ```txt + /models + ``` + + Вы также можете добавлять модели через конфигурацию opencode. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +### Cortecs + +1. Перейдите в [консоль Cortecs](https://cortecs.ai/), создайте учетную запись и сгенерируйте ключ API. + +2. Запустите команду `/connect` и найдите **Cortecs**. + + ```txt + /connect + ``` + +3. Введите свой ключ API Cortecs. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать такую ​​модель, как _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. Перейдите в [консоль DeepSeek](https://platform.deepseek.com/), создайте учетную запись и нажмите **Создать новый ключ API**. + +2. Запустите команду `/connect` и найдите **DeepSeek**. + + ```txt + /connect + ``` + +3. Введите свой ключ API DeepSeek. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать модель DeepSeek, например _DeepSeek Reasoner_. + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. Перейдите на панель мониторинга Deep Infra](https://deepinfra.com/dash), создайте учетную запись и сгенерируйте ключ API. + +2. Запустите команду `/connect` и найдите **Deep Infra**. + + ```txt + /connect + ``` + +3. Введите свой ключ API Deep Infra. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать модель. + + ```txt + /models + ``` + +--- + +### Firmware + +1. Перейдите на [панель Firmware](https://app.firmware.ai/signup), создайте учетную запись и сгенерируйте ключ API. + +2. Запустите команду `/connect` и найдите **Firmware**. + + ```txt + /connect + ``` + +3. Введите ключ API Firmware. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать модель. + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. Перейдите в [консоль Fireworks AI](https://app.fireworks.ai/), создайте учетную запись и нажмите **Создать ключ API**. + +2. Запустите команду `/connect` и найдите **Fireworks AI**. + + ```txt + /connect + ``` + +3. Введите ключ API Fireworks AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать такую ​​модель, как _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo предоставляет агентский чат на базе искусственного интеллекта со встроенными возможностями вызова инструментов через прокси-сервер GitLab Anthropic. + +1. Запустите команду `/connect` и выберите GitLab. + + ```txt + /connect + ``` + +2. Выберите метод аутентификации: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ + ``` + + #### Использование OAuth (рекомендуется) + + Выберите **OAuth**, и ваш браузер откроется для авторизации. + + #### Использование токена личного доступа + 1. Перейдите в [Настройки пользователя GitLab > Токены доступа](https://gitlab.com/-/user_settings/personal_access_tokens). + 2. Нажмите **Добавить новый токен**. + 3. Имя: `OpenCode`, Области применения: `api` + 4. Скопируйте токен (начинается с `glpat-`) + 5. Введите его в терминал + +3. Запустите команду `/models`, чтобы просмотреть доступные модели. + + ```txt + /models + ``` + + Доступны три модели на основе Claude: + - **duo-chat-haiku-4-5** (по умолчанию) — быстрые ответы на быстрые задачи. + - **duo-chat-sonnet-4-5** — сбалансированная производительность для большинства рабочих процессов. + - **duo-chat-opus-4-5** — Наиболее способен к комплексному анализу. + +:::note +Вы также можете указать переменную среды «GITLAB_TOKEN», если не хотите. +для хранения токена в хранилище аутентификации opencode. +::: + +##### Самостоятельная GitLab + +:::note[примечание о соответствии] +opencode использует небольшую модель для некоторых задач ИИ, таких как создание заголовка сеанса. +По умолчанию он настроен на использование gpt-5-nano, размещенного на Zen. Чтобы заблокировать opencode +чтобы использовать только свой собственный экземпляр, размещенный на GitLab, добавьте следующее в свой +`opencode.json` файл. Также рекомендуется отключить совместное использование сеансов. + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +Для самостоятельных экземпляров GitLab: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +Если в вашем экземпляре используется собственный AI-шлюз: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +Или добавьте в свой профиль bash: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +Ваш администратор GitLab должен включить следующее: + +1. [Платформа Duo Agent](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) для пользователя, группы или экземпляра +2. Флаги функций (через консоль Rails): + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: + +##### OAuth для локальных экземпляров + +Чтобы Oauth работал на вашем локальном экземпляре, вам необходимо создать +новое приложение (Настройки → Приложения) с +URL обратного вызова `http://127.0.0.1:8080/callback` и следующие области: + +- API (Доступ к API от вашего имени) +- read_user (прочитать вашу личную информацию) +- read_repository (разрешает доступ к репозиторию только для чтения) + +Затем укажите идентификатор приложения как переменную среды: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +Дополнительная документация на домашней странице [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth). + +##### Конфигурация + +Настройте через `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### Инструменты API GitLab (необязательно, но настоятельно рекомендуется) + +Чтобы получить доступ к инструментам GitLab (мерж-реквесты, задачи, конвейеры, CI/CD и т. д.): + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +Этот плагин предоставляет комплексные возможности управления репозиторием GitLab, включая проверки MR, отслеживание проблем, мониторинг конвейера и многое другое. + +--- + +### GitHub Copilot + +Чтобы использовать подписку 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). +::: + +1. Запустите команду `/connect` и найдите GitHub Copilot. + + ```txt + /connect + ``` + +2. Перейдите на [github.com/login/device](https://github.com/login/device) и введите код. + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + └ Waiting for authorization... + ``` + +3. Теперь запустите команду `/models`, чтобы выбрать нужную модель. + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +Чтобы использовать Google Vertex AI с opencode: + +1. Перейдите в **Model Garden** в Google Cloud Console и проверьте + модели, доступные в вашем регионе. + + :::note + Вам необходим проект Google Cloud с включенным Vertex AI API. + ::: + +2. Установите необходимые переменные среды: + - `GOOGLE_CLOUD_PROJECT`: идентификатор вашего проекта Google Cloud. + - `VERTEX_LOCATION` (необязательно): регион для Vertex AI (по умолчанию `global`). + - Аутентификация (выберите одну): + - `GOOGLE_APPLICATION_CREDENTIALS`: путь к ключевому файлу JSON вашего сервисного аккаунта. + - Аутентификация через CLI gcloud: `gcloud auth application-default login`. + + Установите их во время запуска opencode. + + ```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode + ``` + + Или добавьте их в свой профиль bash. + + ```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` повышает доступность и уменьшает количество ошибок без дополнительных затрат. Используйте региональные конечные точки (например, `us-central1`) для требований к местонахождению данных. [Подробнее](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. Запустите команду `/models`, чтобы выбрать нужную модель. + + ```txt + /models + ``` + +--- + +### Groq + +1. Перейдите в консоль Groq](https://console.groq.com/), нажмите **Создать ключ API** и скопируйте ключ. + +2. Запустите команду `/connect` и найдите Groq. + + ```txt + /connect + ``` + +3. Введите ключ API для провайдера. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать тот, который вам нужен. + + ```txt + /models + ``` + +--- + +### Hugging Face + +[Hugging Face Inference Providers](https://huggingface.co/docs/inference-providers) предоставляют доступ к открытым моделям, поддерживаемым более чем 17 поставщиками. + +1. Перейдите в [Настройки Hugging Face](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained), чтобы создать токен с разрешением совершать вызовы к поставщикам выводов. + +2. Запустите команду `/connect` и найдите **Hugging Face**. + + ```txt + /connect + ``` + +3. Введите свой токен Hugging Face. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать такую ​​модель, как _Kimi-K2-Instruct_ или _GLM-4.6_. + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) — это платформа наблюдения LLM, которая обеспечивает ведение журнала, мониторинг и аналитику для ваших приложений искусственного интеллекта. Helicone AI Gateway автоматически направляет ваши запросы соответствующему поставщику на основе модели. + +1. Перейдите в [Helicone](https://helicone.ai), создайте учетную запись и сгенерируйте ключ API на своей панели управления. + +2. Запустите команду `/connect` и найдите **Helicone**. + + ```txt + /connect + ``` + +3. Введите свой ключ API Helicone. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать модель. + + ```txt + /models + ``` + +Дополнительные сведения о дополнительных провайдерах и расширенных функциях, таких как кэширование и ограничение скорости, см. в [Документация Helicone](https://docs.helicone.ai). + +#### Дополнительные конфигурации + +Если вы видите функцию или модель от Helicone, которая не настраивается автоматически через opencode, вы всегда можете настроить ее самостоятельно. + +Вот [Справочник моделей Helicone](https://helicone.ai/models), он понадобится вам, чтобы получить идентификаторы моделей, которые вы хотите добавить. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### Пользовательские заголовки + +Helicone поддерживает пользовательские заголовки для таких функций, как кэширование, отслеживание пользователей и управление сеансами. Добавьте их в конфигурацию вашего провайдера, используя `options.headers`: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### Отслеживание сеансов + +Функция 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 +``` + +Добавьте его в свою конфигурацию. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +Плагин вставляет в ваши запросы заголовки `Helicone-Session-Id` и `Helicone-Session-Name`. На странице «Сеансы» Helicone вы увидите каждый диалог opencode, указанный как отдельный сеанс. + +##### Общие разъемы Helicone + +| Заголовок | Описание | +| -------------------------- | ------------------------------------------------------------------------------ | +| `Helicone-Cache-Enabled` | Включить кэширование ответов (`true`/`false`) | +| `Helicone-User-Id` | Отслеживание показателей по пользователю | +| `Helicone-Property-[Name]` | Добавьте пользовательские свойства (например, `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | Связывание запросов с версиями промптов | + +См. [Справочник заголовков Helicone](https://docs.helicone.ai/helicone-headers/header-directory) для всех доступных заголовков. + +--- + +### llama.cpp + +Вы можете настроить opencode для использования локальных моделей с помощью [утилиты llama-server llama.cpp's](https://github.com/ggml-org/llama.cpp) + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +В этом примере: + +- `llama.cpp` — это идентификатор пользовательского поставщика. Это может быть любая строка, которую вы хотите. +- `npm` указывает пакет, который будет использоваться для этого поставщика. Здесь `@ai-sdk/openai-compatible` используется для любого API-интерфейса, совместимого с OpenAI. +- `name` — это отображаемое имя поставщика в пользовательском интерфейсе. +- `options.baseURL` — конечная точка локального сервера. +- `models` — это карта идентификаторов моделей с их конфигурациями. Название модели будет отображаться в списке выбора модели. + +--- + +### IO.NET + +IO.NET предлагает 17 моделей, оптимизированных для различных случаев использования: + +1. Перейдите в консоль IO.NET](https://ai.io.net/), создайте учетную запись и сгенерируйте ключ API. + +2. Запустите команду `/connect` и найдите **IO.NET**. + + ```txt + /connect + ``` + +3. Введите свой ключ API IO.NET. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать модель. + + ```txt + /models + ``` + +--- + +### LM Studio + +Вы можете настроить opencode для использования локальных моделей через LM Studio. + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +В этом примере: + +- `lmstudio` — это идентификатор пользовательского поставщика. Это может быть любая строка, которую вы хотите. +- `npm` указывает пакет, который будет использоваться для этого поставщика. Здесь `@ai-sdk/openai-compatible` используется для любого API-интерфейса, совместимого с OpenAI. +- `name` — это отображаемое имя поставщика в пользовательском интерфейсе. +- `options.baseURL` — конечная точка локального сервера. +- `models` — это карта идентификаторов моделей с их конфигурациями. Название модели будет отображаться в списке выбора модели. + +--- + +### Moonshot AI + +Чтобы использовать Кими К2 из Moonshot AI: + +1. Перейдите в [консоль Moonshot AI](https://platform.moonshot.ai/console), создайте учетную запись и нажмите **Создать ключ API**. + +2. Запустите команду `/connect` и найдите **Moonshot AI**. + + ```txt + /connect + ``` + +3. Введите свой API-ключ Moonshot. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать _Kimi K2_. + + ```txt + /models + ``` + +--- + +### MiniMax + +1. Перейдите в [консоль API MiniMax](https://platform.minimax.io/login), создайте учетную запись и сгенерируйте ключ API. + +2. Запустите команду `/connect` и найдите **MiniMax**. + + ```txt + /connect + ``` + +3. Введите свой ключ API MiniMax. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать модель типа _M2.1_. + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. Перейдите в консоль Nebius Token Factory](https://tokenfactory.nebius.com/), создайте учетную запись и нажмите **Добавить ключ**. + +2. Запустите команду `/connect` и найдите **Nebius Token Factory**. + + ```txt + /connect + ``` + +3. Введите ключ API фабрики токенов Nebius. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать такую ​​модель, как _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Ollama + +Вы можете настроить opencode для использования локальных моделей через Ollama. + +:::tip +Ollama может автоматически настроиться для opencode. Подробности см. в документации по интеграции Ollama](https://docs.ollama.com/integrations/opencode). +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +В этом примере: + +- `ollama` — это идентификатор пользовательского поставщика. Это может быть любая строка, которую вы хотите. +- `npm` указывает пакет, который будет использоваться для этого поставщика. Здесь `@ai-sdk/openai-compatible` используется для любого API-интерфейса, совместимого с OpenAI. +- `name` — это отображаемое имя поставщика в пользовательском интерфейсе. +- `options.baseURL` — конечная точка локального сервера. +- `models` — это карта идентификаторов моделей с их конфигурациями. Название модели будет отображаться в списке выбора модели. + +:::tip +Если вызовы инструментов не работают, попробуйте увеличить `num_ctx` в Олламе. Начните с 16–32 тысяч. +::: + +--- + +### Ollama Cloud + +Чтобы использовать Ollama Cloud с opencode: + +1. Перейдите на [https://ollama.com/](https://ollama.com/) и войдите в систему или создайте учетную запись. + +2. Перейдите в **Настройки** > **Ключи** и нажмите **Добавить ключ API**, чтобы создать новый ключ API. + +3. Скопируйте ключ API для использования в opencode. + +4. Запустите команду `/connect` и найдите **Ollama Cloud**. + + ```txt + /connect + ``` + +5. Введите свой ключ API Ollama Cloud. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **Важно**. Перед использованием облачных моделей в opencode необходимо получить информацию о модели локально: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. Запустите команду `/models`, чтобы выбрать модель облака Ollama. + + ```txt + /models + ``` + +--- + +### OpenAI + +Мы рекомендуем подписаться на [ChatGPT Plus или Pro](https://chatgpt.com/pricing). + +1. После регистрации выполните команду `/connect` и выберите OpenAI. + + ```txt + /connect + ``` + +2. Здесь вы можете выбрать опцию **ChatGPT Plus/Pro**, и ваш браузер откроется. + и попросите вас пройти аутентификацию. + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. Теперь все модели OpenAI должны быть доступны при использовании команды `/models`. + + ```txt + /models + ``` + +##### Использование ключей API + +Если у вас уже есть ключ API, вы можете выбрать **Ввести ключ API вручную** и вставить его в свой терминал. + +--- + +### OpenCode Zen + +OpenCode Zen — это список протестированных и проверенных моделей, предоставленный командой opencode. [Подробнее](/docs/zen). + +1. Войдите в систему **OpenCode Zen** и нажмите **Создать ключ API**. + +2. Запустите команду `/connect` и найдите **OpenCode Zen**. + + ```txt + /connect + ``` + +3. Введите свой ключ API opencode. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать такую ​​модель, как _Qwen 3 Coder 480B_. + + ```txt + /models + ``` + +--- + +### OpenRouter + +1. Перейдите на панель управления OpenRouter](https://openrouter.ai/settings/keys), нажмите **Создать ключ API** и скопируйте ключ. + +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 можно найти в разделе **Сервисы** > **Экземпляры и подписки** в панели управления BTP. + ::: + +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: + + ```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 + ``` + +--- + +### OVHcloud AI Endpoints + +1. Перейдите к [OVHcloud Panel](https://ovh.com/manager). Перейдите в раздел `Public Cloud`, `AI & Machine Learning` > `AI Endpoints` и на вкладке `API Keys` нажмите **Создать новый ключ API**. + +2. Запустите команду `/connect` и найдите **Конечные точки OVHcloud AI**. + + ```txt + /connect + ``` + +3. Введите ключ API конечных точек OVHcloud AI. + + ```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. Перейдите к [Настройки IAM консоли Scaleway](https://console.scaleway.com/iam/api-keys), чтобы сгенерировать новый ключ API. + +2. Запустите команду `/connect` и найдите **Scaleway**. + + ```txt + /connect + ``` + +3. Введите ключ API Scaleway. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать модель, например _devstral-2-123b-instruct-2512_ или _gpt-oss-120b_. + + ```txt + /models + ``` + +--- + +### Together AI + +1. Перейдите в [консоль Together AI](https://api.together.ai), создайте учетную запись и нажмите **Добавить ключ**. + +2. Запустите команду `/connect` и найдите **Together AI**. + + ```txt + /connect + ``` + +3. Введите ключ API Together AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать такую ​​модель, как _Kimi K2 Instruct_. + + ```txt + /models + ``` + +--- + +### Venice AI + +1. Перейдите к [консоли Venice AI](https://venice.ai), создайте учетную запись и сгенерируйте ключ API. + +2. Запустите команду `/connect` и найдите **Venice AI**. + + ```txt + /connect + ``` + +3. Введите свой ключ API Venice AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать модель типа _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + +### Vercel AI Gateway + +Vercel AI Gateway позволяет получать доступ к моделям OpenAI, Anthropic, Google, xAI и других источников через единую конечную точку. Модели предлагаются по прейскурантной цене без наценок. + +1. Перейдите на [панель мониторинга Vercel](https://vercel.com/), перейдите на вкладку **AI Gateway** и нажмите **Ключи API**, чтобы создать новый ключ API. + +2. Запустите команду `/connect` и найдите **Vercel AI Gateway**. + + ```txt + /connect + ``` + +3. Введите ключ API Vercel AI Gateway. + + ```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](https://console.x.ai/), создайте учетную запись и сгенерируйте ключ API. + +2. Запустите команду `/connect` и найдите **xAI**. + + ```txt + /connect + ``` + +3. Введите свой ключ API xAI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать такую ​​модель, как _Grok Beta_. + + ```txt + /models + ``` + +--- + +### Z.AI + +1. Перейдите в [консоль Z.AI API](https://z.ai/manage-apikey/apikey-list), создайте учетную запись и нажмите **Создать новый ключ API**. + +2. Запустите команду `/connect` и найдите **Z.AI**. + + ```txt + /connect + ``` + + Если вы подписаны на **План кодирования GLM**, выберите **План кодирования Z.AI**. + +3. Введите свой ключ API Z.AI. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать модель типа _GLM-4.7_. + + ```txt + /models + ``` + +--- + +### ZenMux + +1. Перейдите на [панель управления ZenMux](https://zenmux.ai/settings/keys), нажмите **Создать ключ API** и скопируйте ключ. + +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-совместимого провайдера с открытым кодом. Большинство современных поставщиков ИИ предлагают API-интерфейсы, совместимые с OpenAI. +::: + +1. Запустите команду `/connect` и прокрутите вниз до пункта **Другое**. + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. Введите уникальный идентификатор провайдера. + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::примечание + Выберите запоминающийся идентификатор, вы будете использовать его в своем файле конфигурации. + ::: + +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. + - **имя**: отображаемое имя в пользовательском интерфейсе. + - **модели**: Доступные модели. + - **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). +- **заголовки**: пользовательские заголовки, отправляемые с каждым запросом. +- **limit.context**: Максимальное количество входных токенов, которые принимает модель. +- **limit.output**: Максимальное количество токенов, которые может сгенерировать модель. + +Поля `limit` позволяют opencode понять, сколько контекста у вас осталось. Стандартные поставщики автоматически извлекают их из models.dev. + +--- + +## Поиск неисправностей + +Если у вас возникли проблемы с настройкой провайдера, проверьте следующее: + +1. **Проверьте настройку аутентификации**: запустите `opencode auth list`, чтобы проверить, верны ли учетные данные. + для провайдера добавлены в ваш конфиг. + + Это не относится к таким поставщикам, как Amazon Bedrock, которые для аутентификации полагаются на переменные среды. + +2. Для пользовательских поставщиков проверьте конфигурацию opencode и: + - Убедитесь, что идентификатор провайдера, используемый в команде `/connect`, соответствует идентификатору в вашей конфигурации opencode. + - Для провайдера используется правильный пакет npm. Например, используйте `@ai-sdk/cerebras` для Cerebras. А для всех других поставщиков, совместимых с OpenAI, используйте `@ai-sdk/openai-compatible`. + - Убедитесь, что в поле `options.baseURL` используется правильная конечная точка API. diff --git a/packages/web/src/content/docs/ru/rules.mdx b/packages/web/src/content/docs/ru/rules.mdx new file mode 100644 index 00000000000..d553bd0ced7 --- /dev/null +++ b/packages/web/src/content/docs/ru/rules.mdx @@ -0,0 +1,180 @@ +--- +title: Правила +description: Установите пользовательские инструкции для opencode. +--- + +Вы можете предоставить собственные инструкции для opencode, создав файл `AGENTS.md`. Это похоже на правила Cursor. Он содержит инструкции, которые будут включены в контекст LLM для настройки его поведения для вашего конкретного проекта. + +--- + +## Инициализировать + +Чтобы создать новый файл `AGENTS.md`, вы можете запустить команду `/init` в opencode. + +:::tip +Вам следует закоммитить файл `AGENTS.md` вашего проекта в Git. +::: + +Это позволит отсканировать ваш проект и все его содержимое, чтобы понять, о чем этот проект, и сгенерировать с его помощью файл `AGENTS.md`. Это помогает opencode лучше ориентироваться в проекте. + +Если у вас есть существующий файл `AGENTS.md`, мы попытаемся добавить его. + +--- + +## Пример + +Вы также можете просто создать этот файл вручную. Вот пример того, что вы можете поместить в файл `AGENTS.md`. + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +Мы добавляем сюда инструкции для конкретного проекта, и они будут доступны всей вашей команде. + +--- + +## Типы + +opencode также поддерживает чтение файла `AGENTS.md` из нескольких мест. И это служит разным целям. + +### Проект + +Поместите `AGENTS.md` в корень вашего проекта для правил, специфичных для проекта. Они применяются только тогда, когда вы работаете в этом каталоге или его подкаталогах. + +### Глобальный + +Вы также можете иметь глобальные правила в файле `~/.config/opencode/AGENTS.md`. Это применяется ко всем сеансам opencode. + +Поскольку это не коммитится в Git и не передается вашей команде, мы рекомендуем использовать его для указания любых личных правил, которым должен следовать LLM. + +### Совместимость кода Клода + +Для пользователей, переходящих с Claude Code, opencode поддерживает файловые соглашения Claude Code в качестве резерва: + +- **Правила проекта**: `CLAUDE.md` в каталоге вашего проекта (используется, если `AGENTS.md` не существует). +- **Глобальные правила**: `~/.claude/CLAUDE.md` (используется, если `~/.config/opencode/AGENTS.md` не существует). +- **Навыки**: `~/.claude/skills/` — подробности см. в [Навыки агента](/docs/skills/). + +Чтобы отключить совместимость Claude Code, установите одну из этих переменных среды: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## Приоритет + +Когда opencode запускается, он ищет файлы правил в следующем порядке: + +1. **Локальные файлы** путем перехода вверх из текущего каталога (`AGENTS.md`, `CLAUDE.md`) +2. **Глобальный файл** в `~/.config/opencode/AGENTS.md`. +3. **Файл кода Клауда** по адресу `~/.claude/CLAUDE.md` (если не отключено) + +Первый совпадающий файл побеждает в каждой категории. Например, если у вас есть и `AGENTS.md`, и `CLAUDE.md`, используется только `AGENTS.md`. Аналогично, `~/.config/opencode/AGENTS.md` имеет приоритет над `~/.claude/CLAUDE.md`. + +--- + +## Пользовательские инструкции + +Вы можете указать собственные файлы инструкций в `opencode.json` или в глобальном `~/.config/opencode/opencode.json`. Это позволит вам и вашей команде повторно использовать существующие правила вместо того, чтобы дублировать их на AGENTS.md. + +Пример: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Вы также можете использовать удаленные URL-адреса для загрузки инструкций из Интернета. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +Удаленные инструкции извлекаются с таймаутом в 5 секунд. + +Все файлы инструкций объединяются с вашими файлами `AGENTS.md`. + +--- + +## Ссылки на внешние файлы + +Хотя opencode не анализирует автоматически ссылки на файлы в `AGENTS.md`, аналогичной функциональности можно добиться двумя способами: + +### Использование opencode.json + +Рекомендуемый подход — использовать поле `instructions` в `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### Ручные инструкции в AGENTS.md + +Вы можете научить opencode читать внешние файлы, предоставив явные инструкции в файле `AGENTS.md`. Вот практический пример: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +Такой подход позволяет: + +- Создавайте модульные файлы правил многократного использования. +- Делитесь правилами между проектами с помощью символических ссылок или подмодулей git. +- Сохраняйте AGENTS.md кратким, ссылаясь на подробные инструкции. +- Убедитесь, что opencode загружает файлы только тогда, когда это необходимо для конкретной задачи. + +:::tip +Для монорепозиториев или проектов с общими стандартами использование `opencode.json` с шаблонами glob (например, `packages/*/AGENTS.md`) более удобно в обслуживании, чем инструкции вручную. +::: diff --git a/packages/web/src/content/docs/ru/sdk.mdx b/packages/web/src/content/docs/ru/sdk.mdx new file mode 100644 index 00000000000..1269d9fc083 --- /dev/null +++ b/packages/web/src/content/docs/ru/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: Типобезопасный JS-клиент для сервера opencode. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +SDK JS/TS с открытым кодом предоставляет типобезопасный клиент для взаимодействия с сервером. +Используйте его для создания интеграции и программного управления открытым кодом. + +[Узнайте больше](/docs/server) о том, как работает сервер. Примеры можно найти в [projects](/docs/ecosystem#projects), созданном сообществом. + +--- + +## Установить + +Установите SDK из npm: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## Создать клиента + +Создайте экземпляр opencode: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +Это запускает и сервер, и клиент. + +#### Параметры + +| Вариант | Тип | Описание | По умолчанию | +| ---------- | ------------- | ------------------------------ | ------------ | +| `hostname` | `string` | Server hostname | `127.0.0.1` | +| `port` | `number` | Server port | `4096` | +| `signal` | `AbortSignal` | Abort signal for cancellation | `undefined` | +| `timeout` | `number` | Timeout in ms for server start | `5000` | +| `config` | `Config` | Configuration object | `{}` | + +--- + +## Конфигурация + +Вы можете передать объект конфигурации для настройки поведения. Экземпляр по-прежнему получает ваш `opencode.json`, но вы можете переопределить или добавить встроенную конфигурацию: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## Только клиент + +Если у вас уже есть работающий экземпляр opencode, вы можете создать экземпляр клиента для подключения к нему: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### Параметры + +| Вариант | Тип | Описание | По умолчанию | +| --------------- | ---------- | -------------------------------- | ----------------------- | +| `baseUrl` | `string` | URL of the server | `http://localhost:4096` | +| `fetch` | `function` | Custom fetch implementation | `globalThis.fetch` | +| `parseAs` | `string` | Response parsing method | `auto` | +| `responseStyle` | `string` | Return style: `data` or `fields` | `fields` | +| `throwOnError` | `boolean` | Throw errors instead of return | `false` | + +--- + +## Типы + +SDK включает определения TypeScript для всех типов API. Импортируйте их напрямую: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +Все типы генерируются на основе спецификации OpenAPI сервера и доступны в файле types. + +--- + +## Ошибки + +SDK может выдавать ошибки, которые вы можете отловить и обработать: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## API + +SDK предоставляет все серверные API через типобезопасный клиент. + +--- + +### Глобальный + +| Метод | Описание | Ответ | +| ----------------- | ------------------------------- | ------------------------------------ | +| `global.health()` | Check server health and version | `{ healthy: true, version: string }` | + +--- + +#### Примеры + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### Приложение + +| Метод | Описание | Ответ | +| -------------- | ------------------------- | ------------------------------------------- | +| `app.log()` | Write a log entry | `boolean` | +| `app.agents()` | List all available agents | Agent[] | + +--- + +#### Примеры + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### Проект + +| Метод | Описание | Ответ | +| ------------------- | ------------------- | --------------------------------------------- | +| `project.list()` | List all projects | Project[] | +| `project.current()` | Get current project | Project | + +--- + +#### Примеры + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### Путь + +| Метод | Описание | Ответ | +| ------------ | ---------------- | ---------------------------------------- | +| `path.get()` | Get current path | Path | + +--- + +#### Примеры + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### Конфигурация + +| Метод | Описание | Ответ | +| -------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | Get config info | Config | +| `config.providers()` | List providers and default models | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### Примеры + +```javascript +const config = await client.config.get() + +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` | + +--- + +#### Примеры + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### Файлы + +| Метод | Описание | Ответ | +| ------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------- | +| `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[] | + +`find.files` поддерживает несколько дополнительных полей запроса: + +- `type`: `"file"` или `"directory"` +- `directory`: переопределить корень проекта для поиска. +- `limit`: максимальное количество результатов (1–200) + +--- + +#### Примеры + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| Метод | Описание | Ответ | +| ------------------------------ | ------------------------- | --------- | +| `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` | + +--- + +#### Примеры + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### Аутентификация + +| Метод | Описание | Ответ | +| ------------------- | ------------------------------ | --------- | +| `auth.set({ ... })` | Set authentication credentials | `boolean` | + +--- + +#### Примеры + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### События + +| Метод | Описание | Ответ | +| ------------------- | ------------------------- | ------------------------- | +| `event.subscribe()` | Server-sent events stream | Server-sent events stream | + +--- + +#### Примеры + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/ru/server.mdx b/packages/web/src/content/docs/ru/server.mdx new file mode 100644 index 00000000000..898789c29ac --- /dev/null +++ b/packages/web/src/content/docs/ru/server.mdx @@ -0,0 +1,287 @@ +--- +title: Сервер +description: Взаимодействуйте с сервером opencode через HTTP. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +Команда `opencode serve` запускает автономный HTTP-сервер, который предоставляет конечную точку OpenAPI, которую может использовать клиент с открытым кодом. + +--- + +### Использование + +```bash +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 | `[]` | + +`--cors` можно передать несколько раз: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### Аутентификация + +Установите `OPENCODE_SERVER_PASSWORD`, чтобы защитить сервер с помощью базовой аутентификации HTTP. Имя пользователя по умолчанию — `opencode` или установите `OPENCODE_SERVER_USERNAME`, чтобы переопределить его. Это относится как к `opencode serve`, так и к `opencode web`. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### Как это работает + +Когда вы запускаете `opencode`, он запускает TUI и сервер. Где находится TUI +клиент, который общается с сервером. Сервер предоставляет спецификацию OpenAPI 3.1. +конечная точка. Эта конечная точка также используется для создания файла [SDK](/docs/sdk). + +:::tip +Используйте сервер opencode для программного взаимодействия с открытым кодом. +::: + +Эта архитектура позволяет открытому коду поддерживать несколько клиентов и позволяет программно взаимодействовать с открытым кодом. + +Вы можете запустить `opencode serve`, чтобы запустить автономный сервер. Если у вас есть +TUI с открытым кодом запущен, `opencode serve` запустит новый сервер. + +--- + +#### Подключиться к существующему серверу + +Когда вы запускаете TUI, он случайным образом назначает порт и имя хоста. Вместо этого вы можете передать `--hostname` и `--port` [flags](/docs/cli). Затем используйте это для подключения к его серверу. + +Конечную точку [`/tui`](#tui) можно использовать для управления TUI через сервер. Например, вы можете предварительно заполнить или запустить подсказку. Эта настройка используется плагинами opencode [IDE](/docs/ide). + +--- + +## Спецификация + +Сервер публикует спецификацию OpenAPI 3.1, которую можно просмотреть по адресу: + +``` +http://:/doc +``` + +For example, `http://localhost:4096/doc`. Use the spec to generate clients or inspect request and response types. Or view it in a Swagger explorer. + +--- + +## API + +Сервер opencode предоставляет следующие API. + +--- + +### Глобальный + +| Метод | Путь | Описание | Ответ | +| ----- | ---------------- | ------------------------------ | ------------------------------------ | +| `GET` | `/global/health` | Get server health and version | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | Get global events (SSE stream) | Event stream | + +--- + +### Проект + +| Метод | Путь | Описание | Ответ | +| ----- | ------------------ | ----------------------- | --------------------------------------------- | +| `GET` | `/project` | List all projects | Project[] | +| `GET` | `/project/current` | Get the current project | Project | + +--- + +### Путь и система контроля версий + +| Метод | Путь | Описание | Ответ | +| ----- | ------- | ------------------------------------ | ------------------------------------------- | +| `GET` | `/path` | Get the current path | Path | +| `GET` | `/vcs` | Get VCS info for the current project | VcsInfo | + +--- + +### Экземпляр + +| Метод | Путь | Описание | Ответ | +| ------ | ------------------- | ---------------------------- | --------- | +| `POST` | `/instance/dispose` | Dispose the current instance | `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` | `/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` | `/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/: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` | `/command` | List all commands | 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[] | + +#### `/find/file` параметры запроса + +- `query` (обязательно) — строка поиска (нечеткое совпадение) +- `type` (необязательно) — ограничить результаты `"file"` или `"directory"`. +- `directory` (необязательно) — переопределить корень проекта для поиска. +- `limit` (необязательно) — максимальное количество результатов (1–200) +- `dirs` (необязательно) — устаревший флаг (`"false"` возвращает только файлы) + +--- + +### Инструменты (Экспериментальные) + +| Метод | Путь | Описание | Ответ | +| ----- | ------------------------------------------- | ---------------------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | List all tool IDs | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | List tools with JSON schemas for a model | 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` | `/agent` | List all available agents | Agent[] | + +--- + +### Ведение журнала + +| Метод | Путь | Описание | Ответ | +| ------ | ------ | ------------------------------------------------------------ | --------- | +| `POST` | `/log` | Write log entry. 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` | + +--- + +### Авторизация + +| Метод | Путь | Описание | Ответ | +| ----- | ----------- | --------------------------------------------------------------- | --------- | +| `PUT` | `/auth/:id` | Set authentication credentials. Body must match provider schema | `boolean` | + +--- + +### События + +| Метод | Путь | Описание | Ответ | +| ----- | -------- | ----------------------------------------------------------------------------- | ------------------------- | +| `GET` | `/event` | Server-sent events stream. First event is `server.connected`, then bus events | Server-sent events stream | + +--- + +### Документы + +| Метод | Путь | Описание | Ответ | +| ----- | ------ | ------------------------- | --------------------------- | +| `GET` | `/doc` | OpenAPI 3.1 specification | HTML page with OpenAPI spec | diff --git a/packages/web/src/content/docs/ru/share.mdx b/packages/web/src/content/docs/ru/share.mdx new file mode 100644 index 00000000000..c4df3b6a703 --- /dev/null +++ b/packages/web/src/content/docs/ru/share.mdx @@ -0,0 +1,128 @@ +--- +title: Делиться +description: Поделитесь своими разговорами об opencode. +--- + +Функция общего доступа opencode позволяет вам создавать общедоступные ссылки на ваши беседы opencode, чтобы вы могли сотрудничать с товарищами по команде или получать помощь от других. + +:::note +Общие беседы общедоступны для всех, у кого есть ссылка. +::: + +--- + +## Как это работает + +Когда вы делитесь беседой, opencode: + +1. Создает уникальный общедоступный URL-адрес для вашего сеанса. +2. Синхронизирует историю ваших разговоров с нашими серверами +3. Делает беседу доступной по общей ссылке — `opncd.ai/s/`. + +--- + +## Совместное использование + +opencode поддерживает три режима общего доступа, которые контролируют общий доступ к разговорам: + +--- + +### Ручной (по умолчанию) + +По умолчанию opencode использует режим совместного использования вручную. Сессии не передаются автоматически, но вы можете поделиться ими вручную с помощью команды `/share`: + +``` +/share +``` + +Это создаст уникальный URL-адрес, который будет скопирован в буфер обмена. + +Чтобы явно установить ручной режим в вашем [файле конфигурации](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### Автоматическая публикация + +Вы можете включить автоматический общий доступ для всех новых разговоров, установив для параметра `share` значение `"auto"` в вашем [файле конфигурации](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +Если функция автоматического обмена включена, каждый новый разговор будет автоматически опубликован и будет создана ссылка. + +--- + +### Отключено + +Вы можете полностью отключить общий доступ, установив для параметра `share` значение `"disabled"` в вашем [файле конфигурации](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +Чтобы обеспечить соблюдение этого правила для всей вашей команды в конкретном проекте, добавьте его в `opencode.json` вашего проекта и зарегистрируйтесь в Git. + +--- + +## Отменить совместное использование + +Чтобы прекратить делиться беседой и удалить ее из общего доступа: + +``` +/unshare +``` + +Это приведет к удалению ссылки общего доступа и удалению данных, связанных с разговором. + +--- + +## Конфиденциальность + +Есть несколько вещей, которые следует учитывать при общении. + +--- + +### Хранение данных + +Общие разговоры остаются доступными до тех пор, пока вы явно не отмените общий доступ к ним. Этот +включает в себя: + +- Полная история разговоров +- Все сообщения и ответы +- Метаданные сеанса + +--- + +### Рекомендации + +- Делитесь только разговорами, которые не содержат конфиденциальной информации. +- Прежде чем поделиться, просмотрите содержимое разговора. +- Отмените общий доступ к разговорам после завершения сотрудничества. +- Избегайте обмена разговорами с проприетарным кодом или конфиденциальными данными. +- Для конфиденциальных проектов полностью отключите общий доступ. + +--- + +## Для предприятий + +Для корпоративных развертываний функция общего доступа может быть: + +- **Отключено** полностью из соображений безопасности. +- **Доступно только** для пользователей, прошедших аутентификацию посредством единого входа. +- **Автономное размещение** в вашей собственной инфраструктуре + +[Узнайте больше](/docs/enterprise) об использовании opencode в вашей организации. diff --git a/packages/web/src/content/docs/ru/skills.mdx b/packages/web/src/content/docs/ru/skills.mdx new file mode 100644 index 00000000000..152e48782bc --- /dev/null +++ b/packages/web/src/content/docs/ru/skills.mdx @@ -0,0 +1,222 @@ +--- +title: Навыки агента +description: Определите повторно используемое поведение с помощью определений SKILL.md +--- + +Навыки агента позволяют opencode обнаруживать многократно используемые инструкции из вашего репозитория или домашнего каталога. +Навыки загружаются по требованию с помощью встроенного инструмента `skill`: агенты видят доступные навыки и при необходимости могут загрузить весь контент. + +--- + +## Разместить файлы + +Создайте одну папку для каждого имени навыка и поместите в нее `SKILL.md`. +opencode выполняет поиск в следующих местах: + +- Конфигурация проекта: `.opencode/skills//SKILL.md` +- Глобальная конфигурация: `~/.config/opencode/skills//SKILL.md`. +- Совместимость с Project Claude: `.claude/skills//SKILL.md` +- Глобальная совместимость с Claude: `~/.claude/skills//SKILL.md` +- Совместимость с агентом проекта: `.agents/skills//SKILL.md` +- Совместимость с глобальным агентом: `~/.agents/skills//SKILL.md` + +--- + +## Понимание обнаружения + +Для локальных путей проекта opencode переходит из вашего текущего рабочего каталога, пока не достигнет рабочего дерева git. +Он загружает все соответствующие `skills/*/SKILL.md` в `.opencode/` и все соответствующие `.claude/skills/*/SKILL.md` или `.agents/skills/*/SKILL.md` по пути. + +Глобальные определения также загружаются из `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md` и `~/.agents/skills/*/SKILL.md`. + +--- + +## Напишите заголовок + +Каждый `SKILL.md` должен начинаться с заголовка YAML. +Распознаются только эти поля: + +- `name` (required) +- `description` (required) +- `license` (необязательно) +- `compatibility` (необязательно) +- `metadata` (необязательно, преобразование строк в строки) + +Неизвестные поля заголовка игнорируются. + +--- + +## Проверка имен + +`name` должен: + +- Длина от 1 до 64 символов. +- Используйте строчные буквы и цифры с одинарным дефисом. +- Не начинаться и не заканчиваться на `-`. +- Не содержать последовательных `--` +- Сопоставьте имя каталога, содержащее `SKILL.md`. + +Эквивалентное регулярное выражение: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## Соблюдайте правила длины + +`description` должно содержать от 1 до 1024 символов. +Держите его достаточно конкретным, чтобы агент мог сделать правильный выбор. + +--- + +## Используйте пример + +Создайте `.opencode/skills/git-release/SKILL.md` следующим образом: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## Распознавание описания инструмента + +opencode перечисляет доступные навыки в описании инструмента `skill`. +Каждая запись включает название и описание навыка: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +Агент загружает навык, вызывая инструмент: + +``` +skill({ name: "git-release" }) +``` + +--- + +## Настройка разрешений + +Контролируйте, к каким навыкам агенты могут получить доступ, используя разрешения на основе шаблонов в `opencode.json`: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| Разрешение | Поведение | +| ---------- | ----------------------------------------- | +| `allow` | Skill loads immediately | +| `deny` | Skill hidden from agent, access rejected | +| `ask` | User prompted for approval before loading | + +Шаблоны поддерживают подстановочные знаки: `internal-*` соответствует `internal-docs`, `internal-tools` и т. д. + +--- + +## Переопределить для каждого агента + +Предоставьте конкретным агентам разрешения, отличные от глобальных настроек по умолчанию. + +**Для пользовательских агентов** (в заголовке агента): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**Для встроенных агентов** (в формате `opencode.json`): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## Отключить инструмент навыков + +Полностью отключить навыки для агентов, которым не следует их использовать: + +**Для индивидуальных агентов**: + +```yaml +--- +tools: + skill: false +--- +``` + +**Для встроенных агентов**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +Если этот параметр отключен, раздел `` полностью опускается. + +--- + +## Устранение неполадок с загрузкой + +Если навык не отображается: + +1. Убедитесь, что `SKILL.md` написано заглавными буквами. +2. Убедитесь, что заголовок включает `name` и `description`. +3. Убедитесь, что названия навыков уникальны во всех локациях. +4. Проверьте разрешения — навыки с `deny` скрыты от агентов. diff --git a/packages/web/src/content/docs/ru/themes.mdx b/packages/web/src/content/docs/ru/themes.mdx new file mode 100644 index 00000000000..2e5219e4c5a --- /dev/null +++ b/packages/web/src/content/docs/ru/themes.mdx @@ -0,0 +1,369 @@ +--- +title: Темы +description: Выберите встроенную тему или определите свою собственную. +--- + +С помощью opencode вы можете выбрать одну из нескольких встроенных тем, использовать тему, которая адаптируется к теме вашего терминала, или определить свою собственную тему. + +По умолчанию opencode использует нашу собственную тему `opencode`. + +--- + +## Требования к терминалу + +Чтобы темы корректно отображались в полной цветовой палитре, ваш терминал должен поддерживать **truecolor** (24-битный цвет). Большинство современных терминалов поддерживают это по умолчанию, но вам может потребоваться включить его: + +- **Проверьте поддержку**: запустите `echo $COLORTERM` — должен появиться `truecolor` или `24bit`. +- **Включить truecolor**: установите переменную среды `COLORTERM=truecolor` в профиле shell. +- **Совместимость терминала**: убедитесь, что ваш эмулятор терминала поддерживает 24-битный цвет (большинство современных терминалов, таких как iTerm2, Alacritty, Kitty, Windows Terminal и последние версии GNOME Terminal, поддерживают). + +Без поддержки truecolor темы могут отображаться с пониженной точностью цветопередачи или вернуться к ближайшему приближению к 256 цветам. + +--- + +## Встроенные темы + +opencode поставляется с несколькими встроенными темами. + +| Имя | Описание | +| ---------------------- | ---------------------------------------------------------------------------- | +| `system` | Адаптируется к фоновому цвету терминала | +| `tokyonight` | Based on the [tokyonight](https://github.com/folke/tokyonight.nvim) theme | +| `everforest` | Based on the [Everforest](https://github.com/sainnhe/everforest) theme | +| `ayu` | Based on the [Ayu](https://github.com/ayu-theme) dark theme | +| `catppuccin` | Based on the [Catppuccin](https://github.com/catppuccin) theme | +| `catppuccin-macchiato` | Based on the [Catppuccin](https://github.com/catppuccin) theme | +| `gruvbox` | Based on the [Gruvbox](https://github.com/morhetz/gruvbox) theme | +| `kanagawa` | Based on the [Kanagawa](https://github.com/rebelot/kanagawa.nvim) theme | +| `nord` | Based on the [Nord](https://github.com/nordtheme/nord) theme | +| `matrix` | Хакерская тема: зеленый на черном | +| `one-dark` | Based on the [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark theme | + +И более того, мы постоянно добавляем новые темы. + +--- + +## Системная тема + +Тема `system` автоматически адаптируется к цветовой схеме вашего терминала. В отличие от традиционных тем, использующих фиксированные цвета, тема _system_: + +- **Создает шкалу серого**: создает пользовательскую шкалу серого на основе цвета фона вашего терминала, обеспечивая оптимальный контраст. +- **Использует цвета ANSI**: использует стандартные цвета ANSI (0–15) для подсветки синтаксиса и элементов пользовательского интерфейса, которые соответствуют цветовой палитре вашего терминала. +- **Сохраняет настройки терминала по умолчанию**: использует `none` для цветов текста и фона, чтобы сохранить естественный вид вашего терминала. + +Системная тема предназначена для пользователей, которые: + +- Хотите, чтобы opencode соответствовал внешнему виду их терминала +- Используйте пользовательские цветовые схемы терминала +- Предпочитайте единообразный вид для всех терминальных приложений. + +--- + +## Использование темы + +Вы можете выбрать тему, вызвав выбор темы с помощью команды `/theme`. Или вы можете указать это в файле [config](/docs/config). + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## Пользовательские темы + +opencode поддерживает гибкую систему тем на основе JSON, которая позволяет пользователям легко создавать и настраивать темы. + +--- + +### Иерархия + +Темы загружаются из нескольких каталогов в следующем порядке: более поздние каталоги переопределяют предыдущие: + +1. **Встроенные темы** – они встроены в двоичный файл. +2. **Каталог конфигурации пользователя** – определяется в `~/.config/opencode/themes/*.json` или `$XDG_CONFIG_HOME/opencode/themes/*.json`. +3. **Корневой каталог проекта** – определено в `/.opencode/themes/*.json`. +4. **Текущий рабочий каталог** – определено в `./.opencode/themes/*.json`. + +Если несколько каталогов содержат тему с одинаковым именем, будет использоваться тема из каталога с более высоким приоритетом. + +--- + +### Создание темы + +Чтобы создать собственную тему, создайте файл JSON в одном из каталогов темы. + +Для глобальных тем: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +Для тем проекта: + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### Формат JSON + +В темах используется гибкий формат JSON с поддержкой: + +- **Шестнадцатеричные цвета**: `"#ffffff"` +- **Цвета ANSI**: `3` (0–255). +- **Ссылки на цвета**: `"primary"` или пользовательские определения. +- **Темный/светлый варианты**: `{"dark": "#000", "light": "#fff"}` +- **Нет цвета**: `"none"` — используется цвет терминала по умолчанию или прозрачный. + +--- + +### Определения цвета + +Раздел `defs` является необязательным и позволяет вам определять повторно используемые цвета, на которые можно ссылаться в теме. + +--- + +### Настройки терминала по умолчанию + +Специальное значение `"none"` можно использовать для любого цвета, чтобы наследовать цвет терминала по умолчанию. Это особенно полезно для создания тем, которые органично сочетаются с цветовой схемой вашего терминала: + +- `"text": "none"` — использует цвет переднего плана терминала по умолчанию. +- `"background": "none"` — использует цвет фона терминала по умолчанию. + +--- + +### Пример + +Вот пример пользовательской темы: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/ru/tools.mdx b/packages/web/src/content/docs/ru/tools.mdx new file mode 100644 index 00000000000..333216b3749 --- /dev/null +++ b/packages/web/src/content/docs/ru/tools.mdx @@ -0,0 +1,379 @@ +--- +title: Инструменты +description: Управляйте инструментами, которые может использовать LLM. +--- + +Инструменты позволяют LLM выполнять действия в вашей кодовой базе. opencode поставляется с набором встроенных инструментов, но вы можете расширить его с помощью [пользовательских инструментов](/docs/custom-tools) или [MCP-серверов](/docs/mcp-servers). + +По умолчанию все инструменты **включены** и не требуют разрешения для запуска. Вы можете контролировать поведение инструмента через [permissions](/docs/permissions). + +--- + +## Настройка + +Используйте поле `permission` для управления поведением инструмента. Вы можете разрешить, запретить или потребовать одобрения для каждого инструмента. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +Вы также можете использовать подстановочные знаки для одновременного управления несколькими инструментами. Например, чтобы потребовать одобрения всех инструментов с сервера MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[Подробнее](/docs/permissions) о настройке разрешений. + +--- + +## Встроенный + +Вот все встроенные инструменты, доступные в opencode. + +--- + +### bash + +Выполняйте shell-команды в среде вашего проекта. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +Этот инструмент позволяет LLM запускать команды терминала, такие как `npm install`, `git status` или любую другую shell-команду. + +--- + +### edit + +Измените существующие файлы, используя точную замену строк. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Этот инструмент выполняет точное редактирование файлов, заменяя точные совпадения текста. Это основной способ изменения кода в LLM. + +--- + +### write + +Создавайте новые файлы или перезаписывайте существующие. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Используйте это, чтобы позволить LLM создавать новые файлы. Он перезапишет существующие файлы, если они уже существуют. + +:::note +Инструмент `write` контролируется разрешением `edit`, которое распространяется на все модификации файлов (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### read + +Прочитайте содержимое файла из вашей кодовой базы. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +Этот инструмент читает файлы и возвращает их содержимое. Он поддерживает чтение определенных диапазонов строк для больших файлов. + +--- + +### grep + +Поиск содержимого файла с помощью регулярных выражений. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +Быстрый поиск контента по вашей кодовой базе. Поддерживает полный синтаксис регулярных выражений и фильтрацию шаблонов файлов. + +--- + +### glob + +Найдите файлы по шаблону. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +Ищите файлы, используя шаблоны glob, например `**/*.js` или `src/**/*.ts`. Возвращает соответствующие пути к файлам, отсортированные по времени изменения. + +--- + +### list + +Список файлов и каталогов по заданному пути. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +Этот инструмент отображает содержимое каталога. Он принимает шаблоны glob для фильтрации результатов. + +--- + +### lsp (экспериментальный) + +Взаимодействуйте с настроенными серверами LSP, чтобы получить функции анализа кода, такие как определения, ссылки, информация о наведении и иерархия вызовов. + +:::note +Этот инструмент доступен только при `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (или `OPENCODE_EXPERIMENTAL=true`). +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +Поддерживаемые операции включают `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls` и `outgoingCalls`. + +Чтобы настроить серверы LSP, доступные для вашего проекта, см. [LSP Servers](/docs/lsp). + +--- + +### patch + +Применяйте патчи к файлам. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Этот инструмент применяет файлы исправлений к вашей кодовой базе. Полезно для применения различий и патчей из различных источников. + +:::note +Инструмент `patch` контролируется разрешением `edit`, которое распространяется на все модификации файлов (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### skill + +Загрузите [skill](/docs/skills) (файл `SKILL.md`) и верните его содержимое в диалог. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +Управляйте списками дел во время сеансов кодирования. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +Создает и обновляет списки задач для отслеживания прогресса во время сложных операций. LLM использует это для организации многоэтапных задач. + +:::note +По умолчанию этот инструмент отключен для субагентов, но вы можете включить его вручную. [Подробнее](/docs/agents/#permissions) +::: + +--- + +### todoread + +Прочтите существующие списки дел. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +Считывает текущее состояние списка дел. Используется LLM для отслеживания задач, ожидающих или завершенных. + +:::note +По умолчанию этот инструмент отключен для субагентов, но вы можете включить его вручную. [Подробнее](/docs/agents/#permissions) +::: + +--- + +### webfetch + +Получить веб-контент. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +Позволяет LLM получать и читать веб-страницы. Полезно для поиска документации или исследования онлайн-ресурсов. + +--- + +### websearch + +Найдите информацию в Интернете. + +:::note +Этот инструмент доступен только при использовании поставщика opencode или когда для переменной среды `OPENCODE_ENABLE_EXA` установлено любое истинное значение (например, `true` или `1`). + +Чтобы включить при запуске opencode: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +Выполняет поиск в Интернете с помощью Exa AI для поиска соответствующей информации в Интернете. Полезно для исследования тем, поиска текущих событий или сбора информации, выходящей за рамки данных обучения. + +Ключ API не требуется — инструмент подключается напрямую к сервису MCP, размещенному на Exa AI, без аутентификации. + +:::tip +Используйте `websearch`, когда вам нужно найти информацию (обнаружение), и `webfetch`, когда вам нужно получить контент с определенного URL-адреса (извлечение). +::: + +--- + +### question + +Задавайте вопросы пользователю во время выполнения. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +Этот инструмент позволяет LLM задавать вопросы пользователю во время выполнения задачи. Это полезно для: + +- Сбор предпочтений или требований пользователей +- Уточнение двусмысленных инструкций +- Получение решений по вариантам реализации +- Предлагая выбор, в каком направлении двигаться + +Каждый вопрос включает заголовок, текст вопроса и список вариантов. Пользователи могут выбрать один из предложенных вариантов или ввести собственный ответ. Если вопросов несколько, пользователи могут перемещаться между ними, прежде чем отправлять все ответы. + +--- + +## Пользовательские инструменты + +Пользовательские инструменты позволяют вам определять собственные функции, которые может вызывать LLM. Они определены в вашем файле конфигурации и могут выполнять произвольный код. + +[Подробнее](/docs/custom-tools) о создании собственных инструментов. + +--- + +## MCP-серверы + +Серверы MCP (Model Context Protocol) позволяют интегрировать внешние инструменты и сервисы. Сюда входит доступ к базе данных, интеграция API и сторонние сервисы. + +[Подробнее](/docs/mcp-servers) о настройке серверов MCP. + +--- + +## Внутреннее устройство + +Внутренне такие инструменты, как `grep`, `glob` и `list`, используют [ripgrep](https://github.com/BurntSushi/ripgrep). По умолчанию ripgrep учитывает шаблоны `.gitignore`, что означает, что файлы и каталоги, перечисленные в вашем `.gitignore`, будут исключены из поиска и списков. + +--- + +### Игнорировать шаблоны + +Чтобы включить файлы, которые обычно игнорируются, создайте файл `.ignore` в корне вашего проекта. Этот файл может явно разрешать определенные пути. + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +Например, этот файл `.ignore` позволяет ripgrep выполнять поиск в каталогах `node_modules/`, `dist/` и `build/`, даже если они указаны в `.gitignore`. diff --git a/packages/web/src/content/docs/ru/troubleshooting.mdx b/packages/web/src/content/docs/ru/troubleshooting.mdx new file mode 100644 index 00000000000..d1d240cb713 --- /dev/null +++ b/packages/web/src/content/docs/ru/troubleshooting.mdx @@ -0,0 +1,300 @@ +--- +title: Поиск неисправностей +description: Распространенные проблемы и способы их решения. +--- + +Чтобы устранить проблемы с opencode, начните с проверки журналов и локальных данных, которые он хранит на диске. + +--- + +## Журналы + +Лог-файлы записываются в: + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: нажмите `WIN+R` и вставьте `%USERPROFILE%\.local\share\opencode\log`. + +Файлам журналов присваиваются имена с метками времени (например, `2025-01-09T123456.log`), и сохраняются 10 последних файлов журналов. + +Вы можете установить уровень журнала с помощью CLI-параметра `--log-level`, чтобы получить более подробную информацию об отладке. Например, `opencode --log-level DEBUG`. + +--- + +## Хранилище + +opencode хранит данные сеанса и другие данные приложения на диске по адресу: + +- **macOS/Linux**: `~/.local/share/opencode/` +- **Windows**: нажмите `WIN+R` и вставьте `%USERPROFILE%\.local\share\opencode`. + +Этот каталог содержит: + +- `auth.json` – данные аутентификации, такие как ключи API и токены OAuth. +- `log/` – журналы приложений. +- `project/` — данные, специфичные для проекта, такие как данные сеанса и сообщения. + - Если проект находится в репозитории Git, он хранится в `.//storage/`. + - Если это не репозиторий Git, он хранится в `./global/storage/`. + +--- + +## Настольное приложение + +opencode Desktop запускает локальный сервер opencode (спутник `opencode-cli`) в фоновом режиме. Большинство проблем вызвано неправильно работающим плагином, поврежденным кешем или неверными настройками сервера. + +### Быстрые проверки + +- Полностью закройте и перезапустите приложение. +- Если приложение отображает экран с ошибкой, нажмите **Перезапустить** и скопируйте сведения об ошибке. +- Только для macOS: меню `OpenCode` -> **Обновить веб-просмотр** (помогает, если пользовательский интерфейс пуст или завис). + +--- + +### Отключить плагины + +Если настольное приложение дает сбой при запуске, зависает или ведет себя странно, начните с отключения плагинов. + +#### Проверьте глобальную конфигурацию + +Откройте файл глобальной конфигурации и найдите ключ `plugin`. + +- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (или `~/.config/opencode/opencode.json`) +- **macOS/Linux** (более ранние версии): `~/.local/share/opencode/opencode.jsonc` +- **Windows**: нажмите `WIN+R` и вставьте `%USERPROFILE%\.config\opencode\opencode.jsonc`. + +Если у вас настроены плагины, временно отключите их, удалив ключ или установив для него пустой массив: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### Проверьте каталоги плагинов + +opencode также может загружать локальные плагины с диска. Временно переместите их в сторону (или переименуйте папку) и перезапустите настольное приложение: + +- **Глобальные плагины** + - **macOS/Linux**: `~/.config/opencode/plugins/` + - **Windows**: нажмите `WIN+R` и вставьте `%USERPROFILE%\.config\opencode\plugins`. +- **Плагины проекта** (только если вы используете конфигурацию для каждого проекта) + - `/.opencode/plugins/` + +Если приложение снова начнет работать, повторно включите плагины по одному, чтобы определить, какой из них вызывает проблему. + +--- + +### Очистить кеш + +Если отключение плагинов не помогает (или установка плагина зависла), очистите кеш, чтобы opencode мог его пересобрать. + +1. Полностью закройте opencode Desktop. +2. Удалите каталог кэша: + +- **macOS**: Finder -> `Cmd+Shift+G` -> вставить `~/.cache/opencode`. +- **Linux**: удалите `~/.cache/opencode` (или запустите `rm -rf ~/.cache/opencode`). +- **Windows**: нажмите `WIN+R` и вставьте `%USERPROFILE%\.cache\opencode`. + +3. Перезапустите рабочий стол opencode. + +--- + +### Исправить проблемы с подключением к серверу + +opencode Desktop может либо запустить собственный локальный сервер (по умолчанию), либо подключиться к настроенному вами URL-адресу сервера. + +Если вы видите диалоговое окно **Ошибка подключения** (или приложение никогда не выходит за пределы заставки), проверьте URL-адрес пользовательского сервера. + +#### Очистите URL-адрес сервера по умолчанию для рабочего стола. + +На главном экране щелкните имя сервера (с точкой состояния), чтобы открыть окно выбора сервера. В разделе **Сервер по умолчанию** нажмите **Очистить**. + +#### Удалите `server.port`/`server.hostname` из вашей конфигурации. + +Если ваш `opencode.json(c)` содержит раздел `server`, временно удалите его и перезапустите настольное приложение. + +#### Проверьте переменные среды + +Если в вашей среде установлен `OPENCODE_PORT`, настольное приложение попытается использовать этот порт для локального сервера. + +- Отмените настройку `OPENCODE_PORT` (или выберите свободный порт) и перезапустите. + +--- + +### Linux: проблемы с Wayland/X11 + +В Linux некоторые настройки Wayland могут вызывать пустые окна или ошибки компоновщика. + +- Если вы используете Wayland, а приложение не работает или вылетает, попробуйте запустить с помощью `OC_ALLOW_WAYLAND=1`. +- Если это усугубляет ситуацию, удалите его и попробуйте вместо этого запустить сеанс X11. + +--- + +### Windows: среда выполнения WebView2. + +В Windows для opencode Desktop требуется Microsoft Edge **WebView2 Runtime**. Если приложение открывается в пустом окне или не запускается, установите/обновите WebView2 и повторите попытку. + +--- + +### Windows: общие проблемы с производительностью + +Если вы испытываете низкую производительность, проблемы с доступом к файлам или проблемы с terminal в Windows, попробуйте использовать [WSL (подсистема Windows для Linux)](/docs/windows-wsl). WSL предоставляет среду Linux, которая более эффективно работает с функциями opencode. + +--- + +### Уведомления не отображаются + +opencode Desktop отображает системные уведомления только в следующих случаях: + +- уведомления для opencode включены в настройках вашей ОС, и +- окно приложения не в фокусе. + +--- + +### Сбросить хранилище настольных приложений (последнее средство) + +Если приложение не запускается и вы не можете очистить настройки из пользовательского интерфейса, сбросьте сохраненное состояние настольного приложения. + +1. Закройте рабочий стол opencode. +2. Найдите и удалите эти файлы (они находятся в каталоге данных приложения opencode Desktop): + +- `opencode.settings.dat` (URL-адрес сервера по умолчанию для рабочего стола) +- `opencode.global.dat` и `opencode.workspace.*.dat` (состояние пользовательского интерфейса, например, недавние серверы/проекты) + +Чтобы быстро найти каталог: + +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (затем найдите имена файлов, указанные выше) +- **Linux**: найдите в `~/.local/share` имена файлов, указанные выше. +- **Windows**: нажмите `WIN+R` -> `%APPDATA%` (затем найдите имена файлов, указанные выше). + +--- + +## Получение помощи + +Если у вас возникли проблемы с opencode: + +1. **Сообщайте о проблемах на GitHub** + + Лучший способ сообщить об ошибках или запросить новые функции — через наш репозиторий GitHub: + + [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + + Прежде чем создавать новую проблему, выполните поиск по существующим проблемам, чтобы узнать, не сообщалось ли уже о вашей проблеме. + +2. **Присоединяйтесь к нашему Discord** + + Для получения помощи в режиме реального времени и обсуждения в сообществе присоединяйтесь к нашему серверу Discord: + + [**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## Общие проблемы + +Вот некоторые распространенные проблемы и способы их решения. + +--- + +### opencode не запускается + +1. Проверьте журналы на наличие сообщений об ошибках +2. Попробуйте запустить `--print-logs`, чтобы увидеть вывод в terminal. +3. Убедитесь, что у вас установлена ​​последняя версия `opencode upgrade`. + +--- + +### Проблемы аутентификации + +1. Попробуйте выполнить повторную аутентификацию с помощью команды `/connect` в TUI. +2. Убедитесь, что ваши ключи API действительны +3. Убедитесь, что ваша сеть разрешает подключения к API провайдера. + +--- + +### Модель недоступна + +1. Убедитесь, что вы прошли аутентификацию у провайдера +2. Проверьте правильность названия модели в вашей конфигурации. +3. Для некоторых моделей может потребоваться специальный доступ или подписка. + +Если вы столкнулись с `ProviderModelNotFoundError`, вы, скорее всего, ошибаетесь. +ссылка на модель где-то. +На модели следует ссылаться следующим образом: `/`. + +Примеры: + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +Чтобы выяснить, к каким моделям у вас есть доступ, запустите `opencode models`. + +--- + +### ProviderInitError + +Если вы столкнулись с ошибкой ProviderInitError, скорее всего, у вас неверная или поврежденная конфигурация. + +Чтобы решить эту проблему: + +1. Сначала убедитесь, что ваш провайдер настроен правильно, следуя [руководству провайдеров](/docs/providers) +2. Если проблема не устранена, попробуйте очистить сохраненную конфигурацию: + + ```bash + rm -rf ~/.local/share/opencode + ``` + + В Windows нажмите `WIN+R` и удалите: `%USERPROFILE%\.local\share\opencode`. + +3. Повторно выполните аутентификацию у своего провайдера, используя команду `/connect` в TUI. + +--- + +### AI_APICallError и проблемы с пакетом провайдера + +Если вы столкнулись с ошибками вызова API, это может быть связано с устаревшими пакетами провайдера. opencode динамически устанавливает пакеты провайдеров (OpenAI, Anthropic, Google и т. д.) по мере необходимости и кэширует их локально. + +Чтобы решить проблемы с пакетом поставщика: + +1. Очистите кеш пакетов провайдера: + + ```bash + rm -rf ~/.cache/opencode + ``` + + В Windows нажмите `WIN+R` и удалите: `%USERPROFILE%\.cache\opencode`. + +2. Перезапустите opencode, чтобы переустановить последние пакеты поставщиков. + +Это заставит opencode загружать самые последние версии пакетов провайдеров, что часто решает проблемы совместимости с параметрами модели и изменениями API. + +--- + +### Копирование/вставка не работает в Linux + +Для работы функций копирования/вставки пользователям Linux необходимо установить одну из следующих утилит буфера обмена: + +**Для систем X11:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**Для систем Wayland:** + +```bash +apt install -y wl-clipboard +``` + +**Для headless-сред:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +opencode определит, используете ли вы Wayland и предпочитаете `wl-clipboard`, в противном случае он попытается найти инструменты буфера обмена в порядке: `xclip` и `xsel`. diff --git a/packages/web/src/content/docs/ru/tui.mdx b/packages/web/src/content/docs/ru/tui.mdx new file mode 100644 index 00000000000..0134e29c482 --- /dev/null +++ b/packages/web/src/content/docs/ru/tui.mdx @@ -0,0 +1,390 @@ +--- +title: TUI +description: Использование TUI opencode. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +opencode предоставляет интерактивный terminal интерфейс или TUI для работы над вашими проектами с помощью LLM. + +Запуск opencode запускает TUI для текущего каталога. + +```bash +opencode +``` + +Или вы можете запустить его для определенного рабочего каталога. + +```bash +opencode /path/to/project +``` + +Как только вы окажетесь в TUI, вы можете запросить его с помощью сообщения. + +```text +Give me a quick summary of the codebase. +``` + +--- + +## Ссылки на файлы + +Вы можете ссылаться на файлы в своих сообщениях, используя `@`. Это выполняет нечеткий поиск файлов в текущем рабочем каталоге. + +:::tip +Вы также можете использовать `@` для ссылки на файлы в своих сообщениях. +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +Содержимое файла добавляется в беседу автоматически. + +--- + +## Bash-команды + +Начните сообщение с `!`, чтобы запустить shell-команду. + +```bash frame="none" +!ls -la +``` + +Вывод команды добавляется в диалог как результат работы инструмента. + +--- + +## Команды + +При использовании opencode TUI вы можете ввести `/`, а затем имя команды, чтобы быстро выполнить действия. Например: + +```bash frame="none" +/help +``` + +Большинство команд также имеют привязку клавиш с использованием `ctrl+x` в качестве ведущей клавиши, где `ctrl+x` — это ведущая клавиша по умолчанию. [Подробнее ](/docs/keybinds). + +Вот все доступные слэш-команды: + +--- + +### connect + +Добавьте провайдера в opencode. Позволяет выбирать из доступных поставщиков и добавлять их ключи API. + +```bash frame="none" +/connect +``` + +--- + +### compact + +Сжать текущий сеанс. _Псевдоним_: `/summarize` + +```bash frame="none" +/compact +``` + +**Привязка клавиш:** `ctrl+x c` + +--- + +### details + +Переключить детали выполнения инструмента. + +```bash frame="none" +/details +``` + +**Привязка клавиш:** `ctrl+x d` + +--- + +### editor + +Открыть внешний редактор для составления сообщений. Использует редактор, установленный в переменной среды `EDITOR`. [Подробнее ](#editor-setup). + +```bash frame="none" +/editor +``` + +**Привязка клавиш:** `ctrl+x e` + +--- + +### exit + +Выйдите из opencode. _Псевдонимы_: `/quit`, `/q` + +```bash frame="none" +/exit +``` + +**Привязка клавиш:** `ctrl+x q` + +--- + +### export + +Экспортируйте текущий разговор в Markdown и откройте его в редакторе по умолчанию. Использует редактор, установленный в переменной среды `EDITOR`. [Подробнее ](#editor-setup). + +```bash frame="none" +/export +``` + +**Привязка клавиш:** `ctrl+x x` + +--- + +### help + +Показать диалоговое окно помощи. + +```bash frame="none" +/help +``` + +**Привязка клавиш:** `ctrl+x h` + +--- + +### init + +Создайте или обновите файл `AGENTS.md`. [Подробнее ](/docs/rules). + +```bash frame="none" +/init +``` + +**Привязка клавиш:** `ctrl+x i` + +--- + +### models + +Перечислите доступные модели. + +```bash frame="none" +/models +``` + +**Привязка клавиш:** `ctrl+x m` + +--- + +### new + +Начать новый сеанс. _Псевдоним_: `/clear` + +```bash frame="none" +/new +``` + +**Привязка клавиш:** `ctrl+x n` + +--- + +### redo + +Повторить ранее отмененное сообщение. Доступно только после использования `/undo`. + +:::tip +Любые изменения файлов также будут восстановлены. +::: + +Внутри это использует Git для управления изменениями файлов. Итак, ваш проект ** должен +быть репозиторием Git**. + +```bash frame="none" +/redo +``` + +**Привязка клавиш:** `ctrl+x r` + +--- + +### sessions + +Составляйте список и переключайтесь между сеансами. _Псевдонимы_: `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +**Привязка клавиш:** `ctrl+x l` + +--- + +### share + +Поделиться текущим сеансом. [Подробнее](/docs/share). + +```bash frame="none" +/share +``` + +**Привязка клавиш:** `ctrl+x s` + +--- + +### theme + +Список доступных тем. + +```bash frame="none" +/theme +``` + +**Привязка клавиш:** `ctrl+x t` + +--- + +### thinking + +Переключить видимость блоков мышления/рассуждения в разговоре. Если этот параметр включен, вы можете увидеть процесс рассуждения модели для моделей, поддерживающих расширенное мышление. + +:::note +Эта команда только контролирует, будут ли **отображаться** блоки мышления, но не включает и не отключает возможности модели по рассуждению. Чтобы переключить фактические возможности рассуждения, используйте `ctrl+t` для циклического переключения вариантов модели. +::: + +```bash frame="none" +/thinking +``` + +--- + +### undo + +Отменить последнее сообщение в разговоре. Удаляет самое последнее сообщение пользователя, все последующие ответы и любые изменения файлов. + +:::tip +Любые внесенные изменения в файле также будут отменены. +::: + +Внутри это использует Git для управления изменениями файлов. Итак, ваш проект ** должен +быть репозиторием Git**. + +```bash frame="none" +/undo +``` + +**Привязка клавиш:** `ctrl+x u` + +--- + +### unshare + +Отменить общий доступ к текущему сеансу. [Подробнее](/docs/share#un-sharing). + +```bash frame="none" +/unshare +``` + +--- + +## Настройка редактора + +Команды `/editor` и `/export` используют редактор, указанный в переменной среды `EDITOR`. + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + + Чтобы сделать его постоянным, добавьте это в свой профиль shell; + `~/.bashrc`, `~/.zshrc` и т. д. + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + + Чтобы сделать его постоянным, используйте **Свойства системы** > **Среда + Переменные**. + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + + Чтобы сделать его постоянным, добавьте его в свой профиль PowerShell. + + + + +Популярные варианты редактора включают в себя: + +- `code` — VS Code +- `cursor` — Cursor +- `windsurf` - Windsurf +- `nvim` - Редактор Neovim +- `vim` — редактор Vim +- `nano` — Нано-редактор +- `notepad` — Блокнот Windows +- `subl` — Sublime Text + +:::note +Некоторые редакторы, такие как VS Code, необходимо запускать с флагом `--wait`. +::: + +Некоторым редакторам для работы в режиме блокировки необходимы CLI-аргументы. Флаг `--wait` блокирует процесс редактора до его закрытия. + +--- + +## Настройка + +Вы можете настроить поведение TUI через файл конфигурации opencode. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### Параметры + +- `scroll_acceleration` — включите ускорение прокрутки в стиле macOS для плавной и естественной прокрутки. Если этот параметр включен, скорость прокрутки увеличивается при быстрой прокрутке и остается точной при более медленных движениях. **Этот параметр имеет приоритет над `scroll_speed` и переопределяет его, если он включен.** +- `scroll_speed` — контролирует скорость прокрутки TUI при использовании команд прокрутки (минимум: `1`). По умолчанию `3`. **Примечание. Это игнорируется, если для `scroll_acceleration.enabled` установлено значение `true`.** + +--- + +## Кастомизация + +Вы можете настроить различные аспекты представления TUI, используя палитру команд (`ctrl+x h` или `/help`). Эти настройки сохраняются после перезапуска. + +--- + +#### Отображение имени пользователя + +Включите, будет ли ваше имя пользователя отображаться в сообщениях чата. Доступ к этому через: + +- Палитра команд: поиск «имя пользователя» или «скрыть имя пользователя». +- Настройка сохраняется автоматически и будет запоминаться во время сеансов TUI. diff --git a/packages/web/src/content/docs/ru/web.mdx b/packages/web/src/content/docs/ru/web.mdx new file mode 100644 index 00000000000..53122749f2b --- /dev/null +++ b/packages/web/src/content/docs/ru/web.mdx @@ -0,0 +1,142 @@ +--- +title: Интернет +description: Использование opencode в вашем браузере. +--- + +opencode может работать как веб-приложение в вашем браузере, обеспечивая такой же мощный опыт кодирования AI без необходимости использования терминала. + +![opencode Web — новый сеанс](../../../assets/web/web-homepage-new-session.png) + +## Начало работы + +Запустите веб-интерфейс, выполнив: + +```bash +opencode web +``` + +Это запустит локальный сервер `127.0.0.1` со случайным доступным портом и автоматически откроет opencode в браузере по умолчанию. + +:::caution +Если `OPENCODE_SERVER_PASSWORD` не установлен, сервер будет незащищен. Это подходит для локального использования, но его следует настроить для доступа к сети. +::: + +:::tip[Пользователи Windows] +Для получения наилучших результатов запустите `opencode web` из [WSL](/docs/windows-wsl), а не из PowerShell. Это обеспечивает правильный доступ к файловой системе и интеграцию терминала. +::: + +--- + +## Конфигурация + +Вы можете настроить веб-сервер с помощью CLI-флагов или в файле [config file](/docs/config). + +### Порт + +По умолчанию opencode выбирает доступный порт. Вы можете указать порт: + +```bash +opencode web --port 4096 +``` + +### Имя хоста + +По умолчанию сервер привязывается к `127.0.0.1` (только локальный хост). Чтобы сделать opencode доступным в вашей сети: + +```bash +opencode web --hostname 0.0.0.0 +``` + +При использовании `0.0.0.0` opencode будет отображать как локальные, так и сетевые адреса: + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### Обнаружение mDNS + +Включите mDNS, чтобы ваш сервер был доступен для обнаружения в локальной сети: + +```bash +opencode web --mdns +``` + +Это автоматически устанавливает имя хоста `0.0.0.0` и объявляет сервер как `opencode.local`. + +Вы можете настроить доменное имя mDNS для запуска нескольких экземпляров в одной сети: + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +Чтобы разрешить дополнительные домены для CORS (полезно для пользовательских интерфейсов): + +```bash +opencode web --cors https://example.com +``` + +### Аутентификация + +Чтобы защитить доступ, установите пароль, используя переменную среды `OPENCODE_SERVER_PASSWORD`: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +Имя пользователя по умолчанию — `opencode`, но его можно изменить с помощью `OPENCODE_SERVER_USERNAME`. + +--- + +## Использование веб-интерфейса + +После запуска веб-интерфейс предоставляет доступ к вашим сеансам opencode. + +### Сессии + +Просматривайте свои сеансы и управляйте ими с главной страницы. Вы можете видеть активные сеансы и начинать новые. + +![opencode Web — активный сеанс](../../../assets/web/web-homepage-active-session.png) + +### Статус сервера + +Нажмите «Просмотреть серверы», чтобы просмотреть подключенные серверы и их статус. + +![opencode Web — см. Серверы](../../../assets/web/web-homepage-see-servers.png) + +--- + +## Подключение терминала + +Вы можете подключить TUI терминала к работающему веб-серверу: + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +Это позволяет вам одновременно использовать веб-интерфейс и терминал, используя одни и те же сеансы и состояние. + +--- + +## Конфигурационный файл + +Вы также можете настроить параметры сервера в файле конфигурации `opencode.json`: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +CLI-флаги имеют приоритет над настройками файла конфигурации. diff --git a/packages/web/src/content/docs/ru/windows-wsl.mdx b/packages/web/src/content/docs/ru/windows-wsl.mdx new file mode 100644 index 00000000000..7ca28449b5f --- /dev/null +++ b/packages/web/src/content/docs/ru/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: Запускайте opencode в Windows через WSL. +--- + +import { Steps } from "@astrojs/starlight/components" + +opencode можно запускать напрямую в Windows, но для лучшего опыта мы рекомендуем [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install). WSL дает Linux-среду, которая отлично работает с возможностями opencode. + +:::tip[Почему WSL?] +WSL дает более высокую производительность файловой системы, полноценную поддержку терминала и совместимость с инструментами разработки, на которые опирается opencode. +::: + +--- + +## Настройка + + + +1. **Установите WSL** + + Если вы еще не сделали этого, установите WSL по [официальному руководству Microsoft](https://learn.microsoft.com/en-us/windows/wsl/install). + +2. **Установите opencode в WSL** + + После настройки WSL откройте терминал WSL и установите opencode одним из [способов установки](/docs/). + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **Запускайте opencode из WSL** + + Перейдите в каталог проекта (к файлам Windows можно обращаться через `/mnt/c/`, `/mnt/d/` и т.д.) и запустите opencode. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## Десктопное приложение + сервер в WSL + +Если вы предпочитаете opencode Desktop, но хотите запускать сервер в WSL: + +1. **Запустите сервер в WSL** с параметром `--hostname 0.0.0.0`, чтобы разрешить внешние подключения: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **Подключите десктопное приложение** к `http://localhost:4096` + +:::note +Если в вашей конфигурации `localhost` не работает, используйте IP-адрес WSL (выполните в WSL: `hostname -I`) и подключайтесь по `http://:4096`. +::: + +:::caution +При использовании `--hostname 0.0.0.0` задайте `OPENCODE_SERVER_PASSWORD`, чтобы защитить сервер. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## Веб-клиент + WSL + +Для лучшего веб-опыта в Windows: + +1. **Запускайте `opencode web` в терминале WSL**, а не в PowerShell: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Открывайте в браузере Windows** адрес `http://localhost:` (opencode выведет URL) + +Запуск `opencode web` из WSL обеспечивает корректный доступ к файловой системе и интеграцию с терминалом, при этом интерфейс остается доступным из браузера Windows. + +--- + +## Доступ к файлам Windows + +WSL может получать доступ ко всем вашим файлам Windows через каталог `/mnt/`: + +- `C:` drive → `/mnt/c/` +- `D:` drive → `/mnt/d/` +- И так далее + +Пример: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +Для максимально плавной работы стоит клонировать или скопировать репозиторий в файловую систему WSL (например, в `~/code/`) и запускать opencode оттуда. +::: + +--- + +## Советы + +- Даже для проектов на дисках Windows запускайте opencode в WSL, чтобы получить более плавный доступ к файлам +- Используйте opencode вместе с [расширением WSL для VS Code](https://code.visualstudio.com/docs/remote/wsl) для единого рабочего процесса +- Конфигурация и сессии opencode хранятся в среде WSL по пути `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/ru/zen.mdx b/packages/web/src/content/docs/ru/zen.mdx new file mode 100644 index 00000000000..d0563bdcdf6 --- /dev/null +++ b/packages/web/src/content/docs/ru/zen.mdx @@ -0,0 +1,254 @@ +--- +title: Zen +description: Кураторский список моделей, предоставленный opencode. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen — это список протестированных и проверенных моделей, предоставленный командой opencode. + +:::note +OpenCode Zen в настоящее время находится в стадии бета-тестирования. +::: + +Zen работает как любой другой провайдер в opencode. Вы входите в OpenCode Zen и получаете +ваш ключ API. Это **совершенно необязательно**, и вам не обязательно использовать его для использования +Открытый код. + +--- + +## Предыстория + +Существует большое количество моделей, но лишь некоторые из них. +эти модели хорошо работают в качестве агентов кодирования. Кроме того, большинство провайдеров +настроен совсем по-другому; так что вы получите совсем другую производительность и качество. + +:::tip +Мы протестировали избранную группу моделей и поставщиков, которые хорошо работают с opencode. +::: + +Поэтому, если вы используете модель через что-то вроде OpenRouter, вы никогда не сможете +уверен, что вы получаете лучшую версию модели, которую хотите. + +Чтобы это исправить, мы сделали пару вещей: + +1. Мы протестировали избранную группу моделей и поговорили с их командами о том, как + лучше всего запустить их. +2. Затем мы поработали с несколькими поставщиками услуг, чтобы убедиться, что они обслуживаются. + правильно. +3. Наконец, мы сравнили комбинацию модель/провайдер и пришли к выводу, что + со списком, который мы с удовольствием рекомендуем. + +OpenCode Zen — это шлюз искусственного интеллекта, который дает вам доступ к этим моделям. + +--- + +## Как это работает + +OpenCode Zen работает так же, как и любой другой поставщик opencode. + +1. Вы входите в систему **OpenCode Zen**, добавляете свой платежный аккаунт. + подробности и скопируйте свой ключ API. +2. Вы запускаете команду `/connect` в TUI, выбираете OpenCode Zen и вставляете свой ключ API. +3. Запустите `/models` в TUI, чтобы просмотреть список рекомендуемых нами моделей. + +С вас взимается плата за каждый запрос, и вы можете добавить кредиты на свой счет. + +--- + +## Конечные точки + +Вы также можете получить доступ к нашим моделям через следующие конечные точки API. + +| Модель | Идентификатор модели | Конечная точка | Пакет AI SDK | +| ------------------ | -------------------- | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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` | + +[модель id](/docs/config/#models) в вашей конфигурации opencode +использует формат `opencode/`. Например, для Кодекса GPT 5.2 вы должны +используйте `opencode/gpt-5.2-codex` в вашей конфигурации. + +--- + +### Модели + +Полный список доступных моделей и их метаданные можно получить по адресу: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## Цены + +Мы поддерживаем модель оплаты по мере использования. Ниже приведены цены **за 1 миллион токенов**. + +| Модель | Вход | Выход | Кэшированное чтение | Кэшированная запись | +| -------------------------------------- | --------- | --------- | ------------------- | ------------------- | +| Big Pickle | Бесплатно | Бесплатно | Бесплатно | - | +| MiniMax M2.1 Free | Бесплатно | Бесплатно | Бесплатно | - | +| MiniMax 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 (≤ 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 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.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), которая используется для создания заголовков ваших сеансов. + +:::note +Комиссии по кредитной карте учитываются по себестоимости (4,4% + 0,30 доллара США за транзакцию); мы не взимаем ничего сверх этого. +::: + +Бесплатные модели: + +- GLM 4.7 Free доступен на opencode в течение ограниченного времени. Команда использует это время для сбора отзывов и улучшения модели. +- Kimi K2.5 Free доступен на opencode в течение ограниченного времени. Команда использует это время для сбора отзывов и улучшения модели. +- MiniMax M2.1 Free доступен на opencode в течение ограниченного времени. Команда использует это время для сбора отзывов и улучшения модели. +- Big Pickle — это стелс-модель, которая доступна бесплатно на opencode в течение ограниченного времени. Команда использует это время для сбора отзывов и улучшения модели. + +Свяжитесь с нами, если у вас есть вопросы. + +--- + +### Автопополнение + +Если ваш баланс упадет ниже 5 долларов, Zen автоматически пополнит 20 долларов. + +Вы можете изменить сумму автопополнения. Вы также можете полностью отключить автоматическую перезагрузку. + +--- + +### Ежемесячные лимиты + +Вы также можете установить месячный лимит использования для всего рабочего пространства и для каждого +член вашей команды. + +Например, предположим, что вы установили ежемесячный лимит использования в размере 20 долларов США, Zen не будет использовать +более 20 долларов в месяц. Но если у вас включена автоматическая перезагрузка, Дзен может оказаться +взимать с вас более 20 долларов США, если ваш баланс опускается ниже 5 долларов США. + +--- + +## Конфиденциальность + +Все наши модели размещены в США. Наши поставщики придерживаются политики нулевого хранения и не используют ваши данные для обучения моделей, за следующими исключениями: + +- Big Pickle: во время бесплатного периода собранные данные могут быть использованы для улучшения модели. +- GLM 4.7 Free: в течение бесплатного периода собранные данные могут использоваться для улучшения модели. +- Kimi K2.5 Free: в течение бесплатного периода собранные данные могут использоваться для улучшения модели. +- MiniMax M2.1 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). + +--- + +## Для команд + +Дзен также отлично подходит для команд. Вы можете приглашать товарищей по команде, назначать роли, курировать +модели, которые использует ваша команда, и многое другое. + +:::note +Рабочие пространства в настоящее время бесплатны для команд в рамках бета-тестирования. +::: + +Управление вашим рабочим пространством в настоящее время бесплатно для команд в рамках бета-тестирования. Мы будем +скоро поделимся более подробной информацией о ценах. + +--- + +### Роли + +Вы можете приглашать товарищей по команде в свое рабочее пространство и распределять роли: + +- **Администратор**: управляйте моделями, участниками, ключами API и выставлением счетов. +- **Участник**: Управляйте только своими собственными ключами API. + +Администраторы также могут установить ежемесячные лимиты расходов для каждого участника, чтобы держать расходы под контролем. + +--- + +### Доступ к модели + +Администраторы могут включать или отключать определенные модели для рабочей области. Запросы, сделанные к отключенной модели, вернут ошибку. + +Это полезно в случаях, когда вы хотите отключить использование модели, которая +собирает данные. + +--- + +### Принесите свой ключ + +Вы можете использовать свои собственные ключи API OpenAI или Anthropic, сохраняя при этом доступ к другим моделям в Zen. + +Когда вы используете свои собственные ключи, счета за токены взимаются непосредственно провайдером, а не Zen. + +Например, у вашей организации уже может быть ключ для OpenAI или Anthropic. +и вы хотите использовать его вместо того, который предоставляет Zen. + +--- + +## Цели + +Мы создали OpenCode Zen, чтобы: + +1. **Сравните** лучшие модели/поставщики агентов кодирования. +2. Получите доступ к вариантам **самого высокого качества**, не снижая производительность и не обращаясь к более дешевым поставщикам. +3. Не допускайте **падения цен**, продавая по себестоимости; поэтому единственная надбавка предназначена для покрытия наших сборов за обработку. +4. Не допускайте **привязки**, позволяя использовать его с любым другим агентом кодирования. И всегда позволяйте вам использовать любого другого провайдера с opencode. diff --git a/packages/web/src/content/docs/th/acp.mdx b/packages/web/src/content/docs/th/acp.mdx new file mode 100644 index 00000000000..f7850ed4077 --- /dev/null +++ b/packages/web/src/content/docs/th/acp.mdx @@ -0,0 +1,156 @@ +--- +title: การรองรับ ACP +description: ใช้ OpenCode ในโปรแกรมแก้ไขที่รองรับ ACP +--- + +OpenCode รองรับ [Agent Client Protocol](https://agentclientprotocol.com) (ACP) ซึ่งช่วยให้สามารถทำงานร่วมกับ editor และ IDE ต่างๆ ได้โดยตรง + +:::tip +สำหรับรายชื่อเครื่องมือที่รองรับ ACP สามารถดูได้ที่ [ACP progress report](https://zed.dev/blog/acp-progress-report#available-now) +::: + +ACP เป็นมาตรฐานเปิดสำหรับการสื่อสารระหว่างโปรแกรมแก้ไขโค้ดและ AI agent + +--- + +## การกำหนดค่า + +ในการใช้ OpenCode ผ่าน ACP ให้กำหนดค่าโปรแกรมแก้ไขของคุณให้รันคำสั่ง `opencode acp` + +คำสั่งนี้จะเริ่ม OpenCode เป็น process ย่อยที่รองรับ ACP ซึ่งสื่อสารกับโปรแกรมแก้ไขของคุณผ่าน JSON-RPC ทาง stdio + +นี่คือตัวอย่างสำหรับโปรแกรมแก้ไขยอดนิยมที่รองรับ ACP + +--- + +### Zed + +สำหรับ [Zed](https://zed.dev) (`~/.config/zed/settings.json`): + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +สิ่งนี้จะเปิดใช้ `agent: new thread` ใน **Command Palette** + +คุณต้องตั้งค่า keybinding ใน `keymap.json` ของคุณ: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### JetBrains IDEs + +เพิ่มลงใน acp.json ของ [JetBrains IDE](https://www.jetbrains.com/) ของคุณตาม [เอกสาร](https://www.jetbrains.com/help/ai-assistant/acp.html): + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +นี่เป็นการเปิดให้ตัวแทน 'OpenCode' ในเนื้อหาของตัวแทน AI Chat + +--- + +### Avante.nvim + +ยังคงมี [Avante.nvim](https://github.com/yetone/avante.nvim) ของคุณ: + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +หากคุณต้องการส่งผ่าน environment variables (เช่น `OPENCODE_API_KEY`) คุณต้องระบุใน `env`: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +ลองใช้ OpenCode ACP ใน [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim) ให้เพิ่มสิ่งต่อไปนี้ใน Neovim ของคุณ: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +คุณสามารถใช้ CodeCompanion เพื่อใช้ opencode เป็น ACP agent สำหรับแชท + +หากคุณต้องส่ง environment variables (เช่น `OPENCODE_API_KEY`) โปรดดู [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) ในเอกสารของ CodeCompanion.nvim สำหรับรายละเอียดทั้งหมด + +## การรองรับ + +opencode ทำงานผ่าน ACP เหมือนกับใน terminal และรองรับฟีเจอร์ทั้งหมด: + +:::note +คำสั่ง slash ในตัวบางคำสั่งเช่น `/undo` และ `/redo` ยังไม่รองรับในขณะนี้ +::: + +- เครื่องมือใน (ไฟล์ไฟล์คำสั่งอื่นๆ) +- คำอธิบายและคำสั่งสแลช +- MCP แขกที่นี่คือข้อมูลเพิ่มเติมของ OpenCode ของคุณ +- กฎเฉพาะโครงการจาก `AGENTS.md` +- คนจัดรูปแบบและ linters เวียนนา +- ระบบตัวแทนและระบบ diff --git a/packages/web/src/content/docs/th/agents.mdx b/packages/web/src/content/docs/th/agents.mdx new file mode 100644 index 00000000000..567125aced0 --- /dev/null +++ b/packages/web/src/content/docs/th/agents.mdx @@ -0,0 +1,736 @@ +--- +title: เอเจนต์ +description: เอเจนต์พิเศษและปรับแต่งได้ +--- + +เอเจนต์ (Agent) คือผู้ช่วย AI ที่เชี่ยวชาญในงานเฉพาะด้าน คุณสามารถสร้างเอเจนต์ที่มีเครื่องมือ (tools) ที่เหมาะสมกับงานและคำสั่งระบบ (system prompt) ที่ต้องการได้ + +:::tip +ใช้เอเจนต์ **Plan** เพื่อวิเคราะห์โค้ดและตรวจสอบเหตุผลก่อนทำการเปลี่ยนแปลงโค้ดใดๆ +::: + +คุณสามารถสลับเอเจนต์ได้ระหว่างการสนทนาโดยใช้ปุ่ม **Tab** หรือเรียกใช้โดยระบุ `@` + +--- + +## ประเภท + +OpenCode มีเอเจนต์สองประเภท: **Primary Agent** (เอเจนต์หลัก) และ **Subagent** (เอเจนต์ย่อย) + +--- + +### Primary Agent (เอเจนต์หลัก) + +Primary Agent คือผู้ช่วยหลักที่คุณคุยด้วยโดยตรง คุณสามารถวนดูเอเจนต์หลักที่มีอยู่ได้โดยกดปุ่ม **Tab** หรือปุ่ม `switch_agent` ที่ตั้งค่าไว้ เอเจนต์เหล่านี้สามารถจัดการงานที่ซับซ้อนและเข้าถึงเครื่องมือที่มีความเสี่ยงสูงได้ เช่น **Build** ที่มีเครื่องมือทั้งหมด หรือ **Plan** ที่ถูกจำกัดสิทธิ์ + +:::tip +**Tab** จะเก็บประวัติการสนทนาไว้เมื่อสลับระหว่างเอเจนต์ +::: + +OpenCode มีเอเจนต์หลักในตัวได้แก่ **Build** และ **Plan** +ดูรายละเอียดด้านล่าง + +--- + +### Subagent (เอเจนต์ย่อย) + +Subagent คือผู้ช่วยเฉพาะทางที่ Primary Agent สามารถเรียกใช้งานได้ หรือคุณสามารถเรียกใช้โดยตรงโดยพิมพ์ **@** ตามด้วยชื่อเอเจนต์ในข้อความของคุณ + +OpenCode มี subagent ในตัวได้แก่ **General** และ **Explore** + +--- + +## บิวท์อิน + +OpenCode มาพร้อมกับเอเจนต์หลักและ subagent ในตัวดังนี้ + +--- + +### Build + +_Mode_: `primary` + +เอเจนต์หลักสำหรับ **การพัฒนา** มาพร้อมกับเครื่องมือทั้งหมดเพื่อให้มีสิทธิ์การเข้าถึงไฟล์และคำสั่งระบบโดยสมบูรณ์ + +--- + +### Plan + +_Mode_: `primary` + +เอเจนต์ที่ถูกจำกัดสิทธิ์ เน้นการคิดวิเคราะห์และวางแผน โดยป้องกันการเปลี่ยนแปลงไฟล์โดยไม่ได้ตั้งใจ +เครื่องมือต่อไปนี้จะถูกตั้งค่าเป็น `ask` (ต้องขออนุญาต): + +- `file edits`: การแก้ไขไฟล์, patch, และการเขียนไฟล์ +- `bash`: คำสั่ง bash ทั้งหมด + +เอเจนต์นี้มีประโยชน์เมื่อต้องการให้ LLM ตรวจสอบโค้ด หรือสร้างแผนงานก่อนที่จะลงมือทำจริง + +--- + +### General + +_Mode_: `subagent` + +เอเจนต์สำหรับตอบคำถามทั่วไปและการคิดวิเคราะห์หลายขั้นตอน อนุญาตให้เข้าถึงเครื่องมือต่างๆ (ยกเว้นการแก้ไขไฟล์) ใช้สิ่งนี้เมื่อต้องการรันงานที่ไม่ต้องแก้ไขโค้ด + +--- + +### Explore + +_Mode_: `subagent` + +เอเจนต์ความเร็วสูงสำหรับอ่านและสำรวจ codebase ใช้สิ่งนี้เมื่อคุณต้องการค้นหาไฟล์อย่างรวดเร็ว, ค้นหาโค้ดด้วยคำสำคัญ, หรือสอบถามเกี่ยวกับโครงสร้าง codebase + +--- + +### Compact + +_Mode_: `primary` + +เอเจนต์ระบบที่มีหน้าที่สรุปประวัติการสนทนาที่ยาวให้สั้นลง โดยยังคงใจความสำคัญไว้ + +--- + +### Name + +_Mode_: `primary` + +เอเจนต์ระบบที่มีหน้าที่สร้างชื่อ session ให้สั้นและได้ใจความ ทำงานอัตโนมัติโดยไม่ต้องมี UI + +--- + +### Summarize + +_Mode_: `primary` + +เอเจนต์ระบบที่มีหน้าที่สร้างสรุปการเปลี่ยนแปลงและงานที่ทำไป ทำงานอัตโนมัติโดยไม่ต้องมี UI + +--- + +## การใช้งาน + +1. สำหรับ Primary Agent ให้ใช้ปุ่ม **Tab** เพื่อวนดูเอเจนต์ที่มีอยู่ หรือใช้ keybind `switch_agent` ที่คุณตั้งค่าไว้ + +2. สำหรับ Subagent: + - เรียกใช้โดย Primary Agent โดยอัตโนมัติตามความเหมาะสม + - เรียกใช้ด้วยตนเองโดยพิมพ์ **@** ตามด้วยชื่อ subagent ในข้อความของคุณ เช่น + + ```txt frame="none" + @general help me search for this function + ``` + +3. **การนำทางระหว่าง Agent**: เมื่อ Subagent ทำงานเสร็จและส่งผลลัพธ์กลับมายัง Primary Agent คุณสามารถดูประวัติการทำงานได้: + - **\+Right** (หรือ `session_child_cycle` keybind) เพื่อวนผ่าน parent → child1 → child2 → ... → parent + - **\+Left** (หรือ `session_child_cycle_reverse` keybind) เพื่อวนย้อนกลับผ่าน parent ← child1 ← child2 ← ... ← parent + +--- + +## การกำหนดค่า + +คุณสามารถปรับแต่งเอเจนต์ที่มีอยู่หรือสร้างเอเจนต์ใหม่ได้สองวิธี: + +--- + +### JSON + +กำหนดค่าเอเจนต์ในไฟล์ `opencode.json` ของคุณ: + +```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 + +คุณสามารถกำหนดเอเจนต์ด้วยไฟล์ Markdown ได้ใน: + +- ระดับผู้ใช้ (Global): `~/.config/opencode/agents/` +- ระดับโปรเจ็กต์: `.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 จะกลายเป็นชื่อเอเจนต์ เช่น `review.md` สร้างเอเจนต์ `review` + +--- + +## ตัวเลือก + +มาดูรายละเอียดของตัวเลือกต่างๆ + +--- + +### Description (คำอธิบาย) + +ใช้ฟิลด์ `description` เพื่ออธิบายว่าเอเจนต์นี้ทำอะไร + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +ฟิลด์นี้ **จำเป็น** สำหรับ JSON + +--- + +### Temperature (อุณหภูมิ) + +ควบคุมความสุ่มและความคิดสร้างสรรค์ของการตอบกลับของ LLM ด้วย `temperature` + +ค่าที่ต่ำกว่าจะให้ผลลัพธ์ที่แน่นอนและแม่นยำกว่า ส่วนค่าที่สูงกว่าจะให้ความหลากหลายและความคิดสร้างสรรค์มากกว่า + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +ช่วงอุณหภูมิอยู่ระหว่าง 0.0 ถึง 1.0: + +- **0.0-0.2**: แน่นอนและแม่นยำ เหมาะสำหรับการเขียนโค้ดและการวางแผน +- **0.3-0.5**: สมดุล เหมาะสำหรับการพัฒนาทั่วไป +- **0.6-1.0**: สร้างสรรค์ เหมาะสำหรับการระดมสมอง + +```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}" + } + } +} +``` + +หมายเหตุ: OpenCode ค่าเริ่มต้นคือ 0 สำหรับโมเดลส่วนใหญ่ และ 0.55 สำหรับโมเดล Qwen + +--- + +### Steps (ขั้นตอน) + +จำกัดจำนวนการวนซ้ำ (iterations) สูงสุดที่เอเจนต์สามารถทำได้ เพื่อควบคุมค่าใช้จ่ายและป้องกันการทำงานไม่รู้จบ + +หากไม่ได้ตั้งค่านี้ เอเจนต์จะทำงานต่อไปจนกว่างานจะเสร็จหรือผู้ใช้ขัดจังหวะ + +```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 + } + } +} +``` + +เมื่อถึงขีดจำกัด เอเจนต์จะได้รับพรอมต์พิเศษเพื่อสรุปงานและสิ่งที่เหลืออยู่ + +:::caution +ฟิลด์ `maxSteps` แบบเดิมเลิกใช้แล้ว โปรดใช้ `steps` แทน +::: + +--- + +### Disable (ปิดใช้งาน) + +ตั้งค่าเป็น `true` เพื่อปิดการใช้งานเอเจนต์ + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### พรอมต์ + +ระบุ System Prompt สำหรับเอเจนต์นี้ด้วย `prompt` + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +รองรับเส้นทางสัมพัทธ์ (Relative paths) ซึ่งทำให้ใช้งานได้สะดวกทั้งในระดับ Global และ Project + +--- + +### Model (โมเดล) + +ใช้ตัวเลือก `model` เพื่อกำหนดโมเดลเฉพาะสำหรับเอเจนต์นี้ มีประโยชน์เมื่อต้องการใช้โมเดลที่เชี่ยวชาญเฉพาะด้าน หรือโมเดลที่มี Context window ขนาดใหญ่สำหรับการตรวจสอบ codebase + +:::tip +หากไม่ได้ระบุโมเดล เอเจนต์จะใช้ [โมเดลเริ่มต้น](/docs/config#models) ของ OpenCode +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +ID ของโมเดลใช้รูปแบบ `provider/model-id` + +--- + +### เครื่องมือ + +กำหนดเครื่องมือที่เอเจนต์สามารถใช้งานได้ด้วย `tools` คุณสามารถระบุชื่อเครื่องมือ หรือใช้ wildcard + +```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 +การกำหนดค่าเครื่องมือในระดับเอเจนต์จะมีความสำคัญเหนือกว่าระดับ Global +::: + +คุณสามารถใช้ wildcard `*` เพื่อควบคุมเครื่องมือหลายรายการพร้อมกัน เช่น เครื่องมือจากเซิร์ฟเวอร์ MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[เรียนรู้เพิ่มเติมเกี่ยวกับเครื่องมือ](/docs/tools) + +--- + +### Permissions (สิทธิ์) + +กำหนดสิทธิ์สำหรับเครื่องมือที่มีความละเอียดอ่อน เช่น `edit`, `bash` และ `webfetch`: + +- `"ask"` — ต้องขออนุมัติจากผู้ใช้ก่อน +- `"allow"` — อนุญาตให้ทำงานได้โดยไม่ต้องถาม +- `"deny"` — ไม่อนุญาตให้ใช้ + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +คุณสามารถกำหนดสิทธิ์ในระดับเอเจนต์ได้: + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +ใน Markdown agent: + +```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. +``` + +คุณสามารถกำหนดสิทธิ์สำหรับคำสั่ง bash เฉพาะได้: + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +รองรับ glob patterns: + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +ใช้ `*` wildcard เพื่อตั้งค่าเริ่มต้นสำหรับคำสั่งอื่นๆ ทั้งหมด กฎที่ตรงกันล่าสุดจะมีผลบังคับใช้ (Last match wins): + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[เรียนรู้เพิ่มเติมเกี่ยวกับสิทธิ์](/docs/permissions) + +--- + +### Mode (โหมด) + +กำหนดโหมดของเอเจนต์ด้วย `mode` + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +`mode` สามารถเป็น `primary`, `subagent` หรือ `all` หากไม่ระบุ ค่าเริ่มต้นจะเป็น `all` + +--- + +### Hidden (ซ่อน) + +ซ่อน subagent จากเมนู autocomplete `@` ด้วย `hidden: true` มีประโยชน์สำหรับ subagent ภายในที่ถูกเรียกใช้โดยเอเจนต์อื่นผ่านเครื่องมือ task เท่านั้น + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +:::note +ใช้ได้กับเอเจนต์ที่มี `mode: subagent` เท่านั้น +::: + +--- + +### Task Permissions (สิทธิ์งาน) + +กำหนดว่า subagent ใดที่เอเจนต์นี้สามารถเรียกใช้ได้ผ่านเครื่องมือ task ด้วย `permission.task` + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +หากตั้งเป็น `deny` เอเจนต์จะมองไม่เห็นเครื่องมือ task สำหรับ subagent นั้นๆ + +:::tip +กฎทำงานตามลำดับ และ **กฎที่ตรงกันล่าสุดจะมีผล** ในตัวอย่างข้างต้น `orchestrator-planner` ตรงกับทั้ง `*` (deny) และ `orchestrator-*` (allow) แต่เนื่องจาก `orchestrator-*` มาทีหลัง ผลลัพธ์จึงเป็น `allow` +::: + +--- + +### สี + +ปรับแต่งสีของเอเจนต์ใน UI ด้วยตัวเลือก `color` + +ใช้รหัสสี hex (เช่น `#FF5733`) หรือชื่อสีมาตรฐาน: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info` + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +ควบคุมความหลากหลายของการตอบกลับด้วยตัวเลือก `top_p` + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +ช่วงค่า 0.0 ถึง 1.0 ค่าที่ต่ำกว่าจะเน้นไปที่โทเค็นที่มีความน่าจะเป็นสูง + +--- + +### Additional (เพิ่มเติม) + +คุณสมบัติอื่นๆ ที่คุณระบุใน object ของเอเจนต์จะถูก **ส่งผ่านโดยตรง** ไปยัง LLM config + +เช่น สำหรับโมเดลที่มีการให้เหตุผลของ OpenAI: + +```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" + } + } +} +``` + +ตรวจสอบเอกสารของแต่ละโมเดลสำหรับตัวเลือกที่รองรับ + +:::tip +ใช้ `opencode models` เพื่อดูรายการตัวเลือกทั้งหมด +::: + +--- + +## การสร้างเอเจนต์ + +สร้างเอเจนต์ใหม่ด้วยคำสั่ง: + +```bash +opencode agent create +``` + +คำสั่งแบบโต้ตอบจะถาม: + +1. สถานที่บันทึก (Global หรือ Project) +2. คำอธิบายหน้าที่ของเอเจนต์ +3. สร้างพรอมต์และเลือกไอคอนที่เหมาะสม +4. เลือกเครื่องมือที่เอเจนต์สามารถใช้ได้ +5. สร้างไฟล์ Markdown ของเอเจนต์ + +--- + +## ตัวอย่างการใช้งาน + +ต่อไปนี้เป็นกรณีการใช้งานทั่วไปสำหรับเอเจนต์ต่างๆ + +- **Developer**: งานพัฒนาทั่วไป ใช้เครื่องมือทั้งหมด +- **Planner**: วิเคราะห์และวางแผนโดยไม่ทำการเปลี่ยนแปลง +- **Reviewer**: ตรวจสอบโค้ดแบบอ่านอย่างเดียว (Read-only) +- **Debugger**: แก้ไขข้อผิดพลาดโดยเน้นการอ่าน log และทดสอบ +- **Docs Writer**: เขียนและปรับปรุงเอกสาร + +--- + +## ตัวอย่างเอเจนต์ + +นี่คือตัวอย่างเอเจนต์ที่คุณอาจพบว่ามีประโยชน์ + +:::tip +คุณมีเอเจนต์เจ๋งๆ ที่ต้องการแบ่งปันหรือไม่? [ส่ง PR มาที่นี่](https://github.com/anomalyco/opencode) +::: + +### Docs Writer + +```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 +``` + +--- + +### Security Auditor + +```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/th/cli.mdx b/packages/web/src/content/docs/th/cli.mdx new file mode 100644 index 00000000000..60e3fac764c --- /dev/null +++ b/packages/web/src/content/docs/th/cli.mdx @@ -0,0 +1,604 @@ +--- +title: CLI +description: สัญญาณและคำสั่งของ OpenCode CLI +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode CLI จะเริ่มต้น [TUI](/docs/tui) เป็นค่าเริ่มต้นเมื่อเรียกใช้โดยไม่มีอาร์กิวเมนต์ + +```bash +opencode +``` + +นอกจากนี้ยังรับคำสั่งและแฟล็ก ซึ่งช่วยให้คุณใช้ OpenCode ผ่านโปรแกรมได้ + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +เริ่ม TUI เพื่อใช้ OpenCode แบบโต้ตอบ + +```bash +opencode [project] +``` + +#### แฟล็ก + +| แฟล็ก | สั้น | คำอธิบาย | +| ------------ | ---- | ---------------------------------------------------------- | +| `--continue` | `-c` | ดำเนินการต่อจากเซสชันล่าสุด | +| `--session` | `-s` | ID เซสชันเพื่อดำเนินการต่อ | +| `--fork` | | แยกเซสชันเมื่อทำต่อ (ใช้กับ `--continue` หรือ `--session`) | +| `--prompt` | | พรอมต์เริ่มต้นที่จะใช้ | +| `--model` | `-m` | โมเดลที่จะใช้ในรูปแบบ provider/model | +| `--agent` | | เอเจนต์ที่จะใช้ | +| `--port` | | พอร์ตที่จะฟัง | +| `--hostname` | | ชื่อโฮสต์ที่จะฟัง | + +--- + +## คำสั่ง + +OpenCode CLI ยังมีคำสั่งย่อยอีกมากมาย + +--- + +### agent + +จัดการเอเจนต์สำหรับ OpenCode + +```bash +opencode agent [command] +``` + +--- + +### attach + +เชื่อมต่อกับเซิร์ฟเวอร์แบ็กเอนด์ OpenCode ที่กำลังทำงานอยู่ ซึ่งเริ่มต้นผ่านคำสั่ง `serve` หรือ `web` + +```bash +opencode attach [url] +``` + +วิธีนี้ช่วยให้คุณใช้ TUI กับแบ็กเอนด์ OpenCode ระยะไกลได้ ตัวอย่าง: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### แฟล็ก + +| แฟล็ก | สั้น | คำอธิบาย | +| ----------- | ---- | -------------------------------------- | +| `--dir` | | ไดเร็กทอรีการทำงานเพื่อเริ่มต้น TUI ใน | +| `--session` | `-s` | ID เซสชันเพื่อดำเนินการต่อ | + +--- + +#### create + +สร้างเอเจนต์ใหม่ + +```bash +opencode agent create +``` + +คำสั่งนี้จะแนะนำคุณตลอดกระบวนการสร้างเอเจนต์ใหม่ พร้อมพรอมต์ระบบและความสามารถของเครื่องมือ + +--- + +#### list + +แสดงรายชื่อเอเจนต์ที่พร้อมใช้งานทั้งหมด + +```bash +opencode agent list +``` + +--- + +### auth + +จัดการการตรวจสอบสิทธิ์และข้อมูลรับรอง + +```bash +opencode auth [command] +``` + +--- + +#### login + +OpenCode ได้รับการกำหนดค่าไว้ล่วงหน้าด้วยรายชื่อผู้ให้บริการทั่วไปที่ [Models.dev](https://models.dev) ดังนั้นคุณเพียงแค่ต้องใส่คีย์ API สำหรับผู้ให้บริการที่คุณต้องการใช้ ข้อมูลนี้จะถูกเก็บไว้ที่ `~/.local/share/opencode/auth.json` + +```bash +opencode auth login +``` + +เมื่อ OpenCode เริ่มต้น ระบบจะโหลดข้อมูลรับรองจากไฟล์นี้ ดังนั้นคุณจึงไม่ต้องกังวลกับการตั้งค่าตัวแปรสภาพแวดล้อมหรือไฟล์ `.env` ในโปรเจ็กต์ของคุณ + +--- + +#### list + +แสดงรายการข้อมูลรับรองการตรวจสอบสิทธิ์ทั้งหมดที่กำหนดค่าไว้ + +```bash +opencode auth list +``` + +หรือใช้นามแฝงสั้น + +```bash +opencode auth ls +``` + +--- + +#### logout + +ออกจากระบบของผู้ให้บริการและลบข้อมูลรับรองออกจากไฟล์ auth + +```bash +opencode auth logout +``` + +--- + +### github + +จัดการเอเจนต์ GitHub สำหรับเวิร์กโฟลว์อัตโนมัติ + +```bash +opencode github [command] +``` + +--- + +#### install + +ติดตั้งเอเจนต์ GitHub ใน repository ของคุณ + +```bash +opencode github install +``` + +คำสั่งนี้จะสร้างเวิร์กโฟลว์ GitHub Actions และแนะนำคุณตลอดกระบวนการตั้งค่า [เรียนรู้เพิ่มเติม](/docs/github) + +--- + +#### run + +รันเอเจนต์ GitHub ด้วยตนเองหรือใน GitHub Actions + +```bash +opencode github run +``` + +##### แฟล็ก + +| แฟล็ก | คำอธิบาย | +| --------- | -------------------------------------- | +| `--event` | เหตุการณ์ GitHub เพื่อทริกเกอร์เอเจนต์ | +| `--token` | GitHub token | + +--- + +### mcp + +จัดการเซิร์ฟเวอร์ Model Context Protocol (MCP) + +```bash +opencode mcp [command] +``` + +--- + +#### add + +เพิ่มเซิร์ฟเวอร์ MCP ลงในการกำหนดค่าของคุณ + +```bash +opencode mcp add +``` + +คำสั่งนี้จะแนะนำคุณผ่านวิซาร์ดเพื่อกำหนดค่าเซิร์ฟเวอร์ MCP ใหม่ + +--- + +#### list + +แสดงรายชื่อเซิร์ฟเวอร์ MCP ทั้งหมดที่กำหนดค่าไว้และสถานะ + +```bash +opencode mcp list +``` + +หรือใช้นามแฝงสั้น + +```bash +opencode mcp ls +``` + +--- + +#### auth + +ยืนยันตัวตนกับเซิร์ฟเวอร์ MCP ที่ต้องการ OAuth + +```bash +opencode mcp auth [name] +``` + +หากไม่ระบุชื่อเซิร์ฟเวอร์ คุณจะได้รับแจ้งให้เลือกจากเซิร์ฟเวอร์ที่รองรับ OAuth ที่พร้อมใช้งาน + +คุณยังสามารถแสดงรายการสถานะการตรวจสอบสิทธิ์ OAuth ได้: + +```bash +opencode mcp auth list +``` + +หรือใช้นามแฝงสั้น + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +ลบข้อมูลรับรอง OAuth สำหรับเซิร์ฟเวอร์ MCP + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +ดีบักการเชื่อมต่อเซิร์ฟเวอร์ MCP + +```bash +opencode mcp debug +``` + +--- + +### models + +แสดงรายการโมเดลที่พร้อมใช้งานทั้งหมดจากผู้ให้บริการที่กำหนดค่าไว้ + +```bash +opencode models [provider] +``` + +คำสั่งนี้จะแสดง ID โมเดลทั้งหมดในรูปแบบ `provider/model` + +คุณสามารถใช้ชื่อโมเดลเหล่านี้ในการกำหนดค่า [config](/docs/config/) ของคุณ + +คุณยังสามารถส่งผ่านรหัสผู้ให้บริการเพื่อกรองโมเดลตามผู้ให้บริการรายนั้นได้ + +```bash +opencode models anthropic +``` + +#### แฟล็ก + +| แฟล็ก | คำอธิบาย | +| ----------- | ------------------------------------------------------ | +| `--refresh` | รีเฟรชแคชโมเดลจาก models.dev | +| `--verbose` | แสดงรายละเอียดโมเดลเพิ่มเติม (รวมข้อมูลเมตาเช่นต้นทุน) | +| `--json` | แสดงผลลัพธ์เป็น JSON | + +ใช้แฟล็ก `--refresh` เพื่ออัปเดตรายการโมเดลที่แคชไว้ มีประโยชน์เมื่อมีการเพิ่มโมเดลใหม่ให้กับผู้ให้บริการและคุณต้องการเห็นใน OpenCode + +```bash +opencode models --refresh +``` + +--- + +### run + +รัน OpenCode โดยไม่ต้องใช้ TUI โดยส่งพรอมต์โดยตรง + +```bash +opencode run [message..] +``` + +มีประโยชน์สำหรับการทำงานอัตโนมัติหรือเมื่อต้องการคำตอบอย่างรวดเร็วโดยไม่ต้องเปิด TUI ตัวอย่าง: + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +คุณยังสามารถแนบไปกับเซิร์ฟเวอร์ `opencode serve` ที่ทำงานอยู่ หรือใช้เซิร์ฟเวอร์ MCP แบบ headless: + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### แฟล็ก + +| แฟล็ก | สั้น | คำอธิบาย | +| ------------ | ---- | ---------------------------------------------------------------------- | +| `--command` | | คำสั่งที่จะรัน (ใช้ส่วนที่เหลือของ args เป็นอาร์กิวเมนต์) | +| `--continue` | `-c` | ดำเนินการต่อจากเซสชันล่าสุด | +| `--session` | `-s` | ID เซสชันเพื่อดำเนินการต่อ | +| `--fork` | | แยกเซสชันเมื่อทำต่อ (ใช้กับ `--continue` หรือ `--session`) | +| `--share` | | สร้างลิงก์แชร์สำหรับเซสชัน | +| `--model` | `-m` | โมเดลที่จะใช้ในรูปแบบ provider/model | +| `--agent` | | เอเจนต์ที่จะใช้ | +| `--file` | `-f` | แนบไฟล์ไปกับข้อความ | +| `--format` | | รูปแบบเอาต์พุต: text (จัดรูปแบบ) หรือ json (JSON ดิบ) | +| `--title` | | ชื่อสำหรับเซสชัน (หากไม่ได้ระบุ จะสร้างจากพรอมต์) | +| `--attach` | | แนบไปกับเซิร์ฟเวอร์ opencode ที่ทำงานอยู่ (เช่น http://localhost:4096) | +| `--port` | | พอร์ตสำหรับเซิร์ฟเวอร์ภายในเครื่อง (หากไม่ได้ระบุ จะใช้พอร์ตสุ่ม) | + +--- + +### serve + +เริ่มต้นเซิร์ฟเวอร์ OpenCode headless ที่ให้บริการ API HTTP ดู [เอกสารเซิร์ฟเวอร์](/docs/server) สำหรับรายละเอียด API เต็มรูปแบบ + +```bash +opencode serve +``` + +คำสั่งนี้จะเริ่มต้นเซิร์ฟเวอร์ HTTP ให้ API เข้าถึงฟังก์ชันการทำงานของ OpenCode ได้โดยไม่ต้องมี TUI นอกจากนี้ยังรองรับการตรวจสอบสิทธิ์พื้นฐาน HTTP (ชื่อผู้ใช้เริ่มต้นคือ `opencode` และรหัสผ่านระบุโดย `OPENCODE_SERVER_PASSWORD`) + +#### แฟล็ก + +| แฟล็ก | คำอธิบาย | +| ------------ | -------------------------------------- | +| `--port` | พอร์ตที่จะฟัง | +| `--hostname` | ชื่อโฮสต์ที่จะฟัง | +| `--mdns` | เปิดใช้งานการค้นหา mDNS | +| `--cors` | ต้นกำเนิดเพิ่มเติมที่อนุญาตสำหรับ CORS | + +--- + +### session + +จัดการเซสชัน OpenCode + +```bash +opencode session [command] +``` + +--- + +#### list + +แสดงรายการเซสชัน OpenCode ทั้งหมด + +```bash +opencode session list +``` + +##### แฟล็ก + +| แฟล็ก | สั้น | คำอธิบาย | +| ------------- | ---- | ----------------------------- | +| `--max-count` | `-n` | จำกัดการแสดงผล N รายการล่าสุด | +| `--format` | | รูปแบบ table หรือ json | + +--- + +### stats + +แสดงสถิติการใช้งานและค่าใช้จ่ายสำหรับ OpenCode ของคุณ + +```bash +opencode stats +``` + +#### แฟล็ก + +| แฟล็ก | คำอธิบาย | +| ----------- | ---------------------------------------------------- | +| `--days` | แสดงสถิติของ N วันที่ผ่านมา (ค่าเริ่มต้น: ตลอดเวลา) | +| `--tools` | แสดงสถิติการใช้เครื่องมือ | +| `--models` | แสดงรายละเอียดการใช้งานโมเดล (ซ่อนไว้ตามค่าเริ่มต้น) | +| `--project` | กรองตามโครงการ (ค่าเริ่มต้น: โครงการปัจจุบัน) | + +--- + +### export + +ส่งออกประวัติเซสชันเป็น JSON + +```bash +opencode export [sessionID] +``` + +หากไม่ระบุรหัสเซสชัน คุณจะได้รับแจ้งให้เลือกจากรายการล่าสุด + +--- + +### import + +นำเข้าเซสชันจากไฟล์ JSON หรือ URL ที่แชร์ของ OpenCode + +```bash +opencode import +``` + +คุณสามารถนำเข้าไฟล์ในเครื่องหรือ URL ที่แชร์ + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +เริ่ม OpenCode ในโหมดเซิร์ฟเวอร์พร้อมเว็บอินเตอร์เฟส + +```bash +opencode web +``` + +คำสั่งนี้จะเริ่มต้นเซิร์ฟเวอร์ HTTP และเปิดเว็บเบราว์เซอร์เพื่อเข้าถึง OpenCode ผ่านทางเว็บอินเตอร์เฟส รองรับการตรวจสอบสิทธิ์พื้นฐาน HTTP (ชื่อผู้ใช้เริ่มต้นคือ `opencode` และรหัสผ่านระบุโดย `OPENCODE_SERVER_PASSWORD`) + +#### แฟล็ก + +| แฟล็ก | คำอธิบาย | +| ------------ | -------------------------------------- | +| `--port` | พอร์ตที่จะฟัง | +| `--hostname` | ชื่อโฮสต์ที่จะฟัง | +| `--mdns` | เปิดใช้งานการค้นหา mDNS | +| `--cors` | ต้นกำเนิดเพิ่มเติมที่อนุญาตสำหรับ CORS | + +--- + +### acp + +เริ่มต้นเซิร์ฟเวอร์ ACP (Agent Client Protocol) + +```bash +opencode acp +``` + +คำสั่งนี้เริ่มต้นเซิร์ฟเวอร์ ACP ที่สื่อสารผ่าน stdin/stdout ด้วย nd-JSON + +#### แฟล็ก + +| แฟล็ก | คำอธิบาย | +| ------------ | ------------------ | +| `--cwd` | ไดเร็กทอรีการทำงาน | +| `--port` | พอร์ตที่จะฟัง | +| `--hostname` | ชื่อโฮสต์ที่จะฟัง | + +--- + +### uninstall + +ถอนการติดตั้ง OpenCode และลบข้อมูลการกำหนดค่าทั้งหมด + +```bash +opencode uninstall +``` + +#### แฟล็ก + +| แฟล็ก | สั้น | คำอธิบาย | +| --------------- | ---- | ----------------------------------- | +| `--keep-config` | `-c` | เก็บไฟล์การกำหนดค่าไว้ | +| `--keep-data` | `-d` | เก็บไฟล์ข้อมูล (เซสชันและสแน็ปช็อต) | +| `--dry-run` | | แสดงสิ่งที่จะลบออกโดยไม่ต้องทำจริง | +| `--force` | `-f` | บังคับลบโดยไม่มีการแจ้งเตือน | + +--- + +### upgrade + +อัปเกรด OpenCode เป็นเวอร์ชันล่าสุดหรือเวอร์ชันที่ระบุ + +```bash +opencode upgrade [target] +``` + +อัปเกรดเป็นเวอร์ชันล่าสุด + +```bash +opencode upgrade +``` + +อัปเกรดเป็นเวอร์ชันที่ระบุ + +```bash +opencode upgrade v0.1.48 +``` + +#### แฟล็ก + +| แฟล็ก | สั้น | คำอธิบาย | +| ---------- | ---- | ----------------------------------------------- | +| `--method` | `-m` | วิธีการติดตั้งที่ใช้ curl, npm, pnpm, bun, brew | + +--- + +## แฟล็กระดับโลก + +OpenCode CLI ยอมรับแฟล็กสากลต่อไปนี้สำหรับทุกคำสั่ง + +| แฟล็ก | สั้น | คำอธิบาย | +| -------------- | ---- | ----------------------------------------- | +| `--help` | `-h` | แสดงความช่วยเหลือ | +| `--version` | `-v` | พิมพ์เวอร์ชัน | +| `--print-logs` | | พิมพ์บันทึกไปยัง stderr | +| `--log-level` | | ระดับการบันทึก (DEBUG, INFO, WARN, ERROR) | + +--- + +## ตัวแปรสภาพแวดล้อม + +OpenCode สามารถกำหนดค่าโดยใช้ตัวแปรสภาพแวดล้อม + +| ตัวแปร | ชนิด | คำอธิบาย | +| ------------------------------------- | ------- | ---------------------------------------------------------------- | +| `OPENCODE_AUTO_SHARE` | Boolean | แชร์เซสชันอัตโนมัติเมื่อสร้าง | +| `OPENCODE_GIT_BASH_PATH` | String | เส้นทางไปยัง Git Bash บน Windows | +| `OPENCODE_CONFIG` | String | เส้นทางไปยังไฟล์การกำหนดค่า | +| `OPENCODE_CONFIG_DIR` | String | เส้นทางไปยังไดเร็กทอรีการกำหนดค่า | +| `OPENCODE_CONFIG_CONTENT` | String | เนื้อหาการกำหนดค่าแบบ inline JSON | +| `OPENCODE_DISABLE_AUTOUPDATE` | Boolean | ปิดใช้งานการอัปเดตอัตโนมัติ | +| `OPENCODE_DISABLE_PRUNE` | Boolean | ปิดใช้งานการลบข้อมูลเซสชันเก่า | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | Boolean | ปิดใช้งานการตั้งชื่อหน้าต่าง terminal | +| `OPENCODE_PERMISSION` | String | การกำหนดค่าสิทธิ์แบบ inline JSON | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | Boolean | ปิดใช้งานปลั๊กอินเริ่มต้น | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | Boolean | ปิดใช้งานการดาวน์โหลด LSP อัตโนมัติ | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | Boolean | เปิดใช้งานโมเดลทดลอง | +| `OPENCODE_DISABLE_AUTOCOMPACT` | Boolean | ปิดใช้งานการบีบอัดบริบทอัตโนมัติ | +| `OPENCODE_DISABLE_CLAUDE_CODE` | Boolean | ปิดใช้งานการนำเข้าจาก `.claude` (prompt + skills) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | Boolean | ปิดใช้งานการนำเข้า `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | Boolean | ปิดใช้งานการนำเข้า `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | Boolean | ปิดใช้งานการดึงรายการโมเดลจากระยะไกล | +| `OPENCODE_FAKE_VCS` | String | เปิดใช้งาน VCS จำลองสำหรับการทดสอบ | +| `OPENCODE_DISABLE_FILETIME_CHECK` | Boolean | ปิดใช้งานการตรวจสอบเวลาแก้ไขไฟล์ | +| `OPENCODE_CLIENT` | String | ตัวระบุไคลเอนต์ (ค่าเริ่มต้นคือ `cli`) | +| `OPENCODE_ENABLE_EXA` | Boolean | เปิดใช้งานการใช้ Exa แทน ls หากมี | +| `OPENCODE_SERVER_PASSWORD` | String | รหัสผ่านสำหรับการตรวจสอบสิทธิ์พื้นฐาน `serve`/`web` | +| `OPENCODE_SERVER_USERNAME` | String | ชื่อผู้ใช้สำหรับการตรวจสอบสิทธิ์พื้นฐาน (ค่าเริ่มต้น `opencode`) | +| `OPENCODE_MODELS_URL` | String | URL ที่กำหนดเองสำหรับการดึงรายการโมเดล | + +--- + +### ขั้นทดลอง + +ตัวแปรสภาพแวดล้อมเหล่านี้เปิดใช้งานฟีเจอร์ทดลองที่อาจมีการเปลี่ยนแปลงหรือถูกลบออก + +| ตัวแปร | ชนิด | คำอธิบาย | +| ----------------------------------------------- | ------- | ---------------------------------------------- | +| `OPENCODE_EXPERIMENTAL` | Boolean | เปิดใช้งานฟีเจอร์ทดลองทั้งหมด | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | Boolean | การค้นหาไอคอนทดลอง | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | Boolean | ปิดใช้งานการคัดลอกเมื่อเลือกใน TUI | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | Number | การหมดเวลาเริ่มต้นสำหรับคำสั่ง bash ในหน่วย ms | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | Number | ขีดจำกัดสูงสุดสำหรับโทเค็นเอาต์พุต LLM | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | Boolean | เปิดใช้งานตัวเฝ้าดูไฟล์สำหรับไดเร็กทอรีทั้งหมด | +| `OPENCODE_EXPERIMENTAL_OXFMT` | Boolean | ใช้ oxfmt เป็นตัวจัดรูปแบบ | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | Boolean | เปิดใช้งานเครื่องมือ LSP ทดลอง | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | Boolean | ปิดใช้งานตัวเฝ้าดูไฟล์ | +| `OPENCODE_EXPERIMENTAL_EXA` | Boolean | ฟีเจอร์ Exa ทดลอง | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | Boolean | การตรวจสอบประเภท LSP แบบทดลอง | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | Boolean | ใช้ Markdown renderer แบบทดลอง | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | Boolean | เปิดใช้งาน Plan mode | diff --git a/packages/web/src/content/docs/th/commands.mdx b/packages/web/src/content/docs/th/commands.mdx new file mode 100644 index 00000000000..0ef947e05fb --- /dev/null +++ b/packages/web/src/content/docs/th/commands.mdx @@ -0,0 +1,320 @@ +--- +title: คำสั่ง +description: คำสั่งที่กำหนดเองสำหรับงานที่ทำซ้ำๆ +--- + +คำสั่งช่วยให้คุณกำหนดชุดของพรอมต์ที่ใช้บ่อย เพื่อให้สามารถเรียกใช้งานได้อย่างรวดเร็วใน TUI + +```bash frame="none" +/my-command +``` + +คำสั่งแบบกำหนดเองเป็นส่วนเพิ่มเติมจากคำสั่งในตัว เช่น `/init`, `/undo`, `/redo`, `/share`, `/help` [เรียนรู้เพิ่มเติม](/docs/tui#คำสั่ง) + +--- + +## การสร้างคำสั่ง + +สร้างไฟล์ Markdown ในไดเร็กทอรี `commands/` เพื่อกำหนดคำสั่งของคุณ + +สร้าง `.opencode/commands/test.md`: + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Frontmatter กำหนดคุณสมบัติของคำสั่ง และเนื้อหาคือพรอมต์ที่จะส่งไปยัง LLM + +ใช้คำสั่งโดยพิมพ์ `/` ตามด้วยชื่อไฟล์ (ไม่รวมนามสกุล) ใน TUI: + +```bash frame="none" +"/test" +``` + +--- + +## วิธีการกำหนด + +คุณสามารถกำหนดคำสั่งได้สองวิธี: ผ่านการกำหนดค่า JSON หรือโดยการสร้างไฟล์ Markdown + +--- + +### JSON + +ใช้ส่วน `command` ในไฟล์ [config](/docs/config) ของ OpenCode: + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +รันคำสั่งนี้ใน TUI: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +หากต้องการกำหนดคำสั่งด้วยไฟล์ Markdown ให้วางไฟล์ไว้ใน: + +- ระดับผู้ใช้ (Global): `~/.config/opencode/commands/` +- ระดับโปรเจ็กต์: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +ชื่อไฟล์ Markdown จะกลายเป็นชื่อคำสั่ง เช่น `test.md` ให้คุณเรียกใช้: + +```bash frame="none" +/test +``` + +--- + +## อาร์กิวเมนต์และการแทนที่ + +คำสั่งรองรับอาร์กิวเมนต์ตามตำแหน่งและการแทนที่ค่าพิเศษหลายรายการ + +--- + +### อาร์กิวเมนต์ + +คุณสามารถส่งผ่านอาร์กิวเมนต์ไปยังคำสั่งของคุณได้โดยใช้ `$ARGUMENTS` + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +รันคำสั่งพร้อมอาร์กิวเมนต์: + +```bash frame="none" +/component Button +``` + +และ `$ARGUMENTS` จะถูกแทนที่ด้วย `Button` + +คุณยังสามารถเข้าถึงแต่ละอาร์กิวเมนต์แยกกันได้: + +- `$1` - อาร์กิวเมนต์แรก +- `$2` - อาร์กิวเมนต์ที่สอง +- `$3` - อาร์กิวเมนต์ที่สาม +- และอื่นๆ... + +ตัวอย่าง: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +รันคำสั่ง: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +ผลลัพธ์ที่ได้: + +- `$1` แทนด้วย `config.json` +- `$2` แทนด้วย `src` +- `$3` แทนด้วย `{ "key": "value" }` + +--- + +### คำสั่ง Shell + +ใช้ _!`command`_ เพื่อแทรกเอาต์พุตของ [คำสั่ง bash](/docs/tui#bash-commands) ใดๆ ลงในพรอมต์ของคุณ + +ตัวอย่างเช่น การรันชุดทดสอบและรวมผลลัพธ์: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +หรือตรวจสอบการเปลี่ยนแปลงล่าสุดใน git: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +คำสั่งจะถูกดำเนินการในไดเร็กทอรีรากของโปรเจ็กต์ + +--- + +### การอ้างอิงไฟล์ + +คุณสามารถรวมเนื้อหาไฟล์ในคำสั่งของคุณโดยใช้ `@` นำหน้าชื่อไฟล์ + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +เนื้อหาของไฟล์จะถูกอ่านและรวมเข้าไปในพรอมต์ที่ส่งไปยัง LLM + +--- + +## ตัวเลือก + +มาดูรายละเอียดของตัวเลือกการกำหนดค่าต่างๆ + +--- + +### Template (เทมเพลต) + +`template` กำหนดพรอมต์ที่จะถูกส่งไปยัง LLM เมื่อเรียกใช้คำสั่ง + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +ฟิลด์นี้ **จำเป็น** สำหรับการกำหนดค่าแบบ JSON (ใน Markdown คือส่วนเนื้อหา) + +--- + +### Description (คำอธิบาย) + +ใช้ตัวเลือก `description` เพื่อให้คำอธิบายโดยย่อเกี่ยวกับสิ่งที่คำสั่งทำ + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +คำอธิบายนี้จะแสดงในรายการเติมคำอัตโนมัติของ TUI เมื่อคุณพิมพ์คำสั่ง + +--- + +### Agent (เอเจนต์) + +ใช้ `agent` เพื่อระบุว่า [เอเจนต์](/docs/agents) ใดควรดำเนินการคำสั่งนี้ + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +นี่คือ **ทางเลือก** หากไม่ได้ระบุ จะใช้เอเจนต์ปัจจุบันของคุณ + +--- + +### Subtask (งานย่อย) + +ใช้ `subtask` (บูลีน) เพื่อระบุว่าคำสั่งควรทำงานเป็น [subagent](/docs/agents/#subagents) หรือไม่ + +การตั้งค่านี้จะป้องกันไม่ให้คำสั่งรบกวนบริบทหลักของเซสชัน และจะ **บังคับ** ให้เอเจนต์ใช้โหมดที่เหมาะสม + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +ส่วนนี้ **ทางเลือก** + +--- + +### Model (โมเดล) + +ใช้ `model` เพื่อกำหนดโมเดลเฉพาะสำหรับคำสั่งนี้ + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +ส่วนนี้ **ทางเลือก** + +--- + +### Built-ins (ในตัว) + +OpenCode มีคำสั่งในตัวหลายคำสั่ง เช่น `/init`, `/undo`, `/redo`, `/share`, `/help` [เรียนรู้เพิ่มเติม](/docs/tui#คำสั่ง) + +:::note +คุณสามารถเขียนทับคำสั่งในตัวได้โดยกำหนดคำสั่งที่กำหนดเองด้วยชื่อเดียวกัน +::: + +อย่างไรก็ตาม เราไม่แนะนำให้ทำเช่นนั้น เว้นแต่คุณจะมีเหตุผลที่เฉพาะเจาะจง diff --git a/packages/web/src/content/docs/th/config.mdx b/packages/web/src/content/docs/th/config.mdx new file mode 100644 index 00000000000..06836aca3be --- /dev/null +++ b/packages/web/src/content/docs/th/config.mdx @@ -0,0 +1,685 @@ +--- +title: การกำหนดค่า +description: การใช้การกำหนดค่า OpenCode JSON +--- + +คุณสามารถกำหนดค่า OpenCode ได้โดยใช้ไฟล์กำหนดค่า JSON + +--- + +## รูปแบบ + +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, +} +``` + +--- + +## สถานที่ + +คุณสามารถวางการกำหนดค่าของคุณในสถานที่ต่าง ๆ สองสามแห่งและมี +ลำดับความสำคัญที่แตกต่างกัน + +:::note +ไฟล์การกำหนดค่า **ถูกรวมเข้าด้วยกัน** โดยไม่มีการแทนที่ +::: + +ไฟล์การกำหนดค่าจะถูกรวมเข้าด้วยกัน โดยไม่มีการแทนที่ การตั้งค่าจากตำแหน่งการกำหนดค่าต่อไปนี้จะรวมกัน การกำหนดค่าในภายหลังจะแทนที่การกำหนดค่าก่อนหน้าสำหรับคีย์ที่ขัดแย้งกันเท่านั้น การตั้งค่าที่ไม่ขัดแย้งจากการกำหนดค่าทั้งหมดจะยังคงอยู่ + +ตัวอย่างเช่น หากการกำหนดค่าส่วนกลางของคุณตั้งค่า `theme: "opencode"` และ `autoupdate: true` และการกำหนดค่าโปรเจ็กต์ของคุณตั้งค่า `model: "anthropic/claude-sonnet-4-5"` การกำหนดค่าสุดท้ายจะรวมการตั้งค่าทั้งสามรายการไว้ด้วย + +--- + +### ลำดับความสำคัญ + +แหล่งที่มาของการกำหนดค่าถูกโหลดตามลำดับนี้ (แหล่งที่มาภายหลังจะแทนที่แหล่งที่มาก่อนหน้า): + +1. **การกำหนดค่าระยะไกล** (จาก `.well-known/opencode`) - ค่าเริ่มต้นขององค์กร +2. **การกำหนดค่าสากล** (`~/.config/opencode/opencode.json`) - การตั้งค่าของผู้ใช้ +3. **การกำหนดค่าแบบกำหนดเอง** (`OPENCODE_CONFIG` env var) - การแทนที่แบบกำหนดเอง +4. **การกำหนดค่าโครงการ** (`opencode.json` ในโครงการ) - การตั้งค่าเฉพาะโครงการ +5. **`.opencode` ไดเรกทอรี** - ตัวแทน คำสั่ง ปลั๊กอิน +6. **การกำหนดค่าแบบอินไลน์** (`OPENCODE_CONFIG_CONTENT` env var) - การแทนที่รันไทม์ + +ซึ่งหมายความว่าการกำหนดค่าโปรเจ็กต์สามารถแทนที่ค่าเริ่มต้นส่วนกลางได้ และการกำหนดค่าส่วนกลางสามารถแทนที่ค่าเริ่มต้นขององค์กรระยะไกลได้ + +:::note +ไดเรกทอรี `.opencode` และ `~/.config/opencode` ใช้ **ชื่อพหูพจน์** สำหรับไดเรกทอรีย่อย: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/` และ `themes/` ชื่อเอกพจน์ (เช่น `agent/`) ยังรองรับความเข้ากันได้แบบย้อนหลังด้วย +::: + +--- + +### ระยะไกล + +องค์กรสามารถจัดเตรียมการกำหนดค่าเริ่มต้นผ่านทางจุดสิ้นสุด `.well-known/opencode` สิ่งนี้จะถูกดึงออกมาโดยอัตโนมัติเมื่อคุณตรวจสอบสิทธิ์กับผู้ให้บริการที่รองรับ + +โหลดการกำหนดค่าระยะไกลก่อน โดยทำหน้าที่เป็นเลเยอร์พื้นฐาน แหล่งการกำหนดค่าอื่นๆ ทั้งหมด (ส่วนกลาง โปรเจ็กต์) สามารถแทนที่ค่าเริ่มต้นเหล่านี้ได้ + +ตัวอย่างเช่น หากองค์กรของคุณมีเซิร์ฟเวอร์ MCP ที่ถูกปิดใช้งานตามค่าเริ่มต้น: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +คุณสามารถเปิดใช้งานเซิร์ฟเวอร์เฉพาะในการกำหนดค่าภายในเครื่องของคุณได้: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### ทั่วโลก + +วางการกำหนดค่า OpenCode ส่วนกลางของคุณใน `~/.config/opencode/opencode.json` ใช้การกำหนดค่าส่วนกลางสำหรับการตั้งค่าทั้งผู้ใช้ เช่น ธีม ผู้ให้บริการ หรือปุ่มลัด + +การกำหนดค่าส่วนกลางจะแทนที่ค่าเริ่มต้นขององค์กรระยะไกล + +--- + +### ต่อโครงการ + +เพิ่ม `opencode.json` ในรูทโปรเจ็กต์ของคุณ การกำหนดค่าโปรเจ็กต์มีความสำคัญสูงสุดในบรรดาไฟล์กำหนดค่ามาตรฐาน โดยจะแทนที่การกำหนดค่าทั้งส่วนกลางและระยะไกล + +:::tip +วางการกำหนดค่าเฉพาะโปรเจ็กต์ไว้ที่รากของโปรเจ็กต์ของคุณ +::: + +เมื่อ OpenCode เริ่มต้นระบบ จะค้นหาไฟล์กำหนดค่าในไดเร็กทอรีปัจจุบันหรือข้ามไปยังไดเร็กทอรี Git ที่ใกล้ที่สุด + +นอกจากนี้ยังปลอดภัยที่จะตรวจสอบใน Git และใช้สคีมาเดียวกันกับสคีมาระดับโลก + +--- + +### เส้นทางที่กำหนดเอง + +ระบุเส้นทางไฟล์กำหนดค่าที่กำหนดเองโดยใช้ตัวแปรสภาพแวดล้อม `OPENCODE_CONFIG` + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +มีการโหลดการกำหนดค่าแบบกำหนดเองระหว่างการกำหนดค่าส่วนกลางและโครงการตามลำดับความสำคัญ + +--- + +### ไดเรกทอรีที่กำหนดเอง + +ระบุไดเร็กทอรีการกำหนดค่าที่กำหนดเองโดยใช้ `OPENCODE_CONFIG_DIR` +ตัวแปรสภาพแวดล้อม ไดเร็กทอรีนี้จะถูกค้นหาตัวแทน, คำสั่ง, +โหมดและปลั๊กอินเหมือนกับไดเร็กทอรี `.opencode` มาตรฐานและควร +เป็นไปตามโครงสร้างเดียวกัน + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +ไดเร็กทอรีที่กำหนดเองถูกโหลดหลังจากไดเร็กทอรี config ส่วนกลางและ `.opencode` ดังนั้นจึง **สามารถแทนที่** การตั้งค่าได้ + +--- + +## สคีมา + +ไฟล์กำหนดค่ามีสคีมาที่กำหนดไว้ใน [**`opencode.ai/config.json`**](https://opencode.ai/config.json) + +ผู้แก้ไขของคุณควรสามารถตรวจสอบและเติมข้อความอัตโนมัติตามสคีมาได้ + +--- + +### TUI + +คุณสามารถกำหนดการตั้งค่าเฉพาะ TUI ผ่านตัวเลือก `tui` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +ตัวเลือกที่มี: + +- `scroll_acceleration.enabled` - ​​เปิดใช้งานการเร่งความเร็วการเลื่อนแบบ macOS **มีลำดับความสำคัญมากกว่า `scroll_speed`.** +- `scroll_speed` - ​​ตัวคูณความเร็วการเลื่อนแบบกำหนดเอง (ค่าเริ่มต้น: `3` ขั้นต่ำ: `1`) ไม่สนใจหาก `scroll_acceleration.enabled` คือ `true` +- `diff_style` - ​​ควบคุมการเรนเดอร์ต่าง `"auto"` ปรับให้เข้ากับความกว้างของ terminal `"stacked"` จะแสดงคอลัมน์เดียวเสมอ + +[เรียนรู้เพิ่มเติมเกี่ยวกับการใช้ TUI ที่นี่](/docs/tui) + +--- + +### เซิร์ฟเวอร์ + +คุณสามารถกำหนดการตั้งค่าเซิร์ฟเวอร์สำหรับคำสั่ง `opencode serve` และ `opencode web` ผ่านตัวเลือก `server` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +ตัวเลือกที่มี: + +- `port` - ​​พอร์ตสำหรับฟัง +- `hostname` - ​​ชื่อโฮสต์ที่จะฟัง เมื่อเปิดใช้งาน `mdns` และไม่ได้ตั้งชื่อโฮสต์ ค่าเริ่มต้นจะเป็น `0.0.0.0` +- `mdns` - ​​เปิดใช้งานการค้นหาบริการ mDNS ซึ่งช่วยให้อุปกรณ์อื่นๆ บนเครือข่ายค้นพบเซิร์ฟเวอร์ OpenCode ของคุณได้ +- `mdnsDomain` - ​​ชื่อโดเมนที่กำหนดเองสำหรับบริการ mDNS ค่าเริ่มต้นเป็น `opencode.local` มีประโยชน์สำหรับการเรียกใช้หลายอินสแตนซ์บนเครือข่ายเดียวกัน +- `cors` - ​​ต้นกำเนิดเพิ่มเติมเพื่ออนุญาต CORS เมื่อใช้เซิร์ฟเวอร์ HTTP จากไคลเอนต์ที่ใช้เบราว์เซอร์ ค่าจะต้องเป็นต้นกำเนิดแบบเต็ม (สคีมา + โฮสต์ + พอร์ตเสริม) เช่น `https://app.example.com` + +[เรียนรู้เพิ่มเติมเกี่ยวกับเซิร์ฟเวอร์ที่นี่](/docs/server) + +--- + +### เครื่องมือ + +คุณสามารถจัดการเครื่องมือที่ LLM สามารถใช้ได้ผ่านตัวเลือก `tools` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[เรียนรู้เพิ่มเติมเกี่ยวกับเครื่องมือที่นี่](/docs/tools) + +--- + +### Models + +คุณสามารถกำหนดค่าผู้ให้บริการและรุ่นที่คุณต้องการใช้ในการกำหนดค่า OpenCode ของคุณได้ผ่านตัวเลือก `provider`, `model` และ `small_model` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +ตัวเลือก `small_model` จะกำหนดค่าโมเดลแยกต่างหากสำหรับงานที่ไม่ซับซ้อน เช่น การสร้างชื่อเรื่อง ตามค่าเริ่มต้น OpenCode จะพยายามใช้โมเดลที่ถูกกว่าหากมีให้บริการจากผู้ให้บริการของคุณ ไม่เช่นนั้นโมเดลจะกลับไปเป็นโมเดลหลักของคุณ + +ตัวเลือกผู้ให้บริการอาจรวมถึง `timeout` และ `setCacheKey`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` - ​​คำขอหมดเวลาเป็นมิลลิวินาที (ค่าเริ่มต้น: 300000) ตั้งค่าเป็น `false` เพื่อปิดใช้งาน +- `setCacheKey` - ​​ตรวจสอบให้แน่ใจว่าได้ตั้งค่าคีย์แคชสำหรับผู้ให้บริการที่กำหนดเสมอ + +คุณยังสามารถกำหนดค่า [รุ่นท้องถิ่น](/docs/models#local) ได้ [เรียนรู้เพิ่มเติม](/docs/models) + +--- + +#### ตัวเลือกเฉพาะของผู้ให้บริการ + +ผู้ให้บริการบางรายรองรับตัวเลือกการกำหนดค่าเพิ่มเติมนอกเหนือจากการตั้งค่า `timeout` และ `apiKey` ทั่วไป + +##### Amazon Bedrock + +Amazon Bedrock รองรับ AWS-การกำหนดค่าเฉพาะ: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` - ​​AWS ภูมิภาคสำหรับ Bedrock (ค่าเริ่มต้นเป็น `AWS_REGION` env var หรือ `us-east-1`) +- `profile` - ​​AWS ตั้งชื่อโปรไฟล์จาก `~/.aws/credentials` (ค่าเริ่มต้นเป็น `AWS_PROFILE` env var) +- `endpoint` - ​​จุดสิ้นสุดที่กำหนดเอง URL สำหรับจุดสิ้นสุด VPC นี่เป็นนามแฝงสำหรับตัวเลือก `baseURL` ทั่วไปโดยใช้คำศัพท์เฉพาะ AWS หากระบุทั้งสองรายการ `endpoint` จะมีความสำคัญกว่า + +:::note +Bearer Token (`AWS_BEARER_TOKEN_BEDROCK` หรือ `/connect`) มีความสำคัญมากกว่าการตรวจสอบสิทธิ์ตามโปรไฟล์ ดู [ลำดับความสำคัญในการรับรองความถูกต้อง](/docs/providers#การรับรองความถูกต้อง-เหนือกว่า) สำหรับรายละเอียด +::: + +[เรียนรู้เพิ่มเติมเกี่ยวกับการกำหนดค่า Amazon Bedrock](/docs/providers#amazon-bedrock) + +--- + +### Themes + +คุณสามารถกำหนดค่าธีมที่คุณต้องการใช้ในการกำหนดค่า OpenCode ของคุณได้ผ่านตัวเลือก `theme` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[เรียนรู้เพิ่มเติมที่นี่](/docs/themes) + +--- + +### Agents + +คุณสามารถกำหนดค่าตัวแทนเฉพาะสำหรับงานเฉพาะผ่านตัวเลือก `agent` + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +คุณยังสามารถกำหนดตัวแทนโดยใช้ไฟล์ Markdown ใน `~/.config/opencode/agents/` หรือ `.opencode/agents/` [เรียนรู้เพิ่มเติมที่นี่](/docs/agents) + +--- + +### Default Agent + +คุณสามารถตั้งค่าตัวแทนเริ่มต้นได้โดยใช้ตัวเลือก `default_agent` ซึ่งจะกำหนดว่าเอเจนต์ใดที่จะใช้เมื่อไม่มีการระบุอย่างชัดเจน + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +ตัวแทนเริ่มต้นจะต้องเป็นตัวแทนหลัก (ไม่ใช่ตัวแทนย่อย) ซึ่งอาจเป็นตัวแทนในตัว เช่น `"build"` หรือ `"plan"` หรือ [ตัวแทนที่กำหนดเอง](/docs/agents) ที่คุณกำหนดไว้ หากไม่มีตัวแทนที่ระบุหรือเป็นตัวแทนย่อย OpenCode จะถอยกลับไปที่ `"build"` พร้อมคำเตือน + +การตั้งค่านี้ใช้กับอินเทอร์เฟซทั้งหมด: TUI, CLI (`opencode run`) แอปเดสก์ท็อป และ GitHub Action + +--- + +### Sharing + +คุณสามารถกำหนดค่าคุณสมบัติ [แบ่งปัน](/docs/share) ได้ผ่านทางตัวเลือก `share` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +ใช้เวลา: + +- `"manual"` - ​​อนุญาตให้แชร์ด้วยตนเองผ่านคำสั่ง (ค่าเริ่มต้น) +- `"auto"` - ​​แบ่งปันการสนทนาใหม่โดยอัตโนมัติ +- `"disabled"` - ​​ปิดการใช้งานการแชร์ทั้งหมด + +ตามค่าเริ่มต้น การแชร์จะถูกตั้งค่าเป็นโหมดกำหนดเอง ซึ่งคุณต้องแชร์การสนทนาอย่างชัดเจนโดยใช้คำสั่ง `/share` + +--- + +### คำสั่ง + +คุณสามารถกำหนดค่าคำสั่งที่กำหนดเองสำหรับงานซ้ำๆ ได้ผ่านตัวเลือก `command` + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +คุณยังสามารถกำหนดคำสั่งโดยใช้ไฟล์ Markdown ใน `~/.config/opencode/commands/` หรือ `.opencode/commands/` [เรียนรู้เพิ่มเติมที่นี่](/docs/commands) + +--- + +### คีย์ลัด + +คุณสามารถปรับแต่งปุ่มลัดของคุณได้ผ่านตัวเลือก `keybinds` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[เรียนรู้เพิ่มเติมที่นี่](/docs/keybinds) + +--- + +### อัปเดตอัตโนมัติ + +OpenCode จะดาวน์โหลดการอัปเดตใหม่โดยอัตโนมัติเมื่อเริ่มต้นระบบ คุณสามารถปิดการใช้งานนี้ได้โดยใช้ตัวเลือก `autoupdate` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +หากคุณไม่ต้องการการอัปเดตแต่ต้องการรับการแจ้งเตือนเมื่อมีเวอร์ชันใหม่ ให้ตั้งค่า `autoupdate` เป็น `"notify"` +โปรดสังเกตว่าสิ่งนี้ใช้ได้เฉพาะเมื่อไม่ได้ติดตั้งโดยใช้ตัวจัดการแพ็คเกจเช่น Homebrew + +--- + +### ตัวจัดรูปแบบ + +คุณสามารถกำหนดค่าตัวจัดรูปแบบโค้ดผ่านตัวเลือก `formatter` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[เรียนรู้เพิ่มเติมเกี่ยวกับฟอร์แมตเตอร์ที่นี่](/docs/formatters) + +--- + +### การอนุญาต + +ตามค่าเริ่มต้น opencode **อนุญาตการดำเนินการทั้งหมด** โดยไม่ต้องมีการอนุมัติอย่างชัดเจน คุณสามารถเปลี่ยนสิ่งนี้ได้โดยใช้ตัวเลือก `permission` + +ตัวอย่างเช่น เพื่อให้แน่ใจว่าเครื่องมือ `edit` และ `bash` ต้องได้รับการอนุมัติจากผู้ใช้: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[เรียนรู้เพิ่มเติมเกี่ยวกับการอนุญาตที่นี่](/docs/permissions) + +--- + +### การบีบอัด + +คุณสามารถควบคุมลักษณะการทำงานของการบีบอัดบริบทได้โดยใช้ตัวเลือก `compaction` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto` - ​​กระชับเซสชันโดยอัตโนมัติเมื่อบริบทเต็ม (ค่าเริ่มต้น: `true`) +- `prune` - ​​ลบเอาท์พุตเครื่องมือเก่าเพื่อบันทึก tokens (ค่าเริ่มต้น: `true`) + +--- + +### ตัวเฝ้าดู + +คุณสามารถกำหนดค่ารูปแบบการละเว้นตัวเฝ้าดูไฟล์ได้ผ่านตัวเลือก `watcher` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +รูปแบบเป็นไปตามไวยากรณ์ glob ใช้ตัวเลือกนี้เพื่อยกเว้นไดเร็กทอรีที่มีเสียงดังจากการดูไฟล์ + +--- + +### MCP Servers + +คุณสามารถกำหนดค่าเซิร์ฟเวอร์ MCP ที่คุณต้องการใช้ผ่านตัวเลือก `mcp` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[เรียนรู้เพิ่มเติมที่นี่](/docs/mcp-servers) + +--- + +### ปลั๊กอิน + +[ปลั๊กอิน](/docs/plugins) ขยาย OpenCode ด้วยเครื่องมือที่กำหนดเอง hooks และการผสานรวม + +วางไฟล์ปลั๊กอินใน `.opencode/plugins/` หรือ `~/.config/opencode/plugins/` คุณยังสามารถโหลดปลั๊กอินจาก npm ผ่านตัวเลือก `plugin` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[เรียนรู้เพิ่มเติมที่นี่](/docs/plugins) + +--- + +### คำแนะนำ + +คุณสามารถกำหนดค่าคำแนะนำสำหรับรุ่นที่คุณใช้ผ่านตัวเลือก `instructions` + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +สิ่งนี้จะนำอาร์เรย์ของเส้นทางและรูปแบบ glob ไปยังไฟล์คำสั่ง [เรียนรู้เพิ่มเติม +เกี่ยวกับกฎที่นี่](/docs/rules) + +--- + +### Disabled Providers + +คุณสามารถปิดการใช้งานผู้ให้บริการที่โหลดโดยอัตโนมัติผ่านตัวเลือก `disabled_providers` สิ่งนี้มีประโยชน์เมื่อคุณต้องการป้องกันไม่ให้โหลดผู้ให้บริการบางรายแม้ว่าจะมีข้อมูลประจำตัวอยู่ก็ตาม + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +`disabled_providers` มีลำดับความสำคัญมากกว่า `enabled_providers` +::: + +ตัวเลือก `disabled_providers` ยอมรับอาร์เรย์ของรหัสผู้ให้บริการ เมื่อผู้ให้บริการถูกปิดใช้งาน: + +- มันจะไม่ถูกโหลดแม้ว่าจะมีการตั้งค่าตัวแปรสภาพแวดล้อมก็ตาม +- มันจะไม่ถูกโหลดแม้ว่าจะมีการกำหนดค่าคีย์ API ผ่านคำสั่ง `/connect` +- รุ่นของผู้ให้บริการจะไม่ปรากฏในรายการการเลือกรุ่น + +--- + +### Enabled Providers + +คุณสามารถระบุรายชื่อผู้ให้บริการที่อนุญาตได้ผ่านตัวเลือก `enabled_providers` เมื่อตั้งค่าแล้ว เฉพาะผู้ให้บริการที่ระบุเท่านั้นที่จะเปิดใช้งาน และผู้ให้บริการอื่นๆ ทั้งหมดจะถูกละเว้น + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +สิ่งนี้มีประโยชน์เมื่อคุณต้องการจำกัด OpenCode ให้ใช้เฉพาะผู้ให้บริการบางราย แทนที่จะปิดการใช้งานทีละราย + +:::note +`disabled_providers` มีลำดับความสำคัญมากกว่า `enabled_providers` +::: + +หากผู้ให้บริการปรากฏทั้ง `enabled_providers` และ `disabled_providers` `disabled_providers` จะมีลำดับความสำคัญสำหรับความเข้ากันได้แบบย้อนหลัง + +--- + +### ขั้นทดลอง + +ปุ่ม `experimental` มีตัวเลือกที่อยู่ระหว่างการพัฒนา + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +ตัวเลือกการทดลองไม่เสถียร อาจมีการเปลี่ยนแปลงหรือลบออกโดยไม่ต้องแจ้งให้ทราบล่วงหน้า +::: + +--- + +## ตัวแปร + +คุณสามารถใช้การทดแทนตัวแปรในไฟล์กำหนดค่าของคุณเพื่ออ้างอิงตัวแปรสภาพแวดล้อมและเนื้อหาไฟล์ได้ + +--- + +### ตัวแปร Env + +ใช้ `{env:VARIABLE_NAME}` เพื่อทดแทนตัวแปรสภาพแวดล้อม: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +หากไม่ได้ตั้งค่าตัวแปรสภาพแวดล้อม ตัวแปรนั้นจะถูกแทนที่ด้วยสตริงว่าง + +--- + +### ไฟล์ + +ใช้ `{file:path/to/file}` เพื่อทดแทนเนื้อหาของไฟล์: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +เส้นทางไฟล์อาจเป็น: + +- สัมพันธ์กับไดเร็กทอรีไฟล์ปรับแต่ง +- หรือเส้นทางที่แน่นอนเริ่มต้นด้วย `/` หรือ `~` + +สิ่งเหล่านี้มีประโยชน์สำหรับ: + +- เก็บข้อมูลที่ละเอียดอ่อนเช่นคีย์ API ไว้ในไฟล์แยกกัน +- รวมไฟล์คำสั่งขนาดใหญ่โดยไม่ทำให้การกำหนดค่าของคุณเกะกะ +- การแชร์ข้อมูลโค้ดการกำหนดค่าทั่วไปในไฟล์กำหนดค่าหลายไฟล์ diff --git a/packages/web/src/content/docs/th/custom-tools.mdx b/packages/web/src/content/docs/th/custom-tools.mdx new file mode 100644 index 00000000000..28cd229cfd8 --- /dev/null +++ b/packages/web/src/content/docs/th/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: เครื่องมือที่กำหนดเอง +description: สร้างเครื่องมือที่ LLM สามารถเรียกใช้ใน opencode +--- + +เครื่องมือแบบกำหนดเองคือฟังก์ชันที่คุณสร้างขึ้นซึ่ง LLM สามารถเรียกใช้ระหว่างการสนทนาได้ โดยทำงานร่วมกับ [เครื่องมือในตัว](/docs/tools) ของ opencode เช่น `read`, `write` และ `bash` + +--- + +## การสร้างเครื่องมือ + +เครื่องมือถูกกำหนดให้เป็นไฟล์ **TypeScript** หรือ **JavaScript** อย่างไรก็ตาม คำจำกัดความของเครื่องมือสามารถเรียกใช้สคริปต์ที่เขียนใน **ภาษาใดก็ได้** — TypeScript หรือ JavaScript ใช้สำหรับคำจำกัดความของเครื่องมือเท่านั้น + +--- + +### ที่ตั้ง + +สามารถกำหนดได้: + +- ภายในเครื่องโดยวางไว้ในไดเรกทอรี `.opencode/tools/` ของโครงการของคุณ +- หรือทั่วโลกโดยวางไว้ที่ `~/.config/opencode/tools/` + +--- + +### โครงสร้าง + +วิธีที่ง่ายที่สุดในการสร้างเครื่องมือคือการใช้ตัวช่วย `tool()` ซึ่งให้ความปลอดภัยและการตรวจสอบประเภท + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +**ชื่อไฟล์** จะกลายเป็น **ชื่อเครื่องมือ** ข้างต้นจะสร้างเครื่องมือ `database` + +--- + +#### เครื่องมือหลายอย่างต่อไฟล์ + +คุณยังสามารถส่งออกเครื่องมือหลายรายการจากไฟล์เดียวได้ การส่งออกแต่ละครั้งจะกลายเป็น **เครื่องมือแยกต่างหาก** โดยมีชื่อ **`_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +สิ่งนี้จะสร้างเครื่องมือสองอย่าง: `math_add` และ `math_multiply` + +--- + +### ข้อโต้แย้ง + +คุณสามารถใช้ `tool.schema` ซึ่งก็คือ [Zod](https://zod.dev) เพื่อกำหนดประเภทอาร์กิวเมนต์ + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +คุณยังสามารถนำเข้า [Zod](https://zod.dev) ได้โดยตรงและส่งคืนออบเจ็กต์ธรรมดา: + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### บริบท + +เครื่องมือได้รับบริบทเกี่ยวกับเซสชันปัจจุบัน: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +ใช้ `context.directory` สำหรับไดเร็กทอรีการทำงานของเซสชัน +ใช้ `context.worktree` สำหรับรูท git worktree + +--- + +## ตัวอย่าง + +### เขียนเครื่องมือใน Python + +คุณสามารถเขียนเครื่องมือของคุณเป็นภาษาใดก็ได้ที่คุณต้องการ นี่คือตัวอย่างที่บวกตัวเลขสองตัวโดยใช้ Python + +ขั้นแรก สร้างเครื่องมือเป็นสคริปต์ Python: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +จากนั้นสร้างคำจำกัดความของเครื่องมือที่เรียกใช้: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +ที่นี่เราใช้ยูทิลิตี้ [`Bun.$`](https://bun.com/docs/runtime/shell) เพื่อรันสคริปต์ Python diff --git a/packages/web/src/content/docs/th/ecosystem.mdx b/packages/web/src/content/docs/th/ecosystem.mdx new file mode 100644 index 00000000000..f1630f9a2f8 --- /dev/null +++ b/packages/web/src/content/docs/th/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: ระบบนิเวศ +description: โปรเจ็กต์และการผสานรวมที่สร้างด้วย OpenCode +--- + +ชุดโครงการชุมชนที่สร้างขึ้นบน OpenCode + +:::note +ต้องการเพิ่มโครงการที่เกี่ยวข้องกับ OpenCode ของคุณลงในรายการนี้หรือไม่ ส่งพีอาร์. +::: + +คุณยังสามารถลองดู [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) และ [opencode.cafe](https://opencode.cafe) ซึ่งเป็นชุมชนที่รวบรวมระบบนิเวศและชุมชนไว้ด้วยกัน + +--- + +## ปลั๊กอิน + +| ชื่อ | คำอธิบาย | +| --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | เรียกใช้เซสชัน OpenCode โดยอัตโนมัติในแซนด์บ็อกซ์ Daytona ที่แยกออกมาพร้อม git sync และการแสดงตัวอย่างแบบสด | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | แทรกส่วนหัวเซสชัน Helicone โดยอัตโนมัติสำหรับการจัดกลุ่มคำขอ | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | ฉีดประเภท TypeScript/Svelte ลงในไฟล์ที่อ่านโดยอัตโนมัติด้วยเครื่องมือค้นหา | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | ใช้การสมัครสมาชิก ChatGPT Plus/Pro แทนเครดิต API | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | ใช้แผน Gemini ที่มีอยู่ของคุณแทนการเรียกเก็บเงิน API | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | ใช้โมเดลฟรีของ Antigravity แทนการเรียกเก็บเงิน API | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | การแยกคอนเทนเนอร์ Devcontainer แบบหลายสาขาพร้อมโคลนแบบตื้นและพอร์ตที่กำหนดอัตโนมัติ | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | ปลั๊กอิน Google Antigravity OAuth พร้อมรองรับ Google Search และการจัดการ API ที่แข็งแกร่งยิ่งขึ้น | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | ปรับการใช้โทเค็นให้เหมาะสมโดยการตัดเอาท์พุตของเครื่องมือที่ล้าสมัย | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | เพิ่มการสนับสนุนการค้นหาเว็บแบบเนทีฟสำหรับผู้ให้บริการที่รองรับด้วยรูปแบบที่มีเหตุผลของ Google | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | ช่วยให้ตัวแทน AI สามารถเรียกใช้กระบวนการเบื้องหลังใน PTY และส่งข้อมูลเชิงโต้ตอบให้พวกเขาได้ | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | คำแนะนำสำหรับคำสั่ง shell แบบไม่โต้ตอบ - ป้องกันการแฮงค์จากการดำเนินการที่ขึ้นอยู่กับ TTY | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | ติดตามการใช้งาน OpenCode ด้วย Wakatime | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | ทำความสะอาดตาราง Markdown ที่ผลิตโดย LLM | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | การแก้ไขโค้ดเร็วขึ้น 10 เท่าด้วย Morph Fast Apply API และเครื่องหมายแก้ไขแบบ Lazy | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | ตัวแทนเบื้องหลัง, เครื่องมือ LSP/AST/MCP ที่สร้างไว้ล่วงหน้า, ตัวแทนที่ได้รับการดูแลจัดการ, เข้ากันได้กับ Claude Code | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | การแจ้งเตือนบนเดสก์ท็อปและเสียงเตือนสำหรับเซสชัน OpenCode | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | การแจ้งเตือนบนเดสก์ท็อปและเสียงเตือนสำหรับการอนุญาต การดำเนินการเสร็จสิ้น และเหตุการณ์ข้อผิดพลาด | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | การตั้งชื่อเซสชัน Zellij อัตโนมัติที่ขับเคลื่อนด้วย AI ตามบริบทของ OpenCode | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | อนุญาตให้ตัวแทน OpenCode โหลดแบบ Lazy Load ตามความต้องการพร้อมการค้นพบทักษะและการแทรก | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | หน่วยความจำถาวรตลอดเซสชันโดยใช้ Supermemory | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | การตรวจสอบแผนเชิงโต้ตอบพร้อมคำอธิบายประกอบแบบภาพและการแชร์ส่วนตัว/offline | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | ขยาย opencode /commands ไปสู่ระบบการประสานที่มีประสิทธิภาพพร้อมการควบคุมโฟลว์แบบละเอียด | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | กำหนดเวลางานที่เกิดซ้ำโดยใช้ launchd (Mac) หรือ systemd (Linux) ด้วยไวยากรณ์ cron | +| [micode](https://github.com/vtemian/micode) | ระดมความคิดอย่างมีโครงสร้าง → วางแผน → นำเวิร์กโฟลว์ไปใช้ด้วยความต่อเนื่องของเซสชัน | +| [octto](https://github.com/vtemian/octto) | UI เบราว์เซอร์แบบโต้ตอบสำหรับการระดมความคิด AI ด้วยแบบฟอร์มคำถามหลายข้อ | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | เอเจนต์พื้นหลังสไตล์ Claude Code พร้อมการมอบหมายแบบอะซิงก์และการคงอยู่ของบริบท | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | การแจ้งเตือนระบบปฏิบัติการดั้งเดิมสำหรับ OpenCode – ทราบเมื่องานเสร็จสมบูรณ์ | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | ชุดสายรัดประสานหลายเอเจนต์ที่ให้มา – ส่วนประกอบ 16 ชิ้น ติดตั้งเพียงครั้งเดียว | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | เวิร์กทรีคอมไพล์ไร้แรงเสียดทานสำหรับ OpenCode | + +--- + +## โครงการ + +| ชื่อ | คำอธิบาย | +| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- | +| [kimaki](https://github.com/remorses/kimaki) | บอท Discord เพื่อควบคุมเซสชัน OpenCode สร้างขึ้นบน SDK | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | ปลั๊กอิน Neovim สำหรับข้อความแจ้งที่ทราบโดยบรรณาธิการ ซึ่งสร้างขึ้นบน API | +| [portal](https://github.com/hosenur/portal) | UI เว็บบนมือถือเป็นครั้งแรกสำหรับ OpenCode บน Tailscale/VPN | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | เทมเพลตสำหรับสร้างปลั๊กอิน OpenCode | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | ส่วนหน้า Neovim สำหรับ opencode - เอเจนต์การเข้ารหัส AI ที่ใช้ terminal | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | ผู้ให้บริการ Vercel AI SDK สำหรับการใช้งาน OpenCode ผ่าน @opencode-ai/sdk | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | แอพเว็บ / เดสก์ท็อปและส่วนขยาย VS Code สำหรับ OpenCode | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | ปลั๊กอิน Obsidian ที่ฝัง OpenCode ไว้ใน UI ของ Obsidian | +| [OpenWork](https://github.com/different-ai/openwork) | ทางเลือกโอเพ่นซอร์สแทน Claude Cowork ซึ่งขับเคลื่อนโดย OpenCode | +| [ocx](https://github.com/kdcokenny/ocx) | ตัวจัดการส่วนขยาย OpenCode พร้อมโปรไฟล์แบบพกพาและแยกส่วน | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | แอปเดสก์ท็อป เว็บ มือถือ และไคลเอ็นต์ระยะไกลสำหรับ OpenCode | + +--- + +## ตัวแทน + +| ชื่อ | คำอธิบาย | +| ----------------------------------------------------------------- | ------------------------------------------------------------------------ | +| [Agentic](https://github.com/Cluster444/agentic) | เอเจนต์ AI แบบแยกส่วนและคำสั่งสำหรับการพัฒนาแบบมีโครงสร้าง | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | กำหนดค่า พรอมต์ เอเจนต์ และปลั๊กอินสำหรับเวิร์กโฟลว์ที่ได้รับการปรับปรุง | diff --git a/packages/web/src/content/docs/th/enterprise.mdx b/packages/web/src/content/docs/th/enterprise.mdx new file mode 100644 index 00000000000..9bc041fa7c3 --- /dev/null +++ b/packages/web/src/content/docs/th/enterprise.mdx @@ -0,0 +1,170 @@ +--- +title: องค์กร +description: การใช้ OpenCode อย่างปลอดภัยในองค์กรของคุณ +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +OpenCode Enterprise เหมาะสำหรับองค์กรที่ต้องการให้แน่ใจว่าโค้ดและข้อมูลของตนไม่หลุดออกจากโครงสร้างพื้นฐาน ซึ่งสามารถทำได้โดยใช้การกำหนดค่าแบบรวมศูนย์ที่ทำงานร่วมกับ SSO และเกตเวย์ AI ภายในของคุณ + +:::note +OpenCode จะไม่เก็บโค้ดหรือข้อมูลบริบทใดๆ ของคุณ +::: + +ในการเริ่มต้นใช้งาน OpenCode Enterprise: + +1. ทดลองใช้งานภายในกับทีมของคุณ +2. **ติดต่อเรา** เพื่อหารือเกี่ยวกับตัวเลือกด้านราคาและการใช้งาน + +--- + +## การทดลอง + +OpenCode เป็นโอเพ่นซอร์สและไม่ได้จัดเก็บโค้ดหรือข้อมูลบริบทใดๆ ของคุณ ดังนั้นนักพัฒนาของคุณสามารถ [เริ่มต้น](/docs/) และดำเนินการทดลองใช้งานได้อย่างง่ายดาย + +--- + +### การจัดการข้อมูล + +**OpenCode จะไม่จัดเก็บโค้ดหรือข้อมูลบริบทของคุณ** การประมวลผลทั้งหมดเกิดขึ้นภายในเครื่องหรือผ่านการเรียก API โดยตรงไปยังผู้ให้บริการ AI ของคุณ + +ซึ่งหมายความว่าตราบใดที่คุณใช้ผู้ให้บริการที่คุณเชื่อถือหรือผู้ให้บริการภายใน +เกตเวย์ AI คุณสามารถใช้ OpenCode ได้อย่างปลอดภัย + +ข้อแม้เดียวที่นี่คือคุณสมบัติเสริม `/share` + +--- + +#### การแบ่งปันการสนทนา + +หากผู้ใช้เปิดใช้งานคุณสมบัติ `/share` การสนทนาและข้อมูลที่เกี่ยวข้องกับการสนทนาจะถูกส่งไปยังบริการที่เราใช้เพื่อโฮสต์เพจแชร์เหล่านี้ที่ opencode.ai + +ขณะนี้ข้อมูลให้บริการผ่านเครือข่าย Edge ของ CDN ของเรา และถูกแคชไว้ที่ Edge ใกล้ผู้ใช้ของคุณ + +เราขอแนะนำให้คุณปิดการใช้งานนี้สำหรับการทดลองใช้ของคุณ + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[เรียนรู้เพิ่มเติมเกี่ยวกับการแชร์](/docs/share) + +--- + +### ความเป็นเจ้าของรหัส + +**คุณเป็นเจ้าของโค้ดทั้งหมดที่สร้างโดย OpenCode** ไม่มีข้อจำกัดด้านใบอนุญาตหรือการอ้างสิทธิ์ความเป็นเจ้าของ + +--- + +## ราคา + +เราใช้แบบจำลองต่อที่นั่งสำหรับ OpenCode Enterprise หากคุณมีเกตเวย์ LLM ของคุณเอง เราจะไม่เรียกเก็บเงินสำหรับtokensที่ใช้ สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับตัวเลือกราคาและการใช้งาน **ติดต่อเรา** + +--- + +## การปรับใช้ + +เมื่อคุณทดลองใช้งานเสร็จแล้วและพร้อมที่จะใช้ OpenCode ที่ +องค์กรของคุณ คุณสามารถ **ติดต่อเรา** เพื่อหารือเกี่ยวกับ +ตัวเลือกการกำหนดราคาและการใช้งาน + +--- + +### การกำหนดค่าส่วนกลาง + +เราสามารถตั้งค่า OpenCode เพื่อใช้การกำหนดค่าส่วนกลางเพียงรายการเดียวสำหรับทั้งองค์กรของคุณได้ + +การกำหนดค่าแบบรวมศูนย์นี้สามารถทำงานร่วมกับผู้ให้บริการ SSO ของคุณได้ และรับรองว่าผู้ใช้ทุกคนจะเข้าถึงเฉพาะเกตเวย์ AI ภายในของคุณเท่านั้น + +--- + +### SSO บูรณาการ + +ด้วยการกำหนดค่าส่วนกลาง OpenCode สามารถทำงานร่วมกับผู้ให้บริการ SSO ขององค์กรของคุณเพื่อตรวจสอบสิทธิ์ได้ + +ซึ่งช่วยให้ OpenCode รับข้อมูลรับรองสำหรับเกตเวย์ AI ภายในของคุณผ่านระบบการจัดการข้อมูลประจำตัวที่คุณมีอยู่ + +--- + +### เกตเวย์ AI ภายใน + +ด้วยการกำหนดค่าส่วนกลาง คุณสามารถกำหนดค่า OpenCode ให้ใช้เกตเวย์ AI ภายในของคุณเท่านั้น + +คุณยังสามารถปิดการใช้งานผู้ให้บริการ AI อื่นๆ ทั้งหมดได้ เพื่อให้มั่นใจว่าคำขอทั้งหมดจะผ่านโครงสร้างพื้นฐานที่ได้รับอนุมัติขององค์กรของคุณ + +--- + +### โฮสติ้งด้วยตนเอง + +ในขณะที่เราแนะนำให้ปิดการใช้งานหน้าแบ่งปันเพื่อให้แน่ใจว่าข้อมูลของคุณจะไม่หายไป +องค์กรของคุณ เราก็สามารถช่วยคุณโฮสต์พวกเขาเองบนโครงสร้างพื้นฐานของคุณได้ + +ขณะนี้อยู่ในแผนงานของเรา หากคุณสนใจ **แจ้งให้เราทราบ** + +--- + +## FAQ + +

+OpenCode Enterprise คืออะไร? + +OpenCode Enterprise เหมาะสำหรับองค์กรที่ต้องการให้แน่ใจว่าโค้ดและข้อมูลของตนไม่หลุดออกจากโครงสร้างพื้นฐาน ซึ่งสามารถทำได้โดยใช้การกำหนดค่าแบบรวมศูนย์ที่ทำงานร่วมกับ SSO และเกตเวย์ AI ภายในของคุณ + +
+ +
+ฉันจะเริ่มต้นใช้งาน OpenCode Enterprise ได้อย่างไร? + +เพียงเริ่มต้นด้วยการทดลองใช้ภายในกับทีมของคุณ ตามค่าเริ่มต้น OpenCode จะไม่จัดเก็บโค้ดหรือข้อมูลบริบทของคุณ ทำให้ง่ายต่อการเริ่มต้น + +จากนั้น **ติดต่อเรา** เพื่อหารือเกี่ยวกับตัวเลือกด้านราคาและการใช้งาน + +
+ +
+ราคาสำหรับองค์กรทำงานอย่างไร? + +เราเสนอราคาสำหรับองค์กรต่อที่นั่ง หากคุณมีเกตเวย์ LLM ของคุณเอง เราจะไม่เรียกเก็บเงินสำหรับtokensที่ใช้ สำหรับรายละเอียดเพิ่มเติม **ติดต่อเรา** เพื่อขอใบเสนอราคาที่กำหนดเองตามความต้องการขององค์กรของคุณ + +
+ +
+ข้อมูลของฉันปลอดภัยกับ OpenCode Enterprise หรือไม่? + +ใช่. OpenCode จะไม่เก็บโค้ดหรือข้อมูลบริบทของคุณ การประมวลผลทั้งหมดเกิดขึ้นภายในเครื่องหรือผ่านการโทรศัพท์ API โดยตรงไปยังผู้ให้บริการ AI ของคุณ ด้วยการกำหนดค่าส่วนกลางและการบูรณาการ SSO ข้อมูลของคุณยังคงปลอดภัยภายในโครงสร้างพื้นฐานขององค์กรของคุณ + +
+ +
+เราสามารถใช้ private NPM registry ของเราเองได้หรือไม่? + +OpenCode รองรับการลงทะเบียน npm ส่วนตัวผ่านการรองรับไฟล์ `.npmrc` ดั้งเดิมของ Bun หากองค์กรของคุณใช้รีจิสทรีส่วนตัว เช่น JFrog Artifactory, Nexus หรือที่คล้ายกัน โปรดตรวจสอบให้แน่ใจว่านักพัฒนาได้รับการตรวจสอบสิทธิ์ก่อนเรียกใช้ OpenCode + +วิธีตั้งค่าการตรวจสอบสิทธิ์กับรีจิสทรีส่วนตัวของคุณ: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +สิ่งนี้จะสร้าง `~/.npmrc` พร้อมรายละเอียดการตรวจสอบสิทธิ์ OpenCode จะอัตโนมัติ +หยิบสิ่งนี้ขึ้นมา + +:::caution +คุณต้องเข้าสู่ระบบรีจิสทรีส่วนตัวก่อนที่จะเรียกใช้ OpenCode +::: + +หรือคุณสามารถกำหนดค่าไฟล์ `.npmrc` ด้วยตนเองได้: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +นักพัฒนาจะต้องลงชื่อเข้าใช้รีจิสทรีส่วนตัวก่อนที่จะเรียกใช้ OpenCode เพื่อให้แน่ใจว่าสามารถติดตั้งแพ็คเกจจากรีจิสทรีขององค์กรของคุณได้ + +
diff --git a/packages/web/src/content/docs/th/formatters.mdx b/packages/web/src/content/docs/th/formatters.mdx new file mode 100644 index 00000000000..e852cb45dc3 --- /dev/null +++ b/packages/web/src/content/docs/th/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: ฟอร์แมตเตอร์ +description: OpenCode ใช้ตัวจัดรูปแบบเฉพาะภาษา +--- + +OpenCode จะจัดรูปแบบไฟล์โดยอัตโนมัติหลังจากที่เขียนหรือแก้ไขโดยใช้ตัวจัดรูปแบบเฉพาะภาษา เพื่อให้แน่ใจว่าโค้ดที่สร้างขึ้นเป็นไปตามสไตล์โค้ดของโปรเจ็กต์ของคุณ + +--- + +## บิวท์อิน + +OpenCode มาพร้อมกับฟอร์แมตเตอร์ในตัวหลายตัวสำหรับภาษาและเฟรมเวิร์กยอดนิยม ด้านล่างนี้คือรายการฟอร์แมตเตอร์ นามสกุลไฟล์ที่รองรับ และคำสั่งหรือตัวเลือกการกำหนดค่าที่ต้องการ + +| ฟอร์แมตเตอร์ | ส่วนขยาย | ความต้องการ | +| -------------- | ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | +| gofmt | .go | `gofmt` คำสั่งใช้ได้ | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | `mix` คำสั่งใช้ได้ | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml และ [เพิ่มเติม](https://prettier.io/docs/en/index.html) | `prettier` การพึ่งพาใน `package.json` | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml และ [เพิ่มเติม](https://biomejs.dev/) | `biome.json(c)` ไฟล์ปรับแต่ง | +| zig | .zig, .zon | `zig` คำสั่งใช้ได้ | +| clang-format | .c, .cpp, .h, .hpp, .ino และ [เพิ่มเติม](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` ไฟล์ปรับแต่ง | +| ktlint | .kt, .kts | `ktlint` คำสั่งใช้ได้ | +| ruff | .py, .pyi | คำสั่ง `ruff` ใช้ได้กับ config | +| rust | .rs | `rustfmt` คำสั่งใช้ได้ | +| cargo fmt | .rs | `cargo fmt` คำสั่งใช้ได้ | +| uv | .py, .pyi | `uv` คำสั่งใช้ได้ | +| rubocop | .rb, .rake, .gemspec, .ru | `rubocop` คำสั่งใช้ได้ | +| standardrb | .rb, .rake, .gemspec, .ru | `standardrb` คำสั่งใช้ได้ | +| htmlbeautifier | .erb, .html.erb | `htmlbeautifier` คำสั่งใช้ได้ | +| air | .r | `air` คำสั่งใช้ได้ | +| dart | .dart | `dart` คำสั่งใช้ได้ | +| ocamlformat | .ml, .mli | มีคำสั่ง `ocamlformat` และไฟล์ปรับแต่ง `.ocamlformat` | +| terraform | .tf, .tfvars | `terraform` คำสั่งใช้ได้ | +| gleam | .gleam | `gleam` คำสั่งใช้ได้ | +| nix | .nix | `nixfmt` คำสั่งใช้ได้ | +| shfmt | .sh, .bash | `shfmt` คำสั่งใช้ได้ | +| pint | .php | `laravel/pint` การพึ่งพาใน `composer.json` | +| oxfmt (ทดลอง) | .js, .jsx, .ts, .tsx | `oxfmt` การพึ่งพาใน `package.json` และ [แฟล็กตัวแปร env ทดลอง](/docs/cli/#experimental) | +| ormolu | .hs | `ormolu` คำสั่งใช้ได้ | + +ดังนั้นหากโปรเจ็กต์ของคุณมี `prettier` ใน `package.json` OpenCode จะใช้มันโดยอัตโนมัติ + +--- + +## มันทำงานอย่างไร + +เมื่อ OpenCode เขียนหรือแก้ไขไฟล์ มันจะ: + +1. ตรวจสอบนามสกุลไฟล์กับฟอร์แมตเตอร์ที่เปิดใช้งานทั้งหมด +2. รันคำสั่งฟอร์แมตเตอร์ที่เหมาะสมบนไฟล์ +3. ใช้การเปลี่ยนแปลงการจัดรูปแบบโดยอัตโนมัติ + +กระบวนการนี้เกิดขึ้นในเบื้องหลัง ทำให้มั่นใจได้ว่าสไตล์โค้ดของคุณจะถูกรักษาไว้โดยไม่มีขั้นตอนที่ต้องทำเอง + +--- + +## กำหนดค่า + +คุณสามารถปรับแต่งฟอร์แมตเตอร์ได้ผ่านทางส่วน `formatter` ในการกำหนดค่า OpenCode ของคุณ + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +การกำหนดค่าฟอร์แมตเตอร์แต่ละรายการรองรับสิ่งต่อไปนี้: + +| คุณสมบัติ | พิมพ์ | คำอธิบาย | +| ------------- | ------- | ------------------------------------------------- | +| `disabled` | บูลีน | ตั้งค่านี้เป็น `true` เพื่อปิดใช้งานฟอร์แมตเตอร์ | +| `command` | สตริง[] | คำสั่งให้เรียกใช้การจัดรูปแบบ | +| `environment` | วัตถุ | ตัวแปรสภาพแวดล้อมที่จะตั้งค่าเมื่อรันฟอร์แมตเตอร์ | +| `extensions` | สตริง[] | นามสกุลไฟล์ที่ฟอร์แมตเตอร์นี้ควรรองรับ | + +ลองดูตัวอย่างบางส่วน + +--- + +### ปิดการใช้งานฟอร์แมตเตอร์ + +หากต้องการปิดการใช้งาน **ทั้งหมด** ฟอร์แมตเตอร์ทั่วโลก ให้ตั้งค่า `formatter` เป็น `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +หากต้องการปิดใช้งานฟอร์แมตเตอร์ **เฉพาะ** ให้ตั้งค่า `disabled` เป็น `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### ตัวจัดรูปแบบที่กำหนดเอง + +คุณสามารถแทนที่ฟอร์แมตเตอร์ที่มีอยู่แล้วภายในหรือเพิ่มฟอร์แมตใหม่ได้โดยการระบุคำสั่ง ตัวแปรสภาพแวดล้อม และนามสกุลไฟล์: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +ตัวยึดตำแหน่ง **`$FILE`** ในคำสั่งจะถูกแทนที่ด้วยเส้นทางไปยังไฟล์ที่กำลังจัดรูปแบบ diff --git a/packages/web/src/content/docs/th/github.mdx b/packages/web/src/content/docs/th/github.mdx new file mode 100644 index 00000000000..40816d78413 --- /dev/null +++ b/packages/web/src/content/docs/th/github.mdx @@ -0,0 +1,321 @@ +--- +title: GitHub +description: ใช้ OpenCode ในปัญหา GitHub และคำขอแบบดึง +--- + +OpenCode ผสานรวมกับเวิร์กโฟลว์ GitHub ของคุณ พูดถึง `/opencode` หรือ `/oc` ในความคิดเห็นของคุณ แล้ว OpenCode จะดำเนินการงานภายใน GitHub Actions runner ของคุณ + +--- + +## คุณสมบัติ + +- **Issue Triage**: ขอให้ OpenCode ตรวจสอบปัญหาและอธิบายให้คุณทราบ +- **แก้ไขและนำไปใช้**: ขอให้ OpenCode แก้ไขปัญหาหรือใช้ฟีเจอร์ และมันจะทำงานในสาขาใหม่และส่ง PR พร้อมการเปลี่ยนแปลงทั้งหมด +- **ปลอดภัย**: OpenCode ทำงานภายในรันเนอร์ของ GitHub ของคุณ + +--- + +## การติดตั้ง + +รันคำสั่งต่อไปนี้ในโปรเจ็กต์ที่อยู่ใน repo GitHub: + +```bash +opencode github install +``` + +ขั้นตอนนี้จะแนะนำคุณตลอดขั้นตอนการติดตั้งแอป GitHub การสร้างเวิร์กโฟลว์ และการตั้งค่าความลับ + +--- + +### การตั้งค่าด้วยตนเอง + +หรือคุณสามารถตั้งค่าได้ด้วยตนเอง + +1. **ติดตั้งแอป GitHub** + + ไปที่ [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent) ตรวจสอบให้แน่ใจว่าได้ติดตั้งบนที่เก็บเป้าหมายแล้ว + +2. **เพิ่มขั้นตอนการทำงาน** + + เพิ่มไฟล์เวิร์กโฟลว์ต่อไปนี้ไปที่ `.github/workflows/opencode.yml` ใน repo ของคุณ ตรวจสอบให้แน่ใจว่าได้ตั้งค่า `model` ที่เหมาะสมและคีย์ API ที่จำเป็นใน `env` + + ```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx + ``` + +3. **เก็บคีย์ API เป็นความลับ** + + ในองค์กรหรือโครงการ **การตั้งค่า** ให้ขยาย **ความลับและตัวแปร** ทางด้านซ้าย แล้วเลือก **การดำเนินการ** และเพิ่มคีย์ API ที่จำเป็น + +--- + +## การกำหนดค่า + +- `model`: โมเดลที่จะใช้กับ OpenCode ใช้รูปแบบของ `provider/model` นี่คือ **จำเป็น** +- `agent`: ตัวแทนที่จะใช้ จะต้องเป็นตัวแทนหลัก ย้อนกลับไปที่ `default_agent` จาก config หรือ `"build"` หากไม่พบ +- `share`: ไม่ว่าจะแชร์เซสชัน OpenCode หรือไม่ ค่าเริ่มต้นเป็น **จริง** สำหรับที่เก็บข้อมูลสาธารณะ +- `prompt`: ตัวเลือกที่กำหนดเองพร้อมท์เพื่อแทนที่การทำงานเริ่มต้น ใช้สิ่งนี้เพื่อปรับแต่งวิธีที่ OpenCode ประมวลผลคำขอ +- `token`: GitHub Access Token เสริมสำหรับการดำเนินการ เช่น การสร้างความคิดเห็น การยอมรับการเปลี่ยนแปลง และการเปิดคำขอดึง ตามค่าเริ่มต้น OpenCode จะใช้โทเค็นการเข้าถึงการติดตั้งจาก OpenCode GitHub App ดังนั้นคอมมิต แสดงความคิดเห็น และคำขอดึงข้อมูลจะปรากฏว่ามาจากแอป + + หรือคุณสามารถใช้ [ในตัว `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) ของ GitHub Action runner ได้โดยไม่ต้องติดตั้งแอป OpenCode GitHub เพียงตรวจสอบให้แน่ใจว่าได้ให้สิทธิ์ที่จำเป็นในขั้นตอนการทำงานของคุณ: + + ```yaml + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + ``` + + คุณยังสามารถใช้ [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) ได้หากต้องการ + +--- + +## กิจกรรมที่รองรับ + +OpenCode สามารถทริกเกอร์ได้โดยเหตุการณ์ GitHub ต่อไปนี้: + +| ประเภทเหตุการณ์ | กระตุ้นโดย | รายละเอียด | +| ----------------------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| `issue_comment` | แสดงความคิดเห็นในประเด็นหรือประชาสัมพันธ์ | พูดถึง `/opencode` หรือ `/oc` ในความคิดเห็นของคุณ OpenCode อ่านบริบทและสามารถสร้างสาขา เปิด PR หรือตอบกลับได้ | +| `pull_request_review_comment` | แสดงความคิดเห็นเกี่ยวกับบรรทัดรหัสเฉพาะในการประชาสัมพันธ์ | พูดถึง `/opencode` หรือ `/oc` ในขณะที่ตรวจสอบโค้ด OpenCode รับเส้นทางไฟล์ หมายเลขบรรทัด และบริบทที่แตกต่าง | +| `issues` | ปัญหาเปิดหรือแก้ไข | ทริกเกอร์ OpenCode โดยอัตโนมัติเมื่อมีการสร้างหรือแก้ไขปัญหา ต้องป้อนข้อมูล `prompt` | +| `pull_request` | PR เปิดหรืออัปเดตแล้ว | ทริกเกอร์ OpenCode โดยอัตโนมัติเมื่อมีการเปิด ซิงโครไนซ์ หรือเปิด PR อีกครั้ง มีประโยชน์สำหรับการตรวจสอบอัตโนมัติ | +| `schedule` | กำหนดการตาม Cron | เรียกใช้ OpenCode ตามกำหนดเวลา ต้องป้อนข้อมูล `prompt` เอาต์พุตไปที่บันทึกและ PR (ไม่มีปัญหาในการแสดงความคิดเห็น) | +| `workflow_dispatch` | ทริกเกอร์ด้วยตนเองจาก GitHub UI | ทริกเกอร์ OpenCode ตามความต้องการผ่านแท็บการดำเนินการ ต้องป้อนข้อมูล `prompt` เอาต์พุตไปที่บันทึกและ PR | + +### ตัวอย่างกำหนดการ + +เรียกใช้ OpenCode ตามกำหนดเวลาเพื่อทำงานอัตโนมัติ: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +สำหรับกิจกรรมที่กำหนดเวลาไว้ อินพุต `prompt` เป็นสิ่งที่จำเป็น\*\* เนื่องจากไม่มีความคิดเห็นที่จะดึงคำแนะนำออกมา เวิร์กโฟลว์ตามกำหนดการทำงานโดยไม่มีบริบทผู้ใช้ในการตรวจสอบสิทธิ์ ดังนั้นเวิร์กโฟลว์จะต้องให้สิทธิ์ `contents: write` และ `pull-requests: write` หากคุณคาดหวังให้ OpenCode สร้างสาขาหรือ PR + +--- + +### ตัวอย่างคำขอดึง + +ตรวจสอบ PR โดยอัตโนมัติเมื่อมีการเปิดหรืออัปเดต: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +สำหรับกิจกรรม `pull_request` หากไม่มีการระบุ `prompt` OpenCode จะใช้ค่าเริ่มต้นในการตรวจสอบคำขอดึง + +--- + +### ตัวอย่าง Triage ปัญหา + +คัดแยกปัญหาใหม่โดยอัตโนมัติ ตัวอย่างนี้กรองไปยังบัญชีที่มีอายุมากกว่า 30 วันเพื่อลดสแปม: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +สำหรับเหตุการณ์ `issues` อินพุต `prompt` นั้น **จำเป็น** เนื่องจากไม่มีความคิดเห็นที่จะดึงคำแนะนำออกมา + +--- + +## ข้อความแจ้งที่กำหนดเอง + +แทนที่ข้อความแจ้งเริ่มต้นเพื่อปรับแต่งการทำงานของ OpenCode สำหรับเวิร์กโฟลว์ของคุณ + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +สิ่งนี้มีประโยชน์สำหรับการบังคับใช้เกณฑ์การตรวจสอบเฉพาะ มาตรฐานการเขียนโค้ด หรือประเด็นมุ่งเน้นที่เกี่ยวข้องกับโครงการของคุณ + +--- + +## ตัวอย่าง + +นี่คือตัวอย่างบางส่วนของวิธีที่คุณสามารถใช้ OpenCode ใน GitHub + +- **อธิบายปัญหา** + + เพิ่มความคิดเห็นนี้ในปัญหา GitHub + + ``` + /opencode explain this issue + ``` + + OpenCode จะอ่านกระทู้ทั้งหมด รวมถึงความคิดเห็นทั้งหมด และตอบกลับพร้อมคำอธิบายที่ชัดเจน + +- **แก้ไขปัญหา** + + ในปัญหา GitHub ให้พูดว่า: + + ``` + /opencode fix this + ``` + + และ OpenCode จะสร้างสาขาใหม่ ดำเนินการเปลี่ยนแปลง และเปิด PR ที่มีการเปลี่ยนแปลง + +- **ตรวจสอบ PR และทำการเปลี่ยนแปลง** + + แสดงความคิดเห็นต่อไปนี้ใน GitHub PR + + ``` + Delete the attachment from S3 when the note is removed /oc + ``` + + OpenCode จะดำเนินการเปลี่ยนแปลงที่ร้องขอและส่งมอบให้กับ PR เดียวกัน + +- **ตรวจสอบบรรทัดรหัสเฉพาะ** + + แสดงความคิดเห็นโดยตรงบนบรรทัดโค้ดในแท็บ "ไฟล์" ของ PR OpenCode จะตรวจจับไฟล์ หมายเลขบรรทัด และบริบทต่างโดยอัตโนมัติเพื่อให้การตอบสนองที่แม่นยำ + + ``` + [Comment on specific lines in Files tab] + /oc add error handling here + ``` + + เมื่อแสดงความคิดเห็นในบรรทัดใดบรรทัดหนึ่ง OpenCode จะได้รับ: + - กำลังตรวจสอบไฟล์ที่แน่นอน + - บรรทัดโค้ดเฉพาะ + - บริบทที่แตกต่างโดยรอบ + - ข้อมูลหมายเลขบรรทัด + + ซึ่งช่วยให้สามารถร้องขอที่ตรงเป้าหมายมากขึ้นโดยไม่จำเป็นต้องระบุเส้นทางไฟล์หรือหมายเลขบรรทัดด้วยตนเอง diff --git a/packages/web/src/content/docs/th/gitlab.mdx b/packages/web/src/content/docs/th/gitlab.mdx new file mode 100644 index 00000000000..44bee1ddac0 --- /dev/null +++ b/packages/web/src/content/docs/th/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: ใช้ OpenCode ในปัญหา GitLab และรวมคำขอ +--- + +OpenCode ทำงานร่วมกับเวิร์กโฟลว์ GitLab ของคุณผ่านไปป์ไลน์ GitLab CI/CD หรือกับ GitLab Duo + +ในทั้งสองกรณี OpenCode จะทำงานบน GitLab runners ของคุณ + +--- + +## GitLab CI + +OpenCode ทำงานในไปป์ไลน์ GitLab ปกติ คุณสามารถสร้างมันลงในไปป์ไลน์เป็น [องค์ประกอบ CI](https://docs.gitlab.com/ee/ci/components/) + +ที่นี่เรากำลังใช้คอมโพเนนต์ CI/CD ที่สร้างโดยชุมชนสำหรับ OpenCode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode) + +--- + +### คุณสมบัติ + +- **ใช้การกำหนดค่าแบบกำหนดเองต่องาน**: กำหนดค่า OpenCode ด้วยไดเร็กทอรีการกำหนดค่าแบบกำหนดเอง เช่น `./config/#custom-directory` เพื่อเปิดหรือปิดฟังก์ชันการทำงานต่อการเรียกใช้ OpenCode +- **การตั้งค่าขั้นต่ำ**: องค์ประกอบ CI จะตั้งค่า OpenCode ในเบื้องหลัง คุณเพียงแค่ต้องสร้างการกำหนดค่า OpenCode และข้อความแจ้งเริ่มต้นเท่านั้น +- **ยืดหยุ่น**: ส่วนประกอบ CI รองรับอินพุตหลายอินพุตเพื่อปรับแต่งลักษณะการทำงาน + +--- + +### ตั้งค่า + +1. จัดเก็บการรับรองความถูกต้อง OpenCode ของคุณ JSON เป็นประเภทไฟล์ CI ตัวแปรสภาพแวดล้อมภายใต้ **การตั้งค่า** > **CI/CD** > **ตัวแปร** ตรวจสอบให้แน่ใจว่าได้ทำเครื่องหมายว่าเป็น "ปิดบังและซ่อนไว้" +2. เพิ่มสิ่งต่อไปนี้ในไฟล์ `.gitlab-ci.yml` ของคุณ + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +หากต้องการข้อมูลเพิ่มเติมและกรณีการใช้งาน [ตรวจสอบเอกสาร](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) สำหรับส่วนประกอบนี้ + +--- + +## GitLab Duo + +OpenCode ทำงานร่วมกับเวิร์กโฟลว์ GitLab ของคุณ +พูดถึง `@opencode` ในความคิดเห็น แล้ว OpenCode จะดำเนินการงานภายในไปป์ไลน์ GitLab CI ของคุณ + +--- + +### คุณสมบัติ + +- **Issue Triage**: ขอให้ OpenCode ตรวจสอบปัญหาและอธิบายให้คุณทราบ +- **แก้ไขและนำไปใช้**: ขอให้ OpenCode แก้ไขปัญหาหรือใช้ฟีเจอร์ + มันจะสร้างสาขาใหม่และขอรวมการเปลี่ยนแปลง +- **ปลอดภัย**: OpenCode ทำงานบนนักวิ่ง GitLab ของคุณ + +--- + +### ตั้งค่า + +OpenCode ทำงานในไปป์ไลน์ GitLab CI/CD ของคุณ นี่คือสิ่งที่คุณจะต้องตั้งค่า: + +:::tip +ตรวจสอบ [**เอกสาร GitLab**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) เพื่อดูคำแนะนำล่าสุด +::: + +1. กำหนดค่าสภาพแวดล้อม GitLab ของคุณ +2. ตั้งค่า CI/CD +3. รับผู้ให้บริการโมเดล AI API คีย์ +4. สร้างบัญชีบริการ +5. กำหนดค่าตัวแปร CI/CD +6. สร้างไฟล์กำหนดค่าโฟลว์ ต่อไปนี้เป็นตัวอย่าง: + +
+ + Flow configuration + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +คุณสามารถดูคำแนะนำโดยละเอียดได้ที่ [GitLab CLI agent docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) + +--- + +### ตัวอย่าง + +นี่คือตัวอย่างบางส่วนของวิธีที่คุณสามารถใช้ OpenCode ใน GitLab + +:::tip +คุณสามารถกำหนดค่าให้ใช้วลีทริกเกอร์ที่แตกต่างจาก `@opencode` +::: + +- **อธิบายปัญหา** + + เพิ่มความคิดเห็นนี้ในปัญหา GitLab + + ``` + @opencode explain this issue + ``` + + OpenCode จะอ่านปัญหาและตอบกลับพร้อมคำอธิบายที่ชัดเจน + +- **แก้ไขปัญหา** + + ในปัญหา GitLab ให้พูดว่า: + + ``` + @opencode fix this + ``` + + OpenCode จะสร้างสาขาใหม่ ดำเนินการเปลี่ยนแปลง และเปิดคำขอรวมที่มีการเปลี่ยนแปลง + +- **ตรวจสอบคำขอรวม** + + แสดงความคิดเห็นต่อไปนี้ในคำขอรวม GitLab + + ``` + @opencode review this merge request + ``` + + OpenCode จะตรวจสอบคำขอรวมและให้ข้อเสนอแนะ diff --git a/packages/web/src/content/docs/th/ide.mdx b/packages/web/src/content/docs/th/ide.mdx new file mode 100644 index 00000000000..5668048231e --- /dev/null +++ b/packages/web/src/content/docs/th/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: ส่วนขยาย OpenCode สำหรับ VS Code, Cursor และ IDE อื่นๆ +--- + +OpenCode ทำงานร่วมกับ VS Code, Cursor หรือ IDE ใดๆ ที่รองรับ terminal เพียงเรียกใช้ `opencode` ใน terminal เพื่อเริ่มต้น + +--- + +## การใช้งาน + +- **เปิดใช้ด่วน**: ใช้ `Cmd+Esc` (Mac) หรือ `Ctrl+Esc` (Windows/Linux) เพื่อเปิด OpenCode ในมุมมอง terminal แบบแยก หรือเน้นเซสชัน terminal ที่มีอยู่หากมีการทำงานอยู่แล้ว +- **เซสชันใหม่**: ใช้ `Cmd+Shift+Esc` (Mac) หรือ `Ctrl+Shift+Esc` (Windows/Linux) เพื่อเริ่มเซสชัน terminal OpenCode ใหม่ แม้ว่าเซสชันหนึ่งจะเปิดอยู่แล้วก็ตาม คุณยังสามารถคลิกปุ่ม OpenCode ใน UI ได้ด้วย +- **การรับรู้บริบท**: แชร์การเลือกหรือแท็บปัจจุบันของคุณโดยอัตโนมัติด้วย OpenCode +- **ทางลัดการอ้างอิงไฟล์**: ใช้ `Cmd+Option+K` (Mac) หรือ `Alt+Ctrl+K` (Linux/Windows) เพื่อแทรกการอ้างอิงไฟล์ ตัวอย่างเช่น `@File#L37-42` + +--- + +## การติดตั้ง + +วิธีติดตั้ง OpenCode บน VS Code และทางแยกยอดนิยม เช่น Cursor, Windsurf, VSCodium: + +1. เปิด VS Code +2. เปิด terminal รวม +3. เรียกใช้ `opencode` - ​​ส่วนขยายจะติดตั้งโดยอัตโนมัติ + +ในทางกลับกัน หากคุณต้องการใช้ IDE ของคุณเองเมื่อคุณเรียกใช้ `/editor` หรือ `/export` จาก TUI คุณจะต้องตั้งค่า `export EDITOR="code --wait"` [เรียนรู้เพิ่มเติม](/docs/tui/#editor-setup) + +--- + +### ติดตั้งด้วยตนเอง + +ค้นหา **OpenCode** ใน Extension Marketplace แล้วคลิก **ติดตั้ง** + +--- + +### การแก้ไขปัญหา + +หากส่วนขยายไม่สามารถติดตั้งได้โดยอัตโนมัติ: + +- ตรวจสอบให้แน่ใจว่าคุณใช้งาน `opencode` ใน terminal รวม +- ยืนยันว่า CLI สำหรับ IDE ของคุณได้รับการติดตั้งแล้ว: + - สำหรับ VS Code: `code` คำสั่ง + - สำหรับ Cursor: `cursor` คำสั่ง + - สำหรับ Windsurf: `windsurf` คำสั่ง + - สำหรับ VSCodium: `codium` คำสั่ง + - ถ้าไม่เช่นนั้น ให้รัน `Cmd+Shift+P` (Mac) หรือ `Ctrl+Shift+P` (Windows/Linux) และค้นหา "Shell Command: Install 'code' command in PATH" (หรือเทียบเท่ากับ IDE ของคุณ) +- ตรวจสอบให้แน่ใจว่ารหัส VS มีสิทธิ์ในการติดตั้งส่วนขยาย diff --git a/packages/web/src/content/docs/th/index.mdx b/packages/web/src/content/docs/th/index.mdx new file mode 100644 index 00000000000..fbf1f7e5752 --- /dev/null +++ b/packages/web/src/content/docs/th/index.mdx @@ -0,0 +1,359 @@ +--- +title: บทนำ +description: เริ่มต้นใช้งาน OpenCode +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**OpenCode**](/) คือเอเจนต์การเข้ารหัส AI แบบโอเพ่นซอร์ส มีให้บริการในรูปแบบอินเทอร์เฟซบน terminal แอปเดสก์ท็อป หรือส่วนขยาย IDE + +![OpenCode TUI พร้อม opencode theme](../../../assets/lander/screenshot.png) + +มาเริ่มกันเลย + +--- + +#### ข้อกำหนดเบื้องต้น + +หากต้องการใช้ OpenCode ใน terminal คุณจะต้องมี: + +1. terminal อีมูเลเตอร์ที่ทันสมัยเช่น: + - [WezTerm](https://wezterm.org) ข้ามแพลตฟอร์ม + - [Alacritty](https://alacritty.org) ข้ามแพลตฟอร์ม + - [Ghostty](https://ghostty.org), Linux และ macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux และ macOS + +2. API Key สำหรับผู้ให้บริการ LLM ที่คุณต้องการใช้ + +--- + +## ติดตั้ง + +วิธีที่ง่ายที่สุดในการติดตั้ง OpenCode คือการใช้สคริปต์การติดตั้ง + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +คุณยังสามารถติดตั้งได้ด้วยคำสั่งต่อไปนี้: + +- **ใช้ Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **ใช้ Homebrew บน macOS และ Linux** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > เราขอแนะนำให้ใช้ OpenCode tap เพื่อเผยแพร่ข้อมูลล่าสุด สูตร `brew install opencode` อย่างเป็นทางการได้รับการดูแลโดยทีมงาน Homebrew และมีการอัปเดตไม่บ่อยนัก + +- **ใช้ Paru บน Arch Linux** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[แนะนำ: ใช้ WSL] +เพื่อประสบการณ์ที่ดีที่สุดบน Windows เราขอแนะนำให้ใช้ [ระบบย่อย Windows สำหรับ Linux (WSL)](/docs/windows-wsl) ให้ประสิทธิภาพที่ดีขึ้นและความเข้ากันได้เต็มรูปแบบกับคุณสมบัติของ OpenCode +::: + +- **ใช้ Chocolatey** + + ```bash + choco install opencode + ``` + +- **ใช้ Scoop** + + ```bash + scoop install opencode + ``` + +- **การใช้ NPM** + + ```bash + npm install -g opencode-ai + ``` + +- **ใช้ Mise** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **ใช้ Docker** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +ขณะนี้การสนับสนุนสำหรับการติดตั้ง OpenCode บน Windows โดยใช้ Bun อยู่ระหว่างดำเนินการ + +คุณยังสามารถคว้าไบนารี่ได้จาก [เผยแพร่](https://github.com/anomalyco/opencode/releases) + +--- + +## กำหนดค่า + +ด้วย OpenCode คุณสามารถใช้ผู้ให้บริการ LLM ใดก็ได้โดยกำหนดค่าคีย์ API + +หากคุณยังใหม่ต่อการใช้ผู้ให้บริการ LLM เราขอแนะนำให้ใช้ [OpenCode Zen](/docs/zen) +เป็นรายการโมเดลที่ได้รับการดูแลจัดการซึ่งได้รับการทดสอบและตรวจสอบโดย OpenCode +ทีม. + +1. เรียกใช้คำสั่ง `/connect` ใน TUI เลือก opencode และไปที่ [opencode.ai/auth](https://opencode.ai/auth) + + ```txt + /connect + ``` + +2. ลงชื่อเข้าใช้ เพิ่มรายละเอียดการเรียกเก็บเงินของคุณ และคัดลอกรหัส API ของคุณ + +3. วางคีย์ API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +หรือคุณสามารถเลือกหนึ่งในผู้ให้บริการรายอื่นได้ [เรียนรู้เพิ่มเติม](/docs/providers#ไดเรกทอรี) + +--- + +## เริ่มต้น + +เมื่อคุณได้กำหนดค่าผู้ให้บริการแล้ว คุณสามารถนำทางไปยังโปรเจ็กต์นั้นได้ +คุณอยากทำงานต่อ + +```bash +cd /path/to/project +``` + +และเรียกใช้ OpenCode + +```bash +opencode +``` + +จากนั้น เริ่มต้น OpenCode สำหรับโปรเจ็กต์โดยการรันคำสั่งต่อไปนี้ + +```bash frame="none" +/init +``` + +นี่จะได้รับ OpenCode เพื่อวิเคราะห์โครงการของคุณและสร้างไฟล์ `AGENTS.md` +รากของโครงการ + +:::tip +คุณควรคอมมิตไฟล์ `AGENTS.md` ของโปรเจ็กต์ของคุณไปที่ Git +::: + +ซึ่งจะช่วยให้ OpenCode เข้าใจโครงสร้างโปรเจ็กต์และรูปแบบการเขียนโค้ด +ใช้แล้ว. + +--- + +## การใช้งาน + +ตอนนี้คุณพร้อมที่จะใช้ OpenCode เพื่อทำงานในโครงการของคุณแล้ว อย่าลังเลที่จะถามมัน +อะไรก็ตาม! + +หากคุณยังใหม่ต่อการใช้เอเจนต์การเข้ารหัส AI ต่อไปนี้คือตัวอย่างบางส่วนที่อาจเป็นไปได้ +ช่วย. + +--- + +### ถามคำถาม + +คุณสามารถขอให้ OpenCode อธิบาย codebase ให้คุณได้ + +:::tip +ใช้ปุ่ม `@` เพื่อค้นหาไฟล์ในโครงการอย่างคลุมเครือ +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +สิ่งนี้มีประโยชน์หากมีส่วนหนึ่งของโค้ดเบสที่คุณไม่ได้ดำเนินการ + +--- + +### เพิ่มคุณสมบัติ + +คุณสามารถขอให้ OpenCode เพิ่มคุณสมบัติใหม่ให้กับโครงการของคุณได้ แม้ว่าเราจะแนะนำให้ขอให้สร้างแผนก่อนก็ตาม + +1. **สร้างแผน** + + OpenCode มีโหมด _Plan_ ที่ปิดการใช้งานความสามารถในการเปลี่ยนแปลงและ + แนะนำ _how_ ว่าจะใช้งานฟีเจอร์นี้แทน + + เปลี่ยนไปใช้ปุ่ม **Tab** คุณจะเห็นตัวบ่งชี้นี้ที่มุมขวาล่าง + + ```bash frame="none" title="Switch to Plan mode" + + ``` + + ตอนนี้เรามาอธิบายสิ่งที่เราต้องการให้ทำ + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + คุณต้องการให้รายละเอียด OpenCode เพียงพอเพื่อทำความเข้าใจสิ่งที่คุณต้องการ มันช่วยได้ + เพื่อพูดคุยเหมือนคุณกำลังพูดคุยกับนักพัฒนารุ่นน้องในทีมของคุณ + + :::tip + ให้บริบทและตัวอย่างมากมายแก่ OpenCode เพื่อช่วยให้เข้าใจสิ่งที่คุณ + ต้องการ. + ::: + +2. **ทบทวนแผน** + + เมื่อมีแผนแล้ว คุณสามารถให้ข้อเสนอแนะหรือเพิ่มรายละเอียดเพิ่มเติมได้ + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + + :::tip + ลากและวางรูปภาพลงใน terminal เพื่อเพิ่มลงในพรอมต์ + ::: + + OpenCode สามารถสแกนรูปภาพที่คุณให้มาและเพิ่มลงในข้อความแจ้งได้ คุณสามารถ + ทำได้โดยลากและวางรูปภาพลงใน terminal + +3. **สร้างฟีเจอร์** + + เมื่อคุณรู้สึกพอใจกับแผนแล้ว ให้เปลี่ยนกลับเป็น _Build mode_ ภายใน + กดปุ่ม **Tab** อีกครั้ง + + ```bash frame="none" + + ``` + + และขอให้ทำการเปลี่ยนแปลง + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### ทำการเปลี่ยนแปลง + +หากต้องการการเปลี่ยนแปลงที่ตรงไปตรงมามากขึ้น คุณสามารถขอให้ OpenCode สร้างมันโดยตรงได้ +โดยไม่ต้องทบทวนแผนก่อน + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +คุณต้องการให้แน่ใจว่าคุณให้รายละเอียดในปริมาณที่เหมาะสมเพื่อให้ OpenCode ดำเนินการได้ถูกต้อง +การเปลี่ยนแปลง + +--- + +### เลิกทำการเปลี่ยนแปลง + +สมมติว่าคุณขอให้ OpenCode ทำการเปลี่ยนแปลงบางอย่าง + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +แต่คุณก็รู้ว่ามันไม่ใช่สิ่งที่คุณต้องการ คุณ **สามารถยกเลิก** การเปลี่ยนแปลงได้ +โดยใช้คำสั่ง `/undo` + +```bash frame="none" +/undo +``` + +OpenCode จะคืนค่าการเปลี่ยนแปลงที่คุณทำและแสดงข้อความต้นฉบับของคุณ +อีกครั้ง. + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +จากที่นี่ คุณสามารถปรับแต่งข้อความแจ้งและขอให้ OpenCode ลองอีกครั้ง + +:::tip +คุณสามารถเรียกใช้ `/undo` ได้หลายครั้งเพื่อเลิกทำการเปลี่ยนแปลงหลายรายการ +::: + +หรือคุณสามารถ **สามารถทำซ้ำ** การเปลี่ยนแปลงโดยใช้คำสั่ง `/redo` + +```bash frame="none" +/redo +``` + +--- + +## แบ่งปัน + +การสนทนาที่คุณมีกับ OpenCode สามารถ [แชร์กับคุณได้ +ทีมงาน](/docs/share) + +```bash frame="none" +/share +``` + +การดำเนินการนี้จะสร้างลิงก์ไปยังการสนทนาปัจจุบันและคัดลอกไปยังคลิปบอร์ดของคุณ + +:::note +การสนทนาจะไม่ถูกแชร์โดยค่าเริ่มต้น +::: + +นี่คือ [ตัวอย่างการสนทนา](https://opencode.ai/s/4XP1fce5) กับ OpenCode + +--- + +## ปรับแต่ง + +แค่นั้นแหละ! ตอนนี้คุณเป็นมืออาชีพในการใช้ OpenCode แล้ว + +หากต้องการทำให้เป็นของคุณเอง เราขอแนะนำให้ [เลือกธีม](/docs/themes), [ปรับแต่งปุ่มลัด](/docs/keybinds), [กำหนดค่าตัวจัดรูปแบบโค้ด](/docs/formatters), [สร้างคำสั่งที่กำหนดเอง](/docs/commands) หรือลองใช้ [การกำหนดค่า OpenCode](/docs/config) diff --git a/packages/web/src/content/docs/th/keybinds.mdx b/packages/web/src/content/docs/th/keybinds.mdx new file mode 100644 index 00000000000..2fbcd02a6e3 --- /dev/null +++ b/packages/web/src/content/docs/th/keybinds.mdx @@ -0,0 +1,192 @@ +--- +title: ปุ่มลัด +description: ปรับแต่งปุ่มลัดของคุณ +--- + +OpenCode มีรายการปุ่มลัดที่คุณปรับแต่งได้ผ่านการกำหนดค่า OpenCode + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## ปุ่ม Leader + +OpenCode ใช้ปุ่ม `leader` สำหรับการเชื่อมโยงคีย์ส่วนใหญ่ วิธีนี้จะหลีกเลี่ยงความขัดแย้งใน terminal ของคุณ + +ตามค่าเริ่มต้น `ctrl+x` จะเป็นปุ่ม leader และการดำเนินการส่วนใหญ่ต้องการให้คุณกดปุ่ม leader ก่อน จากนั้นจึงกดทางลัด ตัวอย่างเช่น หากต้องการเริ่มเซสชันใหม่ คุณต้องกด `ctrl+x` ก่อน จากนั้นจึงกด `n` + +คุณไม่จำเป็นต้องใช้ปุ่ม leader สำหรับการผูกคีย์ แต่เราขอแนะนำให้ทำเช่นนั้น + +--- + +## ปิดการใช้งานการผูกปุ่ม + +คุณสามารถปิดการใช้งานการผูกปุ่มได้โดยการเพิ่มคีย์ลงในการกำหนดค่าของคุณด้วยค่า "none" + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## ทางลัดพร้อมท์เดสก์ท็อป + +การป้อนข้อมูลพร้อมท์ของแอป OpenCode บนเดสก์ท็อปรองรับทางลัด Readline/Emacs-style ทั่วไปสำหรับการแก้ไขข้อความ สิ่งเหล่านี้มีอยู่แล้วภายในและปัจจุบันไม่สามารถกำหนดค่าผ่าน `opencode.json` ได้ + +| ทางลัด | การกระทำ | +| -------- | ------------------------------------------------ | +| `ctrl+a` | ย้ายไปที่จุดเริ่มต้นของบรรทัดปัจจุบัน | +| `ctrl+e` | ย้ายไปที่จุดสิ้นสุดของบรรทัดปัจจุบัน | +| `ctrl+b` | เลื่อนเคอร์เซอร์กลับไปหนึ่งอักขระ | +| `ctrl+f` | เลื่อนเคอร์เซอร์ไปข้างหน้าหนึ่งอักขระ | +| `alt+b` | เลื่อนเคอร์เซอร์กลับไปหนึ่งคำ | +| `alt+f` | เลื่อนเคอร์เซอร์ไปข้างหน้าหนึ่งคำ | +| `ctrl+d` | ลบอักขระใต้เคอร์เซอร์ | +| `ctrl+k` | ลบจนจบแถว | +| `ctrl+u` | ลบจนถึงต้นบรรทัด | +| `ctrl+w` | ลบคำก่อนหน้า | +| `alt+d` | ลบคำถัดไป | +| `ctrl+t` | ย้ายอักขระ | +| `ctrl+g` | ยกเลิกป๊อปโอเวอร์ / ยกเลิกการตอบกลับที่ทำงานอยู่ | + +--- + +## Shift+Enter + +terminal บางตัวไม่ส่งคีย์ตัวปรับแต่งพร้อม Enter เป็นค่าเริ่มต้น คุณอาจต้องกำหนดค่า terminal ของคุณให้ส่ง `Shift+Enter` เป็นลำดับหลีก + +### Windows Terminal + +เปิด `settings.json` ของคุณที่: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +เพิ่มสิ่งนี้ลงในอาร์เรย์ `actions` ระดับรูท: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +เพิ่มสิ่งนี้ลงในอาร์เรย์ `keybindings` ระดับรูท: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +บันทึกไฟล์และรีสตาร์ท Windows Terminal หรือเปิดแท็บใหม่ diff --git a/packages/web/src/content/docs/th/lsp.mdx b/packages/web/src/content/docs/th/lsp.mdx new file mode 100644 index 00000000000..0e5e28c4a6f --- /dev/null +++ b/packages/web/src/content/docs/th/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: LSP เซิร์ฟเวอร์ +description: OpenCode ทำงานร่วมกับเซิร์ฟเวอร์ LSP ของคุณ +--- + +OpenCode ทำงานร่วมกับ Language Server Protocol (LSP) เพื่อช่วยให้ LLM โต้ตอบกับโค้ดเบสของคุณ ใช้การวินิจฉัยเพื่อให้ข้อเสนอแนะไปยัง LLM + +--- + +## บิวท์อิน + +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 จะถูกเปิดใช้งานโดยอัตโนมัติเมื่อตรวจพบนามสกุลไฟล์ใดนามสกุลหนึ่งข้างต้นและเป็นไปตามข้อกำหนด + +:::note +คุณสามารถปิดใช้งานการดาวน์โหลดเซิร์ฟเวอร์ LSP อัตโนมัติได้โดยตั้งค่าตัวแปรสภาพแวดล้อม `OPENCODE_DISABLE_LSP_DOWNLOAD` เป็น `true` +::: + +--- + +## มันทำงานอย่างไร + +เมื่อ opencode เปิดไฟล์ มันจะ: + +1. ตรวจสอบนามสกุลไฟล์กับเซิร์ฟเวอร์ LSP ที่เปิดใช้งานทั้งหมด +2. เริ่มเซิร์ฟเวอร์ LSP ที่เหมาะสมหากยังไม่ได้ทำงาน + +--- + +## กำหนดค่า + +You can customize LSP servers through the `lsp` section in your opencode config. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +เซิร์ฟเวอร์ LSP แต่ละเซิร์ฟเวอร์รองรับสิ่งต่อไปนี้: + +| คุณสมบัติ | พิมพ์ | คำอธิบาย | +| ---------------- | ------- | ------------------------------------------------------ | +| `disabled` | บูลีน | ตั้งค่านี้เป็น `true` เพื่อปิดการใช้งานเซิร์ฟเวอร์ LSP | +| `command` | สตริง[] | คำสั่งเพื่อเริ่มต้นเซิร์ฟเวอร์ LSP | +| `extensions` | สตริง[] | นามสกุลไฟล์ที่เซิร์ฟเวอร์ LSP นี้ควรจัดการ | +| `env` | วัตถุ | ตัวแปรสภาพแวดล้อมที่จะตั้งค่าเมื่อเริ่มต้นเซิร์ฟเวอร์ | +| `initialization` | วัตถุ | ตัวเลือกการเริ่มต้นที่จะส่งไปยังเซิร์ฟเวอร์ LSP | + +ลองดูตัวอย่างบางส่วน + +--- + +### ตัวแปรสภาพแวดล้อม + +ใช้คุณสมบัติ `env` เพื่อตั้งค่าตัวแปรสภาพแวดล้อมเมื่อเริ่มต้นเซิร์ฟเวอร์ LSP: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### ตัวเลือกการเริ่มต้น + +ใช้คุณสมบัติ `initialization` เพื่อส่งตัวเลือกการเริ่มต้นไปยังเซิร์ฟเวอร์ LSP นี่คือการตั้งค่าเฉพาะเซิร์ฟเวอร์ที่ส่งระหว่างคำขอ LSP `initialize`: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +ตัวเลือกการเริ่มต้นจะแตกต่างกันไปตามเซิร์ฟเวอร์ LSP ตรวจสอบเอกสารประกอบของเซิร์ฟเวอร์ LSP ของคุณเพื่อดูตัวเลือกที่มี +::: + +--- + +### ปิดการใช้งานเซิร์ฟเวอร์ LSP + +หากต้องการปิดการใช้งานเซิร์ฟเวอร์ **ทั้งหมด** LSP ทั่วโลก ให้ตั้งค่า `lsp` เป็น `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +หากต้องการปิดการใช้งานเซิร์ฟเวอร์ **เฉพาะ** LSP ให้ตั้งค่า `disabled` เป็น `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### เซิร์ฟเวอร์ LSP แบบกำหนดเอง + +คุณสามารถเพิ่มเซิร์ฟเวอร์ LSP แบบกำหนดเองได้โดยระบุคำสั่งและนามสกุลไฟล์: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## ข้อมูลเพิ่มเติม + +### PHP อินเทเลฟินส์ + +PHP Intelephense นำเสนอคุณสมบัติระดับพรีเมียมผ่านรหัสลิขสิทธิ์ คุณสามารถระบุรหัสสัญญาอนุญาตได้โดยการวาง (เท่านั้น) รหัสในไฟล์ข้อความที่: + +- บน macOS/Linux: `$HOME/intelephense/license.txt` +- บน Windows: `%USERPROFILE%/intelephense/license.txt` + +ไฟล์ควรมีเฉพาะรหัสลิขสิทธิ์โดยไม่มีเนื้อหาเพิ่มเติม diff --git a/packages/web/src/content/docs/th/mcp-servers.mdx b/packages/web/src/content/docs/th/mcp-servers.mdx new file mode 100644 index 00000000000..bd5a4365c36 --- /dev/null +++ b/packages/web/src/content/docs/th/mcp-servers.mdx @@ -0,0 +1,511 @@ +--- +title: MCP เซิร์ฟเวอร์ +description: เพิ่มเครื่องมือ MCP ในพื้นที่และระยะไกล +--- + +คุณสามารถเพิ่มเครื่องมือภายนอกให้กับ OpenCode ได้โดยใช้ _Model Context Protocol_ หรือ MCP OpenCode รองรับทั้งเซิร์ฟเวอร์ภายในและเซิร์ฟเวอร์ระยะไกล + +เมื่อเพิ่มแล้ว เครื่องมือ MCP จะพร้อมใช้งานโดยอัตโนมัติสำหรับ LLM ควบคู่ไปกับเครื่องมือในตัว + +--- + +#### คำเตือน + +เมื่อคุณใช้เซิร์ฟเวอร์ MCP เซิร์ฟเวอร์ดังกล่าวจะเพิ่มบริบท สิ่งนี้สามารถเพิ่มขึ้นได้อย่างรวดเร็วหากคุณมีเครื่องมือมากมาย ดังนั้นเราขอแนะนำให้ระมัดระวังเซิร์ฟเวอร์ MCP ที่คุณใช้ + +:::tip +เซิร์ฟเวอร์ MCP เพิ่มในบริบทของคุณ ดังนั้นคุณจึงต้องระวังด้วยว่าเซิร์ฟเวอร์ใดที่คุณเปิดใช้งาน +::: + +เซิร์ฟเวอร์ MCP บางตัว เช่น เซิร์ฟเวอร์ GitHub MCP มีแนวโน้มที่จะเพิ่มโทเค็นจำนวนมากและอาจเกินขีดจำกัดบริบทได้อย่างง่ายดาย + +--- + +## เปิดใช้งาน + +คุณสามารถกำหนดเซิร์ฟเวอร์ MCP ได้ใน [OpenCode Config](https://opencode.ai/docs/config/) ภายใต้ `mcp` เพิ่ม MCP แต่ละรายการด้วยชื่อที่ไม่ซ้ำใคร คุณสามารถอ้างอิงถึง MCP ด้วยชื่อได้เมื่อแจ้ง LLM + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +คุณยังสามารถปิดการใช้งานเซิร์ฟเวอร์ได้โดยการตั้งค่า `enabled` เป็น `false` สิ่งนี้มีประโยชน์หากคุณต้องการปิดการใช้งานเซิร์ฟเวอร์ชั่วคราวโดยไม่ต้องลบออกจากการกำหนดค่าของคุณ + +--- + +### การเอาชนะค่าเริ่มต้นระยะไกล + +องค์กรสามารถจัดเตรียมเซิร์ฟเวอร์ MCP เริ่มต้นผ่านทางจุดสิ้นสุด `.well-known/opencode` เซิร์ฟเวอร์เหล่านี้อาจถูกปิดใช้งานตามค่าเริ่มต้น ทำให้ผู้ใช้สามารถเลือกใช้เซิร์ฟเวอร์ที่ต้องการได้ + +หากต้องการเปิดใช้งานเซิร์ฟเวอร์เฉพาะจากการกำหนดค่าระยะไกลขององค์กรของคุณ ให้เพิ่มเซิร์ฟเวอร์ดังกล่าวลงในการกำหนดค่าภายในเครื่องของคุณด้วย `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 ลำดับความสำคัญ](/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` | สตริง | ย | ประเภทของการเชื่อมต่อเซิร์ฟเวอร์ MCP ต้องเป็น `"local"` | +| `command` | อาร์เรย์ | ย | คำสั่งและอาร์กิวเมนต์เพื่อรันเซิร์ฟเวอร์ MCP | +| `environment` | วัตถุ | | ตัวแปรสภาพแวดล้อมที่จะตั้งค่าเมื่อรันเซิร์ฟเวอร์ | +| `enabled` | บูลีน | | เปิดหรือปิดใช้งานเซิร์ฟเวอร์ MCP เมื่อเริ่มต้นระบบ | +| `timeout` | ตัวเลข | | หมดเวลาเป็น ms สำหรับการดึงเครื่องมือจากเซิร์ฟเวอร์ MCP ค่าเริ่มต้นคือ 5,000 (5 วินาที) | + +--- + +## ระยะไกล + +เพิ่มเซิร์ฟเวอร์ระยะไกล MCP โดยตั้งค่า `type` เป็น `"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" + } + } + } +} +``` + +`url` คือ URL ของเซิร์ฟเวอร์ MCP ระยะไกล และด้วยตัวเลือก `headers` คุณสามารถส่งผ่านรายการส่วนหัวได้ + +--- + +#### ตัวเลือก + +| ตัวเลือก | พิมพ์ | ที่จำเป็น | คำอธิบาย | +| --------- | ------ | --------- | --------------------------------------------------------------------------------------- | +| `type` | สตริง | ย | ประเภทของการเชื่อมต่อเซิร์ฟเวอร์ MCP ต้องเป็น `"remote"` | +| `url` | สตริง | ย | URL ของเซิร์ฟเวอร์ MCP ระยะไกล | +| `enabled` | บูลีน | | เปิดหรือปิดใช้งานเซิร์ฟเวอร์ MCP เมื่อเริ่มต้นระบบ | +| `headers` | วัตถุ | | ส่วนหัวที่จะส่งพร้อมกับคำขอ | +| `oauth` | วัตถุ | | การกำหนดค่าการตรวจสอบสิทธิ์ OAuth ดูส่วน [OAuth](#oauth) ด้านล่าง | +| `timeout` | ตัวเลข | | หมดเวลาเป็น ms สำหรับการดึงเครื่องมือจากเซิร์ฟเวอร์ MCP ค่าเริ่มต้นคือ 5,000 (5 วินาที) | + +--- + +## OAuth + +OpenCode จะจัดการการตรวจสอบสิทธิ์ OAuth สำหรับเซิร์ฟเวอร์ MCP ระยะไกลโดยอัตโนมัติ เมื่อเซิร์ฟเวอร์ต้องการการรับรองความถูกต้อง OpenCode จะ: + +1. ตรวจหาการตอบสนอง 401 และเริ่มโฟลว์ OAuth +2. ใช้ **การลงทะเบียนไคลเอ็นต์แบบไดนามิก (RFC 7591)** หากเซิร์ฟเวอร์รองรับ +3. จัดเก็บโทเค็นอย่างปลอดภัยสำหรับคำขอในอนาคต + +--- + +### อัตโนมัติ + +สำหรับเซิร์ฟเวอร์ MCP ที่เปิดใช้งาน OAuth ส่วนใหญ่ ไม่จำเป็นต้องมีการกำหนดค่าพิเศษ เพียงกำหนดค่าเซิร์ฟเวอร์ระยะไกล: + +```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 ` + +--- + +### ลงทะเบียนล่วงหน้า + +หากคุณมีข้อมูลประจำตัวไคลเอ็นต์จากผู้ให้บริการเซิร์ฟเวอร์ 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 + +หากคุณต้องการปิดการใช้งาน OAuth อัตโนมัติสำหรับเซิร์ฟเวอร์ (เช่น สำหรับเซิร์ฟเวอร์ที่ใช้คีย์ API แทน) ให้ตั้งค่า `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` | วัตถุ \| เท็จ | ออบเจ็กต์การกำหนดค่า OAuth หรือ `false` เพื่อปิดใช้การตรวจจับอัตโนมัติของ OAuth | +| `clientId` | สตริง | รหัสไคลเอ็นต์ OAuth หากไม่ได้ระบุไว้ จะพยายามลงทะเบียนไคลเอ็นต์แบบไดนามิก | +| `clientSecret` | สตริง | ข้อมูลลับไคลเอ็นต์ OAuth หากเซิร์ฟเวอร์การให้สิทธิ์กำหนดไว้ | +| `scope` | สตริง | ขอบเขต OAuth ที่จะขอระหว่างการให้สิทธิ์ | + +#### การดีบัก + +หากเซิร์ฟเวอร์ 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 ได้เหมือนกับเครื่องมืออื่นๆ + +--- + +### ทั่วโลก + +ซึ่งหมายความว่าคุณสามารถเปิดหรือปิดใช้งานได้ทั่วโลก + +```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 + } +} +``` + +นอกจากนี้เรายังสามารถใช้รูปแบบ glob เพื่อปิดใช้งาน 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 + } +} +``` + +ที่นี่เราใช้รูปแบบ glob `my-mcp*` เพื่อปิดการใช้งาน MCP ทั้งหมด + +--- + +### ต่อตัวแทน + +หากคุณมีเซิร์ฟเวอร์ MCP จำนวนมาก คุณอาจต้องการเปิดใช้งานเซิร์ฟเวอร์เหล่านี้ต่อตัวแทนเท่านั้น และปิดใช้งานเซิร์ฟเวอร์เหล่านั้นทั่วโลก เมื่อต้องการทำสิ่งนี้: + +1. ปิดการใช้งานเป็นเครื่องมือทั่วโลก +2. ใน [agent 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 + } + } + } +} +``` + +--- + +#### รูปแบบ Glob + +รูปแบบ glob ใช้รูปแบบ globbing regex แบบง่าย: + +- `*` ตรงกับอักขระใดๆ ตั้งแต่ศูนย์ขึ้นไป (เช่น `"my-mcp*"` ตรงกับ `my-mcp_search`, `my-mcp_list` ฯลฯ) +- `?` ตรงกับอักขระหนึ่งตัวเท่านั้น +- อักขระอื่นๆ ทั้งหมดตรงกันอย่างแท้จริง + +:::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` + +เพิ่ม `use context7` ในข้อความแจ้งของคุณเพื่อใช้เซิร์ฟเวอร์ Context7 MCP + +```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 + +เพิ่มเซิร์ฟเวอร์ [Grep by Vercel](https://grep.app) MCP เพื่อค้นหาผ่านข้อมูลโค้ดบน GitHub + +```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/th/models.mdx b/packages/web/src/content/docs/th/models.mdx new file mode 100644 index 00000000000..859aff48001 --- /dev/null +++ b/packages/web/src/content/docs/th/models.mdx @@ -0,0 +1,223 @@ +--- +title: โมเดล +description: การกำหนดค่าผู้ให้บริการและรุ่น LLM +--- + +OpenCode ใช้ [AI SDK](https://ai-sdk.dev/) และ [Models.dev](https://models.dev) เพื่อรองรับผู้ให้บริการ **75+ LLM** และรองรับการใช้งานโมเดลท้องถิ่น + +--- + +## ผู้ให้บริการ + +ผู้ให้บริการที่ได้รับความนิยมส่วนใหญ่จะถูกโหลดไว้ล่วงหน้าตามค่าเริ่มต้น หากคุณได้เพิ่มข้อมูลรับรองสำหรับผู้ให้บริการผ่านคำสั่ง `/connect` ข้อมูลเหล่านั้นจะพร้อมใช้งานเมื่อคุณเริ่ม OpenCode + +เรียนรู้เพิ่มเติมเกี่ยวกับ [ผู้ให้บริการ](/docs/providers) + +--- + +## เลือกรุ่น + +เมื่อคุณกำหนดค่าผู้ให้บริการแล้ว คุณสามารถเลือกรุ่นที่ต้องการได้โดยพิมพ์: + +```bash frame="none" +/models +``` + +--- + +## รุ่นที่แนะนำ + +มีโมเดลออกมามากมาย โดยมีโมเดลใหม่ๆ ออกมาทุกสัปดาห์ + +:::tip +พิจารณาใช้รุ่นใดรุ่นหนึ่งที่เราแนะนำ +::: + +อย่างไรก็ตาม มีเพียงไม่กี่ตัวเท่านั้นที่เก่งทั้งการสร้างโค้ดและการเรียกใช้เครื่องมือ + +ต่อไปนี้เป็นโมเดลหลายรุ่นที่ทำงานได้ดีกับ OpenCode โดยไม่เรียงลำดับเป็นพิเศษ (นี่ไม่ใช่รายการที่ครอบคลุมและไม่จำเป็นต้องเป็นข้อมูลล่าสุด): + +- GPT 5.2 +- GPT 5.1 Codex +- Claude Opus 4.5 +- Claude Sonnet 4.5 +- MiniMax M2.1 +- Gemini 3 Pro + +--- + +## ตั้งค่าเริ่มต้น + +หากต้องการตั้งค่าสิ่งใดสิ่งหนึ่งเป็นโมเดลเริ่มต้น คุณสามารถตั้งค่าคีย์ `model` ในของคุณ +การกำหนดค่า OpenCode + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +ID แบบเต็มคือ `provider_id/model_id` ตัวอย่างเช่น หากคุณใช้ [OpenCode Zen](/docs/zen) คุณจะใช้ `opencode/gpt-5.1-codex` สำหรับ GPT 5.1 Codex + +หากคุณได้กำหนดค่า [ผู้ให้บริการที่กำหนดเอง](/docs/providers#กำหนดเอง) `provider_id` จะเป็นคีย์จากส่วน `provider` ของการกำหนดค่าของคุณ และ `model_id` จะเป็นคีย์จาก `provider.models` + +--- + +## กำหนดค่าโมเดล + +คุณสามารถกำหนดค่าตัวเลือกของโมเดลได้ทั่วโลกผ่านการกำหนดค่า + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +ที่นี่เรากำลังกำหนดการตั้งค่าส่วนกลางสำหรับโมเดลในตัวสองรุ่น: `gpt-5` เมื่อเข้าถึงผ่านผู้ให้บริการ `openai` และ `claude-sonnet-4-20250514` เมื่อเข้าถึงผ่านผู้ให้บริการ `anthropic` +สามารถดูผู้ให้บริการและชื่อรุ่นในตัวได้ที่ [Models.dev](https://models.dev) + +คุณยังสามารถกำหนดค่าตัวเลือกเหล่านี้สำหรับตัวแทนใดๆ ที่คุณใช้อยู่ได้ การกำหนดค่าตัวแทนจะแทนที่ตัวเลือกส่วนกลางใดๆ ที่นี่ [เรียนรู้เพิ่มเติม](/docs/agents/#เพิ่มเติม) + +คุณยังสามารถกำหนดตัวแปรแบบกำหนดเองที่ขยายตัวแปรในตัวได้ ตัวแปรช่วยให้คุณกำหนดการตั้งค่าที่แตกต่างกันสำหรับรุ่นเดียวกันโดยไม่ต้องสร้างรายการที่ซ้ำกัน: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## Variants (แบบ) + +โมเดลหลายตัวรองรับหลาย variants (รูปแบบย่อย) ที่มีการกำหนดค่าต่างกัน OpenCode มาพร้อมกับ variants เริ่มต้นในตัวสำหรับผู้ให้บริการยอดนิยม + +### Variants ในตัว (Built-in Variants) + +OpenCode มาพร้อมกับ variants เริ่มต้นสำหรับผู้ให้บริการหลายราย: + +**Anthropic**: + +- `high` - งบประมาณการคิดสูง (ค่าเริ่มต้น) +- `max` - งบประมาณการคิดสูงสุด + +**OpenAI**: + +แตกต่างกันไปตามรุ่น แต่โดยประมาณ: + +- `none` - ไม่ใช้การให้เหตุผล +- `minimal` - ความพยายามในการให้เหตุผลน้อยที่สุด +- `low` - ความพยายามในการให้เหตุผลต่ำ +- `medium` - ความพยายามในการให้เหตุผลปานกลาง +- `high` - ความพยายามในการให้เหตุผลสูง +- `xhigh` - ความพยายามในการให้เหตุผลสูงเป็นพิเศษ + +**Google**: + +- `low` - งบประมาณการคิดต่ำ/token ต่ำ +- `high` - งบประมาณการคิดสูง/token สูง + +:::tip +รายการนี้ไม่ครอบคลุมทั้งหมด ผู้ให้บริการรายอื่นหลายรายก็มีค่าเริ่มต้นในตัวเช่นกัน +::: + +### Variants แบบกำหนดเอง + +คุณสามารถแทนที่ variants ที่มีอยู่หรือเพิ่มของคุณเองได้: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### การหมุนเวียน Variants + +ใช้ปุ่มลัด `variant_cycle` เพื่อสลับระหว่าง variants ต่างๆ อย่างรวดเร็ว [เรียนรู้เพิ่มเติม](/docs/keybinds) + +--- + +## กำลังโหลดโมเดล + +เมื่อ OpenCode เริ่มทำงาน ระบบจะตรวจสอบรุ่นตามลำดับความสำคัญต่อไปนี้: + +1. การตั้งค่าสถานะบรรทัดคำสั่ง `--model` หรือ `-m` รูปแบบจะเหมือนกับในไฟล์ปรับแต่ง: `provider_id/model_id` + +2. รายการโมเดลในการกำหนดค่า OpenCode + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + + รูปแบบที่นี่คือ `provider/model` + +3. รุ่นที่ใช้ล่าสุด. + +4. รุ่นแรกที่ใช้ลำดับความสำคัญภายใน diff --git a/packages/web/src/content/docs/th/modes.mdx b/packages/web/src/content/docs/th/modes.mdx new file mode 100644 index 00000000000..0ed3d4da56f --- /dev/null +++ b/packages/web/src/content/docs/th/modes.mdx @@ -0,0 +1,331 @@ +--- +title: โหมด +description: โหมดที่แตกต่างกันสำหรับกรณีการใช้งานที่แตกต่างกัน +--- + +:::caution +ขณะนี้โหมดได้รับการกำหนดค่าผ่านตัวเลือก `agent` ในการกำหนดค่า opencode ที่ +ตัวเลือก `mode` เลิกใช้แล้ว [เรียนรู้เพิ่มเติม](/docs/agents) +::: + +โหมดใน opencode ช่วยให้คุณปรับแต่งพฤติกรรม เครื่องมือ และพร้อมท์สำหรับกรณีการใช้งานที่แตกต่างกันได้ + +มาพร้อมกับโหมดในตัวสองโหมด: **สร้าง** และ **วางแผน** คุณสามารถปรับแต่งได้ +สิ่งเหล่านี้หรือกำหนดค่าของคุณเองผ่านการกำหนดค่า opencode + +คุณสามารถสลับระหว่างโหมดระหว่างเซสชันหรือกำหนดค่าในไฟล์กำหนดค่าของคุณ + +--- + +## บิวท์อิน + +opencode มาพร้อมกับโหมดในตัวสองโหมด + +--- + +### Build + +Build เป็นโหมด **ค่าเริ่มต้น** โดยที่เครื่องมือทั้งหมดเปิดใช้งานอยู่ นี่คือโหมดมาตรฐานสำหรับงานพัฒนาที่คุณต้องการสิทธิ์เข้าถึงการทำงานของไฟล์และคำสั่งระบบโดยสมบูรณ์ + +--- + +### Plan + +โหมดจำกัดที่ออกแบบมาเพื่อการวางแผนและการวิเคราะห์ ในโหมดแผน เครื่องมือต่อไปนี้จะถูกปิดใช้งานตามค่าเริ่มต้น: + +- `write` - ​​ไม่สามารถสร้างไฟล์ใหม่ได้ +- `edit` - ​​ไม่สามารถแก้ไขไฟล์ที่มีอยู่ได้ ยกเว้นไฟล์ที่อยู่ใน `.opencode/plans/*.md` เพื่อดูรายละเอียดแผนงาน +- `patch` - ​​ไม่สามารถใช้แพตช์ได้ +- `bash` - ​​ไม่สามารถรันคำสั่ง shell ได้ + +โหมดนี้มีประโยชน์เมื่อคุณต้องการให้ AI วิเคราะห์โค้ด แนะนำการเปลี่ยนแปลง หรือสร้างแผนโดยไม่ต้องทำการแก้ไขโค้ดเบสของคุณจริง ๆ + +--- + +## การสลับ + +คุณสามารถสลับระหว่างโหมดระหว่างเซสชันได้โดยใช้ปุ่ม _Tab_ หรือการเชื่อมโยงคีย์ `switch_mode` ที่คุณกำหนดค่าไว้ + +ดูเพิ่มเติมที่: [Formatters](/docs/formatters) สำหรับข้อมูลเกี่ยวกับการกำหนดค่าการจัดรูปแบบโค้ด + +--- + +## กำหนดค่า + +คุณสามารถปรับแต่งโหมดในตัวหรือสร้างโหมดของคุณเองผ่านการกำหนดค่าได้ โหมดสามารถกำหนดค่าได้สองวิธี: + +### การกำหนดค่าด้วย JSON + +กำหนดค่าโหมดในไฟล์กำหนดค่า `opencode.json` ของคุณ: + +```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 + +คุณยังสามารถกำหนดโหมดโดยใช้ไฟล์ Markdown ได้ วางไว้ใน: + +- ทั่วโลก: `~/.config/opencode/modes/` +- โครงการ: `.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. +``` + +ชื่อไฟล์ Markdown จะกลายเป็นชื่อโหมด (เช่น `review.md` สร้างโหมด `review`) + +มาดูรายละเอียดตัวเลือกการกำหนดค่าเหล่านี้กัน + +--- + +### Model (โมเดล) + +ใช้การกำหนดค่า `model` เพื่อแทนที่โมเดลเริ่มต้นสำหรับโหมดนี้ มีประโยชน์สำหรับการใช้โมเดลที่แตกต่างกันซึ่งปรับให้เหมาะกับงานที่แตกต่างกัน ตัวอย่างเช่น โมเดลสำหรับการวางแผนที่เร็วขึ้น โมเดลที่มีความสามารถมากขึ้นสำหรับการนำไปปฏิบัติ + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### Temperature (อุณหภูมิ) + +ควบคุมการสุ่มและความคิดสร้างสรรค์ของการตอบสนองของ AI ด้วยการกำหนดค่า `temperature` ค่าที่ต่ำกว่าจะทำให้คำตอบมีจุดมุ่งหมายและกำหนดได้มากขึ้น ในขณะที่ค่าที่สูงกว่าจะเพิ่มความคิดสร้างสรรค์และความแปรปรวน + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +โดยทั่วไปค่าอุณหภูมิจะอยู่ในช่วงตั้งแต่ 0.0 ถึง 1.0: + +- **0.0-0.2**: การตอบสนองที่มุ่งเน้นและกำหนดไว้อย่างมาก เหมาะสำหรับการวิเคราะห์และวางแผนโค้ด +- **0.3-0.5**: การตอบสนองที่สมดุลและความคิดสร้างสรรค์บางส่วน เหมาะสำหรับงานพัฒนาทั่วไป +- **0.6-1.0**: คำตอบที่สร้างสรรค์และหลากหลายยิ่งขึ้น ซึ่งมีประโยชน์สำหรับการระดมความคิดและการสำรวจ + +```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}" + } + } +} +``` + +หากไม่มีการระบุอุณหภูมิ opencode จะใช้ค่าเริ่มต้นเฉพาะรุ่น (โดยทั่วไปจะเป็น 0 สำหรับรุ่นส่วนใหญ่ และ 0.55 สำหรับรุ่น Qwen) + +--- + +### พรอมต์ + +ระบุไฟล์พรอมต์ระบบที่กำหนดเองสำหรับโหมดนี้ด้วยการกำหนดค่า `prompt` ไฟล์พร้อมท์ควรมีคำแนะนำเฉพาะสำหรับวัตถุประสงค์ของโหมด + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +เส้นทางนี้สัมพันธ์กับตำแหน่งของไฟล์กำหนดค่า ดังนั้นสิ่งนี้จึงใช้ได้กับ +ทั้งการกำหนดค่า opencode ส่วนกลางและการกำหนดค่าเฉพาะโครงการ + +--- + +### เครื่องมือ + +ควบคุมว่าเครื่องมือใดบ้างที่พร้อมใช้งานในโหมดนี้ด้วยการกำหนดค่า `tools` คุณสามารถเปิดหรือปิดใช้งานเครื่องมือเฉพาะได้โดยตั้งค่าเป็น `true` หรือ `false` + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +หากไม่มีการระบุเครื่องมือ เครื่องมือทั้งหมดจะถูกเปิดใช้งานตามค่าเริ่มต้น + +--- + +#### เครื่องมือที่มีอยู่ + +นี่คือเครื่องมือทั้งหมดที่สามารถควบคุมได้ผ่านการกำหนดค่าโหมด + +| เครื่องมือ | คำอธิบาย | +| ----------- | --------------------------- | +| `bash` | ดำเนินการคำสั่ง shell | +| `edit` | แก้ไขไฟล์ที่มีอยู่ | +| `write` | สร้างไฟล์ใหม่ | +| `read` | อ่านเนื้อหาไฟล์ | +| `grep` | ค้นหาเนื้อหาไฟล์ | +| `glob` | ค้นหาไฟล์ตามรูปแบบ | +| `list` | แสดงรายการเนื้อหาไดเร็กทอรี | +| `patch` | ใช้แพทช์กับไฟล์ | +| `todowrite` | จัดการรายการสิ่งที่ต้องทำ | +| `todoread` | อ่านรายการสิ่งที่ต้องทำ | +| `webfetch` | ดึงเนื้อหาเว็บ | + +--- + +## โหมดกำหนดเอง + +คุณสามารถสร้างโหมดที่คุณกำหนดเองได้โดยเพิ่มเข้าไปในการกำหนดค่า นี่คือตัวอย่างที่ใช้ทั้งสองวิธี: + +### ใช้การกำหนดค่า JSON + +```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 + } + } + } +} +``` + +### การใช้ไฟล์ Markdown + +สร้างไฟล์โหมดใน `.opencode/modes/` สำหรับโหมดเฉพาะโครงการหรือ `~/.config/opencode/modes/` สำหรับโหมดทั่วโลก: + +```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 +``` + +--- + +### กรณีการใช้งาน + +ต่อไปนี้เป็นกรณีการใช้งานทั่วไปสำหรับโหมดต่างๆ + +- **Build mode**: งานพัฒนาเต็มรูปแบบโดยเปิดใช้งานเครื่องมือทั้งหมด +- **Plan mode**: วิเคราะห์และวางแผนโดยไม่ทำการเปลี่ยนแปลง +- **Review mode**: การตรวจสอบโค้ดพร้อมการเข้าถึงแบบอ่านอย่างเดียวพร้อมเครื่องมือเอกสารประกอบ +- **Debug mode**: มุ่งเน้นไปที่การตรวจสอบโดยเปิดใช้งานเครื่องมือ bash และอ่าน +- **Docs mode**: การเขียนเอกสารด้วยการทำงานของไฟล์ แต่ไม่มีคำสั่งระบบ + +คุณอาจพบว่ารุ่นต่างๆ นั้นดีสำหรับกรณีการใช้งานที่แตกต่างกัน diff --git a/packages/web/src/content/docs/th/network.mdx b/packages/web/src/content/docs/th/network.mdx new file mode 100644 index 00000000000..86e7f86131c --- /dev/null +++ b/packages/web/src/content/docs/th/network.mdx @@ -0,0 +1,57 @@ +--- +title: เครือข่าย +description: กำหนดค่าพร็อกซีและใบรับรองที่กำหนดเอง +--- + +OpenCode รองรับตัวแปรสภาพแวดล้อมพร็อกซีมาตรฐานและใบรับรองที่กำหนดเองสำหรับสภาพแวดล้อมเครือข่ายองค์กร + +--- + +## พร็อกซี + +OpenCode เคารพตัวแปรสภาพแวดล้อมพร็อกซีมาตรฐาน + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +TUI สื่อสารกับเซิร์ฟเวอร์ HTTP ในพื้นที่ คุณต้องข้ามพร็อกซีสำหรับการเชื่อมต่อนี้เพื่อป้องกันการกำหนดเส้นทางวนซ้ำ +::: + +คุณสามารถกำหนดค่าพอร์ตของเซิร์ฟเวอร์และชื่อโฮสต์ได้โดยใช้ [CLI flags](/docs/cli#run) + +--- + +### การยืนยันตัวตน + +หากพร็อกซีของคุณต้องการการรับรองความถูกต้องขั้นพื้นฐาน ให้ใส่ข้อมูลรับรองใน URL + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +หลีกเลี่ยงรหัสผ่านฮาร์ดโค้ด ใช้ตัวแปรสภาพแวดล้อมหรือที่จัดเก็บข้อมูลรับรองที่ปลอดภัย +::: + +สำหรับพร็อกซีที่ต้องการการรับรองความถูกต้องขั้นสูง เช่น NTLM หรือ Kerberos ให้พิจารณาใช้เกตเวย์ LLM ที่รองรับวิธีการตรวจสอบความถูกต้องของคุณ + +--- + +## ใบรับรองที่กำหนดเอง + +หากองค์กรของคุณใช้ CA แบบกำหนดเองสำหรับการเชื่อมต่อ HTTPS ให้กำหนดค่า OpenCode ให้เชื่อถือ + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +ซึ่งใช้ได้กับทั้งการเชื่อมต่อพร็อกซีและการเข้าถึง API โดยตรง diff --git a/packages/web/src/content/docs/th/permissions.mdx b/packages/web/src/content/docs/th/permissions.mdx new file mode 100644 index 00000000000..c81ee5b3375 --- /dev/null +++ b/packages/web/src/content/docs/th/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: สิทธิ์ +description: ควบคุมการดำเนินการที่ต้องได้รับการอนุมัติจึงจะรันได้ +--- + +OpenCode ใช้การกำหนดค่า `permission` เพื่อตัดสินใจว่าการดำเนินการที่กำหนดควรทำงานโดยอัตโนมัติ แจ้งให้คุณทราบ หรือถูกบล็อก + +ตั้งแต่ `v1.1.1` การกำหนดค่าบูลีนแบบเดิม `tools` เลิกใช้แล้วและได้รวมเข้ากับ `permission` แล้ว การกำหนดค่า `tools` แบบเก่ายังคงรองรับความเข้ากันได้แบบย้อนหลัง + +--- + +## การดำเนินการ + +กฎการอนุญาตแต่ละข้อจะแก้ไขเป็นข้อใดข้อหนึ่งต่อไปนี้ + +- `"allow"` — ทำงานโดยไม่ได้รับการอนุมัติ +- `"ask"` — พร้อมท์สำหรับการอนุมัติ +- `"deny"` — บล็อกการกระทำ + +--- + +## การกำหนดค่า + +คุณสามารถตั้งค่าการอนุญาตทั่วโลก (ด้วย `*`) และแทนที่เครื่องมือเฉพาะ + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +คุณยังสามารถตั้งค่าการอนุญาตทั้งหมดพร้อมกันได้: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## กฎแบบละเอียด (ไวยากรณ์ของวัตถุ) + +สำหรับการอนุญาตส่วนใหญ่ คุณสามารถใช้ออบเจ็กต์เพื่อปรับใช้การดำเนินการต่างๆ ตามอินพุตของเครื่องมือได้ + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +กฎจะได้รับการประเมินโดยการจับคู่รูปแบบ โดย **กฎการจับคู่สุดท้ายจะชนะ** รูปแบบทั่วไปคือการใส่กฎ catch-all `"*"` ก่อน และใส่กฎที่เฉพาะเจาะจงมากขึ้นหลังจากนั้น + +### สัญลักษณ์แทน + +รูปแบบการอนุญาตใช้การจับคู่ไวด์การ์ดแบบง่าย: + +- `*` จับคู่อักขระใดๆ ตั้งแต่ศูนย์ขึ้นไป +- `?` ตรงกับอักขระหนึ่งตัวเท่านั้น +- อักขระอื่นๆ ทั้งหมดตรงกันอย่างแท้จริง + +### การขยายโฮมไดเร็กทอรี + +คุณสามารถใช้ `~` หรือ `$HOME` ที่จุดเริ่มต้นของรูปแบบเพื่ออ้างอิงโฮมไดเร็กตอรี่ของคุณ สิ่งนี้มีประโยชน์อย่างยิ่งสำหรับกฎของ [`external_directory`](#external-directories) + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### ไดเรกทอรีภายนอก + +ใช้ `external_directory` เพื่ออนุญาตการเรียกใช้เครื่องมือที่สัมผัสเส้นทางนอกไดเร็กทอรีการทำงานที่ OpenCode เริ่มทำงาน สิ่งนี้ใช้ได้กับเครื่องมือใดๆ ที่ใช้เส้นทางเป็นอินพุต (เช่น `read`, `edit`, `list`, `glob`, `grep` และคำสั่ง `bash` จำนวนมาก) + +การขยายบ้าน (เช่น `~/...`) ส่งผลต่อวิธีการเขียนรูปแบบเท่านั้น ไม่ได้ทำให้เส้นทางภายนอกเป็นส่วนหนึ่งของพื้นที่ทำงานปัจจุบัน ดังนั้นเส้นทางภายนอกไดเรกทอรีการทำงานยังต้องได้รับอนุญาตผ่าน `external_directory` + +ตัวอย่างเช่น อนุญาตให้เข้าถึงทุกสิ่งภายใต้ `~/projects/personal/`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +ไดเร็กทอรีใดๆ ที่ได้รับอนุญาตที่นี่จะสืบทอดค่าเริ่มต้นเดียวกันกับพื้นที่ทำงานปัจจุบัน เนื่องจาก [`read` มีค่าเริ่มต้นเป็น `allow`](#defaults) การอ่านจึงได้รับอนุญาตสำหรับรายการภายใต้ `external_directory` เว้นแต่จะถูกแทนที่ เพิ่มกฎที่ชัดเจนเมื่อควรจำกัดเครื่องมือในเส้นทางเหล่านี้ เช่น การบล็อกการแก้ไขในขณะที่ยังคงอ่านอยู่: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +ให้รายการมุ่งเน้นไปที่เส้นทางที่เชื่อถือได้ และเลเยอร์อนุญาตหรือปฏิเสธกฎเพิ่มเติมตามที่จำเป็นสำหรับเครื่องมืออื่นๆ (เช่น `bash`) + +--- + +## สิทธิ์ที่มีอยู่ + +สิทธิ์ของ OpenCode จะกำหนดไว้ตามชื่อเครื่องมือ พร้อมด้วย guardrails อีก 2-3 คน: + +- `read` — อ่านไฟล์ (ตรงกับเส้นทางของไฟล์) +- `edit` — การแก้ไขไฟล์ทั้งหมด (ครอบคลุมถึง `edit`, `write`, `patch`, `multiedit`) +- `glob` — ไฟล์ globbing (ตรงกับรูปแบบ glob) +- `grep` — การค้นหาเนื้อหา (ตรงกับรูปแบบ regex) +- `list` — แสดงรายการไฟล์ในไดเร็กทอรี (ตรงกับเส้นทางไดเร็กทอรี) +- `bash` — การรันคำสั่ง shell (ตรงกับคำสั่งที่แยกวิเคราะห์เช่น `git status --porcelain`) +- `task` — การเปิดตัวตัวแทนย่อย (ตรงกับประเภทตัวแทนย่อย) +- `skill` — กำลังโหลดทักษะ (ตรงกับชื่อทักษะ) +- `lsp` — กำลังเรียกใช้คำสั่ง LSP (ปัจจุบันยังไม่ละเอียด) +- `todoread`, `todowrite` — กำลังอ่าน/updating รายการสิ่งที่ต้องทำ +- `webfetch` — กำลังดึง URL (ตรงกับ URL) +- `websearch`, `codesearch` — การค้นหาเว็บ/code (ตรงกับข้อความค้นหา) +- `external_directory` — ทริกเกอร์เมื่อเครื่องมือแตะเส้นทางนอกไดเร็กทอรีการทำงานของโปรเจ็กต์ +- `doom_loop` — ทริกเกอร์เมื่อมีการเรียกใช้เครื่องมือเดียวกันซ้ำ 3 ครั้งโดยมีอินพุตเหมือนกัน + +--- + +## ค่าเริ่มต้น + +หากคุณไม่ได้ระบุสิ่งใด OpenCode จะเริ่มต้นจากค่าเริ่มต้นที่อนุญาต: + +- การอนุญาตส่วนใหญ่มีค่าเริ่มต้นเป็น `"allow"` +- `doom_loop` และ `external_directory` มีค่าเริ่มต้นเป็น `"ask"` +- `read` คือ `"allow"` แต่ไฟล์ `.env` ถูกปฏิเสธโดยค่าเริ่มต้น: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## สิ่งที่ "ถาม" ทำ + +เมื่อ OpenCode แจ้งให้อนุมัติ UI จะเสนอผลลัพธ์สามประการ: + +- `once` — อนุมัติเพียงคำขอนี้ +- `always` — อนุมัติคำขอในอนาคตที่ตรงกับรูปแบบที่แนะนำ (สำหรับส่วนที่เหลือของเซสชัน OpenCode ปัจจุบัน) +- `reject` — ปฏิเสธคำขอ + +ชุดรูปแบบที่ `always` จะอนุมัตินั้นมาจากเครื่องมือ (เช่น โดยทั่วไปการอนุมัติ bash จะกำหนดไวท์ลิสต์คำนำหน้าคำสั่งที่ปลอดภัย เช่น `git status*`) + +--- + +## ตัวแทน + +คุณสามารถแทนที่สิทธิ์ต่อตัวแทนได้ สิทธิ์ของตัวแทนจะผสานเข้ากับการกำหนดค่าส่วนกลาง และกฎของตัวแทนจะมีความสำคัญกว่า [เรียนรู้เพิ่มเติม](/docs/agents#permissions) เกี่ยวกับการอนุญาตของตัวแทน + +:::note +โปรดดูส่วน [กฎแบบละเอียด (ไวยากรณ์ของวัตถุ)](#granular-rules-object-syntax) ด้านบนเพื่อดูตัวอย่างการจับคู่รูปแบบโดยละเอียดเพิ่มเติม +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +คุณยังสามารถกำหนดค่าการอนุญาตตัวแทนใน Markdown ได้: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +ใช้การจับคู่รูปแบบสำหรับคำสั่งที่มีอาร์กิวเมนต์ `"grep *"` อนุญาต `grep pattern file.txt` ในขณะที่ `"grep"` คนเดียวจะบล็อกได้ คำสั่งเช่น `git status` ใช้งานได้กับพฤติกรรมเริ่มต้น แต่ต้องได้รับอนุญาตอย่างชัดเจน (เช่น `"git status *"`) เมื่ออาร์กิวเมนต์ถูกส่งผ่าน +::: diff --git a/packages/web/src/content/docs/th/plugins.mdx b/packages/web/src/content/docs/th/plugins.mdx new file mode 100644 index 00000000000..a2d74ceb9cb --- /dev/null +++ b/packages/web/src/content/docs/th/plugins.mdx @@ -0,0 +1,385 @@ +--- +title: ปลั๊กอิน +description: เขียนปลั๊กอินของคุณเองเพื่อขยาย OpenCode +--- + +ปลั๊กอินช่วยให้คุณสามารถขยาย OpenCode ได้โดยเชื่อมโยงกับเหตุการณ์ต่างๆ และปรับแต่งลักษณะการทำงาน คุณสามารถสร้างปลั๊กอินเพื่อเพิ่มคุณสมบัติใหม่ บูรณาการกับบริการภายนอก หรือแก้ไขการทำงานเริ่มต้นของ OpenCode + +ตัวอย่างเช่น ลองดู [ปลั๊กอิน](/docs/ecosystem#ปลั๊กอิน) ที่สร้างโดยชุมชน + +--- + +## ใช้ปลั๊กอิน + +มีสองวิธีในการโหลดปลั๊กอิน + +--- + +### จากไฟล์ในเครื่อง + +วางไฟล์ JavaScript หรือ TypeScript ในไดเร็กทอรีปลั๊กอิน + +- `.opencode/plugins/` - ​​ปลั๊กอินระดับโครงการ +- `~/.config/opencode/plugins/` - ​​ปลั๊กอินทั่วโลก + +ไฟล์ในไดเร็กทอรีเหล่านี้จะถูกโหลดโดยอัตโนมัติเมื่อเริ่มต้นระบบ + +--- + +### จาก npm + +ระบุแพ็คเกจ npm ในไฟล์ปรับแต่งของคุณ + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +รองรับแพ็คเกจ npm ทั้งแบบปกติและแบบกำหนดขอบเขต + +เรียกดูปลั๊กอินที่มีอยู่ใน [ระบบนิเวศ](/docs/ecosystem#plugins) + +--- + +### วิธีการติดตั้งปลั๊กอิน + +**ปลั๊กอิน npm** ได้รับการติดตั้งโดยอัตโนมัติโดยใช้ Bun เมื่อเริ่มต้น แพ็คเกจและการขึ้นต่อกันถูกแคชไว้ใน `~/.cache/opencode/node_modules/` + +**ปลั๊กอินท้องถิ่น** โหลดโดยตรงจากไดเร็กทอรีปลั๊กอิน หากต้องการใช้แพ็คเกจภายนอก คุณต้องสร้าง `package.json` ภายในไดเร็กทอรีการกำหนดค่าของคุณ (ดู [การพึ่งพา](#dependencies)) หรือเผยแพร่ปลั๊กอินไปที่ npm และ [เพิ่มลงในการกำหนดค่าของคุณ](/docs/config#plugins) + +--- + +### โหลดออเดอร์ + +ปลั๊กอินถูกโหลดจากทุกแหล่งและ hooks ทั้งหมดทำงานตามลำดับ ลำดับการโหลดคือ: + +1. การกำหนดค่าส่วนกลาง (`~/.config/opencode/opencode.json`) +2. การกำหนดค่าโครงการ (`opencode.json`) +3. ไดเร็กทอรีปลั๊กอินสากล (`~/.config/opencode/plugins/`) +4. ไดเรกทอรีปลั๊กอินโครงการ (`.opencode/plugins/`) + +แพ็กเกจ npm ที่ซ้ำกันซึ่งมีชื่อและเวอร์ชันเดียวกันจะถูกโหลดหนึ่งครั้ง อย่างไรก็ตาม ทั้งปลั๊กอินในเครื่องและปลั๊กอิน npm ที่มีชื่อคล้ายกันจะโหลดแยกกัน + +--- + +## สร้างปลั๊กอิน + +ปลั๊กอินคือ **JavaScript/TypeScript module** ที่ส่งออกปลั๊กอินอย่างน้อยหนึ่งรายการ +ฟังก์ชั่น แต่ละฟังก์ชันได้รับวัตถุบริบทและส่งกลับวัตถุ hooks + +--- + +### การพึ่งพาอาศัยกัน + +ปลั๊กอินท้องถิ่นและเครื่องมือแบบกำหนดเองสามารถใช้แพ็คเกจ npm ภายนอกได้ เพิ่ม `package.json` ลงในไดเร็กทอรี config ของคุณด้วยการอ้างอิงที่คุณต้องการ + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +OpenCode รัน `bun install` เมื่อเริ่มต้นเพื่อติดตั้งสิ่งเหล่านี้ ปลั๊กอินและเครื่องมือของคุณสามารถนำเข้าได้ + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### โครงสร้างพื้นฐาน + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +ฟังก์ชั่นปลั๊กอินได้รับ: + +- `project`: ข้อมูลโครงการปัจจุบัน +- `directory`: ไดเร็กทอรีการทำงานปัจจุบัน +- `worktree`: เส้นทางเวิร์กทรีคอมไพล์ +- `client`: ไคลเอนต์ opencode SDK สำหรับการโต้ตอบกับ AI +- `$`: [shell API](https://bun.com/docs/runtime/shell) ของ Bun สำหรับการดำเนินการคำสั่ง + +--- + +### รองรับ TypeScript + +สำหรับปลั๊กอิน TypeScript คุณสามารถนำเข้าประเภทจากแพ็คเกจปลั๊กอินได้: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### กิจกรรม + +ปลั๊กอินสามารถสมัครรับกิจกรรมได้ดังที่แสดงด้านล่างในส่วนตัวอย่าง นี่คือรายการกิจกรรมต่างๆ ที่มี + +#### เหตุการณ์คำสั่ง + +- `command.executed` + +#### ไฟล์เหตุการณ์ + +- `file.edited` +- `file.watcher.updated` + +#### เหตุการณ์การติดตั้ง + +- `installation.updated` + +#### LSP กิจกรรม + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### เหตุการณ์ข้อความ + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### เหตุการณ์การอนุญาต + +- `permission.asked` +- `permission.replied` + +#### เหตุการณ์เซิร์ฟเวอร์ + +- `server.connected` + +#### กิจกรรมเซสชั่น + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### เหตุการณ์ที่ต้องทำ + +- `todo.updated` + +#### กิจกรรมของ shell + +- `shell.env` + +#### เหตุการณ์เครื่องมือ + +- `tool.execute.after` +- `tool.execute.before` + +#### TUI กิจกรรม + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## ตัวอย่าง + +นี่คือตัวอย่างบางส่วนของปลั๊กอินที่คุณสามารถใช้เพื่อขยาย opencode + +--- + +### ส่งการแจ้งเตือน + +ส่งการแจ้งเตือนเมื่อมีเหตุการณ์บางอย่างเกิดขึ้น: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +เรากำลังใช้ `osascript` เพื่อเรียกใช้ AppleScript บน macOS ที่นี่เราใช้มันเพื่อส่งการแจ้งเตือน + +:::note +หากคุณใช้แอปเดสก์ท็อป OpenCode แอปสามารถส่งการแจ้งเตือนของระบบโดยอัตโนมัติเมื่อมีการตอบกลับพร้อมหรือเมื่อเซสชันเกิดข้อผิดพลาด +::: + +--- + +### การป้องกัน .env + +ป้องกันไม่ให้ opencode อ่านไฟล์ `.env`: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### ฉีดตัวแปรสภาพแวดล้อม + +แทรกตัวแปรสภาพแวดล้อมลงในการดำเนินการ shell ทั้งหมด (เครื่องมือ AI และ terminal ผู้ใช้): + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### เครื่องมือที่กำหนดเอง + +ปลั๊กอินยังสามารถเพิ่มเครื่องมือที่กำหนดเองให้กับ opencode: + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +ตัวช่วย `tool` สร้างเครื่องมือแบบกำหนดเองที่สามารถเรียกใช้ opencode ได้ ใช้ฟังก์ชัน Zod schema และส่งกลับคำจำกัดความของเครื่องมือด้วย: + +- `description`: เครื่องมือนี้ทำอะไร +- `args`: Zod schema สำหรับข้อโต้แย้งของเครื่องมือ +- `execute`: ฟังก์ชั่นที่ทำงานเมื่อมีการเรียกใช้เครื่องมือ + +เครื่องมือที่คุณกำหนดเองจะพร้อมใช้งานสำหรับ opencode ควบคู่ไปกับเครื่องมือในตัว + +--- + +### การบันทึก + +ใช้ `client.app.log()` แทน `console.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)สำหรับรายละเอียด + +--- + +### Hooks สำหรับการกระชับข้อมูล + +ปรับแต่งบริบทที่รวมไว้เมื่อมีการกระชับเซสชัน: + +```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` hook เริ่มทำงานก่อนที่ 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` จะถูกละเว้นในกรณีนี้ diff --git a/packages/web/src/content/docs/th/providers.mdx b/packages/web/src/content/docs/th/providers.mdx new file mode 100644 index 00000000000..e9fbb351d7d --- /dev/null +++ b/packages/web/src/content/docs/th/providers.mdx @@ -0,0 +1,1890 @@ +--- +title: ผู้ให้บริการ +description: ใช้ผู้ให้บริการ LLM ใน OpenCode +--- + +import config from "../../../../config.mjs" +export const console = config.console + +OpenCode ใช้ [AI SDK](https://ai-sdk.dev/) และ [Models.dev](https://models.dev) เพื่อรองรับผู้ให้บริการ **75+ LLM** และรองรับการใช้งานโมเดลท้องถิ่น + +หากต้องการเพิ่มผู้ให้บริการ คุณต้อง: + +1. เพิ่มคีย์ API สำหรับผู้ให้บริการโดยใช้คำสั่ง `/connect` +2. กำหนดค่าผู้ให้บริการในการกำหนดค่า OpenCode ของคุณ + +--- + +### ข้อมูลรับรอง + +เมื่อคุณเพิ่มคีย์ API ของผู้ให้บริการด้วยคำสั่ง `/connect` คีย์เหล่านั้นจะถูกเก็บไว้ +ใน `~/.local/share/opencode/auth.json`. + +--- + +### การกำหนดค่า + +คุณสามารถปรับแต่งผู้ให้บริการได้ผ่านทางส่วน `provider` ใน OpenCode ของคุณ +กำหนดค่า + +--- + +#### Base URL (URL พื้นฐาน) + +คุณสามารถปรับแต่งฐาน URL สำหรับผู้ให้บริการรายใดก็ได้โดยตั้งค่าตัวเลือก `baseURL` สิ่งนี้มีประโยชน์เมื่อใช้บริการพร็อกซีหรือจุดสิ้นสุดแบบกำหนดเอง + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen คือรายชื่อโมเดลที่จัดทำโดยทีมงาน OpenCode ที่ได้รับ +ทดสอบและตรวจสอบแล้วว่าทำงานได้ดีกับ OpenCode [เรียนรู้เพิ่มเติม](/docs/zen) + +:::tip +หากคุณยังใหม่ เราขอแนะนำให้เริ่มต้นด้วย OpenCode Zen +::: + +1. เรียกใช้คำสั่ง `/connect` ใน TUI เลือก opencode และไปที่ [opencode.ai/auth](https://opencode.ai/auth) + + ```txt + /connect + ``` + +2. ลงชื่อเข้าใช้ เพิ่มรายละเอียดการเรียกเก็บเงินของคุณ และคัดลอกรหัส API ของคุณ + +3. วางคีย์ API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. เรียกใช้ `/models` ใน TUI เพื่อดูรายการรุ่นที่เราแนะนำ + + ```txt + /models + ``` + +มันทำงานเหมือนกับผู้ให้บริการรายอื่นใน OpenCode และเป็นทางเลือกในการใช้งานโดยสมบูรณ์ + +--- + +## ไดเรกทอรี + +มาดูรายละเอียดผู้ให้บริการบางรายกัน หากคุณต้องการเพิ่มผู้ให้บริการให้กับ +รายการอย่าลังเลที่จะเปิดประชาสัมพันธ์ + +:::note +ไม่เห็นผู้ให้บริการที่นี่ใช่ไหม ส่งพีอาร์. +::: + +--- + +### 302.AI + +1. ไปที่ [302.AI console](https://302.ai/) สร้างบัญชี และสร้างคีย์ API + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **302.AI** + + ```txt + /connect + ``` + +3. ป้อนคีย์ 302.AI API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกรุ่น + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +วิธีใช้ Amazon Bedrock กับ OpenCode: + +1. ไปที่ **แค็ตตาล็อกโมเดล** ในคอนโซล Amazon Bedrock และขอ + เข้าถึงโมเดลที่คุณต้องการ + + :::tip + คุณต้องมีสิทธิ์เข้าถึงโมเดลที่คุณต้องการใน Amazon Bedrock + ::: + +2. **กำหนดค่าการตรวจสอบสิทธิ์** โดยใช้วิธีใดวิธีหนึ่งต่อไปนี้: + + #### ตัวแปรสภาพแวดล้อม (เริ่มต้นอย่างรวดเร็ว) + + ตั้งค่าหนึ่งในตัวแปรสภาพแวดล้อมเหล่านี้ขณะเรียกใช้ opencode: + + ```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode + ``` + + หรือเพิ่มลงในโปรไฟล์ทุบตีของคุณ: + + ```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" + } + } + } + } + ``` + + **ตัวเลือกที่มี:** + - `region` - ​​AWS ภูมิภาค (เช่น `us-east-1`, `eu-west-1`) + - `profile` - ​​AWS ตั้งชื่อโปรไฟล์จาก `~/.aws/credentials` + - `endpoint` - ​​จุดสิ้นสุดที่กำหนดเอง URL สำหรับ VPC จุดสิ้นสุด (นามแฝงสำหรับตัวเลือก `baseURL` ทั่วไป) + + :::tip + ตัวเลือกไฟล์การกำหนดค่ามีความสำคัญเหนือกว่าตัวแปรสภาพแวดล้อม + ::: + + #### ขั้นสูง: VPC จุดสิ้นสุด + + หากคุณใช้จุดสิ้นสุด VPC สำหรับ Bedrock: + + ```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` ทั่วไป โดยใช้คำศัพท์เฉพาะ AWS หากมีการระบุทั้ง `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`**: สร้างคีย์ API ระยะยาวจากคอนโซล Amazon Bedrock + - **`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, โทเค็นข้อมูลประจำตัวของเว็บ (EKS IRSA), ข้อมูลเมตาของอินสแตนซ์ + + :::note + เมื่อตั้งค่าBearer Token (ผ่าน `/connect` หรือ `AWS_BEARER_TOKEN_BEDROCK`) โทเค็นนั้นจะมีความสำคัญเหนือกว่าวิธีการข้อมูลประจำตัว AWS ทั้งหมด รวมถึงโปรไฟล์ที่กำหนดค่าไว้ + ::: + +3. รันคำสั่ง `/models` เพื่อเลือกรุ่นที่ต้องการ + + ```txt + /models + ``` + +:::note +สำหรับโปรไฟล์การอนุมานแบบกำหนดเอง ให้ใช้ชื่อรุ่นและผู้ให้บริการในคีย์และตั้งค่าคุณสมบัติ `id` เป็น arn สิ่งนี้ทำให้มั่นใจได้ว่าแคชถูกต้อง: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. เมื่อคุณสมัครแล้ว ให้รันคำสั่ง `/connect` และเลือก Anthropic + + ```txt + /connect + ``` + +2. ที่นี่คุณสามารถเลือกตัวเลือก **Claude Pro/Max** และมันจะเปิดเบราว์เซอร์ของคุณ + และขอให้คุณตรวจสอบสิทธิ์ + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. ตอนนี้โมเดล Anthropic ทั้งหมดควรจะพร้อมใช้งานเมื่อคุณใช้คำสั่ง `/models` + + ```txt + /models + ``` + +:::info +การใช้การสมัครสมาชิก Claude Pro/Max ใน OpenCode ไม่ได้รับการสนับสนุนอย่างเป็นทางการจาก [Anthropic](https://anthropic.com) +::: + +##### การใช้ API Key + +คุณยังสามารถเลือก **สร้าง API คีย์** หากคุณไม่มีการสมัครสมาชิก Pro/Max นอกจากนี้ยังจะเปิดเบราว์เซอร์ของคุณและขอให้คุณเข้าสู่ระบบ Anthropic และให้รหัสที่คุณสามารถวางใน terminal ของคุณ + +หรือหากคุณมีคีย์ API อยู่แล้ว คุณสามารถเลือก **ป้อนคีย์ API ด้วยตนเอง** และวางลงใน terminal ของคุณ + +--- + +### Azure OpenAI + +:::note +หากคุณพบข้อผิดพลาด "ฉันขอโทษ แต่ฉันไม่สามารถช่วยเหลือคำขอนั้นได้" ให้ลองเปลี่ยนตัวกรองเนื้อหาจาก **DefaultV2** เป็น **Default** ในทรัพยากร Azure ของคุณ +::: + +1. ไปที่ [พอร์ทัล Azure](https://portal.azure.com/) และสร้างทรัพยากร **Azure OpenAI** คุณจะต้องการ: + - **ชื่อทรัพยากร**: นี่จะกลายเป็นส่วนหนึ่งของจุดสิ้นสุด API ของคุณ (`https://RESOURCE_NAME.openai.azure.com/`) + - **API key**: `KEY 1` หรือ `KEY 2` จากทรัพยากรของคุณ + +2. ไปที่ [Azure AI Foundry](https://ai.azure.com/) และปรับใช้โมเดล + + :::note + ชื่อการปรับใช้จะต้องตรงกับชื่อรุ่นเพื่อให้ opencode ทำงานได้อย่างถูกต้อง + ::: + +3. เรียกใช้คำสั่ง `/connect` และค้นหา **Azure** + + ```txt + /connect + ``` + +4. ป้อน API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. ตั้งชื่อทรัพยากรของคุณเป็นตัวแปรสภาพแวดล้อม: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + หรือเพิ่มลงในโปรไฟล์ทุบตีของคุณ: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. รันคำสั่ง `/models` เพื่อเลือกโมเดลที่ปรับใช้ของคุณ + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. ไปที่ [พอร์ทัล Azure](https://portal.azure.com/) และสร้างทรัพยากร **Azure OpenAI** คุณจะต้องการ: + - **ชื่อทรัพยากร**: นี่จะกลายเป็นส่วนหนึ่งของจุดสิ้นสุด API ของคุณ (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) + - **API key**: `KEY 1` หรือ `KEY 2` จากทรัพยากรของคุณ + +2. ไปที่ [Azure AI Foundry](https://ai.azure.com/) และปรับใช้โมเดล + + :::note + ชื่อการปรับใช้จะต้องตรงกับชื่อรุ่นเพื่อให้ opencode ทำงานได้อย่างถูกต้อง + ::: + +3. เรียกใช้คำสั่ง `/connect` และค้นหา **Azure Cognitive Services** + + ```txt + /connect + ``` + +4. ป้อน API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. ตั้งชื่อทรัพยากรของคุณเป็นตัวแปรสภาพแวดล้อม: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + หรือเพิ่มลงในโปรไฟล์ทุบตีของคุณ: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. รันคำสั่ง `/models` เพื่อเลือกโมเดลที่ปรับใช้ของคุณ + + ```txt + /models + ``` + +--- + +### Baseten + +1. ไปที่ [Baseten](https://app.baseten.co/) สร้างบัญชี และสร้างคีย์ API + +2. รันคำสั่ง `/connect` และค้นหา **Baseten** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Baseten API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกรุ่น + + ```txt + /models + ``` + +--- + +### Cerebras + +1. ไปที่ [คอนโซล Cerebras](https://inference.cerebras.ai/) สร้างบัญชี และสร้างคีย์ API + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **Cerebras** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Cerebras API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกรุ่นเช่น _Qwen 3 Coder 480B_ + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +Cloudflare AI Gateway ช่วยให้คุณเข้าถึงโมเดลจาก OpenAI, Anthropic, Workers AI และอื่นๆ อีกมากมายผ่านตำแหน่งข้อมูลแบบรวม ด้วย [การเรียกเก็บเงินแบบรวม](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) คุณไม่จำเป็นต้องใช้คีย์ API แยกต่างหากสำหรับผู้ให้บริการแต่ละราย + +1. ไปที่ [แดชบอร์ด Cloudflare](https://dash.cloudflare.com/) ไปที่ **AI** > **AI Gateway** และสร้างเกตเวย์ใหม่ + +2. ตั้งค่ารหัสบัญชีและรหัสเกตเวย์ของคุณเป็นตัวแปรสภาพแวดล้อม + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. รันคำสั่ง `/connect` และค้นหา **Cloudflare AI Gateway** + + ```txt + /connect + ``` + +4. ป้อน Cloudflare API Token ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + หรือตั้งเป็นตัวแปรสภาพแวดล้อม + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. รันคำสั่ง `/models` เพื่อเลือกรุ่น + + ```txt + /models + ``` + + คุณยังสามารถเพิ่มโมเดลผ่านการกำหนดค่า opencode ของคุณได้ + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +### Cortecs + +1. ไปที่ [คอนโซล Cortecs](https://cortecs.ai/) สร้างบัญชี และสร้างคีย์ API + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **Cortecs** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Cortecs API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกโมเดลเช่น _Kimi K2 Instruct_ + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. ไปที่ [คอนโซล DeepSeek](https://platform.deepseek.com/) สร้างบัญชี แล้วคลิก **สร้างคีย์ API ใหม่** + +2. รันคำสั่ง `/connect` และค้นหา **DeepSeek** + + ```txt + /connect + ``` + +3. ป้อนคีย์ DeepSeek API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกโมเดล DeepSeek เช่น _DeepSeek Reasoner_ + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. ไปที่ [แดชบอร์ด Deep Infra](https://deepinfra.com/dash) สร้างบัญชี และสร้างคีย์ API + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **Deep Infra** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Deep Infra API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกรุ่น + + ```txt + /models + ``` + +--- + +### Firmware + +1. ไปที่ [แดชบอร์ด Firmware](https://app.firmware.ai/signup) สร้างบัญชี และสร้างคีย์ API + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **Firmware** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Firmware API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกรุ่น + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. ไปที่ [คอนโซล Fireworks AI](https://app.fireworks.ai/) สร้างบัญชี แล้วคลิก **Create API Key** + +2. รันคำสั่ง `/connect` และค้นหา **Fireworks AI** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Fireworks AI API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกโมเดลเช่น _Kimi K2 Instruct_ + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo ให้การแชทแบบเอเจนต์ที่ขับเคลื่อนด้วย AI พร้อมความสามารถในการเรียกใช้เครื่องมือแบบเนทีฟผ่านพร็อกซี Anthropic ของ GitLab + +1. รันคำสั่ง `/connect` และเลือก GitLab + + ```txt + /connect + ``` + +2. เลือกวิธีการรับรองความถูกต้องของคุณ: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ + ``` + + #### การใช้ OAuth (แนะนำ) + + เลือก **OAuth** และเบราว์เซอร์ของคุณจะเปิดขึ้นเพื่อรับสิทธิ์ + +#### การใช้ Personal Access Token + +1. ไปที่ [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens) +2. คลิก **เพิ่มโทเค็นใหม่** +3. ชื่อ: `OpenCode`, ขอบเขต: `api` +4. คัดลอกโทเค็น (เริ่มต้นด้วย `glpat-`) +5. ป้อนลงใน terminal + +6. รันคำสั่ง `/models` เพื่อดูรุ่นที่มีจำหน่าย + + ```txt + /models + ``` + + มีโมเดลที่ใช้ Claude สามรุ่นให้เลือก: + - **duo-chat-haiku-4-5** (ค่าเริ่มต้น) - ตอบสนองรวดเร็วสำหรับงานด่วน + - **duo-chat-sonnet-4-5** - ประสิทธิภาพที่สมดุลสำหรับขั้นตอนการทำงานส่วนใหญ่ + - **duo-chat-opus-4-5** - มีความสามารถมากที่สุดสำหรับการวิเคราะห์ที่ซับซ้อน + +:::note +คุณยังสามารถระบุตัวแปรสภาพแวดล้อม 'GITLAB_TOKEN' ได้หากคุณไม่ต้องการ +เพื่อจัดเก็บโทเค็นในที่เก็บข้อมูลการรับรองความถูกต้องของ opencode +::: + +##### GitLab ที่โฮสต์เอง + +:::note[บันทึกการปฏิบัติตาม] +OpenCode ใช้โมเดลขนาดเล็กสำหรับงาน AI บางอย่าง เช่น การสร้างชื่อเซสชัน +มีการกำหนดค่าให้ใช้ gpt-5-nano ตามค่าเริ่มต้น ซึ่งโฮสต์โดย Zen เพื่อล็อค OpenCode +หากต้องการใช้เฉพาะอินสแตนซ์ที่โฮสต์บน GitLab ของคุณเอง ให้เพิ่มสิ่งต่อไปนี้ในของคุณ +`opencode.json` ไฟล์. ขอแนะนำให้ปิดใช้งานการแชร์เซสชันด้วย + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +สำหรับอินสแตนซ์ GitLab ที่โฮสต์เอง: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +หากอินสแตนซ์ของคุณใช้งาน AI Gateway แบบกำหนดเอง: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +หรือเพิ่มในโปรไฟล์ทุบตีของคุณ: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +ผู้ดูแลระบบ 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` + ::: + +##### OAuth สำหรับอินสแตนซ์ที่โฮสต์เอง + +คุณต้องสร้างเพื่อให้ Oauth ทำงานกับอินสแตนซ์ที่โฮสต์เองได้ +แอพพลิเคชั่นใหม่ (Settings → Applications) ด้วย +โทรกลับ URL `http://127.0.0.1:8080/callback` และขอบเขตต่อไปนี้: + +- api (เข้าถึง API ในนามของคุณ) +- read_user (อ่านข้อมูลส่วนตัวของคุณ) +- read_repository (อนุญาตให้เข้าถึงที่เก็บแบบอ่านอย่างเดียว) + +จากนั้นเปิดเผย ID แอปพลิเคชันเป็นตัวแปรสภาพแวดล้อม: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +เอกสารประกอบเพิ่มเติมเกี่ยวกับหน้าแรกของ [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth) + +##### การกำหนดค่า + +ปรับแต่งผ่าน `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### GitLab API Tools (เป็นทางเลือก แต่แนะนำเป็นอย่างยิ่ง) + +วิธีเข้าถึงเครื่องมือ GitLab (รวมคำขอ ปัญหา ไปป์ไลน์ CI/CD ฯลฯ): + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +ปลั๊กอินนี้มอบความสามารถในการจัดการพื้นที่เก็บข้อมูล GitLab ที่ครอบคลุม รวมถึงการตรวจสอบ MR การติดตามปัญหา การตรวจสอบไปป์ไลน์ และอื่นๆ + +--- + +### GitHub Copilot + +วิธีใช้การสมัครสมาชิก GitHub Copilot ด้วย opencode: + +:::note +บางรุ่นอาจต้องมี [Pro+ +subscription](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) +::: + +1. รันคำสั่ง `/connect` และค้นหา GitHub Copilot + + ```txt + /connect + ``` + +2. ไปที่ [github.com/login/device](https://github.com/login/device) และป้อนรหัส + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + │ Waiting for authorization... + ``` + +3. ตอนนี้รันคำสั่ง `/models` เพื่อเลือกรุ่นที่คุณต้องการ + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +วิธีใช้ Google Vertex AI กับ OpenCode: + +1. ไปที่ **Model Garden** ใน Google Cloud Console แล้วตรวจสอบ + รุ่นที่มีในภูมิภาคของคุณ + + :::note + คุณต้องมีโปรเจ็กต์ Google Cloud ที่เปิดใช้งาน Vertex AI API + ::: + +2. ตั้งค่าตัวแปรสภาพแวดล้อมที่ต้องการ: + - `GOOGLE_CLOUD_PROJECT`: รหัสโครงการ Google Cloud ของคุณ + - `VERTEX_LOCATION` (เป็นทางเลือก): ภูมิภาคสำหรับ Vertex AI (ค่าเริ่มต้นคือ `global`) + - การรับรองความถูกต้อง (เลือกหนึ่งรายการ): + - `GOOGLE_APPLICATION_CREDENTIALS`: เส้นทางไปยังบัญชีบริการของคุณ JSON ไฟล์คีย์ + - ตรวจสอบสิทธิ์โดยใช้ gcloud CLI: `gcloud auth application-default login` + + ตั้งค่าในขณะที่เรียกใช้ opencode + + ```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode + ``` + + หรือเพิ่มลงในโปรไฟล์ทุบตีของคุณ + + ```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` ปรับปรุงความพร้อมใช้งานและลดข้อผิดพลาดโดยไม่มีค่าใช้จ่ายเพิ่มเติม ใช้ตำแหน่งข้อมูลระดับภูมิภาค (เช่น `us-central1`) สำหรับข้อกำหนดด้านถิ่นที่อยู่ของข้อมูล [เรียนรู้เพิ่มเติม](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. รันคำสั่ง `/models` เพื่อเลือกรุ่นที่ต้องการ + + ```txt + /models + ``` + +--- + +### Groq + +1. ไปที่ [Groq console](https://console.groq.com/) คลิก **Create API Key** และคัดลอกคีย์ + +2. เรียกใช้คำสั่ง `/connect` และค้นหา Groq + + ```txt + /connect + ``` + +3. ป้อนคีย์ API สำหรับผู้ให้บริการ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกคำสั่งที่คุณต้องการ + + ```txt + /models + ``` + +--- + +### Hugging Face + +[ผู้ให้บริการการอนุมาน Hugging Face](https://huggingface.co/docs/inference-providers) ช่วยให้สามารถเข้าถึงโมเดลแบบเปิดที่รองรับโดยผู้ให้บริการมากกว่า 17 ราย + +1. ไปที่ [การตั้งค่า Hugging Face](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained) เพื่อสร้างโทเค็นที่มีสิทธิ์ในการโทรไปยังผู้ให้บริการการอนุมาน + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **Hugging Face** + + ```txt + /connect + ``` + +3. ป้อน Hugging Face Token ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกโมเดล เช่น _Kimi-K2-Instruct_ หรือ _GLM-4.6_ + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) เป็นแพลตฟอร์มการติดตาม LLM ที่ให้การบันทึก การตรวจสอบ และการวิเคราะห์สำหรับแอปพลิเคชัน AI ของคุณ Helicone AI Gateway กำหนดเส้นทางคำขอของคุณไปยังผู้ให้บริการที่เหมาะสมโดยอัตโนมัติตามรุ่น + +1. ไปที่ [Helicone](https://helicone.ai) สร้างบัญชี และสร้างคีย์ API จากแดชบอร์ดของคุณ + +2. รันคำสั่ง `/connect` และค้นหา **Helicone** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Helicone API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกรุ่น + + ```txt + /models + ``` + +หากต้องการทราบผู้ให้บริการเพิ่มเติมและฟีเจอร์ขั้นสูง เช่น การแคชและการจำกัดอัตรา โปรดตรวจสอบ [เอกสารประกอบของ Helicone](https://docs.helicone.ai) + +#### การกำหนดค่าเพิ่มเติม + +ในกรณีที่คุณเห็นคุณสมบัติหรือรุ่นจาก Helicone ที่ไม่ได้กำหนดค่าโดยอัตโนมัติผ่าน opencode คุณสามารถกำหนดค่าด้วยตนเองได้ตลอดเวลา + +นี่คือ [Helicone's Model Directory](https://helicone.ai/models) คุณจะต้องใช้สิ่งนี้เพื่อรับ ID ของโมเดลที่คุณต้องการเพิ่ม + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### ส่วนหัวที่กำหนดเอง + +Helicone รองรับส่วนหัวแบบกำหนดเองสำหรับฟีเจอร์ต่างๆ เช่น การแคช การติดตามผู้ใช้ และการจัดการเซสชัน เพิ่มลงในการกำหนดค่าผู้ให้บริการของคุณโดยใช้ `options.headers`: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### การติดตามเซสชัน + +คุณลักษณะ [เซสชัน](https://docs.helicone.ai/features/sessions) ของ Helicone ช่วยให้คุณสามารถจัดกลุ่มคำขอ LLM ที่เกี่ยวข้องเข้าด้วยกันได้ ใช้ปลั๊กอิน [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) เพื่อบันทึกการสนทนา OpenCode แต่ละรายการเป็นเซสชันใน Helicone โดยอัตโนมัติ + +```bash +npm install -g opencode-helicone-session +``` + +เพิ่มลงในการกำหนดค่าของคุณ + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +ปลั๊กอินจะแทรกส่วนหัว `Helicone-Session-Id` และ `Helicone-Session-Name` ลงในคำขอของคุณ ในหน้าเซสชันของ Helicone คุณจะเห็นการสนทนา OpenCode แต่ละรายการแยกเป็นเซสชันแยกกัน + +##### ส่วนหัวของ Helicone ทั่วไป + +| ส่วนหัว | คำอธิบาย | +| -------------------------- | ---------------------------------------------------------------- | +| `Helicone-Cache-Enabled` | เปิดใช้งานการแคชการตอบกลับ (`true`/`false`) | +| `Helicone-User-Id` | ติดตามตัวชี้วัดตามผู้ใช้ | +| `Helicone-Property-[Name]` | เพิ่มคุณสมบัติที่กำหนดเอง (เช่น `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | เชื่อมโยงคำขอกับเวอร์ชันพร้อมท์ | + +ดู [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory) สำหรับส่วนหัวที่มีอยู่ทั้งหมด + +--- + +### llama.cpp + +คุณสามารถกำหนดค่า opencode เพื่อใช้โมเดลท้องถิ่นผ่านยูทิลิตี้ [llama.cpp's](https://github.com/ggml-org/llama.cpp) llama-server + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +ในตัวอย่างนี้: + +- `llama.cpp` คือ ID ผู้ให้บริการที่กำหนดเอง นี่อาจเป็นสตริงใดก็ได้ที่คุณต้องการ +- `npm` ระบุแพ็คเกจที่จะใช้สำหรับผู้ให้บริการรายนี้ ในที่นี้ `@ai-sdk/openai-compatible` ใช้สำหรับ API ที่เข้ากันได้กับ OpenAI +- `name` คือชื่อที่แสดงของผู้ให้บริการใน UI +- `options.baseURL` เป็นจุดสิ้นสุดสำหรับเซิร์ฟเวอร์ภายในเครื่อง +- `models` คือแมปของ ID โมเดลกับการกำหนดค่า ชื่อรุ่นจะปรากฏในรายการเลือกรุ่น + +--- + +### IO.NET + +IO.NET มี 17 โมเดลที่ได้รับการปรับให้เหมาะกับการใช้งานที่หลากหลาย: + +1. ไปที่ [IO.NET console](https://ai.io.net/) สร้างบัญชี และสร้างคีย์ API + +2. รันคำสั่ง `/connect` และค้นหา **IO.NET** + + ```txt + /connect + ``` + +3. ป้อนคีย์ IO.NET API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกรุ่น + + ```txt + /models + ``` + +--- + +### LM Studio + +คุณสามารถกำหนดค่า opencode เพื่อใช้โมเดลท้องถิ่นผ่าน LM Studio + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +ในตัวอย่างนี้: + +- `lmstudio` คือ ID ผู้ให้บริการที่กำหนดเอง นี่อาจเป็นสตริงใดก็ได้ที่คุณต้องการ +- `npm` ระบุแพ็คเกจที่จะใช้สำหรับผู้ให้บริการรายนี้ ในที่นี้ `@ai-sdk/openai-compatible` ใช้สำหรับ API ที่เข้ากันได้กับ OpenAI +- `name` คือชื่อที่แสดงของผู้ให้บริการใน UI +- `options.baseURL` เป็นจุดสิ้นสุดสำหรับเซิร์ฟเวอร์ภายในเครื่อง +- `models` คือแมปของ ID โมเดลกับการกำหนดค่า ชื่อรุ่นจะปรากฏในรายการเลือกรุ่น + +--- + +### Moonshot AI + +วิธีใช้ Kimi K2 จาก Moonshot AI: + +1. ไปที่ [Moonshot AI console](https://platform.moonshot.ai/console) สร้างบัญชี แล้วคลิก **Create API Key** + +2. รันคำสั่ง `/connect` และค้นหา **Moonshot AI** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Moonshot API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือก _Kimi K2_ + + ```txt + /models + ``` + +--- + +### MiniMax + +1. ไปที่ [MiniMax API Console](https://platform.minimax.io/login) สร้างบัญชี และสร้างคีย์ API + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **MiniMax** + + ```txt + /connect + ``` + +3. ป้อนคีย์ MiniMax API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกรุ่นเช่น _M2.1_ + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. ไปที่ [คอนโซล Nebius Token Factory](https://tokenfactory.nebius.com/) สร้างบัญชี แล้วคลิก **Add key** + +2. รันคำสั่ง `/connect` และค้นหา **Nebius Token Factory** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Nebius Token Factory API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกโมเดลเช่น _Kimi K2 Instruct_ + + ```txt + /models + ``` + +--- + +### Ollama + +คุณสามารถกำหนดค่า opencode เพื่อใช้โมเดลท้องถิ่นผ่าน Ollama + +:::tip +Ollama สามารถกำหนดค่าตัวเองสำหรับ OpenCode ได้โดยอัตโนมัติ ดู [เอกสารการบูรณาการ Ollama](https://docs.ollama.com/integrations/opencode) เพื่อดูรายละเอียด +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +ในตัวอย่างนี้: + +- `ollama` คือ ID ผู้ให้บริการที่กำหนดเอง นี่อาจเป็นสตริงใดก็ได้ที่คุณต้องการ +- `npm` ระบุแพ็คเกจที่จะใช้สำหรับผู้ให้บริการรายนี้ ในที่นี้ `@ai-sdk/openai-compatible` ใช้สำหรับ API ที่เข้ากันได้กับ OpenAI +- `name` คือชื่อที่แสดงของผู้ให้บริการใน UI +- `options.baseURL` เป็นจุดสิ้นสุดสำหรับเซิร์ฟเวอร์ภายในเครื่อง +- `models` คือแมปของ ID โมเดลกับการกำหนดค่า ชื่อรุ่นจะปรากฏในรายการเลือกรุ่น + +:::tip +หากการเรียกใช้เครื่องมือไม่ทำงาน ให้ลองเพิ่ม `num_ctx` ใน Ollama เริ่มต้นประมาณ 16,000 - 32,000 +::: + +--- + +### Ollama Cloud + +วิธีใช้ Ollama Cloud กับ OpenCode: + +1. ไปที่ [https://ollama.com/](https://ollama.com/) แล้วลงชื่อเข้าใช้หรือสร้างบัญชี + +2. ไปที่ **Settings** > **Keys** แล้วคลิก **Add API Key** เพื่อสร้างคีย์ API ใหม่ + +3. คัดลอกคีย์ API เพื่อใช้ใน OpenCode + +4. เรียกใช้คำสั่ง `/connect` และค้นหา **Ollama Cloud** + + ```txt + /connect + ``` + +5. ป้อนคีย์ Ollama Cloud API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **สำคัญ**: ก่อนที่จะใช้โมเดลคลาวด์ใน OpenCode คุณต้องดึงข้อมูลโมเดลในเครื่อง: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. รันคำสั่ง `/models` เพื่อเลือกโมเดล Ollama Cloud ของคุณ + + ```txt + /models + ``` + +--- + +### OpenAI + +เราขอแนะนำให้สมัคร [ChatGPT Plus หรือ Pro](https://chatgpt.com/pricing) + +1. เมื่อคุณสมัครแล้ว ให้รันคำสั่ง `/connect` และเลือก OpenAI + + ```txt + /connect + ``` + +2. ที่นี่คุณสามารถเลือกตัวเลือก **ChatGPT Plus/Pro** จากนั้นเบราว์เซอร์จะเปิดขึ้นมา + และขอให้คุณตรวจสอบสิทธิ์ + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. ตอนนี้โมเดล OpenAI ทั้งหมดควรจะพร้อมใช้งานเมื่อคุณใช้คำสั่ง `/models` + + ```txt + /models + ``` + +##### การใช้ API Key + +หากคุณมีคีย์ API อยู่แล้ว คุณสามารถเลือก **Manually enter API Key** และวางลงใน terminal ของคุณ + +--- + +### OpenCode Zen + +OpenCode Zen คือรายการโมเดลที่ได้รับการทดสอบและตรวจสอบแล้วโดยทีมงาน OpenCode [เรียนรู้เพิ่มเติม](/docs/zen) + +1. ลงชื่อเข้าใช้ **OpenCode Zen** และคลิก **สร้าง API คีย์** + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **OpenCode Zen** + + ```txt + /connect + ``` + +3. ป้อนคีย์ OpenCode API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกรุ่นเช่น _Qwen 3 Coder 480B_ + + ```txt + /models + ``` + +--- + +### เปิดเราเตอร์ + +1. ไปที่ [แดชบอร์ด OpenRouter](https://openrouter.ai/settings/keys) คลิก **สร้าง API คีย์** และคัดลอกคีย์ + +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 เอไอคอร์ + +SAP AI Core ให้การเข้าถึงโมเดลมากกว่า 40 โมเดลจาก OpenAI, Anthropic, Google, Amazon, Meta, Mistral และ AI21 ผ่านแพลตฟอร์มแบบครบวงจร + +1. ไปที่ห้องนักบิน [SAP BTP](https://account.hana.ondemand.com/) นำทางไปยังอินสแตนซ์บริการ SAP AI Core ของคุณ และสร้างรหัสบริการ + + :::tip + รหัสบริการคือวัตถุ JSON ที่ประกอบด้วย `clientid`, `clientsecret`, `url` และ `serviceurls.AI_API_URL` คุณสามารถค้นหาอินสแตนซ์ AI Core ของคุณได้ภายใต้ **บริการ** > **อินสแตนซ์และการสมัครสมาชิก** ในห้องควบคุม BTP + ::: + +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. ตั้งค่า ID การนำไปใช้งานและกลุ่มทรัพยากรเพิ่มเติม: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + การตั้งค่าเหล่านี้เป็นทางเลือกและควรกำหนดค่าตามการตั้งค่า SAP AI Core ของคุณ + ::: + +5. รันคำสั่ง `/models` เพื่อเลือกจากรุ่นที่มีให้เลือกมากกว่า 40 รุ่น + + ```txt + /models + ``` + +--- + +### ตำแหน่งข้อมูล AI ของ OVHcloud + +1. ไปที่ [แผง OVHcloud](https://ovh.com/manager) ไปที่ส่วน `Public Cloud` `AI & Machine Learning` > `AI Endpoints` และในแท็บ `API Keys` คลิก **สร้างคีย์ API ใหม่** + +2. รันคำสั่ง `/connect` และค้นหา **OVHcloud AI Endpoints** + + ```txt + /connect + ``` + +3. ป้อนคีย์ OVHcloud AI Endpoints API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกโมเดลเช่น _gpt-oss-120b_ + + ```txt + /models + ``` + +--- + +### สเกลเวย์ + +วิธีใช้ [Scaleway Generative API](https://www.scaleway.com/en/docs/generative-apis/) กับ Opencode: + +1. ไปที่ [การตั้งค่า Scaleway Console IAM](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 + ``` + +--- + +### ร่วมกันเอไอ + +1. ไปที่ [Together AI console](https://api.together.ai) สร้างบัญชี แล้วคลิก **เพิ่มรหัส** + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **Together AI** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Together AI API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกโมเดลเช่น _Kimi K2 Instruct_ + + ```txt + /models + ``` + +--- + +### เวนิส เอไอ + +1. ไปที่ [คอนโซล AI ของเวนิส](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 + ``` + +--- + +### เกตเวย์ AI ของ Vercel + +Vercel AI Gateway ช่วยให้คุณเข้าถึงโมเดลจาก OpenAI, Anthropic, Google, xAI และอื่นๆ อีกมากมายผ่านจุดสิ้นสุดแบบรวม โมเดลมีจำหน่ายในราคาปลีกโดยไม่มีส่วนเพิ่ม + +1. ไปที่ [แดชบอร์ด Vercel](https://vercel.com/) ไปที่แท็บ **เกตเวย์ AI** และคลิก **API คีย์** เพื่อสร้างคีย์ 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 + ``` + +--- + +### ซี.เอ.ไอ + +1. ไปที่ [Z.AI API console](https://z.ai/manage-apikey/apikey-list) สร้างบัญชี และคลิก **สร้างคีย์ API ใหม่** + +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](https://zenmux.ai/settings/keys) คลิก **สร้าง API คีย์** และคัดลอกคีย์ + +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` และเลื่อนลงไปที่ **อื่นๆ** + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. ป้อนรหัสเฉพาะสำหรับผู้ให้บริการ + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::note + เลือก 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 + - **ชื่อ**: ชื่อที่แสดงใน UI + - **รุ่น**: รุ่นที่มีจำหน่าย + - **options.baseURL**: API ปลายทาง URL + - **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) +- **ส่วนหัว**: ส่วนหัวที่กำหนดเองส่งไปพร้อมกับคำขอแต่ละรายการ +- **limit.context**: Input Tokens สูงสุดที่โมเดลยอมรับ +- **limit.output**: Output Tokens สูงสุดที่โมเดลสามารถสร้างได้ + +ช่อง `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` diff --git a/packages/web/src/content/docs/th/rules.mdx b/packages/web/src/content/docs/th/rules.mdx new file mode 100644 index 00000000000..c8deed792c6 --- /dev/null +++ b/packages/web/src/content/docs/th/rules.mdx @@ -0,0 +1,180 @@ +--- +title: กฎ +description: ตั้งค่าคำแนะนำที่กำหนดเองสำหรับ opencode +--- + +คุณสามารถให้คำแนะนำที่กำหนดเองแก่ opencode ได้โดยการสร้างไฟล์ `AGENTS.md` ซึ่งคล้ายกับกฎของเคอร์เซอร์ ประกอบด้วยคำแนะนำที่จะรวมอยู่ในบริบทของ LLM เพื่อปรับแต่งลักษณะการทำงานสำหรับโครงการเฉพาะของคุณ + +--- + +## เริ่มต้น + +หากต้องการสร้างไฟล์ `AGENTS.md` ใหม่ คุณสามารถเรียกใช้คำสั่ง `/init` ใน opencode + +:::tip +คุณควรคอมมิตไฟล์ `AGENTS.md` ของโปรเจ็กต์ของคุณไปที่ Git +::: + +การดำเนินการนี้จะสแกนโปรเจ็กต์ของคุณและเนื้อหาทั้งหมดเพื่อทำความเข้าใจว่าโปรเจ็กต์เกี่ยวกับอะไร และสร้างไฟล์ `AGENTS.md` ด้วย สิ่งนี้ช่วยให้ opencode นำทางโครงการได้ดีขึ้น + +หากคุณมีไฟล์ `AGENTS.md` อยู่แล้ว ระบบจะพยายามเพิ่มไฟล์ดังกล่าว + +--- + +## ตัวอย่าง + +คุณสามารถสร้างไฟล์นี้ด้วยตนเองได้ นี่คือตัวอย่างบางสิ่งที่คุณสามารถใส่ลงในไฟล์ `AGENTS.md` + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +เรากำลังเพิ่มคำแนะนำเฉพาะโครงการที่นี่ และจะมีการแชร์กับทีมของคุณ + +--- + +## ประเภท + +opencode ยังรองรับการอ่านไฟล์ `AGENTS.md` จากหลาย ๆ ที่ และสิ่งนี้มีจุดประสงค์ที่แตกต่างกัน + +### โครงการ + +วาง `AGENTS.md` ในรูทโปรเจ็กต์ของคุณสำหรับกฎเฉพาะโปรเจ็กต์ สิ่งเหล่านี้ใช้เฉพาะเมื่อคุณทำงานในไดเร็กทอรีนี้หรือไดเร็กทอรีย่อยเท่านั้น + +### ทั่วโลก + +คุณยังสามารถมีกฎสากลในไฟล์ `~/.config/opencode/AGENTS.md` สิ่งนี้จะนำไปใช้กับเซสชัน opencode ทั้งหมด + +เนื่องจากสิ่งนี้ไม่ได้ผูกมัดกับ Git หรือแชร์กับทีมของคุณ เราขอแนะนำให้ใช้สิ่งนี้เพื่อระบุกฎส่วนบุคคลที่ LLM ควรปฏิบัติตาม + +### ความเข้ากันได้กับ Claude Code + +สำหรับผู้ใช้ที่ย้ายจาก Claude Code นั้น OpenCode รองรับรูปแบบไฟล์ของ Claude Code เป็นทางเลือก: + +- **กฎของโครงการ**: `CLAUDE.md` ในไดเรกทอรีโครงการของคุณ (ใช้หากไม่มี `AGENTS.md`) +- **กฎสากล**: `~/.claude/CLAUDE.md` (ใช้หากไม่มี `~/.config/opencode/AGENTS.md`) +- **ทักษะ**: `~/.claude/skills/` — ดูรายละเอียด [ทักษะตัวแทน](/docs/skills/) + +หากต้องการปิดใช้งานความเข้ากันได้ของ Claude Code ให้ตั้งค่าหนึ่งในตัวแปรสภาพแวดล้อมเหล่านี้: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## ลำดับความสำคัญ + +เมื่อ opencode เริ่มต้นขึ้น มันจะค้นหาไฟล์กฎตามลำดับนี้: + +1. **ไฟล์ในเครื่อง** โดยการสำรวจจากไดเรกทอรีปัจจุบัน (`AGENTS.md`, `CLAUDE.md`) +2. **ไฟล์ทั่วโลก** ที่ `~/.config/opencode/AGENTS.md` +3. **Claude Code files** ที่ `~/.claude/CLAUDE.md` (ยกเว้นปิดการใช้งาน) + +ไฟล์ที่ตรงกันไฟล์แรกจะชนะในแต่ละหมวดหมู่ ตัวอย่างเช่น หากคุณมีทั้ง `AGENTS.md` และ `CLAUDE.md` ระบบจะใช้เฉพาะ `AGENTS.md` ในทำนองเดียวกัน `~/.config/opencode/AGENTS.md` จะมีความสำคัญมากกว่า `~/.claude/CLAUDE.md` + +--- + +## คำแนะนำที่กำหนดเอง + +คุณสามารถระบุไฟล์คำแนะนำที่กำหนดเองได้ใน `opencode.json` หรือ `~/.config/opencode/opencode.json` ทั่วโลก สิ่งนี้ช่วยให้คุณและทีมของคุณสามารถนำกฎที่มีอยู่กลับมาใช้ใหม่ได้ แทนที่จะต้องทำซ้ำกฎเหล่านั้นกับ AGENTS.md + +ตัวอย่าง: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +คุณยังสามารถใช้ URL ระยะไกลเพื่อโหลดคำแนะนำจากเว็บได้ + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +คำแนะนำระยะไกลจะถูกดึงออกมาโดยหมดเวลา 5 วินาที + +ไฟล์คำสั่งทั้งหมดจะรวมกับไฟล์ `AGENTS.md` ของคุณ + +--- + +## การอ้างอิงไฟล์ภายนอก + +แม้ว่า opencode จะไม่แยกวิเคราะห์การอ้างอิงไฟล์ใน `AGENTS.md` โดยอัตโนมัติ แต่คุณสามารถใช้ฟังก์ชันที่คล้ายกันได้สองวิธี: + +### ใช้ opencode.json + +แนวทางที่แนะนำคือการใช้ฟิลด์ `instructions` ใน `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### คำแนะนำแบบแมนนวลใน AGENTS.md + +คุณสามารถสอนให้ opencode อ่านไฟล์ภายนอกได้โดยการให้คำแนะนำที่ชัดเจนใน `AGENTS.md` ของคุณ นี่เป็นตัวอย่างที่เป็นประโยชน์: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +แนวทางนี้ช่วยให้คุณ: + +- สร้างไฟล์กฎแบบโมดูลาร์ที่สามารถนำมาใช้ซ้ำได้ +- แชร์กฎระหว่างโปรเจ็กต์ผ่าน symlink หรือโมดูลย่อย git +- เขียน AGENTS.md ให้กระชับโดยอ้างอิงหลักเกณฑ์โดยละเอียด +- ตรวจสอบให้แน่ใจว่า opencode จะโหลดไฟล์เมื่อจำเป็นสำหรับงานเฉพาะเท่านั้น + +:::tip +สำหรับ monorepos หรือโปรเจ็กต์ที่มีมาตรฐานร่วมกัน การใช้ `opencode.json` ที่มีรูปแบบ glob (เช่น `packages/*/AGENTS.md`) จะสามารถบำรุงรักษาได้ดีกว่าคำสั่งแบบแมนนวล +::: diff --git a/packages/web/src/content/docs/th/sdk.mdx b/packages/web/src/content/docs/th/sdk.mdx new file mode 100644 index 00000000000..b592c1a4e4b --- /dev/null +++ b/packages/web/src/content/docs/th/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: ไคลเอนต์ JS ประเภทที่ปลอดภัยสำหรับเซิร์ฟเวอร์ opencode +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +opencode JS/TS SDK จัดเตรียมไคลเอ็นต์ประเภทที่ปลอดภัยสำหรับการโต้ตอบกับเซิร์ฟเวอร์ +ใช้เพื่อสร้างการบูรณาการและควบคุม opencode โดยทางโปรแกรม + +[เรียนรู้เพิ่มเติม](/docs/server) เกี่ยวกับวิธีการทำงานของเซิร์ฟเวอร์ ตัวอย่างเช่น ลองดู [โครงการ](/docs/ecosystem#โครงการ) ที่สร้างโดยชุมชน + +--- + +## ติดตั้ง + +ติดตั้ง SDK จาก npm: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## สร้างไคลเอนต์ + +สร้างอินสแตนซ์ของ opencode: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +สิ่งนี้จะเริ่มต้นทั้งเซิร์ฟเวอร์และไคลเอนต์ + +#### ตัวเลือก + +| ตัวเลือก | Type | คำอธิบาย | ค่าเริ่มต้น | +| ---------- | ------------- | ------------------------------------------- | ----------- | +| `hostname` | `string` | ชื่อโฮสต์ของเซิร์ฟเวอร์ | `127.0.0.1` | +| `port` | `number` | พอร์ตเซิร์ฟเวอร์ | `4096` | +| `signal` | `AbortSignal` | ยกเลิกสัญญาณสำหรับการยกเลิก | `undefined` | +| `timeout` | `number` | หมดเวลาเป็น ms สำหรับการเริ่มต้นเซิร์ฟเวอร์ | `5000` | +| `config` | `Config` | วัตถุการกำหนดค่า | `{}` | + +--- + +## การกำหนดค่า + +คุณสามารถส่งผ่านออบเจ็กต์การกำหนดค่าเพื่อปรับแต่งลักษณะการทำงานได้ อินสแตนซ์ยังคงรับ `opencode.json` ของคุณ แต่คุณสามารถแทนที่หรือเพิ่มการกำหนดค่าแบบอินไลน์ได้: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## ลูกค้าเท่านั้น + +หากคุณมีอินสแตนซ์ opencode ที่ทำงานอยู่แล้ว คุณสามารถสร้างอินสแตนซ์ไคลเอ็นต์เพื่อเชื่อมต่อได้: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### ตัวเลือก + +| ตัวเลือก | Type | คำอธิบาย | ค่าเริ่มต้น | +| --------------- | ---------- | ---------------------------------------- | ----------------------- | +| `baseUrl` | `string` | URL ของเซิร์ฟเวอร์ | `http://localhost:4096` | +| `fetch` | `function` | การใช้งานการดึงข้อมูลแบบกำหนดเอง | `globalThis.fetch` | +| `parseAs` | `string` | Methodการแยกวิเคราะห์การตอบสนอง | `auto` | +| `responseStyle` | `string` | รูปแบบการคืนสินค้า: `data` หรือ `fields` | `fields` | +| `throwOnError` | `boolean` | โยนข้อผิดพลาดแทนการส่งคืน | `false` | + +--- + +## ประเภท + +SDK มีคำจำกัดความ TypeScript สำหรับ API ประเภททั้งหมด นำเข้าโดยตรง: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +ทุกประเภทสร้างขึ้นจากข้อกำหนด OpenAPI ของเซิร์ฟเวอร์และมีอยู่ใน ไฟล์ประเภท + +--- + +## ข้อผิดพลาด + +SDK อาจทำให้เกิดข้อผิดพลาดที่คุณสามารถจับและจัดการได้: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## API + +SDK เปิดเผย API ของเซิร์ฟเวอร์ทั้งหมดผ่านไคลเอ็นต์ประเภทที่ปลอดภัย + +--- + +### ทั่วโลก + +| Method | คำอธิบาย | การตอบสนอง | +| ----------------- | ------------------------------------ | ------------------------------------ | +| `global.health()` | ตรวจสอบสภาพและเวอร์ชันของเซิร์ฟเวอร์ | `{ healthy: true, version: string }` | + +--- + +#### ตัวอย่าง + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### แอป + +| Method | คำอธิบาย | การตอบสนอง | +| -------------- | ----------------------------- | -------------------------------------------- | +| `app.log()` | เขียนรายการบันทึก | `boolean` | +| `app.agents()` | รายชื่อตัวแทนที่มีอยู่ทั้งหมด | ตัวแทน[] | + +--- + +#### ตัวอย่าง + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### โครงการ + +| Method | คำอธิบาย | การตอบสนอง | +| ------------------- | ------------------------ | --------------------------------------------- | +| `project.list()` | แสดงรายการโครงการทั้งหมด | Project[] | +| `project.current()` | รับโครงการปัจจุบัน | Project | + +--- + +#### ตัวอย่าง + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### เส้นทาง + +| Method | คำอธิบาย | การตอบสนอง | +| ------------ | ------------------ | ---------------------------------------- | +| `path.get()` | รับเส้นทางปัจจุบัน | Path | + +--- + +#### ตัวอย่าง + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### การกำหนดค่า + +| Method | คำอธิบาย | การตอบสนอง | +| -------------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------- | +| `config.get()` | รับข้อมูลการกำหนดค่า | กำหนดค่า | +| `config.providers()` | ผู้ให้บริการรายชื่อและโมเดลเริ่มต้น | `{ providers: `ผู้ให้บริการ[]`, default: { [key: string]: string } }` | + +--- + +#### ตัวอย่าง + +```javascript +const config = await client.config.get() + +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` | + +--- + +#### ตัวอย่าง + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### ไฟล์ + +| Method | คำอธิบาย | การตอบสนอง | +| ------------------------- | ------------------------------ | ----------------------------------------------------------------------------------------- | +| `find.text({ query })` | ค้นหาข้อความในไฟล์ | อาร์เรย์ของวัตถุที่ตรงกับ `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `find.files({ query })` | ค้นหาไฟล์และไดเร็กทอรีตามชื่อ | `string[]` (paths) | +| `find.symbols({ query })` | ค้นหาสัญลักษณ์พื้นที่ทำงาน | Symbol[] | +| `file.read({ query })` | อ่านไฟล์ | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | รับสถานะสำหรับไฟล์ที่ถูกติดตาม | File[] | + +`find.files` รองรับช่องค้นหาเพิ่มเติมบางช่อง: + +- `type`: `"file"` หรือ `"directory"` +- `directory`: แทนที่รูทโปรเจ็กต์สำหรับการค้นหา +- `limit`: ผลลัพธ์สูงสุด (1–200) + +--- + +#### ตัวอย่าง + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| Method | คำอธิบาย | การตอบสนอง | +| ------------------------------ | ------------------------------ | ---------- | +| `tui.appendPrompt({ body })` | เพิ่มข้อความต่อท้ายข้อความแจ้ง | `boolean` | +| `tui.openHelp()` | เปิดกล่องโต้ตอบความช่วยเหลือ | `boolean` | +| `tui.openSessions()` | เปิดตัวเลือกเซสชัน | `boolean` | +| `tui.openThemes()` | เปิดตัวเลือกธีม | `boolean` | +| `tui.openModels()` | เปิดตัวเลือกรุ่น | `boolean` | +| `tui.submitPrompt()` | ส่งข้อความแจ้งปัจจุบัน | `boolean` | +| `tui.clearPrompt()` | ล้างข้อความแจ้ง | `boolean` | +| `tui.executeCommand({ body })` | ดำเนินการคำสั่ง | `boolean` | +| `tui.showToast({ body })` | แสดงการแจ้งเตือนขนมปังปิ้ง | `boolean` | + +--- + +#### ตัวอย่าง + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### การรับรองความถูกต้อง + +| Method | คำอธิบาย | การตอบสนอง | +| ------------------- | ----------------------------------------- | ---------- | +| `auth.set({ ... })` | ตั้งค่าข้อมูลประจำตัวการรับรองความถูกต้อง | `boolean` | + +--- + +#### ตัวอย่าง + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### กิจกรรม + +| Method | คำอธิบาย | การตอบสนอง | +| ------------------- | ------------------------------- | ------------------------------- | +| `event.subscribe()` | สตรีมเหตุการณ์ที่เซิร์ฟเวอร์ส่ง | สตรีมเหตุการณ์ที่เซิร์ฟเวอร์ส่ง | + +--- + +#### ตัวอย่าง + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/th/server.mdx b/packages/web/src/content/docs/th/server.mdx new file mode 100644 index 00000000000..13302cf5780 --- /dev/null +++ b/packages/web/src/content/docs/th/server.mdx @@ -0,0 +1,287 @@ +--- +title: เซิร์ฟเวอร์ +description: โต้ตอบกับเซิร์ฟเวอร์ opencode ผ่าน HTTP +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +คำสั่ง `opencode serve` รันเซิร์ฟเวอร์ HTTP ที่ไม่มีหัวซึ่งเปิดเผยตำแหน่งข้อมูล OpenAPI ที่ไคลเอนต์ opencode สามารถใช้ได้ + +--- + +### การใช้งาน + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### ตัวเลือก + +| Flag | คำอธิบาย | ค่าเริ่มต้น | +| --------------- | ---------------------------------------- | ---------------- | +| `--port` | พอร์ตที่จะฟัง | `4096` | +| `--hostname` | ชื่อโฮสต์ที่จะฟัง | `127.0.0.1` | +| `--mdns` | เปิดใช้งานการค้นพบ mDNS | `false` | +| `--mdns-domain` | ชื่อโดเมนที่กำหนดเองสำหรับบริการ mDNS | `opencode.local` | +| `--cors` | ต้นกำเนิดเบราว์เซอร์เพิ่มเติมที่จะอนุญาต | `[]` | + +`--cors` สามารถส่งผ่านได้หลายครั้ง: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### การรับรองความถูกต้อง + +ตั้งค่า `OPENCODE_SERVER_PASSWORD` เพื่อปกป้องเซิร์ฟเวอร์ด้วย HTTP การตรวจสอบสิทธิ์ขั้นพื้นฐาน ชื่อผู้ใช้มีค่าเริ่มต้นเป็น `opencode` หรือตั้งค่า `OPENCODE_SERVER_USERNAME` เพื่อแทนที่ชื่อผู้ใช้ สิ่งนี้ใช้ได้กับทั้ง `opencode serve` และ `opencode web` + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### มันทำงานอย่างไร + +เมื่อคุณรัน `opencode` มันจะเริ่มต้น TUI และเซิร์ฟเวอร์ โดยที่ TUI คือ +ลูกค้าที่พูดคุยกับเซิร์ฟเวอร์ เซิร์ฟเวอร์เปิดเผยข้อมูลจำเพาะของ OpenAPI 3.1 +จุดสิ้นสุด ตำแหน่งข้อมูลนี้ยังใช้เพื่อสร้าง [SDK](/docs/sdk) + +:::tip +ใช้เซิร์ฟเวอร์ opencode เพื่อโต้ตอบกับ opencode โดยทางโปรแกรม +::: + +สถาปัตยกรรมนี้ช่วยให้ opencode รองรับไคลเอนต์หลายตัว และช่วยให้คุณสามารถโต้ตอบกับ opencode โดยทางโปรแกรมได้ + +คุณสามารถเรียกใช้ `opencode serve` เพื่อเริ่มเซิร์ฟเวอร์แบบสแตนด์อโลน ถ้าคุณมี +opencode TUI ทำงาน `opencode serve` จะเริ่มเซิร์ฟเวอร์ใหม่ + +--- + +#### เชื่อมต่อกับเซิร์ฟเวอร์ที่มีอยู่ + +เมื่อคุณเริ่ม TUI มันจะสุ่มกำหนดพอร์ตและชื่อโฮสต์ คุณสามารถผ่าน `--hostname` และ `--port` [ธง](/docs/cli) แทนได้ จากนั้นใช้สิ่งนี้เพื่อเชื่อมต่อกับเซิร์ฟเวอร์ + +ตำแหน่งข้อมูล [`/tui`](#tui) สามารถใช้เพื่อขับเคลื่อน TUI ผ่านเซิร์ฟเวอร์ ตัวอย่างเช่น คุณสามารถกรอกข้อมูลล่วงหน้าหรือเรียกใช้พร้อมท์ได้ การตั้งค่านี้ถูกใช้โดยปลั๊กอิน OpenCode [IDE](/docs/ide) + +--- + +## ข้อมูลจำเพาะ + +เซิร์ฟเวอร์เผยแพร่ข้อมูลจำเพาะ OpenAPI 3.1 ที่สามารถดูได้ที่: + +``` +http://:/doc +``` + +ตัวอย่างเช่น `http://localhost:4096/doc` ใช้ข้อมูลจำเพาะเพื่อสร้างไคลเอ็นต์หรือตรวจสอบคำขอและประเภทการตอบกลับ หรือดูใน Swagger explorer + +--- + +## API + +เซิร์ฟเวอร์ opencode เปิดเผย API ต่อไปนี้ + +--- + +### ทั่วโลก + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | ---------------- | --------------------------------- | ------------------------------------ | +| `GET` | `/global/health` | รับสถานะและเวอร์ชันของเซิร์ฟเวอร์ | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | รับกิจกรรมระดับโลก (SSE สตรีม) | สตรีมกิจกรรม | + +--- + +### โครงการ + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | ------------------ | ------------------------ | --------------------------------------------- | +| `GET` | `/project` | แสดงรายการโครงการทั้งหมด | Project[] | +| `GET` | `/project/current` | รับโครงการปัจจุบัน | Project | + +--- + +### เส้นทาง & VCS + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | ------- | ----------------------------------- | ------------------------------------------- | +| `GET` | `/path` | รับเส้นทางปัจจุบัน | Path | +| `GET` | `/vcs` | รับข้อมูล VCS สำหรับโครงการปัจจุบัน | VcsInfo | + +--- + +### ตัวอย่าง + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | ------------------- | ---------------------- | ---------- | +| `POST` | `/instance/dispose` | กำจัดอินสแตนซ์ปัจจุบัน | `boolean` | + +--- + +### การกำหนดค่า + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------- | ------------------- | ----------------------------------- | -------------------------------------------------------------------------------------------- | +| `GET` | `/config` | รับข้อมูลการกำหนดค่า | กำหนดค่า | +| `PATCH` | `/config` | อัปเดตการกำหนดค่า | กำหนดค่า | +| `GET` | `/config/providers` | ผู้ให้บริการรายชื่อและโมเดลเริ่มต้น | `{ providers: `ผู้ให้บริการ[]`, default: { [key: string]: string } }` | + +--- + +### ผู้ให้บริการ + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | -------------------------------- | ------------------------------------------- | --------------------------------------------------------------------------------------- | +| `GET` | `/provider` | รายชื่อผู้ให้บริการทั้งหมด | `{ all: `ผู้ให้บริการ[]`, default: {...}, connected: string[] }` | +| `GET` | `/provider/auth` | รับวิธีการตรวจสอบความถูกต้องของผู้ให้บริการ | `{ [providerID: string]: `ProviderAuthMethod[]` }` | +| `POST` | `/provider/{id}/oauth/authorize` | ให้สิทธิ์ผู้ให้บริการโดยใช้ OAuth | การอนุญาตของผู้ให้บริการ | +| `POST` | `/provider/{id}/oauth/callback` | จัดการการโทรกลับ OAuth สำหรับผู้ให้บริการ | `boolean` | + +--- + +### เซสชัน + +| Method | เส้นทาง | คำอธิบาย | หมายเหตุ | +| -------- | ---------------------------------------- | ---------------------------------- | -------------------------------------------------------------------------------- | +| `GET` | `/session` | แสดงรายการเซสชันทั้งหมด | ส่งคืน เซสชัน[] | +| `POST` | `/session` | สร้างเซสชันใหม่ | body: `{ parentID?, title? }` ส่งคืน เซสชัน | +| `GET` | `/session/status` | รับสถานะเซสชันสำหรับเซสชันทั้งหมด | ส่งคืน `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | รับรายละเอียดเซสชั่น | ส่งคืน เซสชัน | +| `DELETE` | `/session/:id` | ลบเซสชันและข้อมูลทั้งหมด | ส่งคืน `boolean` | +| `PATCH` | `/session/:id` | อัปเดตคุณสมบัติเซสชัน | body: `{ title? }` ส่งคืน เซสชัน | +| `GET` | `/session/:id/children` | รับเซสชันย่อยของเซสชัน | ส่งคืน เซสชัน[] | +| `GET` | `/session/:id/todo` | รับรายการสิ่งที่ต้องทำสำหรับเซสชัน | ส่งคืน สิ่งที่ต้องทำ[] | +| `POST` | `/session/:id/init` | วิเคราะห์แอปและสร้าง `AGENTS.md` | เนื้อความ: `{ messageID, providerID, modelID }` ส่งคืน `boolean` | +| `POST` | `/session/:id/fork` | แยกเซสชันที่มีอยู่ไปที่ข้อความ | body: `{ messageID? }` ส่งคืน เซสชัน | +| `POST` | `/session/:id/abort` | ยกเลิกเซสชันที่ทำงานอยู่ | ส่งคืน `boolean` | +| `POST` | `/session/:id/share` | แบ่งปันเซสชั่น | ส่งคืน เซสชัน | +| `DELETE` | `/session/:id/share` | ยกเลิกการแชร์เซสชัน | ส่งคืน เซสชัน | +| `GET` | `/session/:id/diff` | รับความแตกต่างสำหรับเซสชั่นนี้ | ข้อความค้นหา: `messageID?` ส่งคืน FileDiff[] | +| `POST` | `/session/:id/summarize` | สรุปเซสชัน | เนื้อความ: `{ providerID, modelID }` ส่งคืน `boolean` | +| `POST` | `/session/:id/revert` | คืนค่าข้อความ | เนื้อความ: `{ messageID, partID? }` ส่งคืน `boolean` | +| `POST` | `/session/:id/unrevert` | กู้คืนข้อความที่เปลี่ยนกลับทั้งหมด | ส่งคืน `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | ตอบสนองต่อการร้องขอการอนุญาต | เนื้อความ: `{ response, remember? }` ส่งคืน `boolean` | + +--- + +### ข้อความ + +| Method | เส้นทาง | คำอธิบาย | หมายเหตุ | +| ------ | --------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `GET` | `/session/:id/message` | แสดงรายการข้อความในเซสชัน | ข้อความค้นหา: `limit?` ส่งคืน `{ info: `ข้อความ`, parts: `ส่วน[]`}[]` | +| `POST` | `/session/:id/message` | ส่งข้อความและรอการตอบกลับ | เนื้อความ: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }` ส่งคืน `{ info: `ข้อความ`, parts: `ส่วน[]`}` | +| `GET` | `/session/:id/message/:messageID` | รับรายละเอียดข้อความ | ส่งคืน `{ info: `ข้อความ`, parts: `ส่วนหนึ่ง[]`}` | +| `POST` | `/session/:id/prompt_async` | ส่งข้อความแบบอะซิงโครนัส (ไม่ต้องรอ) | เนื้อความ: เหมือนกับ `/session/:id/message` ส่งคืน `204 No Content` | +| `POST` | `/session/:id/command` | ดำเนินการคำสั่งเครื่องหมายทับ | เนื้อความ: `{ messageID?, agent?, model?, command, arguments }` ส่งคืน `{ info: `ข้อความ`, parts: `ส่วน[]`}` | +| `POST` | `/session/:id/shell` | รันคำสั่ง shell | เนื้อความ: `{ agent, model?, command }` ส่งคืน `{ info: `ข้อความ`, parts: `ส่วน[]`}` | + +--- + +### คำสั่ง + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | ---------- | ----------------------- | --------------------------------------------- | +| `GET` | `/command` | แสดงรายการคำสั่งทั้งหมด | Command[] | + +--- + +### ไฟล์ + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | ------------------------ | ------------------------------ | ----------------------------------------------------------------------------------------- | +| `GET` | `/find?pattern=` | ค้นหาข้อความในไฟล์ | อาร์เรย์ของวัตถุที่ตรงกับ `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `GET` | `/find/file?query=` | ค้นหาไฟล์และไดเร็กทอรีตามชื่อ | `string[]` (paths) | +| `GET` | `/find/symbol?query=` | ค้นหาสัญลักษณ์พื้นที่ทำงาน | Symbol[] | +| `GET` | `/file?path=` | แสดงรายการไฟล์และไดเร็กทอรี | FileNode[] | +| `GET` | `/file/content?path=

` | อ่านไฟล์ | เนื้อหาไฟล์ | +| `GET` | `/file/status` | รับสถานะสำหรับไฟล์ที่ถูกติดตาม | File[] | + +#### `/find/file` พารามิเตอร์การสืบค้น + +- `query` (จำเป็น) — สตริงการค้นหา (การจับคู่แบบคลุมเครือ) +- `type` (ไม่บังคับ) — จำกัดผลลัพธ์ไว้ที่ `"file"` หรือ `"directory"` +- `directory` (เป็นทางเลือก) — แทนที่รูทโปรเจ็กต์สำหรับการค้นหา +- `limit` (ไม่บังคับ) — ผลลัพธ์สูงสุด (1–200) +- `dirs` (ไม่บังคับ) — แฟล็กดั้งเดิม (`"false"` ส่งคืนเฉพาะไฟล์) + +--- + +### เครื่องมือ (ขั้นทดลอง) + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | ------------------------------------------- | ----------------------------------------------- | ---------------------------------------------------- | +| `GET` | `/experimental/tool/ids` | แสดงรายการรหัสเครื่องมือทั้งหมด | รหัสเครื่องมือ | +| `GET` | `/experimental/tool?provider=

&model=` | แสดงรายการเครื่องมือที่มีสกีมา JSON สำหรับโมเดล | รายการเครื่องมือ | + +--- + +### LSP, ฟอร์แมตเตอร์ & MCP + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | ------------ | ------------------------------- | -------------------------------------------------------- | +| `GET` | `/lsp` | รับ LSP สถานะเซิร์ฟเวอร์ | LSPStatus[] | +| `GET` | `/formatter` | รับสถานะฟอร์แมตเตอร์ | FormatterStatus[] | +| `GET` | `/mcp` | รับ MCP สถานะเซิร์ฟเวอร์ | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | เพิ่มเซิร์ฟเวอร์ MCP แบบไดนามิก | body: `{ name, config }` ส่งคืนออบเจ็กต์สถานะ MCP | + +--- + +### ตัวแทน + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | -------- | ----------------------------- | -------------------------------------------- | +| `GET` | `/agent` | รายชื่อตัวแทนที่มีอยู่ทั้งหมด | ตัวแทน[] | + +--- + +### การบันทึก + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | ------- | ------------------------------------------------------------------ | ---------- | +| `POST` | `/log` | เขียนรายการบันทึก เนื้อความ: `{ service, level, message, extra? }` | `boolean` | + +--- + +### TUI + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | ----------------------- | ----------------------------------------------- | --------------- | +| `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` | + +--- + +### การรับรองความถูกต้อง + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | ----------- | --------------------------------------------------------------------------------- | ---------- | +| `PUT` | `/auth/:id` | ตั้งค่าข้อมูลประจำตัวการรับรองความถูกต้อง เนื้อความต้องตรงกับสคีมาของผู้ให้บริการ | `boolean` | + +--- + +### กิจกรรม + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | -------- | ---------------------------------------------------------------------------- | ------------------------------- | +| `GET` | `/event` | สตรีมเหตุการณ์ที่เซิร์ฟเวอร์ส่ง งานแรกคือ `server.connected` จากนั้นงานรถบัส | สตรีมเหตุการณ์ที่เซิร์ฟเวอร์ส่ง | + +--- + +### เอกสาร + +| Method | เส้นทาง | คำอธิบาย | การตอบสนอง | +| ------ | ------- | --------------------------- | ---------------------------------- | +| `GET` | `/doc` | ข้อมูลจำเพาะของ OpenAPI 3.1 | HTML หน้าพร้อมข้อมูลจำเพาะ OpenAPI | diff --git a/packages/web/src/content/docs/th/share.mdx b/packages/web/src/content/docs/th/share.mdx new file mode 100644 index 00000000000..195d7696f9b --- /dev/null +++ b/packages/web/src/content/docs/th/share.mdx @@ -0,0 +1,128 @@ +--- +title: แบ่งปัน +description: แบ่งปันการสนทนา OpenCode ของคุณ +--- + +คุณลักษณะการแชร์ของ OpenCode ช่วยให้คุณสร้างลิงก์สาธารณะไปยังการสนทนา OpenCode ของคุณ เพื่อให้คุณสามารถทำงานร่วมกับเพื่อนร่วมทีมหรือรับความช่วยเหลือจากผู้อื่นได้ + +:::note +ทุกคนที่มีลิงก์สามารถเข้าถึงการสนทนาที่แชร์ได้แบบสาธารณะ +::: + +--- + +## มันทำงานอย่างไร + +เมื่อคุณแบ่งปันการสนทนา OpenCode: + +1. สร้าง URL สาธารณะที่ไม่ซ้ำสำหรับเซสชันของคุณ +2. ซิงค์ประวัติการสนทนาของคุณกับเซิร์ฟเวอร์ของเรา +3. ทำให้สามารถเข้าถึงการสนทนาผ่านลิงก์ที่แชร์ได้ — `opncd.ai/s/` + +--- + +## การแบ่งปัน + +OpenCode รองรับโหมดการแชร์สามโหมดที่ควบคุมวิธีการแชร์การสนทนา: + +--- + +### Manual (ค่าเริ่มต้น) + +ตามค่าเริ่มต้น OpenCode จะใช้โหมดการแชร์ด้วยตนเอง เซสชันจะไม่ถูกแชร์โดยอัตโนมัติ แต่คุณสามารถแชร์ได้ด้วยตนเองโดยใช้คำสั่ง `/share`: + +``` +/share +``` + +สิ่งนี้จะสร้าง URL ที่ไม่ซ้ำกันซึ่งจะถูกคัดลอกไปยังคลิปบอร์ดของคุณ + +หากต้องการตั้งค่าโหมดแมนนวลอย่างชัดเจนใน [ไฟล์ปรับแต่ง](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### แชร์อัตโนมัติ + +คุณสามารถเปิดใช้งานการแบ่งปันอัตโนมัติสำหรับการสนทนาใหม่ทั้งหมดโดยตั้งค่าตัวเลือก `share` เป็น `"auto"` ใน [ไฟล์กำหนดค่า](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +เมื่อเปิดใช้งานการแชร์อัตโนมัติ ทุกการสนทนาใหม่จะถูกแชร์โดยอัตโนมัติและลิงก์จะถูกสร้างขึ้น + +--- + +### ปิดการใช้งาน + +คุณสามารถปิดการแชร์ทั้งหมดได้โดยตั้งค่าตัวเลือก `share` เป็น `"disabled"` ใน [ไฟล์กำหนดค่า](/docs/config): + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +หากต้องการบังคับใช้สิ่งนี้กับทีมของคุณสำหรับโปรเจ็กต์ที่กำหนด ให้เพิ่มลงใน `opencode.json` ในโปรเจ็กต์ของคุณและตรวจสอบใน Git + +--- + +## ยกเลิกการแชร์ + +หากต้องการหยุดแชร์การสนทนาและลบออกจากการเข้าถึงแบบสาธารณะ: + +``` +/unshare +``` + +การดำเนินการนี้จะลบลิงก์แชร์และลบข้อมูลที่เกี่ยวข้องกับการสนทนา + +--- + +## ความเป็นส่วนตัว + +มีบางสิ่งที่ต้องคำนึงถึงเมื่อแบ่งปันการสนทนา + +--- + +### การเก็บรักษาข้อมูล + +การสนทนาที่แชร์จะยังสามารถเข้าถึงได้จนกว่าคุณจะยกเลิกการแชร์อย่างชัดเจน นี้ +รวมถึง: + +- ประวัติการสนทนาแบบเต็ม +- ทุกข้อความและการตอบกลับ +- ข้อมูลเมตาของเซสชัน + +--- + +### ข้อแนะนำ + +- แชร์การสนทนาที่ไม่มีข้อมูลที่ละเอียดอ่อนเท่านั้น +- ตรวจสอบเนื้อหาการสนทนาก่อนที่จะแบ่งปัน +- ยกเลิกการแชร์การสนทนาเมื่อการทำงานร่วมกันเสร็จสมบูรณ์ +- หลีกเลี่ยงการแบ่งปันการสนทนาด้วยรหัสที่เป็นกรรมสิทธิ์หรือข้อมูลที่เป็นความลับ +- สำหรับโปรเจ็กต์ที่มีความละเอียดอ่อน ให้ปิดการแชร์ทั้งหมด + +--- + +## สำหรับสถานประกอบการ + +สำหรับการปรับใช้ระดับองค์กร คุณสมบัติการแชร์อาจเป็น: + +- **ปิดการใช้งาน** ทั้งหมดเพื่อความปลอดภัย +- **จำกัด** สำหรับผู้ใช้ที่ผ่านการรับรองความถูกต้องผ่าน SSO เท่านั้น +- **โฮสต์เอง** บนโครงสร้างพื้นฐานของคุณเอง + +[เรียนรู้เพิ่มเติม](/docs/enterprise) เกี่ยวกับการใช้ opencode ในองค์กรของคุณ diff --git a/packages/web/src/content/docs/th/skills.mdx b/packages/web/src/content/docs/th/skills.mdx new file mode 100644 index 00000000000..d3658e66c35 --- /dev/null +++ b/packages/web/src/content/docs/th/skills.mdx @@ -0,0 +1,222 @@ +--- +title: ทักษะของเอเจนต์ +description: "กำหนดพฤติกรรมที่นำมาใช้ซ้ำได้ผ่านคำจำกัดความ SKILL.md" +--- + +ทักษะของเจ้าหน้าที่ช่วยให้ OpenCode ค้นพบคำแนะนำที่ใช้ซ้ำได้จาก repo หรือโฮมไดเร็กทอรีของคุณ +ทักษะจะถูกโหลดตามความต้องการผ่านเครื่องมือ `skill` ดั้งเดิม ตัวแทนจะเห็นทักษะที่มีอยู่และสามารถโหลดเนื้อหาทั้งหมดได้เมื่อจำเป็น + +--- + +## วางไฟล์ + +สร้างหนึ่งโฟลเดอร์ต่อชื่อทักษะ และใส่ `SKILL.md` ไว้ข้างใน +OpenCode ค้นหาตำแหน่งเหล่านี้: + +- การกำหนดค่าโครงการ: `.opencode/skills//SKILL.md` +- การกำหนดค่าส่วนกลาง: `~/.config/opencode/skills//SKILL.md` +- เข้ากันได้กับโครงการ Claude: `.claude/skills//SKILL.md` +- เข้ากันได้กับ Global Claude: `~/.claude/skills//SKILL.md` +- เข้ากันได้กับตัวแทนโครงการ: `.agents/skills//SKILL.md` +- รองรับตัวแทนทั่วโลก: `~/.agents/skills//SKILL.md` + +--- + +## ทำความเข้าใจกับการค้นพบ + +สำหรับเส้นทางภายในโปรเจ็กต์ OpenCode จะเดินขึ้นมาจากไดเร็กทอรีการทำงานปัจจุบันของคุณจนกว่าจะถึงแผนผังงาน git +โดยจะโหลด `skills/*/SKILL.md` ที่ตรงกันใน `.opencode/` และ `.claude/skills/*/SKILL.md` หรือ `.agents/skills/*/SKILL.md` ที่ตรงกันตลอดทาง + +คำจำกัดความสากลยังโหลดจาก `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md` และ `~/.agents/skills/*/SKILL.md` + +--- + +## เขียน frontmatter + +`SKILL.md` แต่ละอันต้องขึ้นต้นด้วย YAML frontmatter +เฉพาะฟิลด์เหล่านี้เท่านั้นที่ได้รับการยอมรับ: + +- `name` (จำเป็น) +- `description` (จำเป็น) +- `license` (ไม่บังคับ) +- `compatibility` (ไม่บังคับ) +- `metadata` (ตัวเลือก แมปแบบสตริงต่อสตริง) + +ช่อง frontmatter ที่ไม่รู้จักจะถูกละเว้น + +--- + +## ตรวจสอบชื่อ + +`name` ต้อง: + +- มีความยาว 1–64 อักขระ +- เป็นตัวพิมพ์เล็กและตัวเลขคละกันที่มีเครื่องหมายยัติภังค์ตัวคั่นเดียว +- ไม่ขึ้นต้นหรือลงท้ายด้วย `-` +- ไม่มี `--` ติดต่อกัน +- จับคู่ชื่อไดเร็กทอรีที่มี `SKILL.md` + +regex ที่เทียบเท่า: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## ปฏิบัติตามกฎความยาว + +`description` ต้องมีความยาว 1-1,024 ตัวอักษร +เจาะจงให้ตัวแทนเลือกได้ถูกต้อง + +--- + +## ใช้ตัวอย่าง + +สร้าง `.opencode/skills/git-release/SKILL.md` แบบนี้: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## การค้นพบคำอธิบายเครื่องมือ + +OpenCode แสดงรายการทักษะที่มีอยู่ในคำอธิบายเครื่องมือ `skill` +แต่ละรายการจะมีชื่อทักษะและคำอธิบาย: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +ตัวแทนโหลดทักษะโดยการเรียกเครื่องมือ: + +``` +skill({ name: "git-release" }) +``` + +--- + +## กำหนดค่าสิทธิ์ + +ควบคุมว่าตัวแทนทักษะใดสามารถเข้าถึงโดยใช้สิทธิ์ตามรูปแบบใน `opencode.json`: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| การอนุญาต | พฤติกรรม | +| --------- | -------------------------------------------- | +| `allow` | โหลดทักษะทันที | +| `deny` | ทักษะถูกซ่อนไม่ให้ตัวแทน การเข้าถึงถูกปฏิเสธ | +| `ask` | ผู้ใช้ได้รับแจ้งให้อนุมัติก่อนที่จะโหลด | + +รูปแบบที่รองรับไวด์การ์ด: `internal-*` ตรงกับ `internal-docs`, `internal-tools` ฯลฯ + +--- + +## แทนที่ต่อเอเจนต์ + +ให้สิทธิ์แก่ตัวแทนเฉพาะเจาะจงที่แตกต่างจากค่าเริ่มต้นทั่วไป + +**สำหรับตัวแทนแบบกำหนดเอง** (ในตัวแทนส่วนหน้า): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**สำหรับตัวแทนในตัว** (ใน `opencode.json`): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## ปิดการใช้งานเครื่องมือทักษะ + +ปิดการใช้งานทักษะโดยสิ้นเชิงสำหรับตัวแทนที่ไม่ควรใช้: + +**สำหรับตัวแทนแบบกำหนดเอง**: + +```yaml +--- +tools: + skill: false +--- +``` + +**สำหรับตัวแทนในตัว**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +เมื่อปิดใช้งาน ส่วน `` จะถูกละเว้นทั้งหมด + +--- + +## แก้ไขปัญหาการโหลด + +หากทักษะไม่แสดง: + +1. ตรวจสอบว่า `SKILL.md` สะกดด้วยตัวพิมพ์ใหญ่ทั้งหมด +2. ตรวจสอบว่าส่วนหน้าประกอบด้วย `name` และ `description` +3. ตรวจสอบให้แน่ใจว่าชื่อทักษะไม่ซ้ำกันในทุกสถานที่ +4. ตรวจสอบการอนุญาต ทักษะที่มี `deny` ถูกซ่อนไม่ให้ตัวแทนเห็น diff --git a/packages/web/src/content/docs/th/themes.mdx b/packages/web/src/content/docs/th/themes.mdx new file mode 100644 index 00000000000..2244c3dcf1b --- /dev/null +++ b/packages/web/src/content/docs/th/themes.mdx @@ -0,0 +1,369 @@ +--- +title: ธีมส์ +description: เลือกธีมในตัวหรือกำหนดธีมของคุณเอง +--- + +ด้วย OpenCode คุณสามารถเลือกจากหนึ่งในธีมที่มีอยู่แล้วภายใน ใช้ธีมที่ปรับให้เข้ากับธีม terminal ของคุณ หรือกำหนดธีมที่คุณกำหนดเองได้ + +ตามค่าเริ่มต้น OpenCode จะใช้ธีม `opencode` ของเราเอง + +--- + +## ข้อกำหนดของ terminal + +เพื่อให้ธีมแสดงได้อย่างถูกต้องด้วยชุดสีทั้งหมด terminal ของคุณต้องรองรับ **truecolor** (สี 24 บิต) terminal สมัยใหม่ส่วนใหญ่จะรองรับสิ่งนี้ตามค่าเริ่มต้น แต่คุณอาจต้องเปิดใช้งาน: + +- **ตรวจสอบการสนับสนุน**: เรียกใช้ `echo $COLORTERM` - ​​ควรส่งออก `truecolor` หรือ `24bit` +- **เปิดใช้งานสีจริง**: ตั้งค่าตัวแปรสภาพแวดล้อม `COLORTERM=truecolor` ในโปรไฟล์ shell ของคุณ +- **ความเข้ากันได้ของ terminal**: ตรวจสอบให้แน่ใจว่าโปรแกรมจำลอง terminal ของคุณรองรับสี 24 บิต (terminal ที่ทันสมัยที่สุด เช่น iTerm2, Alacritty, Kitty, Windows Terminal และ GNOME Terminal do เวอร์ชันล่าสุด) + +หากไม่รองรับสีจริง ธีมอาจปรากฏขึ้นโดยมีความแม่นยำของสีลดลงหรือกลับไปใช้การประมาณสี 256 สีที่ใกล้ที่สุด + +--- + +## ธีมในตัว + +OpenCode มาพร้อมกับธีมในตัวหลายธีม + +| ชื่อ | คำอธิบาย | +| ---------------------- | ------------------------------------------------------------------- | +| `system` | ปรับให้เข้ากับสีพื้นหลังของ terminal ของคุณ | +| `tokyonight` | อิงตามธีมของ [Tokyonight](https://github.com/folke/tokyonight.nvim) | +| `everforest` | อิงตามธีม [Everforest](https://github.com/sainnhe/everforest) | +| `ayu` | อิงตามธีมสีเข้มของ [Ayu](https://github.com/ayu-theme) | +| `catppuccin` | อิงตามธีม [Catppuccin](https://github.com/catppuccin) | +| `catppuccin-macchiato` | อิงตามธีม [Catppuccin](https://github.com/catppuccin) | +| `gruvbox` | อิงตามธีม [Gruvbox](https://github.com/morhetz/gruvbox) | +| `kanagawa` | อิงตามธีมของ [Kanagawa](https://github.com/rebelot/kanagawa.nvim) | +| `nord` | อิงตามธีม [Nord](https://github.com/nordtheme/nord) | +| `matrix` | ธีมสีเขียวสไตล์แฮ็กเกอร์บนสีดำ | +| `one-dark` | อิงตามธีม [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark | + +และยิ่งไปกว่านั้น เรายังเพิ่มธีมใหม่ๆ อย่างต่อเนื่อง + +--- + +## ธีมของระบบ + +ธีม `system` ได้รับการออกแบบให้ปรับให้เข้ากับโทนสีของเครื่อง terminal ของคุณโดยอัตโนมัติ ไม่เหมือนกับธีมดั้งเดิมที่ใช้สีคงที่ ธีม _system_: + +- **สร้างระดับสีเทา**: สร้างระดับสีเทาแบบกำหนดเองตามสีพื้นหลังของ terminal ของคุณ เพื่อให้มั่นใจว่ามีคอนทราสต์ที่เหมาะสมที่สุด +- **ใช้สี ANSI**: ใช้ประโยชน์จากสี ANSI มาตรฐาน (0-15) สำหรับการเน้นไวยากรณ์และองค์ประกอบ UI ซึ่งเคารพชุดสีของ terminal ของคุณ +- **รักษาค่าเริ่มต้นของ terminal**: ใช้ `none` สำหรับสีข้อความและพื้นหลัง เพื่อรักษารูปลักษณ์ดั้งเดิมของ terminal ของคุณ + +ธีมของระบบมีไว้สำหรับผู้ใช้ที่: + +- ต้องการให้ OpenCode ตรงกับรูปลักษณ์ของ terminal +- ใช้โครงร่างสี terminal แบบกำหนดเอง +- ต้องการรูปลักษณ์ที่สอดคล้องกันในแอปพลิเคชัน terminal ทั้งหมด + +--- + +## การใช้ธีม + +คุณสามารถเลือกธีมได้โดยเปิดการเลือกธีมขึ้นมาด้วยคำสั่ง `/theme` หรือคุณสามารถระบุได้ใน [config](/docs/config) + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## ธีมที่กำหนดเอง + +OpenCode รองรับระบบธีมที่ใช้ JSON ที่ยืดหยุ่น ซึ่งช่วยให้ผู้ใช้สามารถสร้างและปรับแต่งธีมได้อย่างง่ายดาย + +--- + +### ลำดับชั้น + +ธีมจะถูกโหลดจากหลายไดเร็กทอรีตามลำดับต่อไปนี้ โดยไดเร็กทอรีรุ่นหลังจะแทนที่ไดเร็กทอรีก่อนหน้า: + +1. **ธีมในตัว** - ธีมเหล่านี้ฝังอยู่ในไบนารี +2. **ไดเรกทอรีกำหนดค่าผู้ใช้** - กำหนดใน `~/.config/opencode/themes/*.json` หรือ `$XDG_CONFIG_HOME/opencode/themes/*.json` +3. **ไดเรกทอรีรากของโครงการ** - กำหนดไว้ใน `/.opencode/themes/*.json` +4. **ไดเร็กทอรีการทำงานปัจจุบัน** - กำหนดใน `./.opencode/themes/*.json` + +หากหลายไดเร็กทอรีมีธีมที่มีชื่อเดียวกัน ธีมจากไดเร็กทอรีที่มีลำดับความสำคัญสูงกว่าจะถูกนำมาใช้ + +--- + +### การสร้างธีม + +หากต้องการสร้างธีมที่กำหนดเอง ให้สร้างไฟล์ JSON ในไดเร็กทอรีธีมรายการใดรายการหนึ่ง + +สำหรับธีมทั้งผู้ใช้: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +และสำหรับธีมเฉพาะโครงการ + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### JSON รูปแบบ + +ธีมใช้รูปแบบ JSON ที่ยืดหยุ่นพร้อมรองรับ: + +- **สีฐานสิบหก**: `"#ffffff"` +- **ANSI สี**: `3` (0-255) +- **การอ้างอิงสี**: `"primary"` หรือคำจำกัดความที่กำหนดเอง +- **Dark/light ตัวแปร**: `{"dark": "#000", "light": "#fff"}` +- **ไม่มีสี**: `"none"` - ​​ใช้สีเริ่มต้นของ terminal หรือโปร่งใส + +--- + +### คำจำกัดความของสี + +ส่วน `defs` เป็นทางเลือก และอนุญาตให้คุณกำหนดสีที่ใช้ซ้ำได้ซึ่งสามารถอ้างอิงในธีมได้ + +--- + +### ค่าเริ่มต้นของ terminal + +ค่าพิเศษ `"none"` สามารถใช้กับสีใดก็ได้เพื่อสืบทอดสีเริ่มต้นของ terminal สิ่งนี้มีประโยชน์อย่างยิ่งสำหรับการสร้างธีมที่ผสมผสานอย่างลงตัวกับโทนสีของ terminal ของคุณ: + +- `"text": "none"` - ​​ใช้สีพื้นหน้าเริ่มต้นของ terminal +- `"background": "none"` - ​​ใช้สีพื้นหลังเริ่มต้นของ terminal + +--- + +### ตัวอย่าง + +นี่คือตัวอย่างของธีมที่กำหนดเอง: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/th/tools.mdx b/packages/web/src/content/docs/th/tools.mdx new file mode 100644 index 00000000000..6db4cfc2a71 --- /dev/null +++ b/packages/web/src/content/docs/th/tools.mdx @@ -0,0 +1,379 @@ +--- +title: เครื่องมือ +description: จัดการเครื่องมือที่ LLM สามารถใช้ได้ +--- + +เครื่องมืออนุญาตให้ LLM ดำเนินการในโค้ดเบสของคุณ OpenCode มาพร้อมกับชุดเครื่องมือในตัว แต่คุณสามารถขยายได้ด้วย [เครื่องมือที่กำหนดเอง](/docs/custom-tools) หรือ [MCP เซิร์ฟเวอร์](/docs/mcp-servers) + +ตามค่าเริ่มต้น เครื่องมือทั้งหมด **เปิดใช้งาน** และไม่จำเป็นต้องมีสิทธิ์ในการทำงาน คุณสามารถควบคุมการทำงานของเครื่องมือผ่าน [สิทธิ์](/docs/permissions) + +--- + +## กำหนดค่า + +ใช้ฟิลด์ `permission` เพื่อควบคุมการทำงานของเครื่องมือ คุณสามารถอนุญาต ปฏิเสธ หรือต้องการการอนุมัติสำหรับเครื่องมือแต่ละรายการได้ + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +คุณยังสามารถใช้ไวด์การ์ดเพื่อควบคุมเครื่องมือหลายรายการพร้อมกันได้ ตัวอย่างเช่น หากต้องการขออนุมัติเครื่องมือทั้งหมดจากเซิร์ฟเวอร์ MCP: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[เรียนรู้เพิ่มเติม](/docs/permissions) เกี่ยวกับการกำหนดค่าสิทธิ์ + +--- + +## บิวท์อิน + +นี่คือเครื่องมือในตัวทั้งหมดที่มีอยู่ใน OpenCode + +--- + +### bash + +ดำเนินการคำสั่ง shell ในสภาพแวดล้อมโปรเจ็กต์ของคุณ + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +เครื่องมือนี้อนุญาตให้ LLM รันคำสั่ง terminal เช่น `npm install`, `git status` หรือคำสั่ง shell อื่น ๆ + +--- + +### edit + +แก้ไขไฟล์ที่มีอยู่โดยใช้การแทนที่สตริงที่แน่นอน + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +เครื่องมือนี้ทำการแก้ไขไฟล์อย่างแม่นยำโดยแทนที่ข้อความที่ตรงกันทุกประการ มันเป็นวิธีหลักที่ LLM แก้ไขโค้ด + +--- + +### write + +สร้างไฟล์ใหม่หรือเขียนทับไฟล์ที่มีอยู่ + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +ใช้สิ่งนี้เพื่ออนุญาตให้ LLM สร้างไฟล์ใหม่ มันจะเขียนทับไฟล์ที่มีอยู่หากมีอยู่แล้ว + +:::note +เครื่องมือ `write` ถูกควบคุมโดยสิทธิ์ `edit` ซึ่งครอบคลุมการแก้ไขไฟล์ทั้งหมด (`edit`, `write`, `patch`, `multiedit`) +::: + +--- + +### read + +อ่านเนื้อหาไฟล์จากโค้ดเบสของคุณ + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +เครื่องมือนี้จะอ่านไฟล์และส่งกลับเนื้อหา รองรับการอ่านช่วงบรรทัดเฉพาะสำหรับไฟล์ขนาดใหญ่ + +--- + +### grep + +ค้นหาเนื้อหาไฟล์โดยใช้นิพจน์ทั่วไป + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +ค้นหาเนื้อหาอย่างรวดเร็วทั่วทั้งโค้ดเบสของคุณ รองรับไวยากรณ์ regex เต็มรูปแบบและการกรองรูปแบบไฟล์ + +--- + +### glob + +ค้นหาไฟล์ตามรูปแบบการจับคู่ + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +ค้นหาไฟล์โดยใช้รูปแบบ glob เช่น `**/*.js` หรือ `src/**/*.ts` ส่งคืนเส้นทางไฟล์ที่ตรงกันโดยจัดเรียงตามเวลาแก้ไข + +--- + +### list + +แสดงรายการไฟล์และไดเร็กทอรีในพาธที่กำหนด + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +เครื่องมือนี้แสดงรายการเนื้อหาไดเร็กทอรี ยอมรับรูปแบบ glob เพื่อกรองผลลัพธ์ + +--- + +### lsp (ขั้นทดลอง) + +โต้ตอบกับเซิร์ฟเวอร์ LSP ที่กำหนดค่าของคุณเพื่อรับฟีเจอร์อัจฉริยะด้านโค้ด เช่น คำจำกัดความ การอ้างอิง ข้อมูลโฮเวอร์ และลำดับชั้นการโทร + +:::note +เครื่องมือนี้ใช้ได้เฉพาะเมื่อ `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (หรือ `OPENCODE_EXPERIMENTAL=true`) +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +การดำเนินการที่รองรับ ได้แก่ `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls` และ `outgoingCalls` + +หากต้องการกำหนดค่าเซิร์ฟเวอร์ LSP ที่พร้อมใช้งานสำหรับโครงการของคุณ โปรดดู [LSP เซิร์ฟเวอร์](/docs/lsp) + +--- + +### patch + +ใช้แพทช์กับไฟล์ + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +เครื่องมือนี้ใช้ไฟล์แพทช์กับโค้ดเบสของคุณ มีประโยชน์สำหรับการใช้ความแตกต่างและแพตช์จากแหล่งต่างๆ + +:::note +เครื่องมือ `patch` ถูกควบคุมโดยสิทธิ์ `edit` ซึ่งครอบคลุมการแก้ไขไฟล์ทั้งหมด (`edit`, `write`, `patch`, `multiedit`) +::: + +--- + +### skill + +โหลด [ทักษะ](/docs/skills) (ไฟล์ `SKILL.md`) และส่งคืนเนื้อหาในการสนทนา + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +จัดการรายการสิ่งที่ต้องทำระหว่างเซสชันการเขียนโค้ด + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +สร้างและอัปเดตรายการงานเพื่อติดตามความคืบหน้าระหว่างการดำเนินการที่ซับซ้อน LLM ใช้สิ่งนี้เพื่อจัดระเบียบงานที่มีหลายขั้นตอน + +:::note +เครื่องมือนี้ปิดใช้งานสำหรับตัวแทนย่อยตามค่าเริ่มต้น แต่คุณสามารถเปิดใช้งานได้ด้วยตนเอง [เรียนรู้เพิ่มเติม](/docs/agents/#สิทธิ์) +::: + +--- + +### todoread + +อ่านรายการสิ่งที่ต้องทำที่มีอยู่ + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +อ่านสถานะรายการสิ่งที่ต้องทำปัจจุบัน ใช้โดย LLM เพื่อติดตามงานที่กำลังรอดำเนินการหรือเสร็จสิ้น + +:::note +เครื่องมือนี้ปิดใช้งานสำหรับตัวแทนย่อยตามค่าเริ่มต้น แต่คุณสามารถเปิดใช้งานได้ด้วยตนเอง [เรียนรู้เพิ่มเติม](/docs/agents/#สิทธิ์) +::: + +--- + +### webfetch + +ดึงเนื้อหาเว็บ + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +อนุญาตให้ LLM ดึงข้อมูลและอ่านหน้าเว็บ มีประโยชน์สำหรับการค้นหาเอกสารหรือค้นคว้าแหล่งข้อมูลออนไลน์ + +--- + +### websearch + +ค้นหาข้อมูลในเว็บ + +:::note +เครื่องมือนี้ใช้ได้เฉพาะเมื่อใช้ผู้ให้บริการ OpenCode หรือเมื่อตัวแปรสภาพแวดล้อม `OPENCODE_ENABLE_EXA` ถูกตั้งค่าเป็นค่าความจริง (เช่น `true` หรือ `1`) + +หากต้องการเปิดใช้งานเมื่อเปิดตัว OpenCode: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +ทำการค้นหาเว็บโดยใช้ Exa AI เพื่อค้นหาข้อมูลที่เกี่ยวข้องทางออนไลน์ มีประโยชน์สำหรับการค้นคว้าหัวข้อ ค้นหาเหตุการณ์ปัจจุบัน หรือการรวบรวมข้อมูลนอกเหนือจากการตัดข้อมูลการฝึกอบรม + +ไม่จำเป็นต้องใช้คีย์ API เครื่องมือนี้เชื่อมต่อโดยตรงกับบริการ MCP ที่โฮสต์ของ Exa AI โดยไม่มีการตรวจสอบสิทธิ์ + +:::tip +ใช้ `websearch` เมื่อคุณต้องการค้นหาข้อมูล (การค้นพบ) และใช้ `webfetch` เมื่อคุณต้องการดึงเนื้อหาจาก URL เฉพาะ (การดึงข้อมูล) +::: + +--- + +### question + +ถามคำถามผู้ใช้ระหว่างการดำเนินการ + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +เครื่องมือนี้อนุญาตให้ LLM ถามคำถามผู้ใช้ระหว่างทำงาน มันมีประโยชน์สำหรับ: + +- การรวบรวมความชอบหรือความต้องการของผู้ใช้ +- ชี้แจงคำแนะนำที่ไม่ชัดเจน +- การตัดสินใจเกี่ยวกับทางเลือกในการดำเนินการ +- เสนอทางเลือกว่าจะไปในทิศทางใด + +คำถามแต่ละข้อประกอบด้วยส่วนหัว ข้อความคำถาม และรายการตัวเลือก ผู้ใช้สามารถเลือกจากตัวเลือกที่มีให้หรือพิมพ์คำตอบที่กำหนดเองได้ เมื่อมีคำถามหลายข้อ ผู้ใช้สามารถสลับไปมาระหว่างคำถามเหล่านั้นก่อนที่จะส่งคำตอบทั้งหมด + +--- + +## เครื่องมือที่กำหนดเอง + +เครื่องมือแบบกำหนดเองช่วยให้คุณสามารถกำหนดฟังก์ชันของคุณเองที่ LLM สามารถเรียกได้ สิ่งเหล่านี้ถูกกำหนดไว้ในไฟล์ปรับแต่งของคุณและสามารถรันโค้ดได้ตามใจชอบ + +[เรียนรู้เพิ่มเติม](/docs/custom-tools) เกี่ยวกับการสร้างเครื่องมือที่กำหนดเอง + +--- + +## MCP เซิร์ฟเวอร์ + +เซิร์ฟเวอร์ MCP (Model Context Protocol) ช่วยให้คุณสามารถรวมเครื่องมือและบริการภายนอกได้ ซึ่งรวมถึงการเข้าถึงฐานข้อมูล การบูรณาการ API และบริการของบุคคลที่สาม + +[เรียนรู้เพิ่มเติม](/docs/mcp-servers) เกี่ยวกับการกำหนดค่าเซิร์ฟเวอร์ MCP + +--- + +## ภายใน + +ภายใน เครื่องมือต่างๆ เช่น `grep`, `glob` และ `list` ใช้ [ripgrep](https://github.com/BurntSushi/ripgrep) ภายใต้ประทุน ตามค่าเริ่มต้น ripgrep เคารพรูปแบบ `.gitignore` ซึ่งหมายความว่าไฟล์และไดเร็กทอรีที่อยู่ใน `.gitignore` ของคุณจะถูกแยกออกจากการค้นหาและรายการ + +--- + +### ละเว้นรูปแบบ + +หากต้องการรวมไฟล์ที่ปกติจะถูกละเว้น ให้สร้างไฟล์ `.ignore` ในรูทโปรเจ็กต์ของคุณ ไฟล์นี้สามารถอนุญาตเส้นทางบางอย่างได้อย่างชัดเจน + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +ตัวอย่างเช่น ไฟล์ `.ignore` นี้อนุญาตให้ ripgrep ค้นหาภายในไดเร็กทอรี `node_modules/`, `dist/` และ `build/` แม้ว่าไดเร็กทอรีเหล่านั้นจะแสดงอยู่ใน `.gitignore` ก็ตาม diff --git a/packages/web/src/content/docs/th/troubleshooting.mdx b/packages/web/src/content/docs/th/troubleshooting.mdx new file mode 100644 index 00000000000..cd50c13797f --- /dev/null +++ b/packages/web/src/content/docs/th/troubleshooting.mdx @@ -0,0 +1,300 @@ +--- +title: การแก้ไขปัญหา +description: ปัญหาทั่วไปและวิธีแก้ปัญหา +--- + +หากต้องการแก้ไขข้อบกพร่องเกี่ยวกับ OpenCode ให้เริ่มต้นด้วยการตรวจสอบบันทึกและข้อมูลในเครื่องที่จัดเก็บไว้ในดิสก์ + +--- + +## บันทึก + +ไฟล์บันทึกถูกเขียนไปที่: + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: กด `WIN+R` แล้ววาง `%USERPROFILE%\.local\share\opencode\log` + +ไฟล์บันทึกจะถูกตั้งชื่อด้วยการประทับเวลา (เช่น `2025-01-09T123456.log`) และไฟล์บันทึกล่าสุด 10 ไฟล์จะถูกเก็บไว้ + +คุณสามารถตั้งค่าระดับการบันทึกด้วยตัวเลือกบรรทัดคำสั่ง `--log-level` เพื่อรับข้อมูลการแก้ไขข้อบกพร่องโดยละเอียดเพิ่มเติม ตัวอย่างเช่น `opencode --log-level DEBUG` + +--- + +## พื้นที่จัดเก็บ + +opencode เก็บข้อมูลเซสชันและข้อมูลแอปพลิเคชันอื่น ๆ ไว้บนดิสก์ที่: + +- **macOS/Linux**: `~/.local/share/opencode/` +- **Windows**: กด `WIN+R` แล้ววาง `%USERPROFILE%\.local\share\opencode` + +ไดเรกทอรีนี้ประกอบด้วย: + +- `auth.json` - ​​ข้อมูลการตรวจสอบสิทธิ์ เช่น คีย์ API, OAuth Token +- `log/` - ​​บันทึกแอปพลิเคชัน +- `project/` - ​​ข้อมูลเฉพาะโครงการ เช่น ข้อมูลเซสชันและข้อความ + - หากโปรเจ็กต์อยู่ภายใน repo Git มันจะถูกจัดเก็บไว้ใน `.//storage/` + - หากไม่ใช่ repo Git มันจะถูกเก็บไว้ใน `./global/storage/` + +--- + +## แอปเดสก์ท็อป + +OpenCode Desktop รันเซิร์ฟเวอร์ OpenCode ในเครื่อง (ไฟล์ `opencode-cli` sidecar) ในเบื้องหลัง ปัญหาส่วนใหญ่มีสาเหตุมาจากปลั๊กอินที่ทำงานผิดปกติ แคชเสียหาย หรือการตั้งค่าเซิร์ฟเวอร์ไม่ถูกต้อง + +### การตรวจสอบอย่างรวดเร็ว + +- ออกจากระบบโดยสมบูรณ์แล้วเปิดแอปใหม่อีกครั้ง +- หากแอปแสดงหน้าจอข้อผิดพลาด ให้คลิก **รีสตาร์ท** และคัดลอกรายละเอียดข้อผิดพลาด +- macOS เท่านั้น: เมนู `OpenCode` -> **โหลด Webview ใหม่** (ช่วยได้หาก UI ว่างเปล่า/frozen) + +--- + +### ปิดการใช้งานปลั๊กอิน + +หากแอปเดสก์ท็อปขัดข้องเมื่อเปิดใช้งาน หยุดทำงาน หรือทำงานผิดปกติ ให้เริ่มต้นด้วยการปิดใช้งานปลั๊กอิน + +#### ตรวจสอบการกำหนดค่าส่วนกลาง + +เปิดไฟล์กำหนดค่าส่วนกลางของคุณแล้วมองหาคีย์ `plugin` + +- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (หรือ `~/.config/opencode/opencode.json`) +- **macOS/Linux** (การติดตั้งเก่ากว่า): `~/.local/share/opencode/opencode.jsonc` +- **Windows**: กด `WIN+R` แล้ววาง `%USERPROFILE%\.config\opencode\opencode.jsonc` + +หากคุณได้กำหนดค่าปลั๊กอินไว้ ให้ปิดการใช้งานชั่วคราวโดยลบคีย์ออกหรือตั้งค่าเป็นอาร์เรย์ว่าง: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### ตรวจสอบไดเร็กทอรีปลั๊กอิน + +OpenCode ยังสามารถโหลดปลั๊กอินในเครื่องจากดิสก์ได้ ย้ายสิ่งเหล่านี้ออกไปชั่วคราว (หรือเปลี่ยนชื่อโฟลเดอร์) และรีสตาร์ทแอปเดสก์ท็อป: + +- **ปลั๊กอินสากล** + - **macOS/Linux**: `~/.config/opencode/plugins/` + - **Windows**: กด `WIN+R` แล้ววาง `%USERPROFILE%\.config\opencode\plugins` +- **ปลั๊กอินโครงการ** (เฉพาะในกรณีที่คุณใช้การกำหนดค่าต่อโครงการ) + - `/.opencode/plugins/` + +หากแอปเริ่มทำงานอีกครั้ง ให้เปิดใช้งานปลั๊กอินอีกครั้งทีละรายการเพื่อดูว่าปลั๊กอินใดเป็นสาเหตุของปัญหา + +--- + +### ล้างแคช + +หากการปิดใช้งานปลั๊กอินไม่ได้ผล (หรือการติดตั้งปลั๊กอินค้าง) ให้ล้างแคชเพื่อให้ OpenCode สามารถสร้างใหม่ได้ + +1. ออกจาก OpenCode Desktop โดยสมบูรณ์ +2. ลบไดเรกทอรีแคช: + +- **macOS**: ตัวค้นหา -> `Cmd+Shift+G` -> วาง `~/.cache/opencode` +- **Linux**: ลบ `~/.cache/opencode` (หรือรัน `rm -rf ~/.cache/opencode`) +- **Windows**: กด `WIN+R` แล้ววาง `%USERPROFILE%\.cache\opencode` + +3. รีสตาร์ทเดสก์ท็อป OpenCode + +--- + +### แก้ไขปัญหาการเชื่อมต่อเซิร์ฟเวอร์ + +OpenCode Desktop สามารถเริ่มต้นเซิร์ฟเวอร์ภายในเครื่องของตนเองได้ (ค่าเริ่มต้น) หรือเชื่อมต่อกับเซิร์ฟเวอร์ URL ที่คุณกำหนดค่าไว้ + +หากคุณเห็นกล่องโต้ตอบ **"การเชื่อมต่อล้มเหลว"** (หรือแอปไม่เคยผ่านหน้าจอเริ่มต้น) ให้ตรวจสอบเซิร์ฟเวอร์ที่กำหนดเอง URL + +#### ล้างเซิร์ฟเวอร์เริ่มต้นของเดสก์ท็อป URL + +จากหน้าจอหลัก คลิกชื่อเซิร์ฟเวอร์ (ที่มีจุดสถานะ) เพื่อเปิดตัวเลือกเซิร์ฟเวอร์ ในส่วน **เซิร์ฟเวอร์เริ่มต้น** คลิก **ล้าง** + +#### ลบ `server.port` / `server.hostname` ออกจากการกำหนดค่าของคุณ + +หาก `opencode.json(c)` ของคุณมีส่วน `server` ให้ลบออกชั่วคราวแล้วรีสตาร์ทแอปเดสก์ท็อป + +#### ตรวจสอบตัวแปรสภาพแวดล้อม + +หากคุณตั้งค่า `OPENCODE_PORT` ในสภาพแวดล้อมของคุณ แอปเดสก์ท็อปจะพยายามใช้พอร์ตนั้นสำหรับเซิร์ฟเวอร์ภายในเครื่อง + +- ยกเลิกการตั้งค่า `OPENCODE_PORT` (หรือเลือกพอร์ตว่าง) แล้วรีสตาร์ท + +--- + +### Linux: ปัญหา Wayland / X11 + +บน Linux การตั้งค่า Wayland บางอย่างอาจทำให้เกิดหน้าต่างว่างหรือข้อผิดพลาดของตัวประกอบ + +- หากคุณอยู่บน Wayland และแอปว่างเปล่า/crashing ให้ลองเปิดใช้งานด้วย `OC_ALLOW_WAYLAND=1` +- หากสิ่งนั้นทำให้สิ่งต่าง ๆ แย่ลง ให้ลบออกแล้วลองเปิดใช้งานภายใต้เซสชัน X11 แทน + +--- + +### Windows: รันไทม์ WebView2 + +บน Windows OpenCode Desktop ต้องใช้ Microsoft Edge **WebView2 Runtime** หากแอปเปิดเป็นหน้าต่างว่างหรือไม่เริ่มทำงาน ให้ติดตั้ง/update WebView2 แล้วลองอีกครั้ง + +--- + +### Windows: ปัญหาด้านประสิทธิภาพทั่วไป + +หากคุณประสบปัญหาประสิทธิภาพการทำงานช้า ปัญหาการเข้าถึงไฟล์ หรือปัญหา terminal บน Windows ให้ลองใช้ [WSL (ระบบย่อย Windows สำหรับ Linux)](/docs/windows-wsl) WSL มอบสภาพแวดล้อม Linux ที่ทำงานร่วมกับคุณสมบัติของ OpenCode ได้อย่างราบรื่นยิ่งขึ้น + +--- + +### การแจ้งเตือนไม่แสดง + +OpenCode Desktop จะแสดงการแจ้งเตือนของระบบเฉพาะเมื่อ: + +- การแจ้งเตือนเปิดใช้งานสำหรับ OpenCode ในการตั้งค่าระบบปฏิบัติการของคุณและ +- หน้าต่างแอพไม่ได้โฟกัส + +--- + +### รีเซ็ตที่เก็บข้อมูลแอปเดสก์ท็อป (วิธีสุดท้าย) + +หากแอปไม่เริ่มทำงานและคุณไม่สามารถล้างการตั้งค่าจากภายใน UI ได้ ให้รีเซ็ตสถานะที่บันทึกไว้ของแอปเดสก์ท็อป + +1. ออกจากเดสก์ท็อป OpenCode +2. ค้นหาและลบไฟล์เหล่านี้ (อยู่ในไดเร็กทอรีข้อมูลแอป OpenCode Desktop): + +- `opencode.settings.dat` (เซิร์ฟเวอร์เริ่มต้นของเดสก์ท็อป URL) +- `opencode.global.dat` และ `opencode.workspace.*.dat` (สถานะ UI เช่น เซิร์ฟเวอร์ล่าสุด/projects) + +หากต้องการค้นหาไดเร็กทอรีอย่างรวดเร็ว: + +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (จากนั้นค้นหาชื่อไฟล์ด้านบน) +- **Linux**: ค้นหาภายใต้ `~/.local/share` สำหรับชื่อไฟล์ด้านบน +- **Windows**: กด `WIN+R` -> `%APPDATA%` (จากนั้นค้นหาชื่อไฟล์ด้านบน) + +--- + +## การขอความช่วยเหลือ + +หากคุณประสบปัญหากับ OpenCode: + +1. **รายงานปัญหาเกี่ยวกับ GitHub** + + วิธีที่ดีที่สุดในการรายงานจุดบกพร่องหรือขอคุณสมบัติคือผ่านพื้นที่เก็บข้อมูล GitHub ของเรา: + + [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + + ก่อนที่จะสร้างปัญหาใหม่ ให้ค้นหาปัญหาที่มีอยู่เพื่อดูว่าปัญหาของคุณได้รับการรายงานแล้วหรือไม่ + +2. **เข้าร่วม Discord ของเรา** + + สำหรับความช่วยเหลือแบบเรียลไทม์และการสนทนาในชุมชน เข้าร่วมเซิร์ฟเวอร์ Discord ของเรา: + + [**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## ปัญหาทั่วไป + +ต่อไปนี้เป็นปัญหาทั่วไปบางประการและวิธีแก้ปัญหา + +--- + +### OpenCode จะไม่เริ่มทำงาน + +1. ตรวจสอบบันทึกเพื่อดูข้อความแสดงข้อผิดพลาด +2. ลองรันด้วย `--print-logs` เพื่อดูเอาต์พุตใน terminal +3. ตรวจสอบให้แน่ใจว่าคุณมีเวอร์ชันล่าสุดด้วย `opencode upgrade` + +--- + +### ปัญหาการรับรองความถูกต้อง + +1. ลองตรวจสอบความถูกต้องอีกครั้งด้วยคำสั่ง `/connect` ใน TUI +2. ตรวจสอบว่าคีย์ API ของคุณถูกต้อง +3. ตรวจสอบให้แน่ใจว่าเครือข่ายของคุณอนุญาตการเชื่อมต่อกับ API ของผู้ให้บริการ + +--- + +### ไม่มีรุ่น + +1. ตรวจสอบว่าคุณได้รับการรับรองความถูกต้องกับผู้ให้บริการแล้ว +2. ตรวจสอบชื่อรุ่นในการกำหนดค่าของคุณถูกต้อง +3. บางรุ่นอาจต้องมีการเข้าถึงหรือสมัครสมาชิกโดยเฉพาะ + +หากคุณพบ `ProviderModelNotFoundError` เป็นไปได้มากว่าคุณจะคิดผิด +อ้างอิงแบบจำลองที่ไหนสักแห่ง +ควรอ้างอิงโมเดลดังนี้: `/` + +ตัวอย่าง: + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +หากต้องการทราบว่าคุณมีสิทธิ์เข้าถึงรุ่นใด ให้เรียกใช้ `opencode models` + +--- + +### ProviderInitError + +หากคุณพบ ProviderInitError คุณอาจมีการกำหนดค่าที่ไม่ถูกต้องหรือเสียหาย + +เพื่อแก้ไขปัญหานี้: + +1. ขั้นแรก ตรวจสอบให้แน่ใจว่าผู้ให้บริการของคุณตั้งค่าอย่างถูกต้องโดยทำตาม [คู่มือผู้ให้บริการ](/docs/providers) +2. หากปัญหายังคงอยู่ ให้ลองล้างการกำหนดค่าที่เก็บไว้: + + ```bash + rm -rf ~/.local/share/opencode + ``` + + บน Windows กด `WIN+R` และลบ: `%USERPROFILE%\.local\share\opencode` + +3. ตรวจสอบความถูกต้องอีกครั้งกับผู้ให้บริการของคุณโดยใช้คำสั่ง `/connect` ใน TUI + +--- + +### AI_APICallError และปัญหาแพ็คเกจผู้ให้บริการ + +หากคุณพบข้อผิดพลาดในการโทร API อาจเนื่องมาจากแพ็คเกจผู้ให้บริการที่ล้าสมัย opencode จะติดตั้งแพ็คเกจของผู้ให้บริการแบบไดนามิก (OpenAI, Anthropic, Google ฯลฯ) ตามความจำเป็น และแคชไว้ในเครื่อง + +ในการแก้ไขปัญหาแพ็คเกจผู้ให้บริการ: + +1. ล้างแคชแพ็คเกจผู้ให้บริการ: + + ```bash + rm -rf ~/.cache/opencode + ``` + + บน Windows กด `WIN+R` และลบ: `%USERPROFILE%\.cache\opencode` + +2. รีสตาร์ท opencode เพื่อติดตั้งแพ็คเกจผู้ให้บริการล่าสุดอีกครั้ง + +การดำเนินการนี้จะบังคับให้ opencode ดาวน์โหลดแพ็คเกจผู้ให้บริการเวอร์ชันล่าสุด ซึ่งมักจะแก้ไขปัญหาความเข้ากันได้กับพารามิเตอร์โมเดลและการเปลี่ยนแปลง API + +--- + +### Copy/paste ไม่ทำงานบน Linux + +ผู้ใช้ Linux จำเป็นต้องติดตั้งยูทิลิตี้คลิปบอร์ดตัวใดตัวหนึ่งต่อไปนี้เพื่อให้ฟังก์ชัน copy/paste ทำงาน: + +**สำหรับระบบ X11:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**สำหรับระบบ Wayland:** + +```bash +apt install -y wl-clipboard +``` + +**สำหรับสภาพแวดล้อมที่ไม่มีหัว:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +opencode จะตรวจพบว่าคุณใช้ Wayland และชอบ `wl-clipboard` หรือไม่เช่นนั้นจะพยายามค้นหาเครื่องมือคลิปบอร์ดตามลำดับ: `xclip` และ `xsel` diff --git a/packages/web/src/content/docs/th/tui.mdx b/packages/web/src/content/docs/th/tui.mdx new file mode 100644 index 00000000000..9151462d70d --- /dev/null +++ b/packages/web/src/content/docs/th/tui.mdx @@ -0,0 +1,390 @@ +--- +title: TUI +description: การใช้อินเทอร์เฟซผู้ใช้ terminal OpenCode +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode มีอินเทอร์เฟซ terminal แบบโต้ตอบหรือ TUI สำหรับการทำงานในโครงการของคุณด้วย LLM + +การรัน OpenCode จะเริ่มต้น TUI สำหรับไดเร็กทอรีปัจจุบัน + +```bash +opencode +``` + +หรือคุณสามารถเริ่มต้นสำหรับไดเร็กทอรีการทำงานเฉพาะได้ + +```bash +opencode /path/to/project +``` + +เมื่อคุณอยู่ใน TUI แล้ว คุณสามารถแจ้งด้วยข้อความได้ + +```text +Give me a quick summary of the codebase. +``` + +--- + +## การอ้างอิงไฟล์ + +คุณสามารถอ้างอิงไฟล์ในข้อความของคุณโดยใช้ `@` นี่เป็นการค้นหาไฟล์ที่ไม่ชัดเจนในไดเร็กทอรีการทำงานปัจจุบัน + +:::tip +คุณยังสามารถใช้ `@` เพื่ออ้างอิงไฟล์ในข้อความของคุณได้ +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +เนื้อหาของไฟล์จะถูกเพิ่มในการสนทนาโดยอัตโนมัติ + +--- + +## คำสั่ง Bash + +เริ่มข้อความด้วย `!` เพื่อรันคำสั่ง shell + +```bash frame="none" +!ls -la +``` + +ผลลัพธ์ของคำสั่งจะถูกเพิ่มเข้าไปในการสนทนาซึ่งเป็นผลลัพธ์ของเครื่องมือ + +--- + +## คำสั่ง + +เมื่อใช้ OpenCode TUI คุณสามารถพิมพ์ `/` ตามด้วยชื่อคำสั่งเพื่อดำเนินการอย่างรวดเร็ว ตัวอย่างเช่น: + +```bash frame="none" +/help +``` + +คำสั่งส่วนใหญ่ยังมีการผูกคีย์โดยใช้ `ctrl+x` เป็นคีย์ผู้นำ โดยที่ `ctrl+x` เป็นคีย์ผู้นำเริ่มต้น [เรียนรู้เพิ่มเติม](/docs/keybinds) + +นี่คือคำสั่งสแลชที่ใช้ได้ทั้งหมด: + +--- + +### connect + +เพิ่มผู้ให้บริการให้กับ OpenCode ให้คุณเลือกจากผู้ให้บริการที่มีอยู่และเพิ่มคีย์ API + +```bash frame="none" +/connect +``` + +--- + +### compact + +กระชับเซสชันปัจจุบัน _นามแฝง_: `/summarize` + +```bash frame="none" +/compact +``` + +**ผูกปุ่ม:** `ctrl+x c` + +--- + +### details + +สลับรายละเอียดการดำเนินการของเครื่องมือ + +```bash frame="none" +/details +``` + +**ผูกปุ่ม:** `ctrl+x d` + +--- + +### editor + +เปิดตัวแก้ไขภายนอกเพื่อเขียนข้อความ ใช้ตัวแก้ไขที่ตั้งค่าไว้ในตัวแปรสภาพแวดล้อม `EDITOR` ของคุณ [เรียนรู้เพิ่มเติม](#editor-setup) + +```bash frame="none" +/editor +``` + +**ผูกปุ่ม:** `ctrl+x e` + +--- + +### exit + +ออกจาก OpenCode _นามแฝง_: `/quit`, `/q` + +```bash frame="none" +/exit +``` + +**ผูกปุ่ม:** `ctrl+x q` + +--- + +### export + +ส่งออกการสนทนาปัจจุบันไปยัง Markdown และเปิดในตัวแก้ไขเริ่มต้นของคุณ ใช้ตัวแก้ไขที่ตั้งค่าไว้ในตัวแปรสภาพแวดล้อม `EDITOR` ของคุณ [เรียนรู้เพิ่มเติม](#editor-setup) + +```bash frame="none" +/export +``` + +**ผูกปุ่ม:** `ctrl+x x` + +--- + +### help + +แสดงกล่องโต้ตอบความช่วยเหลือ + +```bash frame="none" +/help +``` + +**ผูกปุ่ม:** `ctrl+x h` + +--- + +### init + +สร้างหรืออัปเดตไฟล์ `AGENTS.md` [เรียนรู้เพิ่มเติม](/docs/rules) + +```bash frame="none" +/init +``` + +**ผูกปุ่ม:** `ctrl+x i` + +--- + +### models + +รายการรุ่นที่มีจำหน่าย + +```bash frame="none" +/models +``` + +**ผูกปุ่ม:** `ctrl+x m` + +--- + +### new + +เริ่มเซสชันใหม่ _นามแฝง_: `/clear` + +```bash frame="none" +/new +``` + +**ผูกปุ่ม:** `ctrl+x n` + +--- + +### redo + +ทำซ้ำข้อความที่เลิกทำก่อนหน้านี้ ใช้ได้หลังจากใช้ `/undo` เท่านั้น + +:::tip +การเปลี่ยนแปลงไฟล์ใดๆ จะถูกกู้คืนด้วย +::: + +ภายในจะใช้ Git เพื่อจัดการการเปลี่ยนแปลงไฟล์ ดังนั้นโครงการของคุณ **จำเป็นต้อง +เป็นที่เก็บ Git** + +```bash frame="none" +/redo +``` + +**ผูกปุ่ม:** `ctrl+x r` + +--- + +### sessions + +รายการและสลับระหว่างเซสชัน _นามแฝง_: `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +**ผูกปุ่ม:** `ctrl+x l` + +--- + +### share + +แบ่งปันเซสชั่นปัจจุบัน [เรียนรู้เพิ่มเติม](/docs/share) + +```bash frame="none" +/share +``` + +**ผูกปุ่ม:** `ctrl+x s` + +--- + +### themes + +แสดงรายการธีมที่มีอยู่ + +```bash frame="none" +/theme +``` + +**ผูกปุ่ม:** `ctrl+x t` + +--- + +### thinking + +สลับการเปิดเผยการบล็อก thinking/reasoning ในการสนทนา เมื่อเปิดใช้งาน คุณสามารถดูกระบวนการให้เหตุผลของแบบจำลองสำหรับแบบจำลองที่รองรับการคิดแบบขยาย + +:::note +คำสั่งนี้ควบคุมเฉพาะว่าบล็อกการคิด **แสดง** หรือไม่ โดยไม่ได้เปิดใช้งานหรือปิดใช้งานความสามารถในการให้เหตุผลของโมเดล หากต้องการสลับความสามารถในการให้เหตุผลตามจริง ให้ใช้ `ctrl+t` เพื่อหมุนเวียนไปตามตัวแปรโมเดล +::: + +```bash frame="none" +/thinking +``` + +--- + +### undo + +เลิกทำข้อความสุดท้ายในการสนทนา ลบข้อความผู้ใช้ล่าสุด การตอบกลับที่ตามมาทั้งหมด และการเปลี่ยนแปลงไฟล์ใดๆ + +:::tip +การเปลี่ยนแปลงไฟล์ใดๆ ที่ทำจะถูกคืนค่าด้วย +::: + +ภายในจะใช้ Git เพื่อจัดการการเปลี่ยนแปลงไฟล์ ดังนั้นโครงการของคุณ **จำเป็นต้อง +เป็นที่เก็บ Git** + +```bash frame="none" +/undo +``` + +**ผูกปุ่ม:** `ctrl+x u` + +--- + +### unshare + +ยกเลิกการแชร์เซสชันปัจจุบัน [เรียนรู้เพิ่มเติม](/docs/share#un-sharing) + +```bash frame="none" +/unshare +``` + +--- + +## การตั้งค่าตัวแก้ไข + +ทั้งคำสั่ง `/editor` และ `/export` ใช้ตัวแก้ไขที่ระบุในตัวแปรสภาพแวดล้อม `EDITOR` ของคุณ + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + + หากต้องการทำให้เป็นแบบถาวร ให้เพิ่มสิ่งนี้ลงในโปรไฟล์ shell ของคุณ + `~/.bashrc`, `~/.zshrc` ฯลฯ + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + + หากต้องการทำให้เป็นแบบถาวร ให้ใช้ **คุณสมบัติของระบบ** > **สภาพแวดล้อม + ตัวแปร**. + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + + หากต้องการทำให้เป็นแบบถาวร ให้เพิ่มสิ่งนี้ลงในโปรไฟล์ PowerShell ของคุณ + + + + +ตัวเลือกตัวแก้ไขยอดนิยม ได้แก่ : + +- `code` - ​​รหัส Visual Studio +- `cursor` - ​​เคอร์เซอร์ +- `windsurf` - ​​วินด์เซิร์ฟ +- `nvim` - ​​บรรณาธิการ Neovim +- `vim` - ​​โปรแกรมแก้ไขเป็นกลุ่ม +- `nano` - ​​โปรแกรมแก้ไขนาโน +- `notepad` - ​​สมุดบันทึกของ Windows +- `subl` - ​​ข้อความประเสริฐ + +:::note +บรรณาธิการบางคนเช่น VS Code จำเป็นต้องเริ่มต้นด้วยแฟล็ก `--wait` +::: + +ผู้แก้ไขบางรายจำเป็นต้องมีอาร์กิวเมนต์บรรทัดคำสั่งเพื่อทำงานในโหมดการบล็อก แฟล็ก `--wait` ทำให้กระบวนการแก้ไขบล็อกจนกว่าจะปิด + +--- + +## กำหนดค่า + +คุณสามารถปรับแต่งพฤติกรรม TUI ผ่านไฟล์กำหนดค่า OpenCode ของคุณได้ + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### ตัวเลือก + +- `scroll_acceleration` - ​​เปิดใช้งานการเร่งความเร็วการเลื่อนแบบ macOS เพื่อการเลื่อนที่ราบรื่นและเป็นธรรมชาติ เมื่อเปิดใช้งาน ความเร็วในการเลื่อนจะเพิ่มขึ้นตามท่าทางการเลื่อนอย่างรวดเร็ว และคงความแม่นยำไว้สำหรับการเคลื่อนไหวที่ช้าลง **การตั้งค่านี้มีความสำคัญมากกว่า `scroll_speed` และแทนที่เมื่อเปิดใช้งาน** +- `scroll_speed` - ​​ควบคุมความเร็วของการเลื่อน TUI เมื่อใช้คำสั่งการเลื่อน (ขั้นต่ำ: `1`) ค่าเริ่มต้นเป็น `3` **หมายเหตุ: สิ่งนี้จะถูกละเว้นหากตั้งค่า `scroll_acceleration.enabled` เป็น `true`.** + +--- + +## การปรับแต่ง + +คุณสามารถปรับแต่งแง่มุมต่างๆ ของมุมมอง TUI ได้โดยใช้ชุดคำสั่ง (`ctrl+x h` หรือ `/help`) การตั้งค่าเหล่านี้ยังคงมีอยู่ตลอดการรีสตาร์ท + +--- + +#### การแสดงชื่อผู้ใช้ + +สลับว่าจะให้ชื่อผู้ใช้ของคุณปรากฏในข้อความแชทหรือไม่ เข้าถึงสิ่งนี้ผ่าน: + +- Command Palette: ค้นหา "ชื่อผู้ใช้" หรือ "ซ่อนชื่อผู้ใช้" +- การตั้งค่าจะคงอยู่โดยอัตโนมัติและจะถูกจดจำตลอดเซสชัน TUI diff --git a/packages/web/src/content/docs/th/web.mdx b/packages/web/src/content/docs/th/web.mdx new file mode 100644 index 00000000000..33bd3020cf8 --- /dev/null +++ b/packages/web/src/content/docs/th/web.mdx @@ -0,0 +1,142 @@ +--- +title: เว็บ +description: การใช้ OpenCode ในเบราว์เซอร์ของคุณ +--- + +OpenCode สามารถทำงานเป็นเว็บแอปพลิเคชันในเบราว์เซอร์ของคุณได้ โดยมอบประสบการณ์การเขียนโค้ด AI อันทรงพลังแบบเดียวกันโดยไม่ต้องใช้ terminal + +![เว็บ OpenCode - เซสชันใหม่](../../../assets/web/web-homepage-new-session.png) + +## เริ่มต้นใช้งาน + +เริ่มเว็บอินเตอร์เฟสด้วยการรัน: + +```bash +opencode web +``` + +สิ่งนี้จะเริ่มต้นเซิร์ฟเวอร์ท้องถิ่นบน `127.0.0.1` ด้วยพอร์ตที่มีอยู่แบบสุ่มและเปิด OpenCode โดยอัตโนมัติในเบราว์เซอร์เริ่มต้นของคุณ + +:::caution +หากไม่ได้ตั้งค่า `OPENCODE_SERVER_PASSWORD` เซิร์ฟเวอร์จะไม่ปลอดภัย นี่เป็นเรื่องปกติสำหรับการใช้งานภายในเครื่อง แต่ควรตั้งค่าสำหรับการเข้าถึงเครือข่าย +::: + +:::tip[ผู้ใช้ Windows] +เพื่อประสบการณ์ที่ดีที่สุด ให้เรียกใช้ `opencode web` จาก [WSL](/docs/windows-wsl) แทนที่จะเป็น PowerShell สิ่งนี้ทำให้มั่นใจได้ถึงการเข้าถึงระบบไฟล์ที่เหมาะสมและการรวม terminal +::: + +--- + +## การกำหนดค่า + +คุณสามารถกำหนดค่าเว็บเซิร์ฟเวอร์ได้โดยใช้แฟล็กบรรทัดคำสั่งหรือใน [ไฟล์กำหนดค่า](/docs/config) + +### พอร์ต + +ตามค่าเริ่มต้น OpenCode จะเลือกพอร์ตที่พร้อมใช้งาน คุณสามารถระบุพอร์ต: + +```bash +opencode web --port 4096 +``` + +### ชื่อโฮสต์ + +ตามค่าเริ่มต้น เซิร์ฟเวอร์จะเชื่อมโยงกับ `127.0.0.1` (เฉพาะโลคัลโฮสต์เท่านั้น) หากต้องการให้ OpenCode เข้าถึงได้บนเครือข่ายของคุณ: + +```bash +opencode web --hostname 0.0.0.0 +``` + +เมื่อใช้ `0.0.0.0` OpenCode จะแสดงทั้งที่อยู่ในท้องถิ่นและเครือข่าย: + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### การค้นพบ mDNS + +เปิดใช้งาน mDNS เพื่อให้เซิร์ฟเวอร์ของคุณค้นพบได้บนเครือข่ายท้องถิ่น: + +```bash +opencode web --mdns +``` + +สิ่งนี้จะตั้งชื่อโฮสต์เป็น `0.0.0.0` โดยอัตโนมัติและโฆษณาเซิร์ฟเวอร์เป็น `opencode.local` + +คุณสามารถปรับแต่งชื่อโดเมน mDNS เพื่อเรียกใช้หลายอินสแตนซ์บนเครือข่ายเดียวกันได้: + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +หากต้องการอนุญาตโดเมนเพิ่มเติมสำหรับ CORS (มีประโยชน์สำหรับส่วนหน้าที่กำหนดเอง): + +```bash +opencode web --cors https://example.com +``` + +### การรับรองความถูกต้อง + +เพื่อป้องกันการเข้าถึง ให้ตั้งรหัสผ่านโดยใช้ตัวแปรสภาพแวดล้อม `OPENCODE_SERVER_PASSWORD`: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +ชื่อผู้ใช้มีค่าเริ่มต้นเป็น `opencode` แต่สามารถเปลี่ยนได้ด้วย `OPENCODE_SERVER_USERNAME` + +--- + +## การใช้เว็บอินเตอร์เฟส + +เมื่อเริ่มต้นแล้ว เว็บอินเตอร์เฟสจะให้สิทธิ์การเข้าถึงเซสชัน OpenCode ของคุณ + +### เซสชัน + +ดูและจัดการเซสชันของคุณจากหน้าแรก คุณสามารถดูเซสชันที่ใช้งานอยู่และเริ่มต้นเซสชันใหม่ได้ + +![OpenCode Web - เซสชันที่ใช้งานอยู่](../../../assets/web/web-homepage-active-session.png) + +### สถานะเซิร์ฟเวอร์ + +คลิก "ดูเซิร์ฟเวอร์" เพื่อดูเซิร์ฟเวอร์ที่เชื่อมต่อและสถานะ + +![เว็บ OpenCode - ดูเซิร์ฟเวอร์](../../../assets/web/web-homepage-see-servers.png) + +--- + +## การต่อ terminal + +คุณสามารถแนบ terminal TUI กับเว็บเซิร์ฟเวอร์ที่ทำงานอยู่: + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +ซึ่งจะทำให้คุณสามารถใช้ทั้งเว็บอินเทอร์เฟซและ terminal พร้อมกัน โดยแชร์เซสชันและสถานะเดียวกัน + +--- + +## ไฟล์กำหนดค่า + +คุณยังสามารถกำหนดการตั้งค่าเซิร์ฟเวอร์ในไฟล์กำหนดค่า `opencode.json` ของคุณได้: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +ธงบรรทัดคำสั่งมีความสำคัญเหนือกว่าการตั้งค่าไฟล์กำหนดค่า diff --git a/packages/web/src/content/docs/th/windows-wsl.mdx b/packages/web/src/content/docs/th/windows-wsl.mdx new file mode 100644 index 00000000000..93aedd2a325 --- /dev/null +++ b/packages/web/src/content/docs/th/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: ใช้ OpenCode บน Windows ผ่าน WSL ให้ลื่นที่สุด +--- + +import { Steps } from "@astrojs/starlight/components" + +แม้ว่า OpenCode จะรันบน Windows ได้โดยตรง แต่เราแนะนำให้ใช้ [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) เพื่อประสบการณ์ที่ดีที่สุด WSL ให้สภาพแวดล้อม Linux ที่ทำงานร่วมกับฟีเจอร์ของ OpenCode ได้อย่างราบรื่น + +:::tip[ทำไมต้องใช้ WSL?] +WSL ให้ประสิทธิภาพระบบไฟล์ที่ดีกว่า รองรับ terminal ได้เต็มรูปแบบ และเข้ากันได้กับเครื่องมือพัฒนาที่ OpenCode ใช้งาน +::: + +--- + +## การตั้งค่า + + + +1. **ติดตั้ง WSL** + + ถ้ายังไม่ได้ติดตั้ง ให้ทำตามคู่มือทางการของ Microsoft เพื่อ [ติดตั้ง WSL](https://learn.microsoft.com/en-us/windows/wsl/install) + +2. **ติดตั้ง OpenCode ใน WSL** + + เมื่อตั้งค่า WSL เสร็จแล้ว ให้เปิด terminal WSL และติดตั้ง OpenCode ด้วย [วิธีติดตั้ง](/docs/) แบบใดแบบหนึ่ง + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **ใช้งาน OpenCode จาก WSL** + + ไปที่ไดเรกทอรีโปรเจกต์ของคุณ (เข้าถึงไฟล์ Windows ผ่าน `/mnt/c/`, `/mnt/d/` เป็นต้น) แล้วรัน OpenCode + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## เดสก์ท็อปแอป + เซิร์ฟเวอร์บน WSL + +ถ้าคุณต้องการใช้ OpenCode Desktop แต่ให้เซิร์ฟเวอร์ทำงานบน WSL: + +1. **เริ่มเซิร์ฟเวอร์ใน WSL** โดยใช้ `--hostname 0.0.0.0` เพื่อให้เชื่อมต่อจากภายนอกได้: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **เชื่อมต่อเดสก์ท็อปแอป** ไปที่ `http://localhost:4096` + +:::note +ถ้า `localhost` ใช้งานไม่ได้ในสภาพแวดล้อมของคุณ ให้ใช้ IP ของ WSL แทน (จาก WSL: `hostname -I`) แล้วเชื่อมต่อที่ `http://:4096` +::: + +:::caution +เมื่อใช้ `--hostname 0.0.0.0` ให้ตั้งค่า `OPENCODE_SERVER_PASSWORD` เพื่อป้องกันเซิร์ฟเวอร์ + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## เว็บไคลเอนต์ + WSL + +เพื่อประสบการณ์เว็บที่ดีที่สุดบน Windows: + +1. **รัน `opencode web` ใน terminal WSL** แทน PowerShell: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **เข้าจากเบราว์เซอร์บน Windows** ที่ `http://localhost:` (OpenCode จะแสดง URL ให้) + +การรัน `opencode web` จาก WSL ช่วยให้เข้าถึงระบบไฟล์และใช้งาน terminal ได้ถูกต้อง พร้อมเปิดใช้งานผ่านเบราว์เซอร์ Windows ได้เหมือนเดิม + +--- + +## การเข้าถึงไฟล์ Windows + +WSL สามารถเข้าถึงไฟล์ Windows ทั้งหมดของคุณได้ผ่านไดเรกทอรี `/mnt/`: + +- `C:` drive → `/mnt/c/` +- `D:` drive → `/mnt/d/` +- ไดรฟ์อื่นก็ใช้รูปแบบเดียวกัน + +ตัวอย่าง: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +เพื่อให้ใช้งานได้ลื่นที่สุด แนะนำให้โคลนหรือคัดลอกรีโปไปไว้ในไฟล์ซิสเต็มของ WSL (เช่น `~/code/`) แล้วรัน OpenCode จากที่นั่น +::: + +--- + +## เคล็ดลับ + +- แม้โปรเจกต์จะอยู่บนไดรฟ์ Windows ก็ควรรัน OpenCode ใน WSL เพื่อการเข้าถึงไฟล์ที่ลื่นกว่า +- ใช้ OpenCode ควบคู่กับ [WSL extension ของ VS Code](https://code.visualstudio.com/docs/remote/wsl) เพื่อเวิร์กโฟลว์ที่ต่อเนื่อง +- การตั้งค่าและเซสชันของ OpenCode จะถูกเก็บในสภาพแวดล้อม WSL ที่ `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/th/zen.mdx b/packages/web/src/content/docs/th/zen.mdx new file mode 100644 index 00000000000..f0b39ceaaa0 --- /dev/null +++ b/packages/web/src/content/docs/th/zen.mdx @@ -0,0 +1,254 @@ +--- +title: เซน +description: รายการโมเดลที่คัดสรรโดย OpenCode +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen คือรายการโมเดลที่ได้รับการทดสอบและตรวจสอบแล้วโดยทีมงาน OpenCode + +:::note +OpenCode Zen ปัจจุบันอยู่ในช่วงเบต้า +::: + +Zen ทำงานเหมือนกับผู้ให้บริการรายอื่นๆ ใน OpenCode คุณเข้าสู่ระบบ OpenCode Zen และรับ +รหัส API ของคุณ มันเป็น **ทางเลือกโดยสมบูรณ์** และคุณไม่จำเป็นต้องใช้มันเพื่อใช้งาน +โอเพ่นโค้ด + +--- + +## ภูมิหลัง + +มีหลายรุ่นครับ แต่มีเพียงไม่กี่รุ่นเท่านั้น +โมเดลเหล่านี้ทำงานได้ดีในฐานะตัวแทนการเข้ารหัส นอกจากนี้ผู้ให้บริการส่วนใหญ่ก็มี +กำหนดค่าแตกต่างกันมาก ดังนั้นคุณจึงได้รับประสิทธิภาพและคุณภาพที่แตกต่างกันมาก + +:::tip +เราได้ทดสอบกลุ่มโมเดลและผู้ให้บริการที่เลือกซึ่งทำงานได้ดีกับ OpenCode +::: + +ดังนั้นหากคุณใช้โมเดลผ่าน OpenRouter คุณจะไม่มีวันเป็นเช่นนั้น +แน่ใจว่าคุณได้รับรุ่นที่ดีที่สุดของรุ่นที่คุณต้องการหรือไม่ + +เพื่อแก้ไขปัญหานี้ เราได้ทำสองสิ่ง: + +1. เราได้ทดสอบกลุ่มโมเดลที่ได้รับการคัดเลือกและพูดคุยกับทีมของพวกเขาเกี่ยวกับวิธีการ + ดีที่สุดเรียกใช้พวกเขา +2. จากนั้นเราทำงานร่วมกับผู้ให้บริการบางรายเพื่อให้แน่ใจว่าผู้ให้บริการเหล่านี้ได้รับบริการแล้ว + อย่างถูกต้อง +3. ในที่สุด เราก็เปรียบเทียบการรวมกันของ model/provider และได้ผลลัพธ์ออกมา + กับรายการที่เรารู้สึกดีมาแนะนำ + +OpenCode Zen เป็นเกตเวย์ AI ที่ให้คุณเข้าถึงโมเดลเหล่านี้ + +--- + +## มันทำงานอย่างไร + +OpenCode Zen ทำงานเหมือนกับผู้ให้บริการรายอื่นๆ ใน OpenCode + +1. คุณลงชื่อเข้าใช้ **OpenCode Zen** เพิ่มการเรียกเก็บเงินของคุณ + รายละเอียดและคัดลอกรหัส API ของคุณ +2. คุณรันคำสั่ง `/connect` ใน TUI เลือก OpenCode Zen และวางคีย์ API ของคุณ +3. เรียกใช้ `/models` ใน TUI เพื่อดูรายการรุ่นที่เราแนะนำ + +คุณจะถูกเรียกเก็บเงินตามคำขอและคุณสามารถเพิ่มเครดิตให้กับบัญชีของคุณได้ + +--- + +## จุดสิ้นสุด + +คุณยังสามารถเข้าถึงโมเดลของเราผ่านทางจุดสิ้นสุด API ต่อไปนี้ + +| Model | Model ID | Endpoint | แพ็คเกจ AI SDK | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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` | +| 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.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 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` | + +[model id](/docs/config/#models) ในการกำหนดค่า OpenCode ของคุณ +ใช้รูปแบบ `opencode/` ตัวอย่างเช่น สำหรับ GPT 5.2 Codex คุณจะต้อง +ใช้ `opencode/gpt-5.2-codex` ในการกำหนดค่าของคุณ + +--- + +### โมเดล + +คุณสามารถดึงรายชื่อรุ่นที่มีจำหน่ายและข้อมูลเมตาทั้งหมดได้จาก: + +``` +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 | ฟรี | ฟรี | ฟรี | - | + +คุณอาจสังเกตเห็น _Claude Haiku 3.5_ ในประวัติการใช้งานของคุณ นี่คือ [โมเดลราคาประหยัด](/docs/config/#models) ที่ใช้ในการสร้างชื่อเซสชันของคุณ + +:::note +ค่าธรรมเนียมบัตรเครดิตจะถูกส่งต่อในราคาต้นทุน (4.4% + 0.30 ดอลลาร์สหรัฐฯ ต่อธุรกรรม) เราไม่คิดค่าใช้จ่ายใดๆ นอกเหนือจากนั้น +::: + +รุ่นฟรี: + +- GLM 4.7 ใช้งานได้ฟรีบน OpenCode ในระยะเวลาจำกัด ทีมงานใช้เวลานี้เพื่อรวบรวมคำติชมและปรับปรุงโมเดล +- Kimi K2.5 Free พร้อมใช้งานบน OpenCode ในระยะเวลาจำกัด ทีมงานใช้เวลานี้เพื่อรวบรวมคำติชมและปรับปรุงโมเดล +- MiniMax M2.1 Free พร้อมใช้งานบน OpenCode ในระยะเวลาจำกัด ทีมงานใช้เวลานี้เพื่อรวบรวมคำติชมและปรับปรุงโมเดล +- Big Pickle เป็นโมเดลล่องหนที่ให้บริการฟรีบน OpenCode ในระยะเวลาจำกัด ทีมงานใช้เวลานี้เพื่อรวบรวมคำติชมและปรับปรุงโมเดล + +Contact us if you have any questions. + +--- + +### โหลดซ้ำอัตโนมัติ + +หากยอดคงเหลือของคุณต่ำกว่า $5 Zen จะโหลด $20 อีกครั้งโดยอัตโนมัติ + +คุณสามารถเปลี่ยนจำนวนการโหลดอัตโนมัติได้ คุณยังสามารถปิดการโหลดอัตโนมัติทั้งหมดได้อีกด้วย + +--- + +### ขีดจำกัดรายเดือน + +คุณยังสามารถกำหนดขีดจำกัดการใช้งานรายเดือนสำหรับพื้นที่ทำงานทั้งหมดและสำหรับแต่ละรายการได้ +สมาชิกในทีมของคุณ + +ตัวอย่างเช่น สมมติว่าคุณกำหนดขีดจำกัดการใช้งานรายเดือนไว้ที่ 20 ดอลลาร์ Zen จะไม่ใช้ +มากกว่า $20 ในหนึ่งเดือน แต่ถ้าคุณเปิดใช้งานการโหลดซ้ำอัตโนมัติ Zen อาจจะจบลง +เรียกเก็บเงินคุณมากกว่า $20 หากยอดคงเหลือของคุณต่ำกว่า $5 + +--- + +## ความเป็นส่วนตัว + +โมเดลทั้งหมดของเราโฮสต์ในสหรัฐอเมริกา ผู้ให้บริการของเราปฏิบัติตามนโยบายการเก็บรักษาเป็นศูนย์ และไม่ใช้ข้อมูลของคุณสำหรับการฝึกโมเดล โดยมีข้อยกเว้นต่อไปนี้: + +- Big Pickle: ในช่วงระยะเวลาว่าง ข้อมูลที่รวบรวมอาจนำไปใช้ในการปรับปรุงโมเดลได้ +- GLM 4.7 Free: ในช่วงระยะเวลาฟรี ข้อมูลที่รวบรวมอาจนำไปใช้ในการปรับปรุงโมเดล +- Kimi K2.5 Free: ในช่วงระยะเวลาฟรี ข้อมูลที่รวบรวมอาจนำไปใช้ในการปรับปรุงโมเดล +- MiniMax M2.1 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) + +--- + +## สำหรับทีม + +Zen ยังใช้งานได้ดีกับทีมอีกด้วย คุณสามารถเชิญเพื่อนร่วมทีม กำหนดบทบาท ดูแลจัดการได้ +โมเดลที่ทีมของคุณใช้ และอื่นๆ + +:::note +ขณะนี้พื้นที่ทำงานให้บริการฟรีสำหรับทีมโดยเป็นส่วนหนึ่งของเวอร์ชันเบต้า +::: + +ขณะนี้การจัดการพื้นที่ทำงานของคุณให้บริการฟรีสำหรับทีมโดยเป็นส่วนหนึ่งของเวอร์ชันเบต้า เราจะเป็น +แบ่งปันรายละเอียดเพิ่มเติมเกี่ยวกับราคาเร็ว ๆ นี้ + +--- + +### บทบาท + +คุณสามารถเชิญเพื่อนร่วมทีมเข้ามาในพื้นที่ทำงานของคุณและมอบหมายบทบาทได้: + +- **ผู้ดูแลระบบ**: จัดการโมเดล สมาชิก คีย์ API และการเรียกเก็บเงิน +- **สมาชิก**: จัดการเฉพาะคีย์ API ของตนเองเท่านั้น + +ผู้ดูแลระบบยังสามารถกำหนดวงเงินการใช้จ่ายรายเดือนสำหรับสมาชิกแต่ละคนเพื่อควบคุมค่าใช้จ่ายได้ + +--- + +### การเข้าถึงโมเดล + +ผู้ดูแลระบบสามารถเปิดหรือปิดใช้งานโมเดลเฉพาะสำหรับพื้นที่ทำงานได้ คำขอที่ทำกับโมเดลที่ถูกปิดใช้งานจะส่งคืนข้อผิดพลาด + +สิ่งนี้มีประโยชน์สำหรับกรณีที่คุณต้องการปิดการใช้งานโมเดลนั้น +รวบรวมข้อมูล + +--- + +### นำคีย์ของคุณมาเอง + +คุณสามารถใช้คีย์ OpenAI หรือ Anthropic API ของคุณเองในขณะที่ยังเข้าถึงรุ่นอื่นๆ ใน Zen ได้ + +เมื่อคุณใช้คีย์ของคุณเอง tokensจะถูกเรียกเก็บเงินโดยตรงจากผู้ให้บริการ ไม่ใช่โดย Zen + +ตัวอย่างเช่น องค์กรของคุณอาจมีคีย์สำหรับ OpenAI หรือ Anthropic อยู่แล้ว +และคุณต้องการใช้สิ่งนั้นแทนอันที่ Zen มอบให้ + +--- + +## เป้าหมาย + +เราสร้าง OpenCode Zen เพื่อ: + +1. **เกณฑ์มาตรฐาน** โมเดลที่ดีที่สุด/providers สำหรับตัวแทนการเข้ารหัส +2. เข้าถึงตัวเลือก **คุณภาพMax** และไม่ดาวน์เกรดประสิทธิภาพหรือเปลี่ยนเส้นทางไปยังผู้ให้บริการที่ราคาถูกกว่า +3. ส่งต่อ **ราคาที่ลดลง** โดยการขายในราคาต้นทุน ดังนั้นมาร์กอัปเพียงอย่างเดียวคือครอบคลุมค่าธรรมเนียมการดำเนินการของเรา +4. **ไม่มีการล็อคอิน** โดยอนุญาตให้คุณใช้กับเอเจนต์การเขียนโค้ดอื่นๆ และให้คุณใช้ผู้ให้บริการรายอื่นกับ OpenCode ได้เช่นกัน diff --git a/packages/web/src/content/docs/tr/acp.mdx b/packages/web/src/content/docs/tr/acp.mdx new file mode 100644 index 00000000000..abdfda09101 --- /dev/null +++ b/packages/web/src/content/docs/tr/acp.mdx @@ -0,0 +1,156 @@ +--- +title: ACP Desteği +description: opencode'u ACP uyumlu herhangi bir editörde kullanın. +--- + +opencode, [Agent Client Protocol](https://agentclientprotocol.com) veya (ACP) dosyalarını destekleyerek onu doğrudan uyumlu editörlerde ve IDE'lerde kullanmanızı sağlar. + +:::tip +ACP'yi destekleyen editörlerin ve araçların listesi için [ACP progress report](https://zed.dev/blog/acp-progress-report#available-now)'e bakın. +::: + +ACP, kod editörleri ile AI kodlama ajanları arasındaki iletişimi standartlaştıran açık bir protokoldür. + +--- + +## Yapılandırma + +opencode'u ACP aracılığıyla kullanmak için düzenleyicinizi `opencode acp` komutunu çalıştıracak şekilde yapılandırın. + +Komut, opencode'u, editörünüzle stdio aracılığıyla JSON-RPC üzerinden iletişim kuran ACP uyumlu bir alt süreç olarak başlatır. + +Aşağıda ACP'yi destekleyen popüler düzenleyicilere ilişkin örnekler verilmiştir. + +--- + +### Zed + +[Zed](https://zed.dev) yapılandırmanıza (`~/.config/zed/settings.json`) ekleyin: + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +Açmak için **Komut Paleti**'ndeki `agent: new thread` eylemini kullanın. + +`keymap.json` dosyanızı düzenleyerek de bir klavye kısayolunu bağlayabilirsiniz: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### JetBrains IDEs + +[documentation](https://www.jetbrains.com/help/ai-assistant/acp.html) uyarınca [JetBrains IDE](https://www.jetbrains.com/) acp.json dosyanıza ekleyin: + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +Açmak için AI Chat agent seçicisindeki yeni 'OpenCode' ajanını kullanın. + +--- + +### Avante.nvim + +[Avante.nvim](https://github.com/yetone/avante.nvim) yapılandırmanıza ekleyin: + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +Ortam değişkenlerini iletmeniz gerekiyor: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +opencode'u [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim)'de ACP ajanı olarak kullanmak için Neovim yapılandırmanıza aşağıdakileri ekleyin: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +Bu yapılandırma, CodeCompanion'ı opencode'u sohbet için ACP ajanı olarak kullanacak şekilde ayarlar. + +Ortam değişkenlerini (`OPENCODE_API_KEY` gibi) iletmeniz gerekiyorsa, tüm ayrıntılar için CodeCompanion.nvim belgelerindeki [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key)'ye bakın. + +## Destek + +opencode, terminalde olduğu gibi ACP aracılığıyla aynı şekilde çalışır. Tüm özellikler desteklenir: + +:::note +`/undo` ve `/redo` gibi bazı yerleşik slash komutları şu anda desteklenmemektedir. +::: + +- Yerleşik araçlar (dosya işlemleri, terminal komutları vb.) +- Özel araçlar ve slash komutları +- opencode yapılandırmanızda yapılandırılmış MCP sunucuları +- `AGENTS.md`'dan projeye özel kurallar +- Özel biçimlendiriciler ve linter'lar +- Aracılar ve izin sistemi diff --git a/packages/web/src/content/docs/tr/agents.mdx b/packages/web/src/content/docs/tr/agents.mdx new file mode 100644 index 00000000000..47c16abf120 --- /dev/null +++ b/packages/web/src/content/docs/tr/agents.mdx @@ -0,0 +1,1370 @@ +--- +title: Agent'lar +description: Özel agent'ları yapılandırın ve kullanın. +--- + +Agent'lar, belirli görevler ve iş akışları için yapılandırılabilen uzmanlaşmış AI asistanlarıdır. Özel istemler, modeller ve araç erişimiyle odaklanmış araçlar oluşturmanıza olanak tanır. + +:::tip +Herhangi bir kod değişikliği yapmadan kodu analiz etmek ve önerileri gözden geçirmek için Plan agent'ını kullanın. +::: + +Bir oturum sırasında agent'lar arasında geçiş yapabilir veya onları `@` ifadesi ile çağırabilirsiniz. + +--- + +## Türler + +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. + +:::tip +Bir oturum sırasında birincil agent'lar arasında geçiş yapmak için **Sekme** tuşunu kullanabilirsiniz. +::: + +opencode, **Build** ve **Plan** olmak üzere iki yerleşik birincil agent ile birlikte gelir. Bunlara aşağıda bakacağız. + +--- + +### Alt agent'lar + +Alt agent'lar, birincil agent'ların belirli görevler için çağırabileceği uzman yardımcılardır. Ayrıca mesajlarınızda **@ bahsederek** bunları manuel olarak da çağırabilirsiniz. + +opencode, **General** ve **Explore** olmak üzere iki yerleşik alt agent ile birlikte gelir. Buna aşağıda bakacağız. + +--- + +## Yerleşik + +opencode iki yerleşik birincil agent ve iki yerleşik alt agent ile birlikte gelir. + +--- + +### Build Kullanımı + +_Mod_: `primary` + +Build, tüm araçların etkin olduğu **varsayılan** birincil agent'tır. Bu, dosya işlemlerine ve sistem komutlarına tam erişime ihtiyaç duyduğunuz geliştirme çalışmaları için standart agent'tır. + +--- + +### Plan Kullanımı + +_Mod_: `primary` + +Planlama ve analiz için tasarlanmış kısıtlı bir agent. Size daha fazla kontrol sağlamak ve istenmeyen değişiklikleri önlemek için bir izin sistemi kullanıyoruz. +Varsayılan olarak aşağıdakilerin tümü `ask` olarak ayarlanmıştır: + +- `file edits`: Tüm yazmalar, yamalar ve düzenler +- `bash`: Tüm bash komutları + +Bu agent, LLM'in kodu analiz etmesini, değişiklik önermesini veya kod tabanınızda herhangi bir gerçek değişiklik yapmadan plan oluşturmasını istediğinizde kullanışlıdır. + +--- + +### General Kullanımı + +_Mod_: `subagent` + +Karmaşık soruları araştırmak ve çok adımlı görevleri yürütmek için genel amaçlı bir agent. Tam araç erişimine sahiptir (yapılacaklar hariç), böylece gerektiğinde dosya değişiklikleri yapabilir. Birden fazla iş birimini paralel olarak çalıştırmak için bunu kullanın. + +--- + +### Explore Kullanımı + +_Mod_: `subagent` + +Kod tabanlarını keşfetmeye yönelik hızlı, salt okunur bir agent. Dosyalar değiştirilemiyor. Dosyaları kalıplara göre hızla bulmanız, anahtar sözcükler için kod aramanız veya kod tabanıyla ilgili soruları yanıtlamanız gerektiğinde bunu kullanın. + +--- + +### Compact Kullanımı + +_Mod_: `primary` + +Uzun bağlamı daha küçük bir özete sıkıştıran gizli sistem agent'ı. Gerektiğinde otomatik olarak çalışır ve kullanıcı arayüzünde seçilemez. + +--- + +### Title Kullanımı + +_Mod_: `primary` + +Kısa oturum başlıkları oluşturan gizli sistem agent'ı. Otomatik olarak çalışır ve kullanıcı arayüzünde seçilemez. + +--- + +### Summary Kullanımı + +_Mod_: `primary` + +Oturum özetleri oluşturan gizli sistem agent'ı. Otomatik olarak çalışır ve kullanıcı arayüzünde seçilemez. + +--- + +## Kullanım + +1. Birincil agent'lar için, oturum sırasında bunlar arasında geçiş yapmak için **Sekme** tuşunu kullanın. Yapılandırılmış `switch_agent` tuş bağınızı da kullanabilirsiniz. + +2. Alt agent'lar çağrılabilir: + - Açıklamalarına göre özel görevler için birincil agent'lar tarafından **otomatik olarak**. + - Mesajınızda bir alt agent'tan **@ bahsederek** manuel olarak. Örneğin. + + ```txt frame="none" + @general help me search for this function + ``` + +3. **Oturumlar arasında gezinme**: Alt agent'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 alt agent çalışması arasında sorunsuz bir şekilde geçiş yapmanıza olanak tanır. + +--- + +## Yapılandırma + +Yerleşik agent'ları özelleştirebilir 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'in 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 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. + +:::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. +::: + +```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 alt agent'ı `hidden: true` ile gizleyin. Yalnızca diğer agent'lar tarafından Task aracı aracılığıyla programlı olarak çağrılması gereken dahili alt agent'lar için kullanışlıdır. + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +Bu yalnızca otomatik menüdeki görünürlüğü etkiler. İzinler izin verirse, gizli agent'lar model 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 alt agent'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, alt agent 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 alt agent'ı `@` 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 ve parametrelerin 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 sorar; küresel veya projeye özel. +2. Agent'ın ne yapması gerektiğinin açıklamasını ister. +3. Uygun bir sistem prompt'u ve tanımlayıcı oluşturur. +4. Agent'ın hangi araçlara erişebileceğini seçmenize izin verir. +5. Son olarak agent yapılandırmasıyla bir Markdown dosyası oluşturur. + +--- + +## 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 +``` + +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 new file mode 100644 index 00000000000..ae151bd5c9d --- /dev/null +++ b/packages/web/src/content/docs/tr/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: opencode CLI seçenekleri ve komutları. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +opencode CLI herhangi bir argüman olmadan çalıştırıldığında varsayılan olarak [TUI](/docs/tui)'yi başlatır. + +```bash +opencode +``` + +Ancak bu sayfada belgelendiği gibi komutları da kabul eder. Bu, opencode ile programlı olarak etkileşim kurmanıza olanak tanır. + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +opencode terminal kullanıcı arayüzünü başlatır. + +```bash +opencode [project] +``` + +#### Bayraklar + +| Bayrak | Kısa | Açıklama | +| ------------ | ---- | --------------------------------------------------------------------------- | +| `--continue` | `-c` | Son oturuma devam et | +| `--session` | `-s` | Devam edecek oturum kimliği | +| `--fork` | | Devam ederken oturumu fork'lar (`--continue` veya `--session` ile kullanın) | +| `--prompt` | | Kullanılacak prompt | +| `--model` | `-m` | provider/model biçiminde kullanılacak model | +| `--agent` | | Kullanılacak agent | +| `--port` | | Dinlenecek port | +| `--hostname` | | Dinlenecek host adı | + +--- + +## Komutlar + +opencode CLI ayrıca aşağıdaki komutlara da sahiptir. + +--- + +### agent + +opencode için agent'ları yönetin. + +```bash +opencode agent [command] +``` + +--- + +### attach + +`serve` veya `web` komutlarıyla başlatılan, halihazırda çalışan bir opencode arka uç sunucusuna bir terminal ekleyin. + +```bash +opencode attach [url] +``` + +Bu, TUI öğesinin uzak bir opencode arka ucuyla kullanılmasına olanak tanır. Örneğin: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### Bayraklar + +| Bayrak | Kısa | Tanım | +| ----------- | ---- | ------------------------------------ | +| `--dir` | | TUI'yi başlatmak için çalışma dizini | +| `--session` | `-s` | Devam edecek oturum açma bilgileri | + +--- + +#### create + +Özel yapılandırmaya sahip yeni bir agent oluşturun. + +```bash +opencode agent create +``` + +Bu komut, özel sistem istemi ve araç yapılandırmasıyla yeni bir agent oluşturma konusunda size yol gösterecektir. + +--- + +#### list + +Mevcut tüm agent'ları listeleyin. + +```bash +opencode agent list +``` + +--- + +### auth + +Sağlayıcılar için kimlik bilgilerini ve oturum açmayı yönetme komutu. + +```bash +opencode auth [command] +``` + +--- + +#### login + +opencode, [Models.dev](https://models.dev) adresindeki sağlayıcı listesi tarafından desteklenmektedir, dolayısıyla kullanmak istediğiniz herhangi bir sağlayıcı için API anahtarlarını ayarlamak üzere `opencode auth login` kullanabilirsiniz. Bu `~/.local/share/opencode/auth.json`'de saklanıyor. + +```bash +opencode auth login +``` + +opencode başlatıldığında sağlayıcıları kimlik bilgileri dosyasından yükler. Ayrıca ortam değişkenlerindeki veya projenizdeki `.env` dosyasındaki anahtarları da kullanır. + +--- + +#### list + +Kimlik bilgileri dosyasında depolanan tüm kimliği doğrulanmış sağlayıcıları listeler. + +```bash +opencode auth list +``` + +Veya kısa versiyonu. + +```bash +opencode auth ls +``` + +--- + +#### logout + +Bir sağlayıcıyı kimlik bilgileri dosyasından temizleyerek oturumunuzu kapatır. + +```bash +opencode auth logout +``` + +--- + +### github + +Depo otomasyonu için GitHub aracısını yönetin. + +```bash +opencode github [command] +``` + +--- + +#### install + +GitHub aracısını deponuza yükleyin. + +```bash +opencode github install +``` + +Bu komut gerekli GitHub Actions workflow'unu kurar ve yapılandırma adımlarında size rehberlik eder. [Daha fazla bilgi](/docs/github). + +--- + +#### run + +GitHub aracısını çalıştırın. Bu genellikle GitHub Eylemlerinde kullanılır. + +```bash +opencode github run +``` + +##### Bayraklar + +| Bayrak | Açıklama | +| --------- | ------------------------------------------- | +| `--event` | Aracıyı çalıştırmak için GitHub sahte olayı | +| `--token` | GitHub personal access token | + +--- + +### mcp + +Model Bağlam Protokolü sunucularını yönetin. + +```bash +opencode mcp [command] +``` + +--- + +#### add + +Yapılandırmanıza bir MCP sunucusu ekleyin. + +```bash +opencode mcp add +``` + +Bu komut, yerel veya uzak bir MCP sunucusu ekleme konusunda size yol gösterecektir. + +--- + +#### list + +Yapılandırılmış tüm MCP sunucularını ve bağlantı durumlarını listeleyin. + +```bash +opencode mcp list +``` + +Veya kısa versiyonunu kullanın. + +```bash +opencode mcp ls +``` + +--- + +#### auth + +OAuth'un etkin olduğu bir MCP sunucusuyla kimlik doğrulaması yapın. + +```bash +opencode mcp auth [name] +``` + +Sunucu adı belirtmezseniz mevcut OAuth özellikli sunucular arasından seçim yapmanız istenir. + +Ayrıca OAuth özellikli sunucuları ve bunların kimlik doğrulama durumlarını da listeleyebilirsiniz. + +```bash +opencode mcp auth list +``` + +Veya kısa versiyonunu kullanın. + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +MCP sunucusu için OAuth kimlik bilgilerini kaldırın. + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +MCP sunucusu için OAuth bağlantı sorunlarının hatalarını ayıklayın. + +```bash +opencode mcp debug +``` + +--- + +### models + +Yapılandırılmış sağlayıcıların tüm mevcut modellerini listeleyin. + +```bash +opencode models [provider] +``` + +Bu komut, yapılandırdığınız sağlayıcılardaki modelleri `provider/model` formatında listeler. + +Bu, [config dosyanızda](/docs/config/) kullanmanız gereken tam model adını bulmak için kullanışlıdır. + +Modelleri bu sağlayıcıya göre filtrelemek için isteğe bağlı olarak bir sağlayıcı kimliğini iletebilirsiniz. + +```bash +opencode models anthropic +``` + +#### Bayraklar + +| Bayrak | Tanım | +| ----------- | --------------------------------------------------------------------------- | +| `--refresh` | Modeller.dev'den model önbelleğini yenileyin | +| `--verbose` | Daha ayrıntılı model çıktısı kullanın (maliyetler gibi meta veriler içerir) | + +Önbelleğe alınan model listesini güncellemek için `--refresh` bayrağını kullanın. Bu, bir sağlayıcıya yeni modeller eklendiğinde ve bunları opencode'da görmek istediğinizde kullanışlıdır. + +```bash +opencode models --refresh +``` + +--- + +### run + +Doğrudan bir istem ileterek opencode'u etkileşimli olmayan modda çalıştırın. + +```bash +opencode run [message..] +``` + +Bu, komut dosyası oluşturma, otomasyon veya TUI'un tamamını başlatmadan hızlı bir yanıt istediğinizde kullanışlıdır. Örneğin. + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +Ayrıca, her çalıştırmada MCP sunucusunun soğuk önyükleme sürelerini önlemek için çalışan bir `opencode serve` örneğine de ekleyebilirsiniz: + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### Bayraklar + +| Bayrak | Kısa | Açıklama | +| ------------ | ---- | --------------------------------------------------------------------------------- | +| `--command` | | Çalıştırılacak komut, args için mesajı kullanın | +| `--continue` | `-c` | Son oturuma devam et | +| `--session` | `-s` | Devam edecek oturum kimliği | +| `--fork` | | Devam ederken oturumu fork'lar (`--continue` veya `--session` ile kullanın) | +| `--share` | | Oturumu paylaşın | +| `--model` | `-m` | provider/model biçiminde kullanılacak model | +| `--agent` | | Kullanılacak temsilci | +| `--file` | `-f` | Mesaja eklenecek dosya(lar) | +| `--format` | | Biçim: varsayılan (biçimlendirilmiş) veya json (ham JSON olayları) | +| `--title` | | Oturumun başlığı (değer sağlanmazsa kısaltılmış bilgi istemi kullanılır) | +| `--attach` | | Çalışan bir opencode sunucusuna ekleyin (ör. http://localhost:4096) | +| `--port` | | Yerel sunucunun bağlantı noktası (varsayılan olarak rastgele bağlantı noktasıdır) | + +--- + +### serve + +API erişimi için headless bir opencode sunucusu başlatır. Tam HTTP arayüzü için [server docs](/docs/server) sayfasına bakın. + +```bash +opencode serve +``` + +Bu, TUI arayüzü olmadan opencode işlevselliğine API erişimi sağlayan bir HTTP sunucusunu başlatır. HTTP temel kimlik doğrulamasını etkinleştirmek için `OPENCODE_SERVER_PASSWORD` öğesini ayarlayın (kullanıcı adı varsayılan olarak `opencode` şeklindedir). + +#### Bayraklar + +| Bayrak | Tanım | +| ------------ | ------------------------------------------ | +| `--port` | Dinlenecek bağlantı noktası | +| `--hostname` | Dinlenecek ana bilgisayar adı | +| `--mdns` | mDNS bulmayı etkinleştir | +| `--cors` | CORS'a izin verecek ek tarayıcı kaynakları | + +--- + +### session + +opencode oturumlarını yönetin. + +```bash +opencode session [command] +``` + +--- + +#### list + +Tüm opencode oturumlarını listeleyin. + +```bash +opencode session list +``` + +##### Bayraklar + +| Bayrak | Kısa | Tanım | +| ------------- | ---- | -------------------------------------- | +| `--max-count` | `-n` | En son N oturumla sınırla | +| `--format` | | Çıkış formatı: tablo veya json (tablo) | + +--- + +### stats + +opencode oturumlarınız için belirteç kullanımı ve maliyet istatistiklerini gösterin. + +```bash +opencode stats +``` + +#### Bayraklar + +| Bayrak | Açıklama | +| ----------- | ----------------------------------------------------------------------------------------------------------- | +| `--days` | Son N güne ait istatistikleri göster (tüm zamanlar) | +| `--tools` | Gösterilecek araç sayısı (tümü) | +| `--models` | Model kullanım dökümünü göster (varsayılan olarak gizlidir). En üstteki N'yi göstermek için bir sayı iletin | +| `--project` | Projeye göre filtrele (tüm projeler, boş değer: mevcut proje) | + +--- + +### export + +Oturum verilerini JSON olarak dışa aktarın. + +```bash +opencode export [sessionID] +``` + +Bir oturum kimliği sağlamazsanız mevcut oturumlar arasından seçim yapmanız istenir. + +--- + +### import + +Bir JSON dosyasından veya opencode paylaşımından URL oturum verilerini içe aktarın. + +```bash +opencode import +``` + +Yerel bir dosyadan veya opencode paylaşımından (URL) içe aktarabilirsiniz. + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +Web arayüzüyle başsız bir opencode sunucusu başlatın. + +```bash +opencode web +``` + +Bu, bir HTTP sunucusunu başlatır ve bir web arayüzü aracılığıyla opencode'a erişmek için bir web tarayıcısı açar. HTTP temel kimlik doğrulamasını etkinleştirmek için `OPENCODE_SERVER_PASSWORD` öğesini ayarlayın (kullanıcı adı varsayılan olarak `opencode` şeklindedir). + +#### Bayraklar + +| Bayrak | Tanım | +| ------------ | ------------------------------------------ | +| `--port` | Dinlenecek bağlantı noktası | +| `--hostname` | Dinlenecek ana bilgisayar adı | +| `--mdns` | mDNS bulmayı etkinleştir | +| `--cors` | CORS'a izin verecek ek tarayıcı kaynakları | + +--- + +### acp + +Bir ACP (Ajan İstemci Protokolü) sunucusu başlatın. + +```bash +opencode acp +``` + +Bu komut, nd-JSON kullanarak stdin/stdout aracılığıyla iletişim kuran bir ACP sunucusunu başlatır. + +#### Bayraklar + +| Bayrak | Açıklama | +| ------------ | ------------------- | +| `--cwd` | Çalışma dizini | +| `--port` | Dinlenecek port | +| `--hostname` | Dinlenecek host adı | + +--- + +### uninstall + +opencode'u kaldırın ve ilgili tüm dosyaları kaldırın. + +```bash +opencode uninstall +``` + +#### Bayraklar + +| Bayrak | Kısa | Tanım | +| --------------- | ---- | ----------------------------------------------- | +| `--keep-config` | `-c` | Yapılandırma dosyalarını sakla | +| `--keep-data` | `-d` | Oturum verilerini ve anlık görüntüleri saklayın | +| `--dry-run` | | Nelerin kaldırılmadan kaldırılacağı göster | +| `--force` | `-f` | Onay istemlerini atla | + +--- + +### upgrade + +opencode'u en son sürüme veya belirli bir sürüme günceller. + +```bash +opencode upgrade [target] +``` + +En son sürüme yükseltmek için. + +```bash +opencode upgrade +``` + +Belirli bir sürüme yükseltmek için: + +```bash +opencode upgrade v0.1.48 +``` + +#### Bayraklar + +| Bayrak | Kısa | Açıklama | +| ---------- | ---- | ------------------------------------------------------ | +| `--method` | `-m` | Kullanılan kurulum yöntemi: curl, npm, pnpm, bun, brew | + +--- + +## Global bayraklar + +opencode CLI aşağıdaki global bayrakları destekler. + +| Bayrak | Kısa | Tanım | +| -------------- | ---- | ---------------------------------------- | +| `--help` | `-h` | Yardımı görüntüle | +| `--version` | `-v` | Sürüm numarasını yazdır | +| `--print-logs` | | Günlükleri stderr'e yazdır | +| `--log-level` | | Günlük düzeyi (DEBUG, INFO, WARN, ERROR) | + +--- + +## Ortam değişkenleri + +opencode ortam değişkenleri kullanılarak yapılandırılabilir. + +| Değişken | Tip | Açıklama | +| ------------------------------------- | ------- | --------------------------------------------------------------------------- | +| `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_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 | +| `OPENCODE_DISABLE_PRUNE` | boolean | Eski verilerin temizlenmesini devre dışı bırak | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | Otomatik terminal başlığı güncellemelerini devre dışı bırakın | +| `OPENCODE_PERMISSION` | string | Satır içi JSON izin config'i | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | Varsayılan eklentileri devre dışı bırakın | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | Otomatik LSP sunucu indirmelerini devre dışı bırakın | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | Deneysel modelleri etkinleştir | +| `OPENCODE_DISABLE_AUTOCOMPACT` | boolean | Otomatik context sıkıştırmayı devre dışı bırak | +| `OPENCODE_DISABLE_CLAUDE_CODE` | boolean | `.claude`'den okumayı devre dışı bırak (istem + beceriler) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | `~/.claude/CLAUDE.md` dosyasını okumayı devre dışı bırak | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | `.claude/skills` yüklemesini devre dışı bırak | +| `OPENCODE_DISABLE_MODELS_FETCH` | boolean | Uzak kaynaklardan model getirmeyi devre dışı bırakın | +| `OPENCODE_FAKE_VCS` | string | Test amaçlı sahte VCS sağlayıcısı | +| `OPENCODE_DISABLE_FILETIME_CHECK` | boolean | Optimizasyon için dosya süresi kontrolünü devre dışı bırakın | +| `OPENCODE_CLIENT` | string | Client kimliği (varsayılan: `cli`) | +| `OPENCODE_ENABLE_EXA` | boolean | Exa web arama araçlarını etkinleştir | +| `OPENCODE_SERVER_PASSWORD` | string | `serve`/`web` için temel kimlik doğrulamayı etkinleştirin | +| `OPENCODE_SERVER_USERNAME` | string | Temel kimlik doğrulama kullanıcı adını geçersiz kıl (varsayılan `opencode`) | +| `OPENCODE_MODELS_URL` | string | Model yapılandırmasını almak için özel URL | + +--- + +### Deneysel + +Bu ortam değişkenleri değişebilecek veya kaldırılabilecek deneysel özellikleri etkinleştirir. + +| Değişken | Tip | Tanım | +| ----------------------------------------------- | ------- | ------------------------------------------------------- | +| `OPENCODE_EXPERIMENTAL` | boolean | Tüm deneysel özellikleri etkinleştir | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | Simge bulmayı etkinleştir | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | TUI'da seçim yapıldığında kopyalamayı devre dışı bırak | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number | MS cinsinden bash komutları için varsayılan zaman aşımı | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | number | LLM yanıtları için maksimum çıktı belirteçleri | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolean | Tüm dizin için dosya izleyiciyi etkinleştir | +| `OPENCODE_EXPERIMENTAL_OXFMT` | boolean | Oxfmt biçimlendiriciyi etkinleştir | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolean | Deneysel LSP aracını etkinleştir | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | Dosya izleyiciyi devre dışı bırak | +| `OPENCODE_EXPERIMENTAL_EXA` | boolean | Deneysel Exa özelliklerini etkinleştirin | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolean | Deneysel LSP tür denetimini etkinleştir | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolean | Deneysel işaretleme özelliklerini etkinleştir | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolean | Plan modunu etkinleştir | diff --git a/packages/web/src/content/docs/tr/commands.mdx b/packages/web/src/content/docs/tr/commands.mdx new file mode 100644 index 00000000000..a37e98f4ecc --- /dev/null +++ b/packages/web/src/content/docs/tr/commands.mdx @@ -0,0 +1,323 @@ +--- +title: Komutlar +description: Tekrarlanan görevler için özel komutlar oluşturulur. +--- + +Özel komutlar, söz konusu komut TUI'da yürütüldüğünde çalıştırmak istediğiniz istemi belirtmenize olanak tanır. + +```bash frame="none" +/my-command +``` + +Özel komutlar, `/init`, `/undo`, `/redo`, `/share`, `/help` gibi komutlara ek olarak sunulur. [Daha fazla bilgi](/docs/tui#commands). + +--- + +## Komut dosyaları oluşturma + +Özel komutları tanımlamak için `commands/` dizininde işaretleme dosyaları oluşturun. + +`.opencode/commands/test.md` oluştur: + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Ön madde komut özelliklerini tanımlar. İçerik şablon haline gelir. + +`/` ve ardından komut adını yazarak komutu kullanın. + +```bash frame="none" +"/test" +``` + +--- + +## Yapılandırma + +opencode işlemleri aracılığıyla veya `commands/` dizininde işaretleme dosyalarının oluşturulması özel komutlar ile yapılabilir. + +--- + +### JSON + +opencode [config](/docs/config)'deki `command` seçeneğini kullanın: + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Artık bu komutu TUI'da çalıştırabilirsiniz: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +Markdown dosyalarını kullanarak komutları da tanımlayabilirsiniz. Bunları şuraya yerleştirin: + +- Küresel: `~/.config/opencode/commands/` +- Proje başına: `.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Markdown dosyasının adı komut adı olur. Örneğin, `test.md` şunu sağlar: +sen koşuyorsun: + +```bash frame="none" +/test +``` + +--- + +## İstem yapılandırması + +Özel komut istemleri birçok özel yer tutucuyu ve sözdizimini destekler. + +--- + +### Argümanlar + +`$ARGUMENTS` yer tutucusunu kullanarak komutlara argümanları iletin. + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +Komutu bağımsız değişkenlerle çalıştırın: + +```bash frame="none" +/component Button +``` + +Ve `$ARGUMENTS`, `Button` ile değiştirilecektir. + +Konumsal parametreleri kullanarak bağımsız değişkenlere de erişebilirsiniz: + +- `$1` - İlk argüman +- `$2` - İkinci argüman +- `$3` - Üçüncü argüman +- Ve benzeri... + +Örneğin: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +Komutu çalıştırın: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +Bu şunun yerini alır: + +- `$1` ile `config.json` +- `$2` ile `src` +- `$3` ile `{ "key": "value" }` + +--- + +### Shell output + +İsteminize [bash command](/docs/tui#bash-commands) çıktısını enjekte etmek için \__!`command`_ kullanın. + +Örneğin, test kapsamını analiz eden özel bir komut oluşturmak için: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +Or to review recent changes: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +Komutlar projenizin kök dizininde çalışır ve çıktıları istemin bir parçası olur. + +--- + +### Dosya referansları + +Komutunuza `@` ve ardından dosya adını kullanarak dosyaları ekleyin. + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +Dosya içeriği otomatik olarak istemde yer alır. + +--- + +## Seçenekler + +Yapılandırma seçeneklerine ayrıntılı olarak bakalım. + +--- + +### Şablon + +`template` seçeneği, komut yürütüldüğünde LLM'ye gönderilecek olan istemi tanımlar. + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +Bu **gerekli** bir yapılandırma seçeneğidir. + +--- + +### Açıklama + +Komutun ne yaptığına ilişkin kısa bir açıklama sağlamak için `description` seçeneğini kullanın. + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +Bu, komutu yazdığınızda TUI içindeki açıklama olarak gösterilir. + +--- + +### Ajan + +İsteğe bağlı olarak bu komutu hangi [agent](/docs/agents)'nin yürütmesi gerektiğini belirtmek için `agent` yapılandırmasını kullanın. +Bu bir [subagent](/docs/agents/#subagents) ise, komut varsayılan olarak bir alt aracı çağrısını tetikleyecektir. +Bu davranışı devre dışı bırakmak için `subtask` öğesini `false` olarak ayarlayın. + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +Bu **isteğe bağlı** bir yapılandırma seçeneğidir. Belirtilmemişse, varsayılan olarak mevcut temsilciniz kullanılır. + +--- + +### Subtask + +Komutu bir [subagent](/docs/agents/#subagents) çağrısını tetiklemeye zorlamak için `subtask` boolean'ını kullanın. +Bu, komutun birincil bağlamınızı kirletmemesini ve aracıyı bir alt aracı olarak davranmaya **zorlamasını** istiyorsanız kullanışlıdır. +`mode`, [agent](/docs/agents) yapılandırmasında `primary` olarak ayarlanmış olsa bile. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +Bu **isteğe bağlı** bir yapılandırma seçeneğidir. + +--- + +### Modeli + +Bu parçanın varsayılan kodu geçersiz için `model` kontrolünü kullanın. + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +Bu **isteğe bağlı** bir yapılandırma seçeneğidir. + +--- + +## Yerleşik + +opencode, `/init`, `/undo`, `/redo`, `/share`, `/help` gibi çeşitli yerleşik komutlar içerir; [learn more](/docs/tui#commands). + +:::note +Özel komutlar yerleşik komutları geçersiz kılabilir. +::: + +Aynı adda özel bir komut tanımlarsanız yerleşik komutu geçersiz kılar. diff --git a/packages/web/src/content/docs/tr/config.mdx b/packages/web/src/content/docs/tr/config.mdx new file mode 100644 index 00000000000..fe60991c626 --- /dev/null +++ b/packages/web/src/content/docs/tr/config.mdx @@ -0,0 +1,685 @@ +--- +title: Yapılandırma +description: opencode JSON yapılandırması kullanır. +--- + +opencode'u JSON yapılandırma dosyası kullanarak yapılandırabilirsiniz. + +--- + +## Format + +opencode hem **JSON** hem de **JSONC** (JSON Yorumlarla birlikte) formatlarını destekler. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + // Theme configuration + "theme": "opencode", + "model": "anthropic/claude-sonnet-4-5", + "autoupdate": true, +} +``` + +--- + +## Konumlar + +Yapılandırmanızı birkaç farklı konuma yerleştirebilirsiniz ve bunların +farklı öncelik sırası vardır. + +:::note +Yapılandırma dosyaları **birleştirilir**, değiştirilmez. +::: + +Yapılandırma dosyaları değiştirilmez, birleştirilir. Aşağıdaki yapılandırma konumlarındaki ayarlar birleştirilir. Daha sonraki yapılandırmalar, yalnızca çakışan anahtarlar için önceki yapılandırmaları geçersiz kılar. Tüm yapılandırmalardaki çakışmayan ayarlar korunur. + +Örneğin, genel ayarınız `theme: "opencode"` ve `autoupdate: true`'yi ayarlıyorsa ve proje ayarlarınız `model: "anthropic/claude-sonnet-4-5"`'yi ayarlıyorsa, nihai yapılandırma üç ayarı da içerecektir. + +--- + +### Öncelik sırası + +Yapılandırma kaynakları bu sırayla yüklenir (sonraki kaynaklar öncekileri geçersiz kılar): + +1. **Uzak yapılandırma** (`.well-known/opencode`'dan) - kurumsal varsayılanlar +2. **Genel yapılandırma** (`~/.config/opencode/opencode.json`) - kullanıcı tercihleri +3. **Özel yapılandırma** (`OPENCODE_CONFIG` env var) - özel geçersiz kılmalar +4. **Proje yapılandırması** (projedeki `opencode.json`) - projeye özgü ayarlar +5. **`.opencode` dizinleri** - agent'lar, komutlar, eklentiler +6. **Satır içi yapılandırma** (`OPENCODE_CONFIG_CONTENT` env var) - çalışma zamanı geçersiz kılmaları + +Bu, proje yapılandırmalarının genel varsayılanları geçersiz kılabileceği ve genel yapılandırmaların uzak organizasyonel varsayılanları geçersiz kılabileceği anlamına gelir. + +:::note +`.opencode` ve `~/.config/opencode` dizinleri alt dizinler için **çoğul adlar** kullanır: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/` ve `themes/`. Tekil adlar (örneğin, `agent/`) da geriye dönük uyumluluk açısından desteklenir. +::: + +--- + +### Uzak + +Kuruluşlar, `.well-known/opencode` uç noktası aracılığıyla varsayılan yapılandırmayı sağlayabilir. Bu, onu destekleyen bir sağlayıcıyla kimlik doğrulaması yaptığınızda otomatik olarak alınır. + +Uzak yapılandırma ilk olarak yüklenir ve temel katman görevi görür. Diğer tüm yapılandırma kaynakları (genel, proje) bu varsayılanları geçersiz kılabilir. + +Örneğin, kuruluşunuz varsayılan olarak devre dışı bırakılan MCP sunucuları sağlıyorsa: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +Yerel yapılandırmanızda belirli sunucuları etkinleştirebilirsiniz: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### Global + +Global opencode yapılandırmanızı `~/.config/opencode/opencode.json` içine yerleştirin. Temalar, sağlayıcılar veya tuş atamaları gibi kullanıcı çapındaki tercihler için genel yapılandırmayı kullanın. + +Genel yapılandırma, uzak kurumsal varsayılanları geçersiz kılar. + +--- + +### Proje başına + +Proje kökünüze `opencode.json` ekleyin. Proje yapılandırması, standart yapılandırma dosyaları arasında en yüksek önceliğe sahiptir; hem genel hem de uzak yapılandırmaları geçersiz kılar. + +:::tip +Projeye özel yapılandırmayı projenizin köküne yerleştirin. +::: + +opencode başlatıldığında geçerli dizinde bir yapılandırma dosyası arar veya en yakın Git dizinine gider. + +Bunun Git'te kontrol edilmesi de güvenlidir ve global olanla aynı şemayı kullanır. + +--- + +### Özel yol + +`OPENCODE_CONFIG` ortam değişkenini kullanarak özel bir yapılandırma dosyası yolu belirtin. + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +Özel yapılandırma genel ve proje yapılandırmaları arasında öncelik sırasına göre yüklenir. + +--- + +### Özel dizin + +`OPENCODE_CONFIG_DIR` kullanarak özel bir yapılandırma dizini belirtin +ortam değişkeni. Bu dizin agent'lar, komutlar için aranacaktır. +modlar ve eklentiler tıpkı standart `.opencode` dizini gibi olmalıdır ve +aynı yapıyı takip edin. + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +Özel dizin, genel yapılandırma ve `.opencode` dizinlerinden sonra yüklenir, böylece bunların ayarlarını **geçersiz kılabilir**. + +--- + +## Şema + +Yapılandırma dosyası [**`opencode.ai/config.json`**](https://opencode.ai/config.json)'da tanımlanan bir şemaya sahiptir. + +Editörünüz şemaya göre doğrulama ve otomatik tamamlama yapabilmelidir. + +--- + +### TUI + +TUI'ye özgü ayarları `tui` seçeneği aracılığıyla yapılandırabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +Mevcut seçenekler: + +- `scroll_acceleration.enabled` - MacOS tarzı kaydırma hızlandırmayı etkinleştirin. **`scroll_speed`'ye göre önceliklidir.** +- `scroll_speed` - Özel kaydırma hızı çarpanı (varsayılan: `3`, minimum: `1`). `scroll_acceleration.enabled` `true` ise dikkate alınmaz. +- `diff_style` - Fark oluşturmayı kontrol edin. `"auto"` terminal genişliğine uyum sağlar, `"stacked"` her zaman tek sütunu gösterir. + +[TUI kullanımı hakkında daha fazla bilgi](/docs/tui). + +--- + +### Sunucu + +`opencode serve` ve `opencode web` komutları için sunucu ayarlarını `server` seçeneği aracılığıyla yapılandırabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +Mevcut seçenekler: + +- `port` - Dinlenecek port. +- `hostname` - Dinlenecek ana bilgisayar adı. `mdns` etkinleştirildiğinde ve hiçbir ana bilgisayar adı ayarlanmadığında, varsayılan değer `0.0.0.0` olur. +- `mdns` - mDNS hizmet bulmayı etkinleştirin. Bu, ağdaki diğer cihazların opencode sunucunuzu keşfetmesine olanak tanır. +- `mdnsDomain` - mDNS hizmeti için özel alan adı. Varsayılan olarak `opencode.local` şeklindedir. Aynı ağda birden fazla örneği çalıştırmak için kullanışlıdır. +- `cors` - Tarayıcı tabanlı bir istemciden HTTP sunucusunu kullanırken CORS'ye izin verecek ek kaynaklar. Değerler tam kaynaklar olmalıdır (şema + ana bilgisayar + isteğe bağlı bağlantı noktası), örneğin `https://app.example.com`. + +[Sunucu hakkında daha fazla bilgi](/docs/server). + +--- + +### Araçlar + +Bir LLM'nin kullanabileceği araçları `tools` seçeneği aracılığıyla yönetebilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[Araçlar hakkında daha fazla bilgi](/docs/tools). + +--- + +### Modeller + +opencode yapılandırmanızda kullanmak istediğiniz sağlayıcıları ve modelleri `provider`, `model` ve `small_model` seçenekleri aracılığıyla yapılandırabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +`small_model` seçeneği, başlık oluşturma gibi hafif görevler için ayrı bir model yapılandırır. Varsayılan olarak opencode, sağlayıcınızda mevcutsa daha ucuz bir model kullanmaya çalışır, aksi takdirde ana modelinize geri döner. + +Sağlayıcı seçenekleri `timeout` ve `setCacheKey` içerebilir: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` - Milisaniye cinsinden istek zaman aşımı (varsayılan: 300000). Devre dışı bırakmak için `false` olarak ayarlayın. +- `setCacheKey` - Belirlenen sağlayıcı için her zaman bir önbellek anahtarının ayarlandığından emin olun. + +Ayrıca [local models](/docs/models#local) ayarlayabilirsiniz. [Daha fazla bilgi](/docs/models). + +--- + +#### Sağlayıcıya Özel Seçenekler + +Bazı sağlayıcılar genel `timeout` ve `apiKey` ayarlarının ötesinde ek yapılandırma seçeneklerini destekler. + +##### Amazon Bedrock + +Amazon Bedrock, AWS'a özgü yapılandırmayı destekler: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` - Bedrock için AWS bölgesi (varsayılanı `AWS_REGION` env var veya `us-east-1`'dir) +- `profile` - `~/.aws/credentials`'den AWS adlı profil (varsayılanı `AWS_PROFILE` env var'dır) +- `endpoint` - VPC uç noktaları için özel uç nokta URL. Bu, AWS'e özgü terminolojiyi kullanan genel `baseURL` seçeneğinin takma adıdır. Her ikisi de belirtilirse `endpoint` öncelikli olur. + +:::note +Taşıyıcı belirteçleri (`AWS_BEARER_TOKEN_BEDROCK` veya `/connect`) profil tabanlı kimlik doğrulamaya göre önceliklidir. Ayrıntılar için [authentication precedence](/docs/providers#authentication-precedence)'ye bakın. +::: + +[Amazon Bedrock yapılandırması hakkında daha fazla bilgi](/docs/providers#amazon-bedrock). + +--- + +### Temalar + +opencode yapılandırmanızda kullanmak istediğiniz temayı `theme` seçeneği aracılığıyla yapılandırabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[Daha fazla bilgi](/docs/themes). + +--- + +### Agent'lar + +`agent` seçeneği aracılığıyla özel görevlere yönelik özel agent'ları yapılandırabilirsiniz. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + "bash": true, + }, + }, + }, +} +``` + +Agent'ları `~/.config/opencode/agents/` veya `.opencode/agents/` içindeki Markdown dosyalarıyla da tanımlayabilirsiniz. [Daha fazla bilgi](/docs/agents). + +--- + +### Varsayılan agent + +`default_agent` seçeneğini kullanarak varsayılan agent'ı ayarlayabilirsiniz. Bu, hiçbiri açıkça belirtilmediğinde hangi agent'ın kullanılacağını belirler. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +Varsayılan agent, birincil agent olmalıdır (alt agent değil). Bu, `"build"` veya `"plan"` gibi yerleşik bir agent ya da tanımladığınız bir [özel agent](/docs/agents) olabilir. Belirtilen agent mevcut değilse veya bir alt agent ise, opencode bir uyarıyla birlikte `"build"`'ye geri döner. + +Bu ayar tüm arayüzler için geçerlidir: TUI, CLI (`opencode run`), masaüstü uygulaması ve GitHub Action. + +--- + +### Paylaşma + +[share](/docs/share) özelliğini `share` seçeneği aracılığıyla yapılandırabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +Bu şunları gerektirir: + +- `"manual"` - Komutlar aracılığıyla manuel paylaşıma izin ver (varsayılan) +- `"auto"` - Yeni konuşmaları otomatik olarak paylaş +- `"disabled"` - Paylaşımı tamamen devre dışı bırak + +Varsayılan olarak paylaşım, `/share` komutunu kullanarak konuşmaları açıkça paylaşmanız gereken manuel moda ayarlanmıştır. + +--- + +### Komutlar + +`command` seçeneği aracılığıyla tekrarlanan görevler için özel komutlar yapılandırabilirsiniz. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +Komutları `~/.config/opencode/commands/` veya `.opencode/commands/` içindeki Markdown dosyalarıyla da tanımlayabilirsiniz. [Daha fazla bilgi](/docs/commands). + +--- + +### Tuş atamaları + +Tuş atamalarınızı `keybinds` seçeneği aracılığıyla özelleştirebilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[Daha fazla bilgi](/docs/keybinds). + +--- + +### Otomatik Güncelleme + +opencode başlatıldığında yeni güncellemeleri otomatik olarak indirecektir. Bunu `autoupdate` seçeneğiyle devre dışı bırakabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +Güncelleme istemiyor ancak yeni bir sürüm mevcut olduğunda bilgilendirilmek istiyorsanız `autoupdate` öğesini `"notify"` olarak ayarlayın. +Bunun yalnızca Homebrew gibi bir paket yöneticisi kullanılarak yüklenmemişse işe yaradığına dikkat edin. + +--- + +### Biçimlendiriciler + +Kod formatlayıcılarını `formatter` seçeneği aracılığıyla yapılandırabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[Formatter'lar hakkında daha fazla bilgi](/docs/formatters). + +--- + +### İzinler + +Varsayılan olarak, opencode açık bir onay gerektirmeden **tüm işlemlere izin verir**. `permission` seçeneğini kullanarak bunu değiştirebilirsiniz. + +Örneğin, `edit` ve `bash` araçlarının kullanıcı onayı gerektirdiğinden emin olmak için: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[İzinler hakkında daha fazla bilgi](/docs/permissions). + +--- + +### Sıkıştırma + +Bağlam sıkıştırma davranışını `compaction` seçeneği aracılığıyla kontrol edebilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `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`). + +--- + +### İzleyici + +Dosya izleyicinin yok sayma kalıplarını `watcher` seçeneği aracılığıyla yapılandırabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +Desenler glob sözdizimini takip eder. Gürültülü dizinleri dosya izlemenin dışında bırakmak için bunu kullanın. + +--- + +### MCP sunucuları + +Kullanmak istediğiniz MCP sunucularını `mcp` seçeneği aracılığıyla yapılandırabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[Daha fazla bilgi](/docs/mcp-servers). + +--- + +### Eklentiler + +[Eklentiler](/docs/plugins) opencode'u özel araçlar, kancalar ve entegrasyonlarla genişletin. + +Eklenti dosyalarını `.opencode/plugins/` veya `~/.config/opencode/plugins/` içine yerleştirin. Ayrıca eklentileri `plugin` seçeneği aracılığıyla npm'den de yükleyebilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[Daha fazla bilgi](/docs/plugins). + +--- + +### Talimatlar + +Kullandığınız modele ilişkin talimatları `instructions` seçeneği aracılığıyla yapılandırabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Bu, talimat dosyalarına giden bir dizi yolu ve glob desenini alır. [Kurallar hakkında daha fazla bilgiyi buradan edinin](/docs/rules). + +--- + +### Devre dışı bırakılan sağlayıcılar + +`disabled_providers` seçeneği aracılığıyla otomatik olarak yüklenen sağlayıcıları devre dışı bırakabilirsiniz. Bu, belirli sağlayıcıların kimlik bilgileri mevcut olsa bile yüklenmesini engellemek istediğinizde kullanışlıdır. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +`disabled_providers`, `enabled_providers`'ye göre önceliklidir. +::: + +`disabled_providers` seçeneği bir dizi sağlayıcı kimliğini kabul eder. Bir sağlayıcı devre dışı bırakıldığında: + +- Ortam değişkenleri ayarlanmış olsa bile yüklenmez. +- API anahtarları `/connect` komutu aracılığıyla yapılandırılsa bile yüklenmeyecektir. +- Sağlayıcının modelleri, model seçim listesinde görünmez. + +--- + +### Etkin sağlayıcılar + +`enabled_providers` seçeneğini kullanarak sağlayıcıların izin verilenler listesini belirtebilirsiniz. Ayarlandığında yalnızca belirtilen sağlayıcılar etkinleştirilecek ve diğerleri göz ardı edilecektir. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +Bu, opencode'u tek tek devre dışı bırakmak yerine yalnızca belirli sağlayıcıları kullanacak şekilde kısıtlamak istediğinizde kullanışlıdır. + +:::note +`disabled_providers`, `enabled_providers`'ye göre önceliklidir. +::: + +Bir sağlayıcı hem `enabled_providers` hem de `disabled_providers`'de görünüyorsa, geriye dönük uyumluluk için `disabled_providers` önceliğe sahiptir. + +--- + +### Deneysel + +`experimental` anahtarı aktif olarak geliştirilmekte olan seçenekleri içerir. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +Deneysel seçenekler kararlı değildir. Bildirim yapılmaksızın değişebilir veya kaldırılabilirler. +::: + +--- + +## Değişkenler + +Ortam değişkenlerine ve dosya içeriklerine referans vermek için yapılandırma dosyalarınızda değişken değiştirmeyi kullanabilirsiniz. + +--- + +### Ortam değişkenleri + +Ortam değişkenlerini değiştirmek için `{env:VARIABLE_NAME}` kullanın: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +Ortam değişkeni ayarlanmamışsa boş bir dizeyle değiştirilecektir. + +--- + +### Dosyalar + +Bir dosyanın biçimini değiştirmek için `{file:path/to/file}` kullanın: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +Dosya yolları şunlar olabilir: + +- Yapılandırma dosyası dizinine göre +- Veya `/` veya `~` ile başlayan mutlak yollar + +Bunlar aşağıdakiler için faydalıdır: + +- API anahtarları gibi hassas verileri ayrı dosyalarda tutmak. +- Yapılandırmanızı karmaşıklaştırmadan büyük talimat dosyaları içerir. +- Birden fazla yapılandırma dosyasında ortak yapılandırma parçacıklarının paylaşılması. diff --git a/packages/web/src/content/docs/tr/custom-tools.mdx b/packages/web/src/content/docs/tr/custom-tools.mdx new file mode 100644 index 00000000000..cb6a12debb2 --- /dev/null +++ b/packages/web/src/content/docs/tr/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: Özel Araçlar +description: LLM'un opencode'da çağırabileceği araçları birleştirebilir. +--- + +Özel araçlar, LLM'un konuşmalar sırasında arayabileceği, oluşturduğunuz işlevlerdir. opencode'un [built-in tools](/docs/tools) ile birlikte `read`, `write` ve `bash` gibi çalışırlar. + +--- + +## Araç oluşturma + +Araçlar **TypeScript** veya **JavaScript** dosyaları olarak tanımlanır. Ancak araç tanımı **herhangi bir dilde** yazılmış komut dosyalarını çağırabilir; TypeScript veya JavaScript yalnızca araç tanımının kendisi için kullanılır. + +--- + +### Konum + +Bunlar tanımlanabilir: + +- Yerel olarak bunları projenizin `.opencode/tools/` dizinine yerleştirerek. +- Veya küresel olarak bunları `~/.config/opencode/tools/` içine yerleştirerek. + +--- + +### Yapı + +Araç oluşturmanın en kolay yolu, tür güvenliği ve doğrulama sağlayan `tool()` yardımcısını kullanmaktır. + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +**dosya adı**, **araç adı** olur. Yukarıdakiler bir `database` aracı oluşturur. + +--- + +#### Dosya başına birden fazla araç + +Ayrıca tek bir dosyadan birden fazla aracı dışa aktarabilirsiniz. Her dışa aktarma, **`_`** adıyla **ayrı bir araç** haline gelir: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +Bu iki araç oluşturur: `math_add` ve `math_multiply`. + +--- + +### 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. + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +Ayrıca [Zod](https://zod.dev) öğesini doğrudan içe aktarabilir ve düz bir nesne döndürebilirsiniz: + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### Bağlam + +Araçlar geçerli oturumla ilgili bağlamı alır: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +Oturum çalışma dizisi için `context.directory` kullanın. +Git çalışma ağacı kökü için `context.worktree` kullanın. + +--- + +## Örnekler + +### Python ile araç yazma + +Araçlarınızı dilediğiniz dilde yazabilirsiniz. İşte Python kullanarak iki sayıyı toplayan bir örnek. + +Öncelikle aracı bir Python betiği olarak oluşturun: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +Ardından onu çağıran araç tanımını oluşturun: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +Burada Python betiğini çalıştırmak için [`Bun.$`](https://bun.com/docs/runtime/shell) yardımcı programını kullanıyoruz. diff --git a/packages/web/src/content/docs/tr/ecosystem.mdx b/packages/web/src/content/docs/tr/ecosystem.mdx new file mode 100644 index 00000000000..835d9ba895b --- /dev/null +++ b/packages/web/src/content/docs/tr/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: Ekosistem +description: opencode ile ilgili tasarımlar ve entegrasyonlar. +--- + +opencode üzerine inşa edilmiş bir topluluk projeleri koleksiyonu. + +:::note +opencode ile ilgili projenizi bu listeye eklemek ister misiniz? Bir PR gönderin. +::: + +Ayrıca ekosistemi ve topluluğu bir araya getiren bir topluluk olan [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) ve [opencode.cafe](https://opencode.cafe)'e de göz atabilirsiniz. + +--- + +## Eklentiler + +| İsim | Açıklama | +| --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | opencode oturumlarını git senkronizasyonu ve canlı önizlemelerle izole Daytona sanal alanlarında otomatik olarak çalıştırın | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | İstek gruplaması için Helicone oturum başlıklarını otomatik olarak ekleme | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | Arama araçlarıyla TypeScript/Svelte türlerini dosya okumalarına otomatik olarak enjekte edin | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | API kredisi yerine ChatGPT Plus/Pro aboneliğinizi kullanın | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | API faturalandırma yerine mevcut Gemini planınızı kullanın | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | API faturalandırma yerine Antigravity'nin ücretsiz modellerini kullanın | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Sığ klonlar ve otomatik atanan bağlantı noktalarıyla çok dallı devcontainer izolasyonu | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Google Arama desteği ve daha sağlam API işleme özelliğiyle Google Antigravity OAuth Eklentisi | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Optimize token usage by pruning obsolete tool outputs | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Desteklenen sağlayıcılar için Google tabanlı stil ile yerel web araması desteği ekleyin | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Yapay zeka aracılarının bir PTY'de arka plan işlemlerini çalıştırmasına ve onlara etkileşimli girdi göndermesine olanak tanır. | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Etkileşimli olmayan kabuk komutlarına yönelik talimatlar - TTY bağımlı işlemlerden kaynaklanan askıda kalmaları önler | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Wakatime ile opencode kullanımını izleyin | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Clean up markdown tables produced by LLMs | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | Morph Fast Apply API ve yavaş düzenleme işaretçileriyle 10 kat daha hızlı kod düzenleme | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Background agents, pre-built LSP/AST/MCP tools, curated agents, Claude Code compatible | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | opencode oturumları için masaüstü bildirimleri ve sesli uyarılar | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | İzin, tamamlama ve hata olayları için masaüstü bildirimleri ve sesli uyarılar | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | opencode bağlamına dayalı yapay zeka destekli otomatik Zellij oturumu adlandırma | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | opencode temsilcilerinin, beceri keşfi ve ekleme ile istek üzerine istemleri yavaş yüklemesine izin verin | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Supermemory kullanarak oturumlar arasında kalıcı hafıza | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Görsel açıklama ve private/offline paylaşımıyla etkileşimli plan incelemesi | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | opencode'u/komutları ayrıntılı akış kontrolüyle güçlü bir orkestrasyon sistemine genişletin | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | Cron sözdizimi ile launchd (Mac) veya systemd (Linux) kullanarak yinelenen işleri planlayın | +| [micode](https://github.com/vtemian/micode) | Yapılandırılmış Beyin Fırtınası → Planla → Oturum sürekliliği ile iş akışını uygulama | +| [octto](https://github.com/vtemian/octto) | Çoklu soru formlarıyla yapay zeka beyin fırtınası için etkileşimli tarayıcı arayüzü | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | Eşzamansız delegasyon ve bağlam kalıcılığına sahip Claude Code tarzı arka plan aracıları | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | opencode için yerel işletim sistemi bildirimleri – görevlerin ne zaman tamamlandığını bilin | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | Birlikte verilen çok aracılı orkestrasyon donanımı – 16 bileşen, tek kurulum | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | opencode için sıfır sürtünmeli git çalışma ağaçları | + +--- + +## Projeler + +| İsim | Tanım | +| ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- | +| [kimaki](https://github.com/remorses/kimaki) | SDK üzerine kurulu opencode oturumlarını kontrol eden Discord botu | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | API temel alınarak oluşturulmuş, editöre duyarlı istemler için Neovim eklentisi | +| [portal](https://github.com/hosenur/portal) | Tailscale/VPN üzerinden opencode için mobil öncelikli web kullanıcı arayüzü | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | opencode eklentileri oluşturmak için şablon | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | opencode için Neovim ön ucu - terminal tabanlı bir AI kodlama aracısı | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | @opencode-ai/sdk aracılığıyla opencode'u kullanmak için Vercel AI SDK sağlayıcısı | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | opencode için Web / Masaüstü Uygulaması ve VS Code Uzantısı | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | opencode'u Obsidian'ın kullanıcı arayüzüne yerleştiren Obsidian eklentisi | +| [OpenWork](https://github.com/different-ai/openwork) | opencode tarafından desteklenen, Claude Cowork'e açık kaynaklı bir alternatif | +| [ocx](https://github.com/kdcokenny/ocx) | Taşınabilir, yalıtılmış profillere sahip opencode uzantı yöneticisi. | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | opencode için Masaüstü, Web, Mobil ve Uzak İstemci Uygulaması | + +--- + +## Agent'lar + +| İsim | Açıklama | +| ----------------------------------------------------------------- | --------------------------------------------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | Yapılandırılmış geliştirme için modüler yapay zeka aracıları ve komutları | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | Gelişmiş iş akışları için yapılandırmalar, istemler, aracılar ve eklentiler | diff --git a/packages/web/src/content/docs/tr/enterprise.mdx b/packages/web/src/content/docs/tr/enterprise.mdx new file mode 100644 index 00000000000..af2a0360bbb --- /dev/null +++ b/packages/web/src/content/docs/tr/enterprise.mdx @@ -0,0 +1,170 @@ +--- +title: Kurumsal +description: opencode'u kuruluşunuzda güvenli bir şekilde kullanma. +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +opencode Enterprise, kodlarının ve verilerinin altyapılarından asla ayrılmamasını sağlamak isteyen kuruluşlar içindir. Bunu, SSO ve dahili AI ağ geçidinizle entegre olan merkezi bir yapılandırma kullanarak yapabilir. + +:::note +opencode kodunuzu veya içerik verilerinizi saklamaz. +::: + +opencode Enterprise'ı kullanmaya başlamak için: + +1. Ekibinizle dahili olarak bir deneme yapın. +2. Fiyatlandırma ve uygulama seçeneklerini görüşmek için **bize ulaşın**. + +--- + +## Deneme + +opencode açık kaynaktır ve herhangi bir kodunuzu veya içerik verilerinizi saklamaz; böylece geliştiricileriniz [hemen başlayıp](/docs/) bir deneme gerçekleştirebilir. + +--- + +### Veri işleme + +**opencode, kodunuzu veya içerik verilerinizi saklamaz.** Tüm işlemler yerel olarak veya AI sağlayıcınıza doğrudan API çağrıları yoluyla gerçekleştirilir. + +Bu, güvendiğiniz bir sağlayıcıyı veya dahili bir sağlayıcıyı kullandığınız sürece +AI ağ geçidi, opencode'u güvenli bir şekilde kullanabilirsiniz. + +saklama alanının tek izolasyonuna bağlı `/share` özelliğidir. + +--- + +#### Konuşmaları paylaşma + +Bir kullanıcı `/share` özelliğini etkinleştirirse, görüşme ve onunla ilişkili veriler, bu paylaşım sayfalarını opencode.ai'de barındırmak için kullandığımız hizmete gönderilir. + +Veriler şu anda CDN uç ağımız üzerinden sunuluyor ve kullanıcılarınızın yakınındaki uçta önbelleğe alınıyor. + +Deneme süreniz için bunu devre dışı bırakmanızı öneririz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[Paylaşım hakkında daha fazla bilgi](/docs/share). + +--- + +### Kod sahipliği + +**opencode tarafından üretilen tüm kodlara sahipsiniz.** Herhangi bir lisans kısıtlaması veya mülkiyet iddiası yoktur. + +--- + +## Fiyatlandırma + +opencode Enterprise için koltuk başına model kullanıyoruz. Kendi LLM ağ geçidiniz varsa, kullanılan token'lar için ücret talep etmiyoruz. Fiyatlandırma ve uygulama seçenekleri hakkında daha fazla ayrıntı için **bize ulaşın**. + +--- + +## Dağıtım + +Deneme sürenizi tamamladıktan ve opencode'u şu adreste kullanmaya hazır olduğunuzda: +kuruluşunuz hakkında görüşmek üzere **bizimle iletişime geçebilirsiniz** +fiyatlandırma ve uygulama seçenekleri. + +--- + +### Merkezi Yapılandırma + +opencode'u tüm organizasyonunuz için tek bir merkezi yapılandırma kullanacak şekilde ayarlayabiliriz. + +Bu merkezi yapılandırma, SSO sağlayıcınızla entegre olabilir ve tüm kullanıcıların yalnızca dahili AI ağ geçidinize erişmesini sağlar. + +--- + +### SSO entegrasyonu + +Merkezi yapılandırma aracılığıyla opencode, kimlik doğrulama için kuruluşunuzun SSO sağlayıcısıyla entegre olabilir. + +Bu, opencode'un mevcut kimlik yönetimi sisteminiz aracılığıyla dahili AI ağ geçidiniz için kimlik bilgileri almasına olanak tanır. + +--- + +### Dahili AI ağ geçidi + +Merkezi yapılandırmayla opencode yalnızca dahili AI ağ geçidinizi kullanacak şekilde de yapılandırılabilir. + +Ayrıca tüm isteklerin kuruluşunuzun onaylı altyapısından geçmesini sağlayarak diğer tüm AI sağlayıcılarını devre dışı bırakabilirsiniz. + +--- + +### Kendi kendine barındırma + +Verilerinizin asla silinmediğinden emin olmak için paylaşım sayfalarını devre dışı bırakmanızı öneririz. +Kuruluşunuzda, bunları altyapınızda kendiniz barındırmanıza da yardımcı olabiliriz. + +Bu şu anda yol haritamızda yer alıyor. İlgileniyorsanız **bize bildirin**. + +--- + +## SSS + +

+opencode Enterprise nedir? + +opencode Enterprise, kodlarının ve verilerinin altyapılarından asla ayrılmamasını sağlamak isteyen kuruluşlar içindir. Bunu, SSO ve dahili AI ağ geçidinizle entegre olan merkezi bir yapılandırma kullanarak yapabilir. + +
+ +
+opencode Enterprise'a nasıl başlarım? + +Ekibinizle dahili bir denemeyle başlayın. opencode varsayılan olarak kodunuzu veya içerik verilerinizi saklamaz, bu da başlamayı kolaylaştırır. + +Daha sonra fiyatlandırma ve uygulama seçeneklerini görüşmek için **bizimle iletişime geçin**. + +
+ +
+Kurumsal fiyatlandırma nasıl çalışır? + +Koltuk başına kurumsal fiyatlandırma sunuyoruz. Kendi LLM ağ geçidiniz varsa, kullanılan token'lar için ücret talep etmiyoruz. Daha fazla ayrıntı için kuruluşunuzun ihtiyaçlarına göre özel bir fiyat teklifi almak üzere **bize ulaşın**. + +
+ +
+Verilerim opencode Enterprise ile güvende mi? + +Evet. opencode kodunuzu veya içerik verilerinizi saklamaz. Tüm işlemler yerel olarak veya AI sağlayıcınıza doğrudan API çağrıları yoluyla gerçekleşir. Merkezi yapılandırma ve SSO entegrasyonuyla verileriniz kuruluşunuzun altyapısında güvende kalır. + +
+ +
+Kendi özel NPM kayıt defterimizi kullanabilir miyiz? + +opencode, Bun'un yerel `.npmrc` dosya desteği aracılığıyla özel npm kayıtlarını destekler. Kuruluşunuz JFrog Artifactory, Nexus veya benzeri gibi özel bir kayıt defteri kullanıyorsa, opencode'u çalıştırmadan önce geliştiricilerin kimlik doğrulamasının yapıldığından emin olun. + +Özel kayıt defterinizle kimlik doğrulamayı ayarlamak için: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +Bu, kimlik doğrulama ayrıntılarını içeren `~/.npmrc` öğesini oluşturur. opencode otomatik olarak +bunu alır. + +:::caution +opencode'u çalıştırmadan önce özel kayıt defterinde oturum açmalısınız. +::: + +Alternatif olarak, bir `.npmrc` dosyasını manuel olarak yapılandırabilirsiniz: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +Paketlerin kurumsal kayıt defterinizden yüklenebildiğinden emin olmak için geliştiricilerin opencode'u çalıştırmadan önce özel kayıt defterinde oturum açmaları gerekir. + +
diff --git a/packages/web/src/content/docs/tr/formatters.mdx b/packages/web/src/content/docs/tr/formatters.mdx new file mode 100644 index 00000000000..b6db406e167 --- /dev/null +++ b/packages/web/src/content/docs/tr/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: Biçimlendiriciler +description: opencode dile özgü biçimlendiriciler kullanır. +--- + +opencode, dosyaları dile özgü formatlayıcılar kullanılarak yazıldıktan veya düzenlendikten sonra otomatik olarak formatlar. Bu, oluşturulan kodun projenizin kod stillerine uymasını sağlar. + +--- + +## Yerleşik + +opencode, popüler diller ve çerçeveler için çeşitli yerleşik biçimlendiricilerle birlikte gelir. Aşağıda ihtiyaç duyduğu biçimlendiricilerin, desteklenen dosya uzantılarının ve komutların veya yapılandırma seçeneklerinin bir listesi bulunmaktadır. + +| Biçimlendirici | Uzantılar | Gereksinimler | +| ---------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------ | +| gofmt | .go | `gofmt` komutu mevcut | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | `mix` komutu mevcut | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml ve [daha fazla](https://prettier.io/docs/en/index.html) | `package.json` içinde `prettier` bağımlılığı | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml ve [daha fazla](https://biomejs.dev/) | `biome.json(c)` yapılandırma dosyası | +| zig | .zig, .zon | `zig` komutu mevcut | +| clang-format | .c, .cpp, .h, .hpp, .ino ve [daha fazla](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` yapılandırma dosyası | +| ktlint | .kt, .kts | `ktlint` komutu mevcut | +| ruff | .py, .pyi | `ruff` komutu yapılandırmayla kullanılabilir | +| rustfmt | .rs | `rustfmt` komutu mevcut | +| cargofmt | .rs | `cargo fmt` komutu mevcut | +| uv | .py, .pyi | `uv` komutu mevcut | +| rubocop | .rb, .rake, .gemspec, .ru | `rubocop` komutu mevcut | +| standardrb | .rb, .rake, .gemspec, .ru | `standardrb` komutu mevcut | +| htmlbeautifier | .erb, .html.erb | `htmlbeautifier` komutu mevcut | +| air | .R | `air` komutu mevcut | +| dart | .dart | `dart` komutu mevcut | +| ocamlformat | .ml, .mli | `ocamlformat` komutu mevcut ve `.ocamlformat` yapılandırma dosyası | +| terraform | .tf, .tfvars | `terraform` komutu mevcut | +| gleam | .gleam | `gleam` komutu mevcut | +| nixfmt | .nix | `nixfmt` komutu mevcut | +| shfmt | .sh, .bash | `shfmt` komutu mevcut | +| pint | .php | `composer.json` içinde `laravel/pint` bağımlılığı | +| oxfmt (Deneysel) | .js, .jsx, .ts, .tsx | `package.json` içinde `oxfmt` bağımlılığı ve [experimental env variable flag](/docs/cli/#experimental) | +| ormolu | .hs | `ormolu` komutu mevcut | + +Yani eğer projenizin `package.json` dosyasında `prettier` varsa, opencode bunu otomatik olarak kullanacaktır. + +--- + +## Nasıl çalışır? + +opencode bir dosyayı yazdığında veya düzenlediğinde: + +1. Dosya uzantısını tüm etkin formatlayıcılara göre kontrol eder. +2. Dosyada uygun biçimlendirici komutunu çalıştırır. +3. Biçimlendirme değişikliklerini otomatik olarak uygular. + +Bu işlem arka planda gerçekleşir ve kod stillerinizin herhangi bir manuel adım olmadan korunmasını sağlar. + +--- + +## Yapılandırma + +Biçimlendiricileri opencode yapılandırmanızdaki `formatter` bölümü aracılığıyla özelleştirebilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +Her formatlayıcı yapılandırması aşağıdakileri destekler: + +| Özellik | Tip | Açıklama | +| ------------- | -------- | ---------------------------------------------------------------------- | +| `disabled` | boolean | Biçimlendiriciyi devre dışı bırakmak için bunu `true` olarak ayarlayın | +| `command` | string[] | Biçimlendirme için çalıştırılacak komut | +| `environment` | object | Biçimlendiriciyi çalıştırırken ayarlanacak ortam değişkenleri | +| `extensions` | string[] | Bu formatlayıcının işlemesi gereken dosya uzantıları | + +Bazı örneklere bakalım. + +--- + +### Biçimlendiricileri devre dışı bırakma + +**tüm** biçimlendiricileri genel olarak devre dışı bırakmak için `formatter` değerini `false` olarak ayarlayın: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +**Belirli** bir biçimlendiriciyi devre dışı bırakmak için `disabled` değerini `true` olarak ayarlayın: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### Özel biçimlendiriciler + +Komutu, ortam değişkenlerini ve dosya uzantılarını belirterek yerleşik biçimlendiricileri geçersiz kılabilir veya yenilerini ekleyebilirsiniz: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +Komuttaki **`$FILE` yer tutucusu**, biçimlendirilen dosyanın yolu ile değiştirilecektir. diff --git a/packages/web/src/content/docs/tr/github.mdx b/packages/web/src/content/docs/tr/github.mdx new file mode 100644 index 00000000000..8a5ea203fbb --- /dev/null +++ b/packages/web/src/content/docs/tr/github.mdx @@ -0,0 +1,321 @@ +--- +title: GitHub +description: GitHub sorunlarında ve çekme isteklerinde opencode'u kullanın. +--- + +opencode, GitHub iş akışınızla bütünleşir. Yorumunuzda `/opencode` veya `/oc`'den bahsedin; opencode, GitHub Actions çalıştırıcınızdaki görevleri yürütecektir. + +--- + +## Özellikler + +- **Sorunları önceliklendirin**: opencode'dan bir sorunu araştırıp size açıklamasını isteyin. +- **Düzelt ve uygula**: opencode'dan bir sorunu düzeltmesini veya bir özelliği uygulamasını isteyin. Ve yeni bir şubede çalışacak ve tüm değişiklikleri içeren bir PR gönderecek. +- **Güvenli**: opencode, GitHub'ınızın çalıştırıcılarının içinde çalışır. + +--- + +## Kurulum + +GitHub deposundaki bir projede aşağıdaki komutu çalıştırın: + +```bash +opencode github install +``` + +Bu size GitHub uygulamasını yükleme, iş akışını oluşturma ve gizli dizileri ayarlama adımlarında yol gösterecektir. + +--- + +### Manuel Kurulum + +Veya manuel olarak ayarlayabilirsiniz. + +1. **GitHub uygulamasını yükleyin** + + [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent)'a gidin. Hedef depoya kurulu olduğundan emin olun. + +2. **İş akışını ekleyin** + + Aşağıdaki iş akışı dosyasını deponuzdaki `.github/workflows/opencode.yml`'a ekleyin. `model`'de uygun `env` ve gerekli API anahtarlarını ayarladığınızdan emin olun. + + ```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx + ``` + +3. **API anahtarlarını gizli olarak saklayın** + + Kuruluşunuzda veya projenizde **ayarlarda**, soldaki **Gizli bilgiler ve değişkenler**'i genişletin ve **Eylemler**'i seçin. Ve gerekli API anahtarlarını ekleyin. + +--- + +## Yapılandırma + +- `model`: opencode ile kullanılacak model. `provider/model` biçimini alır. Bu **gerekli**. +- `agent`: Kullanılacak aracı. Birincil ajan olmalı. Yapılandırmadan `default_agent`'ye veya bulunamazsa `"build"`'ye geri döner. +- `share`: opencode hesabının paylaşılıp paylaşılmayacağı. Genel depolar için varsayılan olarak **true** olur. +- `prompt`: Varsayılan çalışma geçersiz olduğundan dolayı özel istem. opencode'un işleme biçimini kişiselleştirmek için bunu kullanın. +- `token`: Yorum oluşturma, değişiklik yapma ve çekme isteklerini açma gibi işlemleri gerçekleştirmek için isteğe bağlı GitHub erişim belirteci. Varsayılan olarak opencode, opencode GitHub Uygulamasındaki kurulum erişim belirtecini kullanır, bu nedenle taahhütler, yorumlar ve çekme istekleri uygulamadan geliyormuş gibi görünür. + + Alternatif olarak, opencode GitHub'u yüklemeden GitHub Eylem çalıştırıcısının [built-in `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) akışını kullanabilirsiniz. İşinizde gerekli izinlere sahip olduğunuzdan emin olun: + + ```yaml + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + ``` + + Tercih edilirse [personal access tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) de kullanabilirsiniz. + +--- + +## Desteklenen Olaylar + +opencode aşağıdaki GitHub olayları tarafından tetiklenebilir: + +| Olay Tipi | Tetikleyen | Detaylar | +| ----------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `issue_comment` | Bir soruna veya halkla ilişkilere yorum yapın | Yorumunuzda `/opencode` veya `/oc`'den bahsedin. opencode bağlamı okur ve şubeler oluşturabilir, PR'leri açabilir veya yanıt verebilir. | +| `pull_request_review_comment` | PR'deki belirli kod satırlarına yorum yapın | Kodu incelerken `/opencode` veya `/oc`'den bahsedin. opencode dosya yolunu, satır numaralarını ve fark içeriğini alır. | +| `issues` | Sayı açıldı veya düzenlendi | Sorunlar oluşturulduğunda veya değiştirildiğinde opencode'u otomatik olarak tetikleyin. `prompt` girişi gerektirir. | +| `pull_request` | PR açıldı veya güncellendi | PR'ler açıldığında, senkronize edildiğinde veya yeniden açıldığında opencode'u otomatik olarak tetikleyin. Otomatik incelemeler için kullanışlıdır. | +| `schedule` | Cron tabanlı program | opencode'u bir programa göre çalıştırın. `prompt` girişi gerektirir. Çıktı, günlüklere ve PR'lere gider (yorum yapılacak bir sorun yoktur). | +| `workflow_dispatch` | GitHub kullanıcı arayüzünden manuel tetikleme | Eylemler sekmesi aracılığıyla opencode'u isteğe bağlı olarak tetikleyin. `prompt` girişi gerektirir. Çıktı günlüklere ve PR'lere gider. | + +### Zamanlama Örneği + +Otomatik görevleri gerçekleştirmek için opencode'u bir zamanlamaya göre çalıştırın: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +Zamanlanmış etkinlikler için, talimatların alınabileceği bir yorum bulunmadığından `prompt` girişi **gereklidir**. Zamanlanmış iş akışları, izin kontrolü yapılacak bir kullanıcı bağlamı olmadan çalışır; bu nedenle, opencode'un şubeler veya PR'ler oluşturmasını bekliyorsanız iş akışının `contents: write` ve `pull-requests: write` vermesi gerekir. + +--- + +### Çekme İsteği Örneği + +PR'leri açıldığında veya güncellendiğinde otomatik olarak inceleyin: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +`pull_request` olaylar için, `prompt` sağlanmazsa, opencode varsayılan olarak çekme isteklerini inceler. + +--- + +### Sorun Önceliklendirme Örneği + +Yeni sorunları otomatik olarak önceliklendirin. Bu örnek, spam'i azaltmak için 30 günden eski hesapları filtreler: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +`issues` olayları için, talimatların çıkarılacağı bir yorum olmadığından `prompt` girişi **gereklidir**. + +--- + +## Özel istemler + +opencode'un davranışını iş akışınız için özelleştirmek için varsayılan istemi geçersiz kılın. + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +Bu, projenizle ilgili spesifik inceleme kriterlerini, kodlama standartlarını veya odak alanlarını uygulamak için kullanışlıdır. + +--- + +## Örnekler + +GitHub'da opencode'u nasıl kullanabileceğinize dair bazı örnekleri burada bulabilirsiniz. + +- **Bir sorunu açıklama** + + Bu yorumu GitHub sayısına ekleyin. + + ``` + /opencode explain this issue + ``` + + opencode, tüm yorumlar da dahil olmak üzere ileti dizisinin tamamını okuyacak ve net bir açıklama ile yanıt verecektir. + +- **Bir sorunu düzeltme** + + In a GitHub issue, say: + + ``` + /opencode fix this + ``` + + Ve opencode yeni bir şube oluşturacak, değişiklikleri uygulayacak ve değişiklikleri içeren bir PR açacak. + +- **PR'leri inceleyin ve değişiklik yapın** + + GitHub PR'a aşağıdaki yorumu bırakın. + + ``` + Delete the attachment from S3 when the note is removed /oc + ``` + + opencode istenen değişikliği uygulayacak ve aynı PR'ye uygulayacaktır. + +- **Belirli kod satırlarını inceleme** + + PR'nin "Dosyalar" sekmesindeki kod satırlarına doğrudan yorum bırakın. opencode, kesin yanıtlar sağlamak için dosyayı, satır numaralarını ve fark içeriğini otomatik olarak algılar. + + ``` + [Comment on specific lines in Files tab] + /oc add error handling here + ``` + + Belirli satırlara yorum yaparken opencode şunları alır: + - İncelenmekte olan dosyanın tamamı + - Belirli kod satırları + - Çevreleyen fark bağlamı + - Satır numarası bilgisi + + Bu, dosya yollarını veya satır numaralarını manuel olarak belirtmeye gerek kalmadan daha hedefli isteklere olanak tanır. diff --git a/packages/web/src/content/docs/tr/gitlab.mdx b/packages/web/src/content/docs/tr/gitlab.mdx new file mode 100644 index 00000000000..23f15c6826c --- /dev/null +++ b/packages/web/src/content/docs/tr/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: GitLab sorunlarında ve birleştirme isteklerinde opencode'u kullanın. +--- + +opencode, GitLab CI/CD işlem hattınız veya GitLab Duo aracılığıyla GitLab iş akışınızla bütünleşir. + +Her iki durumda da opencode, GitLab çalıştırıcılarınızda çalışacaktır. + +--- + +## GitLab CI + +opencode normal bir GitLab işlem hattında çalışır. Bunu bir [CI component](https://docs.gitlab.com/ee/ci/components/) olarak bir işlem hattına oluşturabilirsiniz. + +Burada opencode için topluluk tarafından oluşturulan bir CI/CD bileşeni kullanıyoruz — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode). + +--- + +### Özellikler + +- **İş başına özel işlemleri kullanın**: opencode parçalarının kullanıma veya devre dışı bırakmak için opencode'u özel bir yapılandırma dizini ile yapılandırın; örneğin `./config/#custom-directory`. +- **Minimum kurulum**: CI bileşeni opencode'u arka planda kurar; yalnızca opencode yapılandırmasını ve ilk istemi oluşturmanız gerekir. +- **Esnek**: CI bileşeni, davranışını özelleştirmek için çeşitli girişleri destekler + +--- + +### Kurulum + +1. opencode kimlik doğrulamanızı JSON **Ayarlar** > **CI/CD** > **Değişkenler** altında Dosya türü CI ortam değişkenleri olarak saklayın. Bunları "Maskeli ve gizli" olarak işaretlediğinizden emin olun. +2. Aşağıdakileri `.gitlab-ci.yml` dosyanıza ekleyin. + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +Daha fazla girdi ve bu bileşene yönelik kullanım durumları için [check out the docs](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode). + +--- + +## GitLab Duo + +opencode, GitLab iş akışınızla bütünleşir. +Bir yorumda `@opencode`'dan bahsedin; opencode, GitLab CI işlem hattınızdaki görevleri yürütecektir. + +--- + +### Özellikler + +- **Sorunları önceliklendirin**: opencode'dan bir sorunu araştırıp size açıklamasını isteyin. +- **Düzelt ve uygula**: opencode'dan bir sorunu düzeltmesini veya bir özelliği uygulamasını isteyin. + Yeni bir dal oluşturacak ve değişikliklerle birlikte bir birleştirme isteği oluşturacaktır. +- **Güvenli**: opencode, GitLab çalıştırıcılarınızda çalışır. + +--- + +### Yapılandırma + +opencode, GitLab CI/CD işlem hattınızda çalışır; bunu ayarlamak için ihtiyacınız olacaklar: + +:::tip +Güncel talimatlar için [**GitLab docs**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/)'a göz atın. +::: + +1. GitLab ortamınızı yapılandırın +2. CI/CD'yi kurma +3. Bir AI model sağlayıcısı API anahtarını gösterir +4. Hizmet hesabı oluşturun +5. CI/CD değişkenlerini yapılandırma +6. Bir akış yapılandırma dosyası oluşturun; işte bir örnek: + +
+ + Akış yapılandırması + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +Ayrıntılı talimatlar için [GitLab CLI agents docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/)'a başvurabilirsiniz. + +--- + +### Örnekler + +GitLab'da opencode'u nasıl kullanabileceğinize dair bazı örnekleri burada bulabilirsiniz. + +:::tip +`@opencode`'dan farklı bir tetikleyici ifade kullanacak şekilde yapılandırabilirsiniz. +::: + +- **Bir sorunu açıklama** + + Bu yorumu bir GitLab sayısına ekleyin. + + ``` + @opencode explain this issue + ``` + + opencode konuyu okuyacak ve net bir açıklama ile yanıt verecektir. + +- **Bir sorunu düzeltme** + + In a GitLab issue, say: + + ``` + @opencode fix this + ``` + + opencode yeni bir dal oluşturacak, değişiklikleri uygulayacak ve değişiklikleri içeren bir birleştirme isteği açacaktır. + +- **Birleştirme isteklerini inceleme** + + GitLab birleştirme isteğine aşağıdaki yorumu bırakın. + + ``` + @opencode review this merge request + ``` + + opencode, birleştirme isteğini inceleyecek ve geri bildirim sağlayacaktır. diff --git a/packages/web/src/content/docs/tr/ide.mdx b/packages/web/src/content/docs/tr/ide.mdx new file mode 100644 index 00000000000..334b0cf7c6a --- /dev/null +++ b/packages/web/src/content/docs/tr/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: VS Code, Cursor ve diğer IDE'ler için opencode uzantısı +--- + +opencode, VS Code, Cursor veya bir terminali destekleyen herhangi bir IDE ile entegre olur. Başlamak için terminalde `opencode` komutunu çalıştırmanız yeterli. + +--- + +## Kullanım + +- **Hızlı Başlatma**: opencode'u bölünmüş terminal görünümünde açmak veya zaten çalışıyorsa mevcut bir terminal oturumuna odaklanmak için `Cmd+Esc` (Mac) veya `Ctrl+Esc` (Windows/Linux) kullanın. +- **Yeni Oturum**: Zaten açık olsa bile yeni bir opencode terminal oturumu başlatmak için `Cmd+Shift+Esc` (Mac) veya `Ctrl+Shift+Esc` (Windows/Linux) kullanın. Ayrıca kullanıcı arayüzündeki opencode düğmesini de tıklayabilirsiniz. +- **Bağlam Farkındalığı**: Geçerli seçiminizi veya sekmenizi opencode ile otomatik olarak paylaşın. +- **Dosya Referansı Kısayolları**: Dosya referansları eklemek için `Cmd+Option+K` (Mac) veya `Alt+Ctrl+K` (Linux/Windows) kullanın. Örneğin, `@File#L37-42`. + +--- + +## Kurulum + +opencode'u VS Code'a ve Cursor, Windsurf, VSCodium gibi popüler çatallara yüklemek için: + +1. VS Code'u Aç +2. Entegre terminali açın +3. `opencode` komutunu çalıştırın - uzantı otomatik olarak yüklenir + +TUI içinden `/editor` veya `/export` komutlarını çalıştırdığınızda kendi IDE'nizi kullanmak istiyorsanız `export EDITOR="code --wait"` ayarlayın. [Daha fazla bilgi](/docs/tui/#editor-setup). + +--- + +### Manuel Kurulum + +Extension Marketplace'te **opencode**'u arayın ve **Yükle**'ye tıklayın. + +--- + +### Sorun giderme + +Uzantı otomatik olarak yüklenemezse: + +- Entegre terminalde `opencode` çalıştırdığınızdan emin olun. +- IDE cihazınız için CLI'nin kurulu olduğunu doğrulayın: + - VS Code için: `code` komutu + - Cursor için: `cursor` komutu + - Windsurf için: `windsurf` komutu + - VSCodium için: `codium` komutu + - Değilse `Cmd+Shift+P` (Mac) veya `Ctrl+Shift+P` (Windows/Linux) çalıştırın ve "Shell Command: Install 'code' command in PATH" komutunu seçin (veya IDE'nizdeki eşdeğerini kullanın). +- VS Code'un uzantı yükleme iznine sahip olduğundan emin olun diff --git a/packages/web/src/content/docs/tr/index.mdx b/packages/web/src/content/docs/tr/index.mdx new file mode 100644 index 00000000000..7c31f5bd344 --- /dev/null +++ b/packages/web/src/content/docs/tr/index.mdx @@ -0,0 +1,352 @@ +--- +title: Giriş +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 TUI with the opencode theme](../../../assets/lander/screenshot.png) + +Başlayalım. + +--- + +#### Ön koşullar + +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 + - [Ghostty](https://ghostty.org), Linux ve macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux ve macOS + +2. Kullanmak istediğiniz LLM sağlayıcılarının API anahtarları. + +--- + +## Kurulum + +opencode'u kurmanın en kolay yolu kurulum betiğidir. + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +Ayrıca aşağıdaki komutlarla da yükleyebilirsiniz: + +- **Node.js'yi kullanma** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **Homebrew'u macOS ve Linux'ta kullanma** + + ```bash + 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. + +- **Paru'yu Arch Linux'ta kullanma** + + ```bash + paru -S opencode-bin + ``` + +#### 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. +::: + +- **Chocolatey Kullanımı** + + ```bash + choco install opencode + ``` + +- **Scoop Kullanımı** + + ```bash + scoop install opencode + ``` + +- **NPM kullanarak** + + ```bash + npm install -g opencode-ai + ``` + +- **Mise Kullanımı** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **Docker'ı kullanma** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +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. + +--- + +## Yapılandırma + +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. + +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 + ``` + +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 + ``` + +Alternatif olarak diğer sağlayıcılardan birini seçebilirsiniz. [Daha fazla bilgi](/docs/providers#directory). + +--- + +## Başlatma + +Artık bir sağlayıcı yapılandırdığınıza göre, bir projeye gidebilirsiniz. +üzerinde çalışmak istiyorsun. + +```bash +cd /path/to/project +``` + +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. + +```bash frame="none" +/init +``` + +Bu, opencode'un projenizi analiz etmesini ve bir `AGENTS.md` dosyası oluşturmasını sağlayacaktır. +proje kökü. + +:::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. + +--- + +## Kullanım + +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. + +--- + +### Soru Sorma + +opencode'dan kod tabanını size açıklamasını isteyebilirsiniz. + +:::tip +Projedeki dosyaları bulanık aramak için `@` tuşunu kullanın. +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +Kod tabanının üzerinde çalışmadığınız bir kısmı varsa bu yararlı olur. + +--- + +### Özellik Ekleme + +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. + 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. + + ```bash frame="none" title="Plan moduna geç" + + ``` + + Şimdi ne yapmasını istediğimizi anlatalım. + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + 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 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. + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + + :::tip + İ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. + 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. + + ```bash frame="none" + + ``` + + Ardından değişiklikleri yapmasını isteyin. + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### Değişiklik Yapma + +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 +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. + +--- + +### Değişiklikleri Geri Alma + +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. + +```bash frame="none" +/undo +``` + +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. + +:::tip +Birden çok değişikliği geri almak için `/undo` komutunu birden çok kez çalıştırabilirsiniz. +::: + +Veya `/redo` komutunu kullanarak değişiklikleri **yeniden yapabilirsiniz**. + +```bash frame="none" +/redo +``` + +--- + +## Paylaşma + +opencode ile yaptığınız görüşmeleri [ekibinizle paylaşabilirsiniz](/docs/share). + +```bash frame="none" +/share +``` + +Bu, mevcut konuşmaya bir bağlantı oluşturacak ve bunu panonuza kopyalayacaktır. + +:::note +Konuşmalar varsayılan olarak paylaşılmaz. +::: + +İşte opencode'lu bir [örnek konuşma](https://opencode.ai/s/4XP1fce5). + +--- + +## Özelleştirme + +İş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. diff --git a/packages/web/src/content/docs/tr/keybinds.mdx b/packages/web/src/content/docs/tr/keybinds.mdx new file mode 100644 index 00000000000..9a22c329cc7 --- /dev/null +++ b/packages/web/src/content/docs/tr/keybinds.mdx @@ -0,0 +1,192 @@ +--- +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. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## Leader tuşu + +opencode çoğu tuş ataması için `leader` anahtarını kullanır. Bu, terminalinizdeki çakışmaları önler. + +Varsayılan olarak `ctrl+x` lider tuştur ve çoğu eylem önce lider tuşa, ardından kısayola basmanızı gerektirir. Örneğin, yeni bir oturum başlatmak için önce `ctrl+x` tuşuna, ardından `n` tuşuna basarsınız. + +Tuş atamalarınız için lider anahtar kullanmanıza gerek yoktur ancak bunu yapmanızı öneririz. + +--- + +## Tuş atamasını devre dışı bırak + +Anahtarı yapılandırmanıza "none" değeriyle ekleyerek bir tuş atamasını devre dışı bırakabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## Masaüstü istemi kısayolları + +opencode masaüstü uygulaması bilgi istemi girişi, metni düzenlemek için yaygın Readline/Emacs tarzı kısayolları destekler. Bunlar yerleşiktir ve şu anda `opencode.json` aracılığıyla yapılandırılamaz. + +| Shortcut | Action | +| -------- | ---------------------------------------- | +| `ctrl+a` | Geçerli satırın başına git | +| `ctrl+e` | Move to end of current line | +| `ctrl+b` | Move cursor back one character | +| `ctrl+f` | Move cursor forward one character | +| `alt+b` | Move cursor back one word | +| `alt+f` | Move cursor forward one word | +| `ctrl+d` | Delete character under cursor | +| `ctrl+k` | Kill to end of line | +| `ctrl+u` | Satırın başına kadar öldür | +| `ctrl+w` | Kill previous word | +| `alt+d` | Kill next word | +| `ctrl+t` | Transpose characters | +| `ctrl+g` | Cancel popovers / abort running response | + +--- + +## Shift+Enter + +Bazı terminaller varsayılan olarak Enter ile değiştirici tuşlar göndermez. Terminalinizi, kaçış dizisi olarak `Shift+Enter` gönderecek şekilde yapılandırmanız gerekebilir. + +### Windows Terminali + +`settings.json` cihazınızı şu adreste açın: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +Bunu kök düzeyindeki `actions` dizisine ekleyin: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Bunu kök düzeyindeki `keybindings` dizisine ekleyin: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +Dosyayı kaydedin ve Windows Terminalini yeniden başlatın veya yeni bir sekme açın. diff --git a/packages/web/src/content/docs/tr/lsp.mdx b/packages/web/src/content/docs/tr/lsp.mdx new file mode 100644 index 00000000000..db742113854 --- /dev/null +++ b/packages/web/src/content/docs/tr/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: LSP Sunucuları +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. + +--- + +## Yerleşik + +opencode, popüler diller için çeşitli yerleşik LSP sunucularıyla birlikte gelir: + +| LSP Sunucu | Uzantılar | Gereksinimler | +| ------------------ | ------------------------------------------------------------------- | --------------------------------------------------------------------- | +| astro | .astro | Astro projeleri için otomatik kurulumlar | +| bash | .sh, .bash, .zsh, .ksh | `bash-language-server`'ı otomatik olarak yükler | +| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | C/C++ projeleri için otomatik kurulumlar | +| csharp | .cs | `.NET SDK` kurulu | +| clojure-lsp | .clj, .cljs, .cljc, .edn | `clojure-lsp` komutu mevcut | +| dart | .dart | `dart` komutu mevcut | +| deno | .ts, .tsx, .js, .jsx, .mjs | `deno` komutu mevcut (deno.json/deno.jsonc otomatik olarak algılanır) | +| elixir-ls | .ex, .exs | `elixir` komutu mevcut | +| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | Projede `eslint` bağımlılığı | +| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` kurulu | +| gleam | .gleam | `gleam` komutu mevcut | +| gopls | .go | `go` komutu mevcut | +| hls | .hs, .lhs | `haskell-language-server-wrapper` komutu mevcut | +| jdtls | .java | `Java SDK (version 21+)` 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 | +| ocaml-lsp | .ml, .mli | `ocamllsp` komutu mevcut | +| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | Projede `oxlint` bağımlılığı | +| php intelephense | .php | PHP projeleri için otomatik yüklemeler | +| prisma | .prisma | `prisma` komutu mevcut | +| pyright | .py, .pyi | `pyright` bağımlılığı kurulu | +| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | `ruby` ve `gem` komutları mevcut | +| rust | .rs | `rust-analyzer` komutu mevcut | +| sourcekit-lsp | .swift, .objc, .objcpp | `swift` kurulu (macOS'ta `xcode`) | +| svelte | .svelte | Svelte projeleri için otomatik kurulumlar | +| terraform | .tf, .tfvars | GitHub sürümlerinden otomatik yüklemeler | +| tinymist | .typ, .typc | GitHub sürümlerinden otomatik yüklemeler | +| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | Projede `typescript` bağımlılığı | +| vue | .vue | Vue projeleri için otomatik yüklemeler | +| yaml-ls | .yaml, .yml | Red Hat yaml-language-server'ı otomatik olarak yükler | +| zls | .zig, .zon | `zig` komutu mevcut | + +Yukarıdaki dosya uzantılarından biri tespit edildiğinde ve gereksinimler karşılandığında LSP sunucuları otomatik olarak etkinleştirilir. + +:::note +`OPENCODE_DISABLE_LSP_DOWNLOAD` ortam değişkenini `true` olarak ayarlayarak otomatik LSP sunucu indirmelerini devre dışı bırakabilirsiniz. +::: + +--- + +## Nasıl Çalışır? + +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. + +--- + +## Yapılandırma + +LSP sunucularını, opencode yapılandırmanızdaki `lsp` bölümü aracılığıyla özelleştirebilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +Her LSP sunucusu aşağıdakileri destekler: + +| Özellik | Tip | Açıklama | +| ---------------- | -------- | -------------------------------------------------------------------- | +| `disabled` | boolean | LSP sunucusunu devre dışı bırakmak için bunu `true` olarak ayarlayın | +| `command` | string[] | LSP sunucusunu başlatma komutu | +| `extensions` | string[] | Bu LSP sunucusunun işlemesi gereken dosya uzantıları | +| `env` | object | Sunucuyu başlatırken ayarlanacak ortam değişkenleri | +| `initialization` | object | LSP sunucusuna gönderilecek başlatma seçenekleri | + +Bazı örneklere bakalım. + +--- + +### Ortam değişkenleri + +LSP sunucusunu başlatırken ortam değişkenlerini ayarlamak için `env` özelliğini kullanın: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### Başlatma seçenekleri + +Başlatma seçeneklerini LSP sunucusuna iletmek için `initialization` özelliğini kullanın. Bunlar LSP `initialize` isteği sırasında gönderilen sunucuya özel ayarlardır: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +Başlatma seçenekleri LSP sunucusuna göre değişir. Mevcut seçenekler için LSP sunucunuzun belgelerine bakın. +::: + +--- + +### LSP sunucularını devre dışı bırakma + +**tüm** LSP sunucularını genel olarak devre dışı bırakmak için `lsp`'yi `false` olarak ayarlayın: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +**Belirli** bir LSP sunucusunu devre dışı bırakmak için `disabled`'yi `true` olarak ayarlayın: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### Özel LSP sunucuları + +Komutu ve dosya uzantılarını belirterek özel LSP sunucuları ekleyebilirsiniz: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## Ek Bilgiler + +### PHP Intelephense + +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` +- 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/mcp-servers.mdx b/packages/web/src/content/docs/tr/mcp-servers.mdx new file mode 100644 index 00000000000..0f60c5633c7 --- /dev/null +++ b/packages/web/src/content/docs/tr/mcp-servers.mdx @@ -0,0 +1,511 @@ +--- +title: MCP sunucuları +description: Yerel ve uzak MCP araçlarını ekleyin. +--- + +_Model Bağlam Protokolü_ veya MCP kullanarak opencode'a harici araçlar ekleyebilirsiniz. opencode hem yerel hem de uzak sunucuları destekler. + +MCP araçları eklendikten sonra yerleşik araçların yanı sıra LLM tarafından otomatik olarak kullanılabilir. + +--- + +#### Uyarılar + +Bir MCP sunucusu kullandığınızda bağlama eklenir. Çok fazla aletiniz varsa, bu hızla artabilir. Bu nedenle hangi MCP sunucularını kullandığınıza dikkat etmenizi öneririz. + +:::tip +MCP sunucuları içeriğinize katkıda bulunur, bu nedenle hangilerini etkinleştirdiğinize dikkat etmek istersiniz. +::: + +GitHub MCP sunucusu gibi belirli MCP sunucuları çok sayıda belirteç ekleme eğilimindedir ve bağlam sınırını kolayca aşabilir. + +--- + +## Etkinleştirme + +MCP sunucularını [opencode Config](https://opencode.ai/docs/config/)'nizde `mcp` altında tanımlayabilirsiniz. Her MCP'ü benzersiz bir adla ekleyin. LLM isteminde bulunurken bu MCP adına başvurabilirsiniz. + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +Ayrıca `enabled` öğesini `false` olarak ayarlayarak bir sunucuyu devre dışı bırakabilirsiniz. Bir sunucuyu yapılandırmanızdan kaldırmadan geçici olarak devre dışı bırakmak istiyorsanız bu kullanışlıdır. + +--- + +### Uzak varsayılanları geçersiz kılma + +Kuruluşlar, `.well-known/opencode` uç noktaları aracılığıyla varsayılan MCP sunucularını sağlayabilir. Bu sunucular varsayılan olarak devre dışı bırakılarak kullanıcıların ihtiyaç duydukları sunucuları seçmelerine olanak tanınabilir. + +Kuruluşunuzun uzak yapılandırmasından belirli bir sunucuyu etkinleştirmek için onu `enabled: true` ile yerel yapılandırmanıza ekleyin: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +Yerel yapılandırma değerleriniz uzak varsayılanları geçersiz kılar. Daha fazla ayrıntı için [config precedence](/docs/config#precedence-order)'a bakın. + +--- + +## Yerel + +`type` kullanarak yerel MCP sunucularını MCP nesnesi içindeki `"local"`'ye ekleyin. + +```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", + }, + }, + }, +} +``` + +Komut, yerel MCP sunucusunun nasıl başlatıldığıdır. Ayrıca ortam değişkenlerinin bir listesini de iletebilirsiniz. + +Örneğin, [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) MCP test sunucusunu şu şekilde görebilirsiniz. + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "mcp_everything": { + "type": "local", + "command": ["npx", "-y", "@modelcontextprotocol/server-everything"], + }, + }, +} +``` + +Ve bunu kullanmak için istemlerime `use the mcp_everything tool` kullanıyorum. + +```txt "mcp_everything" +use the mcp_everything tool to add the number 3 and 4 +``` + +--- + +#### Seçenekler + +Yerel bir MCP sunucusunu yapılandırmak için tüm seçenekler burada verilmiştir. + +| Seçenek | Tür | Gerekli | Açıklama | +| ------------- | ------- | ------- | ---------------------------------------------------------------------------------------------- | +| `type` | Dize | Y | MCP sunucu bağlantısı türü, `"local"` olmalıdır. | +| `command` | Dizi | Y | MCP sunucusunu çalıştırmak için komut ve argümanlar. | +| `environment` | Nesne | | Sunucuyu çalıştırırken ayarlanacak ortam değişkenleri. | +| `enabled` | Boolean | | Başlangıçta MCP sunucusunu etkinleştirin veya devre dışı bırakın. | +| `timeout` | Sayı | | MCP sunucusundan araçları getirirken ms cinsinden zaman aşımı. Varsayılan 5000'dir (5 saniye). | + +--- + +## Uzak + +`type`'yi `"remote"` olarak ayarlayarak uzak MCP sunucularını ekleyin. + +```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` uzak MCP sunucusunun URL'sidir ve `headers` seçeneğiyle bir başlık listesi iletebilirsiniz. + +--- + +#### Seçenekler + +| Seçenek | Tür | Gerekli | Açıklama | +| --------- | ------- | ------- | ---------------------------------------------------------------------------------------------- | +| `type` | Dize | Y | MCP sunucu bağlantısı türü, `"remote"` olmalıdır. | +| `url` | Dize | Y | Uzak MCP sunucusunun URL. | +| `enabled` | Boolean | | Başlangıçta MCP sunucusunu etkinleştirin veya devre dışı bırakın. | +| `headers` | Nesne | | İstekle birlikte gönderilecek başlıklar. | +| `oauth` | Object | | OAuth authentication configuration. See [OAuth](#oauth) section below. | +| `timeout` | Sayı | | MCP sunucusundan araçları getirirken ms cinsinden zaman aşımı. Varsayılan 5000'dir (5 saniye). | + +--- + +## OAuth + +opencode, uzak MCP sunucuları için OAuth kimlik doğrulamasını otomatik olarak yönetir. Bir sunucu kimlik doğrulaması gerektirdiğinde opencode şunları yapar: + +1. 401 yanıtını tespit edin ve OAuth akışını başlatın +2. Sunucu tarafından destekleniyorsa **Dinamik İstemci Kaydı (RFC 7591)** kullanın +3. Gelecekteki istekler için belirteçleri güvenli bir şekilde saklayın + +--- + +### Otomatik + +OAuth'un etkin olduğu çoğu MCP sunucusu için özel bir yapılandırmaya gerek yoktur. Uzak sunucuyu yapılandırmanız yeterli: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "my-oauth-server": { + "type": "remote", + "url": "https://mcp.example.com/mcp" + } + } +} +``` + +Sunucu kimlik doğrulama gerektiriyorsa opencode, onu ilk kez kullanmaya çalıştığınızda kimlik doğrulamanızı isteyecektir. Değilse, `opencode mcp auth ` ile [manually trigger the flow](#authenticating) yapabilirsiniz. + +--- + +### Ön kayıtlı + +MCP sunucu sağlayıcısından istemci kimlik bilgileriniz varsa, bunları yapılandırabilirsiniz: + +```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" + } + } + } +} +``` + +--- + +### Kimlik doğrulama + +Kimlik doğrulamayı manuel olarak tetikleyebilir veya kimlik bilgilerini yönetebilirsiniz. + +Belirli bir MCP sunucusuyla kimlik doğrulaması yapın: + +```bash +opencode mcp auth my-oauth-server +``` + +Tüm MCP sunucularını ve kimlik doğrulama durumlarını listeleyin: + +```bash +opencode mcp list +``` + +Remove stored credentials: + +```bash +opencode mcp logout my-oauth-server +``` + +`mcp auth` komutu tarayıcınızı yetkilendirme için açacaktır. Yetkilendirmenizin ardından opencode, belirteçleri `~/.local/share/opencode/mcp-auth.json`'de güvenli bir şekilde saklar. + +--- + +#### OAuth'u devre dışı bırakma + +Bir sunucu için otomatik OAuth'u devre dışı bırakmak istiyorsanız (örneğin, bunun yerine API anahtarlarını kullanan sunucular için), `oauth`'yi `false` olarak ayarlayın: + +```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 Seçenekleri + +| Seçenek | Tür | Açıklama | +| -------------- | --------------- | -------------------------------------------------------------------------------- | +| `oauth` | Object \| false | OAuth config object, or `false` to disable OAuth auto-detection. | +| `clientId` | Dize | OAuth istemci kimliği. Sağlanmadığı takdirde dinamik müşteri kaydı denenecektir. | +| `clientSecret` | Dize | Yetkilendirme sunucusu gerektiriyorsa OAuth istemci sırrı. | +| `scope` | String | OAuth scopes to request during authorization. | + +#### Hata Ayıklama + +Uzak bir MCP sunucusunun kimlik doğrulaması başarısız olursa aşağıdakileri kullanarak sorunları teşhis edebilirsiniz: + +```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` komutu mevcut kimlik doğrulama durumunu gösterir, HTTP bağlantısını test eder ve OAuth bulma akışını dener. + +--- + +## Yönetim + +MCP'leriniz yerleşik araçların yanı sıra opencode'da araç olarak mevcuttur. Böylece bunları diğer araçlar gibi opencode yapılandırması aracılığıyla yönetebilirsiniz. + +--- + +### Global + +Bu, bunları global olarak etkinleştirebileceğiniz veya devre dışı bırakabileceğiniz anlamına gelir. + +```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 + } +} +``` + +Eşleşen tüm MCP'leri devre dışı bırakmak için bir glob modeli de kullanabiliriz. + +```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 + } +} +``` + +Burada tüm MCP'leri devre dışı bırakmak için `my-mcp*` glob modelini kullanıyoruz. + +--- + +### Agent başına + +Çok sayıda MCP sunucunuz varsa, bunları yalnızca aracı başına etkinleştirmek ve genel olarak devre dışı bırakmak isteyebilirsiniz. Bunu yapmak için: + +1. Global olarak bir araç olarak devre dışı bırakın. +2. [agent config](/docs/agents#tools)'nizde, MCP sunucusunu bir araç olarak etkinleştirin. + +```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 + } + } + } +} +``` + +--- + +#### Glob desenleri + +Glob modeli, basit normal ifade globbing modellerini kullanır: + +- `*` herhangi bir karakterin sıfır veya daha fazlasıyla eşleşir (örneğin, `"my-mcp*"` `my-mcp_search`, `my-mcp_list` vb. ile eşleşir) +- `?` matches exactly one character +- All other characters match literally + +:::note +MCP sunucu araçları önek olarak sunucu adıyla kayıtlıdır, dolayısıyla bir sunucuya ilişkin tüm araçları devre dışı bırakmak için aşağıdakileri kullanmanız yeterlidir: + +``` +"mymcpservername_*": false +``` + +::: + +--- + +## Örnekler + +Aşağıda bazı yaygın MCP sunucularının örnekleri verilmiştir. Diğer sunucuları belgelemek istiyorsanız PR gönderebilirsiniz. + +--- + +### Sentry + +Sentry projelerinizle ve sorunlarınızla etkileşimde bulunmak için [Sentry MCP server](https://mcp.sentry.dev) ekleyin. + +```json title="opencode.json" {4-8} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "sentry": { + "type": "remote", + "url": "https://mcp.sentry.dev/mcp", + "oauth": {} + } + } +} +``` + +Yapılandırmayı ekledikten sonra Sentry ile kimlik doğrulaması yapın: + +```bash +opencode mcp auth sentry +``` + +Bu, OAuth akışını tamamlamak ve opencode'u Sentry hesabınıza bağlamak için bir tarayıcı penceresi açacaktır. + +Kimlik doğrulaması yapıldıktan sonra sorunları, projeleri ve hata verilerini sorgulamak için istemlerinizde Sentry araçlarını kullanabilirsiniz. + +```txt "use sentry" +Show me the latest unresolved issues in my project. use sentry +``` + +--- + +### Context7 + +Dokumanlar arasında arama yapmak için [Context7 MCP server](https://github.com/upstash/context7) ekleyin. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "context7": { + "type": "remote", + "url": "https://mcp.context7.com/mcp" + } + } +} +``` + +Ücretsiz bir hesaba kaydolduysanız API anahtarınızı kullanarak daha yüksek ücret limitleri elde edebilirsiniz. + +```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}" + } + } + } +} +``` + +Burada `CONTEXT7_API_KEY` ortam değişkeninin ayarlandığını varsayıyoruz. + +Context7 MCP sunucunu kullanmak için isteklerinize `use context7` ekleyin. + +```txt "use context7" +Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 +``` + +Alternatif olarak [AGENTS.md](/docs/rules/)'a buna benzer bir şey ekleyebilirsiniz. + +```md title="AGENTS.md" +When you need to search docs, use `context7` tools. +``` + +--- + +### Grep by Vercel + +GitHub'daki kod parçacıkları arasında arama yapmak için [Grep by Vercel](https://grep.app) MCP sunucusunu ekleyin. + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "gh_grep": { + "type": "remote", + "url": "https://mcp.grep.app" + } + } +} +``` + +MCP sunucumuzu `gh_grep` olarak adlandırdığımız için, aracının onu kullanmasını sağlamak için istemlerinize `use the gh_grep tool` ekleyebilirsiniz. + +```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 +``` + +Alternatif olarak [AGENTS.md](/docs/rules/)'a buna benzer bir şey ekleyebilirsiniz. + +```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/tr/models.mdx b/packages/web/src/content/docs/tr/models.mdx new file mode 100644 index 00000000000..45df6e3ffff --- /dev/null +++ b/packages/web/src/content/docs/tr/models.mdx @@ -0,0 +1,223 @@ +--- +title: Modeller +description: LLM sağlayıcılarını ve model seçimlerini yapılandırın. +--- + +opencode, **75+ LLM sağlayıcısını** desteklemek için [AI SDK](https://ai-sdk.dev/) ve [Models.dev](https://models.dev) kullanır ve yerel modellerin çalıştırılmasını destekler. + +--- + +## Sağlayıcılar + +Çoğu popüler sağlayıcı varsayılan olarak önceden yüklenmiştir. Bir sağlayıcının kimlik bilgilerini `/connect` komutu aracılığıyla eklediyseniz, bunlar opencode'u başlattığınızda kullanılabilir olacaktır. + +[Sağlayıcılar](/docs/providers) hakkında daha fazla bilgi edinin. + +--- + +## Model seçimi + +Sağlayıcınızı yapılandırdıktan sonra aşağıdaki komutu yazarak istediğiniz modeli seçebilirsiniz: + +```bash frame="none" +/models +``` + +--- + +## Önerilen modeller + +Piyasada pek çok model var ve her hafta yeni modeller çıkıyor. + +:::tip +Önerdiğimiz modellerden birini kullanmayı düşünün. +::: + +Ancak, hem kod oluşturmada hem de araç çağırmada iyi olan yalnızca birkaçı var. + +Burada, opencode ile belirli bir sıraya göre iyi çalışan birkaç model yer almaktadır. (Bu kapsamlı bir liste değildir ve mutlaka güncel olması da gerekmez): + +- GPT 5.2 +- GPT 5.1 Codex +- Claude Opus 4.5 +- Claude Sonnet 4.5 +- Minimax M2.1 +- Gemini 3 Pro + +--- + +## Varsayılan ayarlama + +Bunlardan birini varsayılan model olarak ayarlamak için `model` anahtarınızı telefonunuzudan ayarlayabilirsiniz. +opencode yapılandırması + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +Burada tam kimlik `provider_id/model_id`'dir. Örneğin, [OpenCode Zen](/docs/zen) kullanıyorsanız, GPT 5.1 Codex için `opencode/gpt-5.1-codex` kullanırsınız. + +Bir [custom provider](/docs/providers#custom) yapılandırılmışsa, `provider_id`, performansınızın `provider` bölümünden gelen anahtardır ve `model_id`, `provider.models`'den gelen anahtardır. + +--- + +## Model yapılandırma + +Bir modelin seçeneklerini genel olarak yapılandırma aracılığıyla yapılandırabilirsiniz. + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +Burada iki yerleşik model için genel ayarları yapılandırıyoruz: `gpt-5` sağlayıcısı aracılığıyla erişildiğinde `openai` ve `claude-sonnet-4-20250514` sağlayıcısı aracılığıyla erişildiğinde `anthropic`. +Yerleşik sağlayıcı ve model adları [Models.dev](https://models.dev) adresinde bulunabilir. + +Bu seçenekleri kullandığınız tüm aracılar için de yapılandırabilirsiniz. Aracı yapılandırması burada tüm genel seçenekleri geçersiz kılar. [Daha fazla bilgi](/docs/agents/#additional). + +Ayrıca yerleşik çeşitleri genişleten özel varyantlar da tanımlayabilirsiniz. Varyantlar, yinelenen girişler oluşturmadan aynı model için farklı ayarları yapılandırmanıza olanak tanır: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## Varyantlar + +Birçok model, farklı konfigürasyonlara sahip birden fazla kapasiteye sahip. opencode, popüler sağlayıcılar için sunulan değişkenlerle birlikte gelir. + +### Yerleşik çeşitler + +opencode birçok sağlayıcı için varsayılan değişkenlerle birlikte gelir: + +**Antropik**: + +- `high` - Yüksek düşünme bütçesi (varsayılan) +- `max` - Maksimum düşünme bütçesi + +**OpenAI**: + +Modele göre değişir ancak kabaca: + +- `none` - Gerekçe yok +- `minimal` - Minimum akıl yürütme çabası +- `low` - Düşük muhakeme çabası +- `medium` - Orta düzey muhakeme çabası +- `high` - Yüksek akıl yürütme çabası +- `xhigh` - Ekstra yüksek muhakeme çabası + +**Google**: + +- `low` - Daha düşük effort/token bütçesi +- `high` - Daha yüksek effort/token bütçesi + +:::tip +Bu liste kapsamlı değildir. Diğer birçok sağlayıcının da yerleşik varsayılanları vardır. +::: + +### Özel çeşitler + +Mevcut varyantları geçersiz kılabilir veya kendinizinkini ekleyebilirsiniz: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### Döngü çeşitleri + +Çeşitler arasında hızlı geçiş yapmak için `variant_cycle` tuş atamasını kullanın. [Daha fazla bilgi](/docs/keybinds). + +--- + +## Modelleri yükleme + +opencode başlatıldığında modelleri aşağıdaki öncelik sırasına göre kontrol eder: + +1. `--model` veya `-m` komut satırı bayrağı. Biçim, yapılandırma dosyasındakiyle aynıdır: `provider_id/model_id`. + +2. opencode yapılandırmasındaki model listesi. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + + Buradaki format `provider/model`'dır. + +3. En son kullanılan model. + +4. Dahili öncelik kullanan ilk model. diff --git a/packages/web/src/content/docs/tr/modes.mdx b/packages/web/src/content/docs/tr/modes.mdx new file mode 100644 index 00000000000..b8dfc838ee6 --- /dev/null +++ b/packages/web/src/content/docs/tr/modes.mdx @@ -0,0 +1,331 @@ +--- +title: Modlar +description: farklı kullanım durumları için farklı modlar. +--- + +:::caution +Modlar artık opencode yapılandırmasındaki `agent` seçeneği aracılığıyla yapılandırılıyor. +`mode` seçeneği artık kullanımdan kaldırıldı. [Daha fazla bilgi](/docs/agents). +::: + +opencode'daki modlar, farklı kullanım durumları için davranışı, araçları ve istemleri özelleştirmenize olanak tanır. + +İki yerleşik modla birlikte gelir: **build** ve **plan**. Kişiselleştirebilirsiniz +bunları veya opencode yapılandırması aracılığıyla kendinizinkini yapılandırın. + +Bir oturum sırasında modlar arasında geçiş yapabilir veya bunları yapılandırma dosyanızda yapılandırabilirsiniz. + +--- + +## Yerleşik + +opencode iki yerleşik modla birlikte gelir. + +--- + +### Build + +Derleme, tüm araçların etkin olduğu **varsayılan** moddur. Bu, dosya işlemlerine ve sistem komutlarına tam erişime ihtiyaç duyduğunuz geliştirme çalışmaları için standart moddur. + +--- + +### Plan + +Planlama ve analiz için tasarlanmış sınırlı bir mod. Plan modunda aşağıdaki araçlar varsayılan olarak devre dışıdır: + +- `write` - Yeni dosyalar oluşturulamıyor +- `edit` - Planın kendisini detaylandırmak için `.opencode/plans/*.md` adresinde bulunan dosyalar dışında mevcut dosyalar değiştirilemez +- `patch` - Yamalar uygulanamaz +- `bash` - Kabuk komutları yürütülemiyor + +Bu mod, yapay zekanın kod tabanınızda herhangi bir gerçek değişiklik yapmadan kodu analiz etmesini, değişiklik önermesini veya plan oluşturmasını istediğinizde kullanışlıdır. + +--- + +## Geçiş + +Bir oturum sırasında _Tab_ tuşunu kullanarak modlar arasında geçiş yapabilirsiniz. Veya yapılandırılmış `switch_mode` tuş bağlantınız. + +Ayrıca bkz.: Kod biçimlendirme yapılandırması hakkında bilgi için [Formatters](/docs/formatters). + +--- + +## Yapılandırma + +Yerleşik modları özelleştirebilir veya yapılandırma aracılığıyla kendinizinkini oluşturabilirsiniz. Modlar iki şekilde yapılandırılabilir: + +### JSON Yapılandırması + +`opencode.json` yapılandırma dosyanızdaki modları yapılandırın: + +```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 Yapılandırması + +Markdown dosyalarını kullanarak modları da tanımlayabilirsiniz. Bunları şuraya yerleştirin: + +- Global: `~/.config/opencode/modes/` +- Project: `.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. +``` + +Markdown dosyası adı mod adı olur (örneğin, `review.md` bir `review` modu oluşturur). + +Bu yapılandırma seçeneklerine ayrıntılı olarak bakalım. + +--- + +### Model + +Bu modun 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. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### Sıcaklık + +`temperature` yapılandırmasıyla yapay zekanın yanıtlarının rastgeleliğini ve yaratıcılığını 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" +{ + "mode": { + "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 planlaması 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" +{ + "mode": { + "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 modele özgü varsayılanları kullanır (çoğu model için genellikle 0, Qwen modelleri için 0,55). + +--- + +### İstem + +`prompt` yapılandırmasıyla bu mod için özel bir sistem bilgi istemi dosyası belirtin. Bilgi istemi dosyası, modun amacına özel talimatlar içermelidir. + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Bu yol, yapılandırma dosyasının bulunduğu yere göredir. Yani bu işe yarıyor +hem global opencode yapılandırması hem de projeye özel yapılandırma. + +--- + +### Araçlar + +`tools` yapılandırmasıyla bu modda hangi araçların kullanılabileceğini kontrol edin. Belirli araçları `true` veya `false` olarak ayarlayarak etkinleştirebilir veya devre dışı bırakabilirsiniz. + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +Hiçbir araç belirtilmezse tüm araçlar varsayılan olarak etkindir. + +--- + +#### Mevcut araçlar + +İşte mod yapılandırması aracılığıyla kontrol edilebilecek tüm araçlar. + +| Araç | Açıklama | +| ----------- | ------------------------------ | +| `bash` | Kabuk komutlarını yürütün | +| `edit` | Mevcut dosyaları değiştirin | +| `write` | Yeni dosyalar oluştur | +| `read` | Dosya içeriğini oku | +| `grep` | Dosya içeriğini ara | +| `glob` | Dosyaları desene göre bul | +| `list` | Dizinin içeriğini listele | +| `patch` | Dosyalara yama uygula | +| `todowrite` | Yapılacaklar listelerini yönet | +| `todoread` | Yapılacaklar listelerini oku | +| `webfetch` | Web içeriğini getir | + +--- + +## Özel modlar + +Yapılandırmaya ekleyerek kendi özel modlarınızı oluşturabilirsiniz. Her iki yaklaşımın kullanıldığı örnekler aşağıda verilmiştir: + +### JSON yapılandırması kullanma + +```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 + } + } + } +} +``` + +### Markdown dosyaları kullanma + +Projeye özel modlar için `.opencode/modes/` veya genel modlar için `~/.config/opencode/modes/`'de mod dosyaları oluşturun: + +```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 +``` + +--- + +### Kullanım Senaryoları + +Farklı modlar için bazı yaygın kullanım senaryoları aşağıda verilmiştir. + +- **Derleme modu**: Tüm araçların etkinleştirildiği tam geliştirme çalışması +- **Plan modu**: Değişiklik yapmadan analiz ve planlama +- **İnceleme modu**: Salt okunur erişim ve belgeleme araçlarıyla kod incelemesi +- **Hata ayıklama modu**: Bash ve okuma araçları etkinken araştırmaya odaklanıldı +- **Belgeler modu**: Dosya işlemleriyle ancak sistem komutları olmadan belge yazma + +Ayrıca farklı modellerin farklı kullanım durumları için iyi olduğunu da görebilirsiniz. diff --git a/packages/web/src/content/docs/tr/network.mdx b/packages/web/src/content/docs/tr/network.mdx new file mode 100644 index 00000000000..b1ea7bc79fd --- /dev/null +++ b/packages/web/src/content/docs/tr/network.mdx @@ -0,0 +1,57 @@ +--- +title: Ağ +description: Proxy'leri ve özel sertifikaları yapılandırın. +--- + +opencode, kurumsal ağ ortamları için standart proxy ortam değişkenlerini ve özel sertifikaları destekler. + +--- + +## Vekil Sunucu + +opencode respects standard proxy environment variables. + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +TUI yerel bir HTTP sunucusuyla iletişim kurar. Yönlendirme döngülerini önlemek için bu bağlantının proxy'sini atlamanız gerekir. +::: + +[CLI flags](/docs/cli#run) kullanarak sunucunun bağlantı noktasını ve ana bilgisayar adını yapılandırabilirsiniz. + +--- + +### Kimlik doğrulama + +Proxy'niz temel kimlik doğrulama gerektiriyorsa, kimlik bilgilerini URL dosyasına ekleyin. + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +Şifreleri sabit kodlamaktan kaçının. Ortam değişkenlerini veya güvenli kimlik bilgileri deposunu kullanın. +::: + +NTLM veya Kerberos gibi gelişmiş kimlik doğrulaması gerektiren proxy'ler için, kimlik doğrulama yönteminizi destekleyen bir LLM Ağ Geçidi kullanmayı düşünün. + +--- + +## Özel sertifikalar + +Kuruluşunuz HTTPS bağlantıları için özel CA'lar kullanıyorsa, opencode'u bunlara güvenecek şekilde yapılandırın. + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +Bu hem proxy bağlantıları hem de doğrudan API erişimi için işe yarar. diff --git a/packages/web/src/content/docs/tr/permissions.mdx b/packages/web/src/content/docs/tr/permissions.mdx new file mode 100644 index 00000000000..1194be9a43f --- /dev/null +++ b/packages/web/src/content/docs/tr/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: İzinler +description: Hangi işlemlerin çalıştırılması için onay sürecini kontrol edin. +--- + +opencode, belirli bir eylemin otomatik olarak mı çalıştırılacağına, size sorulacağına veya engelleneceğine karar vermek için `permission` yapılandırmasını kullanır. + +`v1.1.1` itibarıyla eski `tools` boolean yapılandırması kullanımdan kaldırıldı ve `permission` ile birleştirildi. Eski `tools` yapılandırması geriye dönük uyumluluk açısından hâlâ desteklenmektedir. + +--- + +## Eylemler + +Her izin kuralı şunlardan birine çözümlenir: + +- `"allow"` — onay olmadan çalıştır +- `"ask"` — onay istemi +- `"deny"` — eylemi engelle + +--- + +## Yapılandırma + +İzinleri genel olarak (`*` ile) ayarlayabilir ve belirli araçları geçersiz kılabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +Ayrıca tüm izinleri aynı anda ayarlayabilirsiniz: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## Ayrıntılı Kurallar (Nesne Sözdizimi) + +Çoğu izin için, araç girişine bağlı olarak farklı eylemleri uygulamak için bir nesneyi kullanabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +Kurallar, **son eşleşen kuralın kazanması** ile kalıp eşleşmesine göre değerlendirilir. Yaygın bir model, tümünü yakala `"*"` kuralını ilk sıraya koymak ve daha spesifik kuralları ondan sonra koymaktır. + +### Joker Karakterler + +İzin kalıpları basit joker karakter eşleştirmesini kullanır: + +- `*` herhangi bir karakterin sıfır veya daha fazlasıyla eşleşir +- `?` tam olarak bir karakterle eşleşir +- Diğer tüm karakterler birebir eşleşir + +### Ana Dizin Genişletme + +Ana dizininize referans vermek için bir modelin başlangıcında `~` veya `$HOME` kullanabilirsiniz. Bu özellikle [`external_directory`](#external-directories) kuralları için kullanışlıdır. + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### Harici Dizinler + +opencode'un başlatıldığı çalışma dizini dışındaki yollara dokunan araç çağrılarına izin vermek için `external_directory` kullanın. Bu, girdi olarak bir yolu alan tüm araçlar için geçerlidir (örneğin `read`, `edit`, `list`, `glob`, `grep` ve birçok `bash` komutu). + +Ana sayfa genişletmesi (`~/...` gibi) yalnızca bir kalıbın nasıl yazıldığını etkiler. Geçerli çalışma alanının harici bir yolunu oluşturmaz, dolayısıyla çalışma dizini dışındaki yollara yine de `external_directory` aracılığıyla izin verilmesi gerekir. + +Örneğin bu, `~/projects/personal/` altındaki her şeye erişime izin verir: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +Burada izin verilen herhangi bir dizin, geçerli çalışma alanıyla aynı varsayılanları devralır. [`read` defaults to `allow`](#defaults)'dan bu yana, geçersiz kılınmadığı sürece `external_directory` altındaki girişler için okumalara da izin verilir. Bir aracın bu yollarda kısıtlanması gerektiğinde (okumaları tutarken düzenlemeleri engellemek gibi) açık kurallar ekleyin: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +Listeyi güvenilir yollara odaklı tutun ve diğer araçlar için gereken ekstra izin verme veya reddetme kurallarını katmanlayın (örneğin `bash`). + +--- + +## Mevcut İzinler + +opencode izinleri araç adına ve birkaç güvenlik önlemine göre anahtarlanır: + +- `read` — bir dosyayı okumak (dosya yoluyla eşleşir) +- `edit` — tüm dosya değişiklikleri (`edit`, `write`, `patch`, `multiedit`'yi kapsar) +- `glob` — dosya genellemesi (glob düzeniyle eşleşir) +- `grep` — içerik arama (regex modeliyle eşleşir) +- `list` — bir dizideki dosyaları listeleme (dizin yoluyla eşleşir) +- `bash` — kabuk komutlarını çalıştırma (`git status --porcelain` gibi ayrıştırılmış komutlarla eşleşir) +- `task` — alt agent'ların başlatılması (alt agent türüyle eşleşir) +- `skill` — bir skill yükleniyor (skill adıyla eşleşir) +- `lsp` — LSP sorgularını çalıştırıyor (şu anda ayrıntılı değil) +- `todoread`, `todowrite` — yapılacaklar listesini okuma/güncelleme +- `webfetch` — URL getiriliyor (URL ile eşleşiyor) +- `websearch`, `codesearch` — web/kod arama (sorguyla eşleşir) +- `external_directory` — bir araç proje çalışma dizini dışındaki yollara dokunduğunda tetiklenir +- `doom_loop` — aynı araç çağrısı aynı girdiyle 3 kez tekrarlandığında tetiklenir + +--- + +## Varsayılanlar + +Hiçbir şey belirtmezseniz opencode izin verilen varsayılanlardan başlar: + +- Çoğu izin varsayılan olarak `"allow"` şeklindedir. +- `doom_loop` ve `external_directory` varsayılan olarak `"ask"`'dir. +- `read`, `"allow"`'dır, ancak `.env` dosyaları varsayılan olarak reddedilir: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## “Sor” Ne Yapar? + +opencode onay istediğinde kullanıcı arayüzü üç sonuç sunar: + +- `once` — yalnızca bu isteği onayla +- `always` — önerilen kalıplarla eşleşen gelecekteki istekleri onaylayın (geçerli opencode oturumunun geri kalanı için) +- `reject` — isteği reddet + +`always`'ın onaylayacağı kalıp seti araç tarafından sağlanır (örneğin, bash onayları genellikle `git status*` gibi güvenli bir komut önekini beyaz listeye alır). + +--- + +## Agent'lar + +Agent bazında izinleri geçersiz kılabilirsiniz. Agent izinleri global yapılandırmayla birleştirilir ve agent kuralları önceliklidir. [Daha fazla bilgi](/docs/agents#permissions). + +:::note +Daha ayrıntılı desen eşleştirme örnekleri için yukarıdaki [Ayrıntılı kurallar (nesne söz dizimi)](#granular-rules-object-syntax) bölümüne bakın. +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +Agent izinlerini Markdown'da da yapılandırabilirsiniz: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +Bağımsız değişken içeren komutlar için kalıp eşleştirmeyi kullanın. `"grep *"`, `grep pattern file.txt`'ye izin verir, ancak `"grep"` tek başına onu engeller. `git status` gibi komutlar varsayılan davranış için çalışır ancak argümanlar aktarıldığında açık izin (`"git status *"` gibi) gerektirir. +::: diff --git a/packages/web/src/content/docs/tr/plugins.mdx b/packages/web/src/content/docs/tr/plugins.mdx new file mode 100644 index 00000000000..0b24e48c35e --- /dev/null +++ b/packages/web/src/content/docs/tr/plugins.mdx @@ -0,0 +1,385 @@ +--- +title: Eklentiler +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. + +Örnekler için topluluk tarafından oluşturulan [eklentilere](/docs/ecosystem#plugins) göz atın. + +--- + +## Eklenti kullanımı + +Eklentileri yüklemenin iki yolu vardır. + +--- + +### Yerel dosyalardan + +JavaScript veya TypeScript dosyalarını eklenti dizinine yerleştirin. + +- `.opencode/plugins/` - Proje düzeyinde eklentiler +- `~/.config/opencode/plugins/` - Genel eklentiler + +Bu dizinlerdeki dosyalar başlangıçta otomatik olarak yüklenir. + +--- + +### npm'den + +Yapılandırma dosyanızda npm paketlerini belirtin. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +Hem normal hem de kapsamlı npm paketleri desteklenir. + +[Ekosistem](/docs/ecosystem#plugins)'deki mevcut eklentilere göz atın. + +--- + +### Eklentiler nasıl kurulur? + +**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. + +--- + +### Yükleme sırası + +Eklentiler tüm kaynaklardan yüklenir ve tüm kancalar sırayla çalışır. Yükleme sırası şöyledir: + +1. Global config (`~/.config/opencode/opencode.json`) +2. Project config (`opencode.json`) +3. Global eklenti dizini (`~/.config/opencode/plugins/`) +4. Proje eklenti dizini (`.opencode/plugins/`) + +Aynı ad ve sürüme sahip yinelenen npm paketleri bir kez yüklenir. Ancak benzer adlara sahip bir yerel eklenti ve bir npm eklentisinin her ikisi de ayrı ayrı yüklenir. + +--- + +## 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. + +--- + +### Bağımlılıklar + +Yerel eklentiler ve özel araçlar harici npm paketlerini kullanabilir. İhtiyacınız olan bağımlılıkları içeren config dizininize bir `package.json` ekleyin. + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +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" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### Temel yapı + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +Eklenti işlevi şunları alır: + +- `project`: Mevcut proje bilgisi. +- `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. +- `$`: Bun'un komutları yürütmek için kullandığı [shell API](https://bun.com/docs/runtime/shell). + +--- + +### TypeScript desteği + +TypeScript eklentileri için türleri eklenti paketinden içe aktarabilirsiniz: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### Olaylar + +Eklentiler aşağıdaki Örnekler bölümünde görüldüğü gibi etkinliklere abone olabilirler. Burada mevcut farklı etkinliklerin bir listesi bulunmaktadır. + +#### Komut Olayları + +- `command.executed` + +#### Dosya Olayları + +- `file.edited` +- `file.watcher.updated` + +#### Kurulum Olayları + +- `installation.updated` + +#### LSP Olayları + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### Mesaj Olayları + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### İzin Olayları + +- `permission.asked` +- `permission.replied` + +#### Sunucu Olayları + +- `server.connected` + +#### Oturum Olayları + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### Yapılacaklar Olayları + +- `todo.updated` + +#### Kabuk Olayları + +- `shell.env` + +#### Araç Olayları + +- `tool.execute.after` +- `tool.execute.before` + +#### TUI Olayları + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## Örnekler + +opencode'u genişletmek için kullanabileceğiniz bazı eklenti örneklerini burada bulabilirsiniz. + +--- + +### Bildirim Gönderme + +Belirli olaylar meydana geldiğinde bildirim gönderin: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +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. +::: + +--- + +### .env Koruması + +opencode'un `.env` dosyalarını okumasını önleyin: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### Ortam değişkenlerini enjekte etme + +Ortam değişkenlerini tüm kabuk yürütmeye (AI araçları ve kullanıcı terminalleri) enjekte edin: + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### Özel araçlar + +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" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +`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. + +--- + +### Günlüğe kaydetme + +Yapılandırılmış günlük kaydı için `client.app.log()` yerine `console.log` kullanın: + +```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" }, + }, + }) +} +``` + +Seviyeler: `debug`, `info`, `warn`, `error`. Ayrıntılar için [SDK documentation](https://opencode.ai/docs/sdk)'e bakın. + +--- + +### Sıkıştırma kancaları + +Bir oturum sıkıştırıldığında içerilen bağlamı özelleştirin: + +```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` kancası, LLM bir devam özeti oluşturmadan önce tetiklenir. Varsayılan sıkıştırma isteminin kaçıracağı etki alanına özgü bağlamı enjekte etmek için bunu kullanın. + +Ayrıca `output.prompt` ayarını yaparak sıkıştırma istemini tamamen değiştirebilirsiniz: + +```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` ayarlandığında, varsayılan sıkıştırma isteminin tamamen yerini alır. Bu durumda `output.context` dizisi dikkate alınmaz. diff --git a/packages/web/src/content/docs/tr/providers.mdx b/packages/web/src/content/docs/tr/providers.mdx new file mode 100644 index 00000000000..efe5ff9afa4 --- /dev/null +++ b/packages/web/src/content/docs/tr/providers.mdx @@ -0,0 +1,1890 @@ +--- +title: Sağlayıcılar +description: opencode'da herhangi bir LLM sağlayıcısını kullanma. +--- + +import config from "../../../../config.mjs" +export const console = config.console + +opencode, **75'ten fazla LLM sağlayıcısını** desteklemek için [AI SDK](https://ai-sdk.dev/) ve [Models.dev](https://models.dev) kullanır ve yerel modellerin çalıştırılmasını destekler. + +Bir sağlayıcı eklemek için şunları yapmanız gerekir: + +1. `/connect` komutunu kullanarak sağlayıcı için API anahtarlarını ekleyin. +2. Sağlayıcıyı opencode yapılandırmanızda yapılandırın. + +--- + +### Kimlik Bilgileri + +Bir sağlayıcının API anahtarlarını `/connect` komutuyla eklediğinizde, bunlar saklanır +`~/.local/share/opencode/auth.json` içinde. + +--- + +### Yapılandırma + +Sağlayıcıları opencode'unuzdaki `provider` bölümü aracılığıyla özelleştirebilirsiniz. +config. + +--- + +#### Temel URL + +`baseURL` seçeneğini ayarlayarak URL tabanını herhangi bir sağlayıcı için özelleştirebilirsiniz. Bu, proxy hizmetlerini veya özel uç noktaları kullanırken kullanışlıdır. + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen, opencode ekibi tarafından sağlanan modellerin bir listesidir. +opencode ile iyi çalıştığı test edilip doğrulandı. [Daha fazla bilgi](/docs/zen). + +:::tip +Yeniyseniz OpenCode Zen ile başlamanızı öneririz. +::: + +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 + ``` + +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 +liste, bir PR açmaktan çekinmeyin. + +:::note +Burada bir sağlayıcı göremiyor musunuz? Bir PR gönderin. +::: + +--- + +### 302.AI + +1. [302.AI console](https://302.ai/) adresine gidin, bir hesap oluşturun ve bir API anahtarı oluşturun. + +2. `/connect` komutunu çalıştırın ve **302.AI**'yi arayın. + + ```txt + /connect + ``` + +3. 302.AI API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +Amazon Bedrock'u opencode ile kullanmak için: + +1. Amazon Bedrock konsolundaki **Model kataloğuna** gidin ve istekte bulunun + Dilediğiniz modellere ulaşabilirsiniz. + + :::tip + Amazon Bedrock'ta istediğiniz modele erişiminizin olması gerekiyor. + ::: + +2. **Kimlik doğrulamayı yapılandırın**: Aşağıdaki yöntemlerden birini kullanın: + + #### Ortam Değişkenleri (Hızlı Başlangıç) + + opencode'u çalıştırırken bu ortam değişkenlerinden birini ayarlayın: + + ```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode + ``` + + Veya bunları bash profilinize ekleyin: + + ```bash title="~/.bash_profile" + export AWS_PROFILE=my-dev-profile + export AWS_REGION=us-east-1 + ``` + + #### Yapılandırma Dosyası (Önerilen) + + Projeye özel veya kalıcı yapılandırma için `opencode.json` kullanın: + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile" + } + } + } + } + ``` + + **Mevcut seçenekler:** + - `region` - AWS region (e.g., `us-east-1`, `eu-west-1`) + - `profile` - `~/.aws/credentials`'den AWS adlı profil + - `endpoint` - VPC uç noktaları için özel uç nokta URL (genel `baseURL` seçeneğinin takma adı) + + :::tip + Yapılandırma dosyası seçenekleri ortam değişkenlerine göre önceliklidir. + ::: + +#### Gelişmiş: VPC Uç Noktaları + +Bedrock için VPC uç noktaları kullanıyorsanız: + +```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` seçeneği, AWS'ye özgü terminolojiyi kullanan genel `baseURL` seçeneğinin takma adıdır. Hem `endpoint` hem de `baseURL` belirtilirse, `endpoint` öncelikli olur. +::: + +#### Kimlik Doğrulama Yöntemleri + +- **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: Bir IAM kullanıcısı oluşturun ve AWS Konsolunda erişim anahtarları oluşturun +- **`AWS_PROFILE`**: `~/.aws/credentials`'den adlandırılmış profilleri kullanın. İlk önce `aws configure --profile my-profile` veya `aws sso login` ile yapılandırın +- **`AWS_BEARER_TOKEN_BEDROCK`**: Amazon Bedrock konsolundan uzun vadeli API anahtarları oluşturun +- **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: EKS IRSA (IAM Hizmet Hesapları için Roller) veya OIDC federasyonuna sahip diğer Kubernetes ortamları için. Bu ortam değişkenleri, hizmet hesabı ek açıklamaları kullanılırken Kubernetes tarafından otomatik olarak eklenir. + +#### Kimlik Doğrulama Önceliği + +Amazon Bedrock aşağıdaki kimlik doğrulama önceliğini kullanır: + +1. **Taşıyıcı Belirteç** - `AWS_BEARER_TOKEN_BEDROCK` ortam değişkeni veya `/connect` komutundan belirteç +2. **AWS Credential Chain** - Profil, erişim anahtarları, paylaşılan kimlik bilgileri, IAM rolleri, Web Identity Tokens (EKS IRSA), örnek meta verileri + +:::note +Bir taşıyıcı belirteç ayarlandığında (`/connect` veya `AWS_BEARER_TOKEN_BEDROCK` yoluyla), yapılandırılmış profiller dahil olmak üzere tüm AWS kimlik bilgisi yöntemlerine göre öncelik kazanır. +::: + +3. İstediğiniz modeli seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +:::note +Özel çıkarım profilleri için anahtardaki modeli ve sağlayıcı adını kullanın ve `id` özelliğini arn olarak ayarlayın. Bu, doğru önbelleğe almayı sağlar: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. Kaydolduktan sonra `/connect` komutunu çalıştırın ve Anthropic'i seçin. + + ```txt + /connect + ``` + +2. Burada **Claude Pro/Max** seçeneğini seçebilirsiniz; tarayıcınız açılacaktır. + ve sizden kimlik doğrulamanızı isteyeceğiz. + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. Artık `/models` komutunu kullandığınızda tüm Antropik modeller mevcut olmalıdır. + + ```txt + /models + ``` + +:::info +Claude Pro/Max aboneliğinizi opencode'da kullanmak [Anthropic](https://anthropic.com) tarafından resmi olarak desteklenmemektedir. +::: + +##### API anahtarlarını kullanma + +Pro/Max aboneliğiniz yoksa **API Anahtarı Oluştur** seçeneğini de seçebilirsiniz. Ayrıca tarayıcınızı açacak ve Anthropic'te oturum açmanızı isteyecek ve terminalinize yapıştırabileceğiniz bir kod verecektir. + +Veya zaten bir API anahtarınız varsa **API Anahtarını Manuel Olarak Girin** seçeneğini seçip terminalinize yapıştırabilirsiniz. + +--- + +### Azure OpenAI + +:::note +"Üzgünüm ama bu isteğe yardımcı olamıyorum" hatalarıyla karşılaşırsanız Azure kaynağınızda içerik filtresini **DefaultV2** yerine **Default** olarak değiştirmeyi deneyin. +::: + +1. [Azure portal](https://portal.azure.com/)'a gidin ve bir **Azure OpenAI** kaynağı oluşturun. İhtiyacınız olacak: + - **Kaynak adı**: Bu, API bitiş noktanızın (`https://RESOURCE_NAME.openai.azure.com/`) parçası olur + - **API anahtarı**: Kaynağınızdan `KEY 1` veya `KEY 2` + +2. [Azure AI Foundry](https://ai.azure.com/)'a gidin ve bir model dağıtın. + + :::note + opencode'un düzgün çalışması için dağıtım adının model adıyla eşleşmesi gerekir. + ::: + +3. `/connect` komutunu çalıştırın ve **Azure**'u arayın. + + ```txt + /connect + ``` + +4. API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Kaynak adınızı ortam değişkeni olarak ayarlayın: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + Veya bash profilinize ekleyin: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. Dağıtılan modelinizi seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. [Azure portal](https://portal.azure.com/)'a gidin ve bir **Azure OpenAI** kaynağı oluşturun. İhtiyacınız olacak: + - **Kaynak adı**: Bu, API bitiş noktanızın (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) parçası olur + - **API anahtarı**: Kaynağınızdan `KEY 1` veya `KEY 2` + +2. [Azure AI Foundry](https://ai.azure.com/)'a gidin ve bir model dağıtın. + + :::note + opencode'un düzgün çalışması için dağıtım adının model adıyla eşleşmesi gerekir. + ::: + +3. `/connect` komutunu çalıştırın ve **Azure Cognitive Services**'i arayın. + + ```txt + /connect + ``` + +4. API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. Kaynak adınızı ortam değişkeni olarak ayarlayın: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + Veya bash profilinize ekleyin: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. Dağıtılan modelinizi seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Baseten + +1. [Baseten](https://app.baseten.co/) adresine gidin, bir hesap oluşturun ve bir API anahtarı oluşturun. + +2. `/connect` komutunu çalıştırın ve **Baseten**'i arayın. + + ```txt + /connect + ``` + +3. Baseten API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Cerebras + +1. [Cerebras console](https://inference.cerebras.ai/) adresine gidin, bir hesap oluşturun ve bir API anahtarı oluşturun. + +2. `/connect` komutunu çalıştırın ve **Cerebras**'ı arayın. + + ```txt + /connect + ``` + +3. Cerebras API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _Qwen 3 Coder 480B_ gibi bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +Cloudflare AI Gateway, OpenAI, Anthropic, Workers AI ve daha fazlasındaki modellere birleşik bir uç nokta aracılığıyla erişmenizi sağlar. [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) ile her sağlayıcı için ayrı API anahtarlarına ihtiyacınız yoktur. + +1. [Cloudflare dashboard](https://dash.cloudflare.com/)'a gidin, **AI** > **AI Ağ Geçidi**'ne gidin ve yeni bir ağ geçidi oluşturun. + +2. Hesap Kimliğinizi ve Ağ Geçidi Kimliğinizi ortam değişkenleri olarak ayarlayın. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. `/connect` komutunu çalıştırın ve **Cloudflare AI Gateway**'i arayın. + + ```txt + /connect + ``` + +4. Cloudflare API tokenınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + Veya bunu bir ortam değişkeni olarak ayarlayın. + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. Bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + + Opencode yapılandırmanız aracılığıyla da modeller ekleyebilirsiniz. + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +### Cortecs + +1. [Cortecs console](https://cortecs.ai/) adresine gidin, bir hesap oluşturun ve bir API anahtarı oluşturun. + +2. `/connect` komutunu çalıştırın ve **Cortecs**'i arayın. + + ```txt + /connect + ``` + +3. Cortecs API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _Kimi K2 Instruct_ gibi bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. [DeepSeek console](https://platform.deepseek.com/)'a gidin, bir hesap oluşturun ve **Yeni API anahtarı oluştur**'a tıklayın. + +2. `/connect` komutunu çalıştırın ve **DeepSeek**'i arayın. + + ```txt + /connect + ``` + +3. DeepSeek API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _DeepSeek Reasoner_ gibi bir DeepSeek modeli seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. [Deep Infra dashboard](https://deepinfra.com/dash) adresine gidin, bir hesap oluşturun ve bir API anahtarı oluşturun. + +2. `/connect` komutunu çalıştırın ve **Deep Infra**'yı arayın. + + ```txt + /connect + ``` + +3. Deep Infra API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Firmware + +1. [Firmware dashboard](https://app.firmware.ai/signup) adresine gidin, bir hesap oluşturun ve bir API anahtarı oluşturun. + +2. `/connect` komutunu çalıştırın ve **Firmware**'i arayın. + + ```txt + /connect + ``` + +3. Firmware API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. [Fireworks AI console](https://app.fireworks.ai/)'a gidin, bir hesap oluşturun ve **API Anahtarı Oluştur**'a tıklayın. + +2. `/connect` komutunu çalıştırın ve **Fireworks AI**'yi arayın. + + ```txt + /connect + ``` + +3. Fireworks AI API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _Kimi K2 Instruct_ gibi bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo, GitLab'ın Anthropic proxy'si aracılığıyla yerel araç çağırma yetenekleriyle yapay zeka destekli aracılı sohbet sağlar. + +1. `/connect` komutunu çalıştırın ve GitLab'ı seçin. + + ```txt + /connect + ``` + +2. Kimlik doğrulama yönteminizi seçin: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ + ``` + + #### OAuth Kullanımı (Önerilen) + + **OAuth**'u seçtiğinizde tarayıcınız yetkilendirme için açılacaktır. + + #### Kişisel Erişim Simgesini Kullanma + 1. Go to [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens) + 2. Click **Add new token** + 3. Name: `OpenCode`, Scopes: `api` + 4. Belirteci kopyalayın (`glpat-` ile başlar) + 5. Terminale girin + +3. Mevcut modelleri görmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + + Üç Claude tabanlı model mevcuttur: + - **duo-chat-haiku-4-5** (Varsayılan) - Hızlı görevler için hızlı yanıtlar + - **duo-chat-sonnet-4-5** - Çoğu iş akışı için dengeli performans + - **duo-chat-opus-4-5** - Karmaşık analizler için en yeteneklisi + +:::note +İstemiyorsanız 'GITLAB_TOKEN' ortam değişkenini de belirtebilirsiniz. +to store token in opencode auth storage. +::: + +##### Kendi Kendine Barındırılan GitLab + +:::note[uyumluluk notu] +opencode, oturum başlığını oluşturmak gibi bazı AI görevleri için küçük bir model kullanır. +Varsayılan olarak Zen tarafından barındırılan gpt-5-nano'yu kullanacak şekilde yapılandırılmıştır. opencode'u kilitlemek için +yalnızca kendi GitLab tarafından barındırılan örneğinizi kullanmak için aşağıdakileri ekleyin: +`opencode.json` dosyası. Ayrıca oturum paylaşımını devre dışı bırakmanız da önerilir. + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +Şirket içinde barındırılan GitLab örnekleri için: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +Örneğiniz özel bir AI Ağ Geçidi çalıştırıyorsa: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +Veya bash profilinize ekleyin: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +GitLab yöneticiniz aşağıdakileri etkinleştirmelidir: + +1. Kullanıcı, grup veya örnek için [Duo Agent Platform](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) +2. Feature flags (via Rails console): + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: + +##### Kendi Kendine Barındırılan örnekler için OAuth + +Oauth'un kendi kendine barındırılan örneğiniz için çalışmasını sağlamak amacıyla +yeni bir uygulama (Ayarlar → Uygulamalar) ile +geri arama URL `http://127.0.0.1:8080/callback` ve aşağıdaki kapsamlar: + +- api (Sizin adınıza API'a erişin) +- read_user (Kişisel bilgilerinizi okuyun) +- read_repository (Depoya salt okunur erişime izin verir) + +Then expose application ID as environment variable: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +Daha fazla belge [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth) ana sayfasında. + +##### Yapılandırma + +`opencode.json` üzerinden özelleştirin: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### GitLab API Araçları (İsteğe bağlı, ancak şiddetle önerilir) + +GitLab araçlarına (birleştirme istekleri, sorunlar, işlem hatları, CI/CD vb.) erişmek için: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +Bu eklenti, MR incelemeleri, sorun izleme, işlem hattı izleme ve daha fazlasını içeren kapsamlı GitLab veri havuzu yönetimi yetenekleri sağlar. + +--- + +### GitHub Copilot + +GitHub Copilot aboneliğinizi opencode'la kullanmak için: + +:::note +Bazı modelleri kullanmak için [Pro+ aboneliği](https://github.com/features/copilot/plans) gerekebilir. + +Bazı modellerin [GitHub Copilot settings](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use)'da manuel olarak etkinleştirilmesi gerekir. +::: + +1. `/connect` komutunu çalıştırın ve GitHub Copilot'u arayın. + + ```txt + /connect + ``` + +2. [github.com/login/device](https://github.com/login/device)'a gidin ve kodu girin. + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + └ Waiting for authorization... + ``` + +3. Şimdi istediğiniz modeli seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +Google Vertex AI'yi opencode ile kullanmak için: + +1. Google Cloud Console'daki **Model Bahçesi**'ne gidin ve şunları kontrol edin: + Bölgenizde mevcut modeller. + + :::note + Vertex AI API etkinleştirilmiş bir Google Cloud projenizin olması gerekir. + ::: + +2. Gerekli ortam değişkenlerini ayarlayın: + - `GOOGLE_CLOUD_PROJECT`: Google Cloud proje kimliğiniz + - `VERTEX_LOCATION` (isteğe bağlı): Vertex AI bölgesi (varsayılanı `global`'dir) + - Kimlik Doğrulama (birini seçin): + - `GOOGLE_APPLICATION_CREDENTIALS`: Hizmet hesabınızın yolu JSON anahtar dosyası + - gcloud kullanarak kimlik doğrulaması yapın CLI: `gcloud auth application-default login` + + Bunları opencode çalıştırılırken ayarlayın. + + ```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode + ``` + + Veya bunları bash profilinize ekleyin. + + ```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` bölgesi, hiçbir ekstra maliyet olmaksızın kullanılabilirliği artırır ve hataları azaltır. Veri yerleşimi gereksinimleri için bölgesel uç noktaları (ör. `us-central1`) kullanın. [Daha fazla bilgi](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. İstediğiniz modeli seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Groq + +1. [Groq console](https://console.groq.com/)'a gidin, **API Anahtarı Oluştur**'a tıklayın ve anahtarı kopyalayın. + +2. `/connect` komutunu çalıştırın ve Groq'u arayın. + + ```txt + /connect + ``` + +3. Sağlayıcının API anahtarını girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. İstediğinizi seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Hugging Face + +[Hugging Face Inference Providers](https://huggingface.co/docs/inference-providers) 17'den fazla sağlayıcı tarafından desteklenen açık modellere erişim sağlar. + +1. Çıkarım Sağlayıcılara çağrı yapma iznine sahip bir belirteç oluşturmak için [Hugging Face settings](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained) adresine gidin. + +2. `/connect` komutunu çalıştırın ve **Hugging Face**'i arayın. + + ```txt + /connect + ``` + +3. Hugging Face tokenınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _Kimi-K2-Instruct_ veya _GLM-4.6_ gibi bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai), AI uygulamalarınız için günlük kaydı, izleme ve analiz sağlayan bir LLM gözlemlenebilirlik platformudur. Helicone AI Gateway, taleplerinizi modele göre otomatik olarak uygun sağlayıcıya yönlendirir. + +1. [Helicone](https://helicone.ai) adresine gidin, bir hesap oluşturun ve kontrol panelinizden bir API anahtarı oluşturun. + +2. `/connect` komutunu çalıştırın ve **Helicone**'yu arayın. + + ```txt + /connect + ``` + +3. Helicone API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +Daha fazla sağlayıcı ve önbelleğe alma ve hız sınırlama gibi gelişmiş özellikler için [Helicone documentation](https://docs.helicone.ai)'yi kontrol edin. + +#### İsteğe Bağlı Yapılandırmalar + +Helicone'un opencode aracılığıyla otomatik olarak yapılandırılmayan bir özelliği veya modelini görmeniz durumunda bunu her zaman kendiniz yapılandırabilirsiniz. + +İşte [Helicone's Model Directory](https://helicone.ai/models), eklemek istediğiniz modellerin kimliklerini almak için buna ihtiyacınız olacak. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### Özel Başlıklar + +Helicone, önbelleğe alma, kullanıcı izleme ve oturum yönetimi gibi özellikler için özel başlıkları destekler. `options.headers` kullanarak bunları sağlayıcınızın yapılandırmasına ekleyin: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### Oturum izleme + +Helicone'un [Sessions](https://docs.helicone.ai/features/sessions) özelliği, ilgili LLM isteklerini birlikte gruplandırmanıza olanak tanır. Her opencode görüşmesini Helicone'da bir oturum olarak otomatik olarak kaydetmek için [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) eklentisini kullanın. + +```bash +npm install -g opencode-helicone-session +``` + +Yapılandırmanıza ekleyin. + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +Eklenti isteklerinize `Helicone-Session-Id` ve `Helicone-Session-Name` başlıklarını enjekte eder. Helicone'un Oturumlar sayfasında her opencode görüşmesinin ayrı bir oturum olarak listelendiğini göreceksiniz. + +##### Yaygın Helicone başlıkları + +| Başlık | Açıklama | +| -------------------------- | ------------------------------------------------------------- | +| `Helicone-Cache-Enabled` | Enable response caching (`true`/`false`) | +| `Helicone-User-Id` | Track metrics by user | +| `Helicone-Property-[Name]` | Add custom properties (e.g., `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | İstekleri bilgi istemi sürümleriyle ilişkilendirin | + +Mevcut tüm başlıklar için [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory)'a bakın. + +--- + +### llama.cpp + +opencode'u yerel modelleri kullanacak şekilde [llama.cpp's](https://github.com/ggml-org/llama.cpp) llama-server yardımcı programını kullanarak yapılandırabilirsiniz. + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +Bu örnekte: + +- `llama.cpp` özel sağlayıcı kimliğidir. Bu istediğiniz herhangi bir dize olabilir. +- `npm` bu sağlayıcı için kullanılacak paketi belirtir. Burada `@ai-sdk/openai-compatible`, herhangi bir OpenAI uyumlu API için kullanılır. +- `name` sağlayıcının kullanıcı arayüzündeki görünen adıdır. +- `options.baseURL` yerel sunucunun uç noktasıdır. +- `models` model kimliklerinin konfigürasyonlarına ait bir haritasıdır. Model adı, model seçim listesinde görüntülenecektir. + +--- + +### IO.NET + +IO.NET, çeşitli kullanım durumları için optimize edilmiş 17 model sunar: + +1. [IO.NET console](https://ai.io.net/) adresine gidin, bir hesap oluşturun ve bir API anahtarı oluşturun. + +2. `/connect` komutunu çalıştırın ve **IO.NET** öğesini arayın. + + ```txt + /connect + ``` + +3. IO.NET API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### LM Studio + +LM Studio aracılığıyla opencode'u yerel modelleri kullanacak şekilde yapılandırabilirsiniz. + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +Bu örnekte: + +- `lmstudio` özel sağlayıcı kimliğidir. Bu istediğiniz herhangi bir dize olabilir. +- `npm` bu sağlayıcı için kullanılacak paketi belirtir. Burada `@ai-sdk/openai-compatible`, herhangi bir OpenAI uyumlu API için kullanılır. +- `name` sağlayıcının kullanıcı arayüzündeki görünen adıdır. +- `options.baseURL` yerel sunucunun uç noktasıdır. +- `models` model kimliklerinin konfigürasyonlarına ait bir haritasıdır. Model adı, model seçim listesinde görüntülenecektir. + +--- + +### Moonshot AI + +Moonshot AI'dan Kimi K2'yi kullanmak için: + +1. [Moonshot AI console](https://platform.moonshot.ai/console)'a gidin, bir hesap oluşturun ve **API anahtarı oluştur**'a tıklayın. + +2. `/connect` komutunu çalıştırın ve **Moonshot AI**'yi arayın. + + ```txt + /connect + ``` + +3. Moonshot API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _Kimi K2_ seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### MiniMax + +1. [MiniMax API Console](https://platform.minimax.io/login) adresine gidin, bir hesap oluşturun ve bir API anahtarı oluşturun. + +2. `/connect` komutunu çalıştırın ve **MiniMax**'ı arayın. + + ```txt + /connect + ``` + +3. MiniMax API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _M2.1_ gibi bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. [Nebius Token Factory console](https://tokenfactory.nebius.com/)'a gidin, bir hesap oluşturun ve **Anahtar Ekle**'ye tıklayın. + +2. `/connect` komutunu çalıştırın ve **Nebius Token Factory**'yi arayın. + + ```txt + /connect + ``` + +3. Nebius Token Factory API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _Kimi K2 Instruct_ gibi bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Ollama + +Ollama aracılığıyla opencode'u yerel modelleri kullanacak şekilde yapılandırabilirsiniz. + +:::tip +Ollama kendisini opencode için otomatik olarak yapılandırabilir. Ayrıntılar için [Ollama integration docs](https://docs.ollama.com/integrations/opencode)'a bakın. +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +Bu örnekte: + +- `ollama` özel sağlayıcı kimliğidir. Bu istediğiniz herhangi bir dize olabilir. +- `npm` bu sağlayıcı için kullanılacak paketi belirtir. Burada `@ai-sdk/openai-compatible`, herhangi bir OpenAI uyumlu API için kullanılır. +- `name` sağlayıcının kullanıcı arayüzündeki görünen adıdır. +- `options.baseURL` yerel sunucunun uç noktasıdır. +- `models` model kimliklerinin konfigürasyonlarına ait bir haritasıdır. Model adı, model seçim listesinde görüntülenecektir. + +:::tip +Araç çağrıları çalışmıyorsa Ollama'da `num_ctx` değerini artırmayı deneyin. 16k - 32k civarında başlayın. +::: + +--- + +### Ollama Cloud + +Ollama Cloud'u opencode ile kullanmak için: + +1. [https://ollama.com/](https://ollama.com/) adresine gidin ve oturum açın veya bir hesap oluşturun. + +2. **Ayarlar** > **Anahtarlar**'a gidin ve yeni bir API anahtarı oluşturmak için **API Anahtarı Ekle**'yi tıklayın. + +3. opencode'da kullanmak için API anahtarını kopyalayın. + +4. `/connect` komutunu çalıştırın ve **Ollama Cloud**'u arayın. + + ```txt + /connect + ``` + +5. Ollama Cloud API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **Önemli**: opencode'da bulut modellerini kullanmadan önce model bilgilerini yerel olarak almanız gerekir: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. Ollama Cloud modelinizi seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### OpenAI + +[ChatGPT Plus or Pro](https://chatgpt.com/pricing)'a kaydolmanızı öneririz. + +1. Kaydolduktan sonra `/connect` komutunu çalıştırın ve OpenAI'yi seçin. + + ```txt + /connect + ``` + +2. Burada **ChatGPT Plus/Pro** seçeneğini seçebilirsiniz, tarayıcınız açılacaktır. + ve sizden kimlik doğrulamanızı isteyeceğiz. + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. Artık `/models` komutunu kullandığınızda tüm OpenAI modelleri mevcut olmalıdır. + + ```txt + /models + ``` + +##### API anahtarlarını kullanma + +Zaten bir API anahtarınız varsa, **API Anahtarını Manuel Olarak Girin** seçeneğini seçip terminalinize yapıştırabilirsiniz. + +--- + +### OpenCode Zen + +OpenCode Zen, opencode ekibinin test edip doğruladığı modellerin bir listesidir. [Daha fazla bilgi](/docs/zen). + +1. **OpenCode Zen**'de oturum açın ve **API Anahtarı Oluştur**'u tıklayın. + +2. `/connect` komutunu çalıştırın ve **OpenCode Zen**'i arayın. + + ```txt + /connect + ``` + +3. opencode API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _Qwen 3 Coder 480B_ gibi bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### OpenRouter + +1. [OpenRouter dashboard](https://openrouter.ai/settings/keys)'a gidin, **API Anahtarı Oluştur**'a tıklayın ve anahtarı kopyalayın. + +2. `/connect` komutunu çalıştırın ve OpenRouter'ı arayın. + + ```txt + /connect + ``` + +3. Sağlayıcının API anahtarını girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Birçok OpenRouter modeli varsayılan olarak önceden yüklenmiştir; istediğiniz modeli seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + + opencode yapılandırmanız aracılığıyla ek modeller de ekleyebilirsiniz. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +5. Bunları ayrıca opencode yapılandırmanız aracılığıyla da özelleştirebilirsiniz. Burada bir sağlayıcı belirtmeye ilişkin bir örnek verilmiştir + + ```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, birleşik bir platform aracılığıyla OpenAI, Anthropic, Google, Amazon, Meta, Mistral ve AI21'den 40'tan fazla modele erişim sağlar. + +1. [SAP BTP Cockpit](https://account.hana.ondemand.com/) sunucunuza gidin, SAP AI Core hizmet örneğinize gidin ve bir hizmet anahtarı oluşturun. + + :::tip + Hizmet anahtarı, `clientid`, `clientsecret`, `url` ve `serviceurls.AI_API_URL` içeren bir JSON nesnesidir. AI Core örneğinizi BTP Kokpitinde **Hizmetler** > **Örnekler ve Abonelikler** altında bulabilirsiniz. + ::: + +2. `/connect` komutunu çalıştırın ve **SAP AI Core** arayın. + + ```txt + /connect + ``` + +3. Servis anahtarınızı JSON girin. + + ```txt + ┌ Service key + │ + │ + └ enter + ``` + + Veya `AICORE_SERVICE_KEY` ortam değişkenini ayarlayın: + + ```bash + AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode + ``` + + Veya bash profilinize ekleyin: + + ```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' + ``` + +4. İsteğe bağlı olarak dağıtım kimliğini ve kaynak grubunu ayarlayın: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + Bu ayarlar isteğe bağlıdır ve SAP AI Core kurulumunuza göre yapılandırılmalıdır. + ::: + +5. 40'tan fazla mevcut model arasından 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. + +2. `/connect` komutunu çalıştırın ve **OVHcloud AI Endpoints**'i arayın. + + ```txt + /connect + ``` + +3. OVHcloud AI Uç Noktaları API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _gpt-oss-120b_ gibi bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Scaleway + +[Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/)'yi Opencode ile kullanmak için: + +1. Yeni bir API anahtarı oluşturmak için [Scaleway Console IAM settings](https://console.scaleway.com/iam/api-keys)'a gidin. + +2. `/connect` komutunu çalıştırın ve **Scaleway**'i arayın. + + ```txt + /connect + ``` + +3. Scaleway API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _devstral-2-123b-instruct-2512_ veya _gpt-oss-120b_ gibi bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Together AI + +1. [Together AI console](https://api.together.ai)'a gidin, bir hesap oluşturun ve **Anahtar Ekle**'ye tıklayın. + +2. `/connect` komutunu çalıştırın ve **Together AI**'yi arayın. + + ```txt + /connect + ``` + +3. Together AI API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _Kimi K2 Instruct_ gibi bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Venice AI + +1. [Venice AI console](https://venice.ai) adresine gidin, bir hesap oluşturun ve bir API anahtarı oluşturun. + +2. `/connect` komutunu çalıştırın ve **Venice AI**'yi arayın. + + ```txt + /connect + ``` + +3. Venice AI API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _Llama 3.3 70B_ gibi bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Vercel AI Gateway + +Vercel AI Gateway, OpenAI, Anthropic, Google, xAI ve daha fazlasındaki modellere birleşik bir uç nokta aracılığıyla erişmenizi sağlar. Modeller herhangi bir fark olmadan liste fiyatıyla sunulmaktadır. + +1. [Vercel dashboard](https://vercel.com/)'a gidin, **AI Ağ Geçidi** sekmesine gidin ve yeni bir API anahtarı oluşturmak için **API anahtarlarına** tıklayın. + +2. `/connect` komutunu çalıştırın ve **Vercel AI Gateway**'i arayın. + + ```txt + /connect + ``` + +3. Vercel AI Gateway API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +Modelleri opencode yapılandırmanız aracılığıyla da özelleştirebilirsiniz. Sağlayıcı yönlendirme sırasını belirtmeye ilişkin bir örneği burada bulabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "vercel": { + "models": { + "anthropic/claude-sonnet-4": { + "options": { + "order": ["anthropic", "vertex"] + } + } + } + } + } +} +``` + +Bazı yararlı yönlendirme seçenekleri: + +| Seçenek | Açıklama | +| ------------------- | --------------------------------------------------------------------- | +| `order` | Denenecek sağlayıcı sırası | +| `only` | Belirli sağlayıcılarla sınırla | +| `zeroDataRetention` | Yalnızca sıfır veri saklama politikasına sahip sağlayıcıları kullanın | + +--- + +### xAI + +1. [xAI console](https://console.x.ai/) adresine gidin, bir hesap oluşturun ve bir API anahtarı oluşturun. + +2. `/connect` komutunu çalıştırın ve **xAI**'yi arayın. + + ```txt + /connect + ``` + +3. xAI API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _Grok Beta_ gibi bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### Z.AI + +1. [Z.AI API console](https://z.ai/manage-apikey/apikey-list)'a gidin, bir hesap oluşturun ve **Yeni bir API anahtarı oluştur**'a tıklayın. + +2. `/connect` komutunu çalıştırın ve **Z.AI**'yi arayın. + + ```txt + /connect + ``` + + **GLM Kodlama Planı**'na aboneyseniz **Z.AI Kodlama Planı**'nı seçin. + +3. Z.AI API anahtarınızı girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _GLM-4.7_ gibi bir model seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + +### ZenMux + +1. [ZenMux dashboard](https://zenmux.ai/settings/keys)'a gidin, **API Anahtarı Oluştur**'a tıklayın ve anahtarı kopyalayın. + +2. `/connect` komutunu çalıştırın ve ZenMux'u arayın. + + ```txt + /connect + ``` + +3. Sağlayıcının API anahtarını girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Çoğu ZenMux modeli varsayılan olarak önceden yüklenmiştir; istediğinizi seçmek için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + + opencode yapılandırmanız aracılığıyla ek modeller de ekleyebilirsiniz. + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "zenmux": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +--- + +## Özel sağlayıcı + +`/connect` komutunda listelenmeyen herhangi bir **OpenAI uyumlu** sağlayıcıyı eklemek için: + +:::tip +OpenAI uyumlu herhangi bir sağlayıcıyı opencode ile kullanabilirsiniz. Çoğu modern yapay zeka sağlayıcısı OpenAI uyumlu API'ler sunar. +::: + +1. `/connect` komutunu çalıştırın ve **Diğer** seçeneğine ilerleyin. + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. Sağlayıcı için benzersiz bir kimlik girin. + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::note + Unutulmaz bir kimlik seçin, bunu yapılandırma dosyanızda kullanacaksınız. + ::: + +3. Sağlayıcı için API anahtarınızı girin. + + ```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. Proje dizininizde `opencode.json` dosyanızı oluşturun veya güncelleyin: + + ```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" + } + } + } + } + } + ``` + + Yapılandırma seçenekleri şunlardır: + - **npm**: Kullanılacak AI SDK paketi, OpenAI uyumlu sağlayıcılar için `@ai-sdk/openai-compatible` + - **name**: UI'daki görünen ad. + - **modeller**: Mevcut modeller. + - **options.baseURL**: API endpoint URL. + - **options.apiKey**: Kimlik doğrulama kullanılmıyorsa isteğe bağlı olarak API anahtarını ayarlayın. + - **options.headers**: İsteğe bağlı olarak özel başlıklar ayarlayın. + + Aşağıdaki örnekte gelişmiş seçenekler hakkında daha fazla bilgi bulabilirsiniz. + +5. `/models` komutunu çalıştırın; özel sağlayıcınız ve modelleriniz seçim listesinde görünecektir. + +--- + +##### Örnek + +Burada `apiKey`, `headers` ve model `limit` seçeneklerini ayarlayan bir örnek verilmiştir. + +```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 + } + } + } + } + } +} +``` + +Yapılandırma ayrıntıları: + +- **apiKey**: `env` değişken söz dizimini kullanarak ayarlayın, [daha fazla bilgi](/docs/config#env-vars). +- **headers**: Her istekle birlikte gönderilen özel başlıklar. +- **limit.context**: Modelin kabul ettiği maksimum giriş tokenları. +- **limit.output**: Modelin üretebileceği maksimum token sayısı. + +`limit` alanları opencode'un ne kadar bağlamınız kaldığını anlamasını sağlar. Standart sağlayıcılar bunları models.dev'den otomatik olarak alır. + +--- + +## Sorun Giderme + +Sağlayıcıyı yapılandırma konusunda sorun yaşıyorsanız aşağıdakileri kontrol edin: + +1. **Kimlik doğrulama kurulumunu kontrol edin**: Kimlik bilgilerinin geçerli olup olmadığını görmek için `opencode auth list` komutunu çalıştırın. + sağlayıcı için yapılandırmanıza eklenir. + + Bu, kimlik doğrulaması için ortam değişkenlerine güvenen Amazon Bedrock gibi sağlayıcılar için geçerli değildir. + +2. Özel sağlayıcılar için opencode yapılandırmasını kontrol edin ve: + - `/connect` komutunda kullanılan sağlayıcı kimliğinin, opencode yapılandırmanızdaki kimlikle eşleştiğinden emin olun. + - Sağlayıcı için doğru npm paketi kullanılıyor. Örneğin Cerebras için `@ai-sdk/cerebras` kullanın. Diğer tüm OpenAI uyumlu sağlayıcılar için `@ai-sdk/openai-compatible` kullanın. + - `options.baseURL` alanında doğru API bitiş noktasının kullanıldığını kontrol edin. diff --git a/packages/web/src/content/docs/tr/rules.mdx b/packages/web/src/content/docs/tr/rules.mdx new file mode 100644 index 00000000000..90ae91c9e20 --- /dev/null +++ b/packages/web/src/content/docs/tr/rules.mdx @@ -0,0 +1,180 @@ +--- +title: Kurallar +description: opencode için özel talimatları ayarlayın. +--- + +Bir `AGENTS.md` dosyası oluşturarak opencode için özel talimatlar verebilirsiniz. Bu, Cursor rules yaklaşımına benzer. Özel projeniz için davranışını özelleştirmek amacıyla LLM'in içeriğine dahil edilecek talimatları içerir. + +--- + +## Başlat + +Yeni bir `AGENTS.md` dosyası oluşturmak için `/init` komutunu opencode'da çalıştırabilirsiniz. + +:::tip +Projenizin `AGENTS.md` dosyasını Git'e göndermelisiniz. +::: + +Bu, projenin neyle ilgili olduğunu anlamak için projenizi ve tüm içeriğini tarayacak ve onunla bir `AGENTS.md` dosyası oluşturacaktır. Bu, opencode'un projede daha iyi gezinmesine yardımcı olur. + +Mevcut bir `AGENTS.md` dosyanız varsa, bu dosyaya eklemeye çalışacaktır. + +--- + +## Örnek + +Bu dosyayı manuel olarak da oluşturabilirsiniz. İşte bir `AGENTS.md` dosyasına koyabileceğiniz bazı şeylere bir örnek. + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +Buraya projeye özel talimatlar ekliyoruz ve bu, ekibiniz arasında paylaşılacaktır. + +--- + +## Türler + +opencode ayrıca `AGENTS.md` dosyasının birden fazla konumdan okunmasını da destekler. Ve bu farklı amaçlara hizmet ediyor. + +### Proje + +Projeye özel kurallar için proje kökünüze bir `AGENTS.md` yerleştirin. Bunlar yalnızca bu dizinde veya alt dizinlerinde çalışırken geçerlidir. + +### Global + +Ayrıca `~/.config/opencode/AGENTS.md` dosyasında genel kurallara sahip olabilirsiniz. Bu, tüm opencode oturumlarına uygulanır. + +Bu Git'e kaydedilmediği veya ekibinizle paylaşılmadığı için, LLM'ın uyması gereken kişisel kuralları belirtmek için bunu kullanmanızı öneririz. + +### Claude Code uyumluluğu + +opencode, Claude Code'dan geçiş yapan kullanıcılar için yedek olarak Claude Code'un dosya kurallarını destekler: + +- **Proje kuralları**: Proje dizininizdeki `CLAUDE.md` (`AGENTS.md` yoksa kullanılır) +- **Global kurallar**: `~/.claude/CLAUDE.md` (`~/.config/opencode/AGENTS.md` yoksa kullanılır) +- **Beceriler**: `~/.claude/skills/` — ayrıntılar için [Agent Skills](/docs/skills/)'e bakın + +Claude Code uyumluluğunu kapatmak için aşağıdaki ortam değişkenlerinden birini ayarlayın: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## Öncelik + +Opencode başlatıldığında kural dosyalarını şu sırayla arar: + +1. **Yerel dosyalar** geçerli dizinden yukarıya doğru giderek (`AGENTS.md`, `CLAUDE.md`) +2. **Global dosya** `~/.config/opencode/AGENTS.md` adresinde +3. `~/.claude/CLAUDE.md` adresindeki **Claude Kod dosyası** (devre dışı bırakılmadığı sürece) + +Her kategoride ilk eşleşen dosya kazanır. Örneğin, hem `AGENTS.md` hem de `CLAUDE.md` varsa yalnızca `AGENTS.md` kullanılır. Benzer şekilde, `~/.config/opencode/AGENTS.md`, `~/.claude/CLAUDE.md`'ye göre önceliklidir. + +--- + +## Özel talimatlar + +Özel talimat dosyalarını `opencode.json` veya global `~/.config/opencode/opencode.json`'de belirtebilirsiniz. Bu, sizin ve ekibinizin, mevcut kuralları AGENTS.md'ye kopyalamak yerine yeniden kullanmasına olanak tanır. + +Örnek: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +Web'den talimatlar yüklemek için uzak URL'leri de kullanabilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +Uzaktan talimatlar 5 saniyelik bir zaman aşımı ile getirilir. + +Tüm talimat dosyaları `AGENTS.md` dosyalarınızla birleştirilir. + +--- + +## Harici Dosyalara Referans Verme + +Opencode, `AGENTS.md`'daki dosya referanslarını otomatik olarak ayrıştırmasa da, benzer işlevleri iki şekilde elde edebilirsiniz: + +### opencode.json'u kullanma + +Önerilen yaklaşım, `instructions`'deki `opencode.json` alanını kullanmaktır: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### AGENTS.md içinde manuel talimatlar + +`AGENTS.md`'nizde açık talimatlar sağlayarak opencode'u harici dosyaları okumayı öğretebilirsiniz. İşte pratik bir örnek: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +Bu yaklaşım şunları yapmanızı sağlar: + +- Modüler, yeniden kullanılabilir kural dosyaları oluşturun +- Sembolik bağlantılar veya git alt modülleri aracılığıyla kuralları projeler arasında paylaşın +- AGENTS.md dosyasını kısa tutarken ayrıntılı kılavuzlara referans verin +- opencode'un dosyaları yalnızca belirli bir görev için gerektiğinde yüklediğinden emin olun + +:::tip +Monorepo'lar veya ortak standartlara sahip projeler için, `opencode.json`'yi glob desenleriyle (`packages/*/AGENTS.md` gibi) kullanmak, manuel talimatlara göre daha sürdürülebilirdir. +::: diff --git a/packages/web/src/content/docs/tr/sdk.mdx b/packages/web/src/content/docs/tr/sdk.mdx new file mode 100644 index 00000000000..b5ba99f4374 --- /dev/null +++ b/packages/web/src/content/docs/tr/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: opencode sunucusu için type-safe JS istemcisi. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +opencode JS/TS SDK, sunucu ile etkileşmek için type-safe bir istemci sağlar. +opencode'u programatik olarak kontrol etmek ve entegrasyonlar oluşturmak için kullanabilirsiniz. + +[Sunucu](/docs/server) sayfasında nasıl çalıştığını görebilir, örnekler için topluluğun oluşturduğu [projeler](/docs/ecosystem#projects) bölümüne bakabilirsiniz. + +--- + +## Kurulum + +SDK'yı npm'den yükleyin: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## İstemci Oluşturma + +Bir opencode örneği oluşturun: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +Bu, hem bir sunucu hem de bir istemci başlatır + +#### Seçenekler + +| Seçenek | Tip | Açıklama | Varsayılan | +| ---------- | ------------- | --------------------------------------------- | ----------- | +| `hostname` | `string` | Sunucu ana bilgisayar adı | `127.0.0.1` | +| `port` | `number` | Sunucu bağlantı noktası | `4096` | +| `signal` | `AbortSignal` | İptal için durdurma sinyali | `undefined` | +| `timeout` | `number` | Sunucu başlatma için ms cinsinden zaman aşımı | `5000` | +| `config` | `Config` | Yapılandırma nesnesi | `{}` | + +--- + +## Yapılandırma + +Davranışı özelleştirmek için bir yapılandırma nesnesi iletebilirsiniz. Örnek yine de `opencode.json` dosyanızı alır, ancak yapılandırmayı satır içi olarak geçersiz kılabilir veya ekleyebilirsiniz: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## Yalnızca istemci + +Halihazırda çalışan bir opencode örneğiniz varsa, ona bağlanmak için bir istemci örneği oluşturabilirsiniz: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### Seçenekler + +| Seçenek | Tip | Açıklama | Varsayılan | +| --------------- | ---------- | --------------------------------- | ----------------------- | +| `baseUrl` | `string` | Sunucunun URL'si | `http://localhost:4096` | +| `fetch` | `function` | Özel fetch uygulaması | `globalThis.fetch` | +| `parseAs` | `string` | Yanıt ayrıştırma yöntemi | `auto` | +| `responseStyle` | `string` | Dönüş stili: `data` veya `fields` | `fields` | +| `throwOnError` | `boolean` | Dönüş yerine hata fırlat | `false` | + +--- + +## Türler + +SDK, tüm API türleri için TypeScript tanımlarını içerir. Bunları doğrudan içe aktarın: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +Tüm tipler, sunucunun OpenAPI spesifikasyonundan oluşturulur ve tipler dosyasında mevcuttur. + +--- + +## Hatalar + +SDK, yakalayabileceğiniz ve işleyebileceğiniz hatalar fırlatabilir: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## API'ler + +SDK, tüm sunucu API'lerini type-safe bir istemci aracılığıyla sunar. + +--- + +### Global + +| Yöntem | Açıklama | Yanıt | +| ----------------- | --------------------------------------- | ------------------------------------ | +| `global.health()` | Sunucu sağlığını ve sürümünü kontrol et | `{ healthy: true, version: string }` | + +--- + +#### Örnekler + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### App + +| Yöntem | Açıklama | Yanıt | +| -------------- | ----------------------------- | ------------------------------------------- | +| `app.log()` | Bir günlük girdisi yaz | `boolean` | +| `app.agents()` | Tüm mevcut agent'ları listele | Agent[] | + +--- + +#### Örnekler + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### Project + +| Yöntem | Açıklama | Yanıt | +| ------------------- | --------------------- | --------------------------------------------- | +| `project.list()` | Tüm projeleri listele | Project[] | +| `project.current()` | Mevcut projeyi al | Project | + +--- + +#### Örnekler + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### Path + +| Yöntem | Açıklama | Yanıt | +| ------------ | -------------- | ---------------------------------------- | +| `path.get()` | Mevcut yolu al | Path | + +--- + +#### Örnekler + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### Config + +| Yöntem | Açıklama | Yanıt | +| -------------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | Yapılandırma bilgisini al | Config | +| `config.providers()` | Sağlayıcıları ve varsayılan modelleri listele | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### Örnekler + +```javascript +const config = await client.config.get() + +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 | + +--- + +#### Örnekler + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### Dosyalar + +| Yöntem | Açıklama | Yanıt | +| ------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------- | +| `find.text({ query })` | Dosyalarda metin ara | `path`, `lines`, `line_number`, `absolute_offset`, `submatches` içeren eşleşme nesneleri dizisi | +| `find.files({ query })` | Dosya ve dizinleri isme göre bul | `string[]` (yollar) | +| `find.symbols({ query })` | Çalışma alanı sembollerini bul | Symbol[] | +| `file.read({ query })` | Bir dosyayı oku | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | İzlenen dosyalar için durumu al | File[] | + +`find.files` birkaç isteğe bağlı sorgu alanını destekler: + +- `type`: `"file"` veya `"directory"` +- `directory`: arama için proje kökünü geçersiz kılma +- `limit`: maksimum sonuç (1-200) + +--- + +#### Örnekler + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| Yöntem | Açıklama | Yanıt | +| ------------------------------ | --------------------------- | --------- | +| `tui.appendPrompt({ body })` | İsteme metin ekle | `boolean` | +| `tui.openHelp()` | Yardım iletişim kutusunu aç | `boolean` | +| `tui.openSessions()` | Oturum seçiciyi aç | `boolean` | +| `tui.openThemes()` | Tema seçiciyi aç | `boolean` | +| `tui.openModels()` | Model seçiciyi aç | `boolean` | +| `tui.submitPrompt()` | Mevcut istemi gönder | `boolean` | +| `tui.clearPrompt()` | İstemi temizle | `boolean` | +| `tui.executeCommand({ body })` | Bir komut çalıştır | `boolean` | +| `tui.showToast({ body })` | Toast bildirimi göster | `boolean` | + +--- + +#### Örnekler + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### Auth + +| Yöntem | Açıklama | Yanıt | +| ------------------- | ------------------------- | --------- | +| `auth.set({ ... })` | Kimlik bilgilerini ayarla | `boolean` | + +--- + +#### Örnekler + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### Olaylar + +| Yöntem | Açıklama | Yanıt | +| ------------------- | --------------------------------------- | --------------------------------------- | +| `event.subscribe()` | Sunucu tarafından gönderilen olay akışı | Sunucu tarafından gönderilen olay akışı | + +--- + +#### Örnekler + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/tr/server.mdx b/packages/web/src/content/docs/tr/server.mdx new file mode 100644 index 00000000000..e9af6afd05d --- /dev/null +++ b/packages/web/src/content/docs/tr/server.mdx @@ -0,0 +1,285 @@ +--- +title: Sunucu +description: opencode sunucusuyla HTTP uzerinden etkilesin. +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +`opencode serve` komutu, opencode istemcisinin kullanabileceği bir OpenAPI endpoint'i açan headless bir HTTP sunucusu çalıştırır. + +--- + +### Kullanım + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### Seçenekler + +| Bayrak | Açıklama | Varsayılan | +| --------------- | ---------------------------------------------- | ---------------- | +| `--port` | Dinlenecek bağlantı noktası | `4096` | +| `--hostname` | Dinlenecek ana bilgisayar adı | `127.0.0.1` | +| `--mdns` | mDNS keşfini etkinleştir | `false` | +| `--mdns-domain` | mDNS hizmeti için özel alan adı | `opencode.local` | +| `--cors` | İzin verilecek ek tarayıcı kaynakları (origin) | `[]` | + +`--cors` birden fazla kez geçilebilir: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### Kimlik Doğrulama + +Sunucuyu HTTP temel kimlik doğrulama (basic auth) ile korumak için `OPENCODE_SERVER_PASSWORD` ayarlayın. Kullanıcı adı varsayılan olarak `opencode` değeridir; değiştirmek isterseniz `OPENCODE_SERVER_USERNAME` ayarlayabilirsiniz. Bu ayar hem `opencode serve` hem de `opencode web` için geçerlidir. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### Nasıl çalışır + +`opencode` çalıştırdığınızda hem TUI hem de sunucu başlar. TUI, sunucuyla konuşan istemci tarafıdır. +Sunucu bir OpenAPI 3.1 spesifikasyon uç noktası açar. Bu uç nokta [SDK](/docs/sdk) üretiminde de kullanılır. + +:::tip +opencode ile programatik etkileşim için opencode sunucusunu kullanın. +::: + +Bu mimari, opencode'un birden fazla istemciyi desteklemesini ve programatik kullanımları mümkün kılmasını sağlar. + +`opencode serve` ile bağımsız bir sunucu başlatabilirsiniz. opencode TUI açıksa, `opencode serve` yeni bir sunucu başlatır. + +--- + +#### Mevcut sunucuya bağlanın + +TUI başlarken rastgele bir port ve hostname atanır. Bunun yerine `--hostname` ve `--port` [bayraklarını](/docs/cli) verebilirsiniz. + +[`/tui`](#tui) uç noktası sunucu üzerinden TUI'yi sürmek için kullanılabilir. Örneğin bir istemi önceden doldurabilir veya çalıştırabilirsiniz. Bu kurulum opencode [IDE](/docs/ide) eklentileri tarafından kullanılır. + +--- + +## Spesifikasyon + +Sunucu, şu adreste görülebilen bir OpenAPI 3.1 spesifikasyonu yayınlar: + +``` +http://:/doc +``` + +Örneğin `http://localhost:4096/doc`. İstemci oluşturmak, istek/yanit tiplerini incelemek veya Swagger gezgininde açmak için bu spec'i kullanın. + +--- + +## API'ler + +opencode sunucusu aşağıdaki API'leri sunar. + +--- + +### Global + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | ---------------- | ------------------------------- | ------------------------------------ | +| `GET` | `/global/health` | Sunucu sağlığını ve sürümünü al | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | Küresel olayları al (SSE akışı) | Olay akışı | + +--- + +### Proje + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | ------------------ | --------------------- | --------------------------------------------- | +| `GET` | `/project` | Tüm projeleri listele | Project[] | +| `GET` | `/project/current` | Mevcut projeyi al | Project | + +--- + +### Yol & VCS + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | ------- | ---------------------------------- | ------------------------------------------- | +| `GET` | `/path` | Mevcut yolu al | Path | +| `GET` | `/vcs` | Mevcut proje için VCS bilgisini al | VcsInfo | + +--- + +### Örnek (Instance) + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | ------------------- | ------------------------------ | --------- | +| `POST` | `/instance/dispose` | Mevcut örneği (instance) kapat | `boolean` | + +--- + +### Config + +| Yöntem | Yol | Açıklama | Yanıt | +| ------- | ------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------- | +| `GET` | `/config` | Yapılandırma bilgisini al | Config | +| `PATCH` | `/config` | Yapılandırmayı güncelle | Config | +| `GET` | `/config/providers` | Sağlayıcıları ve varsayılan modelleri listele | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +### Sağlayıcı (Provider) + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | -------------------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------- | +| `GET` | `/provider` | Tüm sağlayıcıları listele | `{ all: `Provider[]`, default: {...}, connected: string[] }` | +| `GET` | `/provider/auth` | Sağlayıcı kimlik doğrulama yöntemlerini al | `{ [providerID: string]: `ProviderAuthMethod[]` }` | +| `POST` | `/provider/{id}/oauth/authorize` | OAuth kullanarak bir sağlayıcıyı yetkilendir | ProviderAuthAuthorization | +| `POST` | `/provider/{id}/oauth/callback` | Bir sağlayıcı için OAuth geri çağrısını işle | `boolean` | + +--- + +### Oturumlar (Sessions) + +| Yöntem | Yol | Açıklama | Notlar | +| -------- | ---------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------ | +| `GET` | `/session` | Tüm oturumları listele | Session[] döndürür | +| `POST` | `/session` | Yeni bir oturum oluştur | gövde: `{ parentID?, title? }`, Session döndürür | +| `GET` | `/session/status` | Tüm oturumlar için durumu al | `{ [sessionID: string]: `SessionStatus` }` döndürür | +| `GET` | `/session/:id` | Oturum ayrıntılarını al | Session döndürür | +| `DELETE` | `/session/:id` | Bir oturumu ve tüm verilerini sil | `boolean` döndürür | +| `PATCH` | `/session/:id` | Oturum özelliklerini güncelle | gövde: `{ title? }`, Session döndürür | +| `GET` | `/session/:id/children` | Bir oturumun alt oturumlarını al | Session[] döndürür | +| `GET` | `/session/:id/todo` | Bir oturum için yapılacaklar listesini al | Todo[] döndürür | +| `POST` | `/session/:id/init` | Uygulamayı analiz et ve `AGENTS.md` oluştur | gövde: `{ messageID, providerID, modelID }`, `boolean` döndürür | +| `POST` | `/session/:id/fork` | Mevcut bir oturumu bir mesajda çatalla | gövde: `{ messageID? }`, Session döndürür | +| `POST` | `/session/:id/abort` | Çalışan bir oturumu iptal et | `boolean` döndürür | +| `POST` | `/session/:id/share` | Bir oturumu paylaş | Session döndürür | +| `DELETE` | `/session/:id/share` | Bir oturumun paylaşımını kaldır | Session döndürür | +| `GET` | `/session/:id/diff` | Bu oturum için farkı (diff) al | sorgu: `messageID?`, FileDiff[] döndürür | +| `POST` | `/session/:id/summarize` | Oturumu özetle | gövde: `{ providerID, modelID }`, `boolean` döndürür | +| `POST` | `/session/:id/revert` | Bir mesajı geri al | gövde: `{ messageID, partID? }`, `boolean` döndürür | +| `POST` | `/session/:id/unrevert` | Geri alınan tüm mesajları geri yükle | `boolean` döndürür | +| `POST` | `/session/:id/permissions/:permissionID` | Bir izin isteğine yanıt ver | gövde: `{ response, remember? }`, `boolean` döndürür | + +--- + +### Mesajlar + +| Yöntem | Yol | Açıklama | Notlar | +| ------ | --------------------------------- | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `GET` | `/session/:id/message` | Bir oturumdaki mesajları listele | sorgu: `limit?`, `{ info: `Message`, parts: `Part[]`}[]` döndürür | +| `POST` | `/session/:id/message` | Bir mesaj gönder ve yanıt bekle | gövde: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, `{ info: `Message`, parts: `Part[]`}` döndürür | +| `GET` | `/session/:id/message/:messageID` | Mesaj ayrıntılarını al | `{ info: `Message`, parts: `Part[]`}` döndürür | +| `POST` | `/session/:id/prompt_async` | Eşzamansız bir mesaj gönder (bekleme yok) | gövde: `/session/:id/message` ile aynı, `204 No Content` döndürür | +| `POST` | `/session/:id/command` | Bir eğik çizgi (slash) komutu çalıştır | gövde: `{ messageID?, agent?, model?, command, arguments }`, `{ info: `Message`, parts: `Part[]`}` döndürür | +| `POST` | `/session/:id/shell` | Bir kabuk komutu çalıştır | gövde: `{ agent, model?, command }`, `{ info: `Message`, parts: `Part[]`}` döndürür | + +--- + +### Komutlar + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | ---------- | --------------------- | --------------------------------------------- | +| `GET` | `/command` | Tüm komutları listele | Command[] | + +--- + +### Dosyalar + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | ------------------------ | -------------------------------- | ----------------------------------------------------------------------------------------------- | +| `GET` | `/find?pattern=` | Dosyalarda metin ara | `path`, `lines`, `line_number`, `absolute_offset`, `submatches` içeren eşleşme nesneleri dizisi | +| `GET` | `/find/file?query=` | Dosya ve dizinleri isme göre bul | `string[]` (yollar) | +| `GET` | `/find/symbol?query=` | Çalışma alanı sembollerini bul | Symbol[] | +| `GET` | `/file?path=` | Dosya ve dizinleri listele | FileNode[] | +| `GET` | `/file/content?path=

` | Bir dosyayı oku | FileContent | +| `GET` | `/file/status` | İzlenen dosyalar için durumu al | File[] | + +#### `/find/file` sorgu parametreleri + +- `query` (gerekli) - arama metni (bulanık eşleşme) +- `type` (isteğe bağlı) - sonuçları `"file"` veya `"directory"` ile sınırlama +- `directory` (isteğe bağlı) - arama için proje kökünü geçersiz kılma +- `limit` (isteğe bağlı) - en fazla sonuç (1-200) +- `dirs` (isteğe bağlı) - eski bayrak (`"false"` sadece dosyaları döndürür) + +--- + +### Araçlar (Deneysel) + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | ------------------------------------------- | ------------------------------------------------ | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | Tüm araç kimliklerini listele | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | Bir model için araçları JSON şemalarıyla listele | ToolList | + +--- + +### LSP, Biçimlendiriciler & MCP + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | ------------ | -------------------------------- | -------------------------------------------------------- | +| `GET` | `/lsp` | LSP sunucu durumunu al | LSPStatus[] | +| `GET` | `/formatter` | Biçimlendirici durumunu al | FormatterStatus[] | +| `GET` | `/mcp` | MCP sunucu durumunu al | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | Dinamik olarak MCP sunucusu ekle | gövde: `{ name, config }`, MCP durum nesnesi döndürür | + +--- + +### Agent'lar + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | -------- | ----------------------------- | ------------------------------------------- | +| `GET` | `/agent` | Tüm mevcut agent'ları listele | Agent[] | + +--- + +### Günlük (Logging) + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | ------ | ---------------------------------------------------------------- | --------- | +| `POST` | `/log` | Günlük girdisi yaz. Gövde: `{ service, level, message, extra? }` | `boolean` | + +--- + +### TUI + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | ----------------------- | ------------------------------------------------------- | ---------------------- | +| `POST` | `/tui/append-prompt` | İsteme metin ekle | `boolean` | +| `POST` | `/tui/open-help` | Yardım iletişim kutusunu aç | `boolean` | +| `POST` | `/tui/open-sessions` | Oturum seçiciyi aç | `boolean` | +| `POST` | `/tui/open-themes` | Tema seçiciyi aç | `boolean` | +| `POST` | `/tui/open-models` | Model seçiciyi aç | `boolean` | +| `POST` | `/tui/submit-prompt` | Mevcut istemi gönder | `boolean` | +| `POST` | `/tui/clear-prompt` | İstemi temizle | `boolean` | +| `POST` | `/tui/execute-command` | Bir komut çalıştır (`{ command }`) | `boolean` | +| `POST` | `/tui/show-toast` | Toast bildirimi göster (`{ title?, message, variant }`) | `boolean` | +| `GET` | `/tui/control/next` | Bir sonraki kontrol isteğini bekle | Kontrol isteği nesnesi | +| `POST` | `/tui/control/response` | Bir kontrol isteğine yanıt ver (`{ body }`) | `boolean` | + +--- + +### Kimlik Doğrulama (Auth) + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | ----------- | ----------------------------------------------------------------- | --------- | +| `PUT` | `/auth/:id` | Kimlik bilgilerini ayarla. Gövde sağlayıcı şemasıyla eşleşmelidir | `boolean` | + +--- + +### Olaylar (Events) + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | -------- | ------------------------------------------------------------------------------------------------------ | --------------------------------------- | +| `GET` | `/event` | Sunucu tarafından gönderilen olay akışı (SSE). İlk olay `server.connected`, ardından veriyolu olayları | Sunucu tarafından gönderilen olay akışı | + +--- + +### Dokümanlar (Docs) + +| Yöntem | Yol | Açıklama | Yanıt | +| ------ | ------ | -------------------------- | -------------------------------- | +| `GET` | `/doc` | OpenAPI 3.1 spesifikasyonu | OpenAPI spec içeren HTML sayfası | diff --git a/packages/web/src/content/docs/tr/share.mdx b/packages/web/src/content/docs/tr/share.mdx new file mode 100644 index 00000000000..1b7abfdb7ea --- /dev/null +++ b/packages/web/src/content/docs/tr/share.mdx @@ -0,0 +1,127 @@ +--- +title: Paylasim +description: opencode konusmalarini genel baglantilarla paylasin. +--- + +opencode'un paylasim ozelligi, konusmalariniz icin genel baglantilar olusturmanizi saglar. Boylece ekip arkadaslarinizla birlikte calisabilir veya diger kisilerden yardim alabilirsiniz. + +:::note +Paylasilan konusmalar, baglantiya sahip herkes tarafindan gorulebilir. +::: + +--- + +## Nasil calisir + +Bir konusmayi paylastiginizda opencode: + +1. Oturumunuz icin benzersiz bir genel URL olusturur +2. Konusma gecmisinizi sunucularimiza senkronize eder +3. Konusmayi paylasim baglantisiyla erisilebilir hale getirir - `opncd.ai/s/` + +--- + +## Paylasim + +opencode, konusmalarin nasil paylasilacagini kontrol eden uc farkli paylasim modu sunar: + +--- + +### Manuel (varsayilan) + +Varsayilan olarak opencode manuel paylasim modunu kullanir. Oturumlar otomatik paylasilmaz, ancak `/share` komutuyla manuel olarak paylasabilirsiniz: + +``` +/share +``` + +Bu komut benzersiz bir URL uretir ve panoya kopyalar. + +Manuel modu acikca ayarlamak icin [config dosyaniza](/docs/config) sunu ekleyin: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### Otomatik paylasim + +Tum yeni konusmalar icin otomatik paylasimi acmak isterseniz, [config dosyanizda](/docs/config) `share` degerini `"auto"` yapin: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +Otomatik paylasim acikken her yeni konusma otomatik olarak paylasilir ve bir baglanti olusturulur. + +--- + +### Devre disi + +Paylasimi tamamen kapatmak icin [config dosyanizda](/docs/config) `share` degerini `"disabled"` yapin: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +Bunu belirli bir projede tum ekip icin zorunlu kilmak icin proje icindeki `opencode.json` dosyasina ekleyip Git'e commit edin. + +--- + +## Paylasimi kaldirma + +Bir konusmanin paylasimini durdurmak ve genel erisimi kaldirmak icin: + +``` +/unshare +``` + +Bu komut paylasim baglantisini kaldirir ve konusmaya ait verileri siler. + +--- + +## Gizlilik + +Bir konusmayi paylasirken akilda tutulmasi gereken bazi noktalar vardir. + +--- + +### Veri saklama + +Paylasilan konusmalar, siz acikca paylasimi kaldirana kadar erisilebilir kalir. Buna sunlar dahildir: + +- Tum konusma gecmisi +- Tum mesajlar ve yanitlar +- Oturum metaverisi + +--- + +### Oneriler + +- Hassas bilgi icermeyen konusmalari paylasin. +- Paylasmadan once konusma icerigini gozden gecirin. +- Is birligi bittiginde paylasimi kaldirin. +- Tescilli kod veya gizli veri iceren konusmalari paylasmayin. +- Hassas projelerde paylasimi tamamen kapatin. + +--- + +## Kurumsal kullanim + +Kurumsal kurulumlarda paylasim ozelligi su sekillerde yapilandirilabilir: + +- Guvenlik uyumu icin tamamen **devre disi** birakilabilir +- Sadece SSO ile dogrulanan kullanicilarla **sinirlandirilabilir** +- Kendi altyapinizda **self-hosted** olarak calistirilabilir + +Kurulusunuzda opencode kullanimi icin [daha fazla bilgi alin](/docs/enterprise). diff --git a/packages/web/src/content/docs/tr/skills.mdx b/packages/web/src/content/docs/tr/skills.mdx new file mode 100644 index 00000000000..7077ed129f1 --- /dev/null +++ b/packages/web/src/content/docs/tr/skills.mdx @@ -0,0 +1,222 @@ +--- +title: "Ajan becerileri" +description: "SKILL.md ile tekrar kullanilabilir davranis tanimlayin" +--- + +Ajan becerileri, opencode'un deponuzdan veya ev dizininizden tekrar kullanilabilir talimatlari kesfetmesini saglar. +Beceriler, yerel `skill` araci uzerinden ihtiyac aninda yuklenir; ajanlar mevcut becerileri gorur ve gerektiginde tam icerigi yukler. + +--- + +## Dosyalari yerlestirin + +Her beceri adi icin bir klasor olusturun ve icine bir `SKILL.md` koyun. +opencode su konumlari tarar: + +- Proje konfigurasyonu: `.opencode/skills//SKILL.md` +- Genel konfigurasyon: `~/.config/opencode/skills//SKILL.md` +- Proje Claude uyumlu: `.claude/skills//SKILL.md` +- Genel Claude uyumlu: `~/.claude/skills//SKILL.md` +- Proje agent uyumlu: `.agents/skills//SKILL.md` +- Genel agent uyumlu: `~/.agents/skills//SKILL.md` + +--- + +## Kesfi anlayin + +Proje yerel yollarinda opencode, mevcut calisma dizininizden baslayip git worktree kokune kadar yukari cikar. +Bu sirada `skills/*/SKILL.md` altindaki eslesen `.opencode/` dosyalarini ve `.claude/skills/*/SKILL.md` ya da `.agents/skills/*/SKILL.md` dosyalarini yukler. + +Genel tanimlar da `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md` ve `~/.agents/skills/*/SKILL.md` yollarindan yuklenir. + +--- + +## Frontmatter yazin + +Her `SKILL.md`, YAML frontmatter ile baslamalidir. +Sadece su alanlar taninir: + +- `name` (zorunlu) +- `description` (zorunlu) +- `license` (istege bagli) +- `compatibility` (istege bagli) +- `metadata` (istege bagli, string-to-string map) + +Bilinmeyen frontmatter alanlari yok sayilir. + +--- + +## Adlari dogrulayin + +`name` su kurallari saglamalidir: + +- 1-64 karakter olmali +- Kucuk harf alfanumerik ve tekli tire ayirici kullanmali +- `-` ile baslamamali veya bitmemeli +- Ardisik `--` icermemeli +- `SKILL.md` dosyasini barindiran klasor adi ile ayni olmali + +Esdeger regex: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## Uzunluk kurallarina uyun + +`description` 1-1024 karakter arasinda olmali. +Ajanin dogru secim yapmasi icin yeterince acik yazin. + +--- + +## Ornek kullanin + +`.opencode/skills/git-release/SKILL.md` dosyasini soyle olusturun: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## Arac aciklamasini taniyin + +opencode, `skill` araci aciklamasinda mevcut becerileri listeler. +Her kayitta beceri adi ve aciklamasi yer alir: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +Ajan, araci cagirarak beceri yukler: + +``` +skill({ name: "git-release" }) +``` + +--- + +## Izinleri yapilandirin + +`opencode.json` icinde pattern tabanli izinlerle ajanlarin hangi becerilere erisecegini kontrol edin: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| Permission | Behavior | +| ---------- | ------------------------------------------ | +| `allow` | Beceri hemen yuklenir | +| `deny` | Beceri ajandan gizlenir, erisim reddedilir | +| `ask` | Yukleme oncesi kullanicidan onay istenir | + +Pattern'lar wildcard destekler: `internal-*`, `internal-docs`, `internal-tools` vb. adlarla eslesir. + +--- + +## Ajan bazinda gecersiz kilin + +Belirli ajanlara genel varsayimlardan farkli izinler verebilirsiniz. + +**Ozel ajanlar icin** (agent frontmatter icinde): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**Yerlesik ajanlar icin** (`opencode.json` icinde): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## Skill aracini kapatin + +Beceri kullanmamasi gereken ajanlar icin skill aracini tamamen kapatabilirsiniz: + +**Ozel ajanlar icin**: + +```yaml +--- +tools: + skill: false +--- +``` + +**Yerlesik ajanlar icin**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +Devre disi oldugunda `` bolumu tamamen kaldirilir. + +--- + +## Yukleme sorunlarini giderin + +Bir beceri listede gorunmuyorsa: + +1. `SKILL.md` adinin tamamen buyuk harfle yazildigini dogrulayin +2. Frontmatter icinde `name` ve `description` oldugunu kontrol edin +3. Tum konumlarda beceri adlarinin benzersiz oldugundan emin olun +4. Izinleri kontrol edin - `deny` olan beceriler ajanlardan gizlenir diff --git a/packages/web/src/content/docs/tr/themes.mdx b/packages/web/src/content/docs/tr/themes.mdx new file mode 100644 index 00000000000..93911315f26 --- /dev/null +++ b/packages/web/src/content/docs/tr/themes.mdx @@ -0,0 +1,369 @@ +--- +title: Temalar +description: Yerleşik bir tema seçin veya kendiniz oluşturun. +--- + +opencode ile birden fazla yerleşik tema arasından seçim yapabilir, terminal temanıza uyum sağlayan bir tema kullanabilir veya kendi özel temanızı tanımlayabilirsiniz. + +Varsayılan olarak opencode kendi `opencode` temasını kullanır. + +--- + +## Terminal gereksinimleri + +Temaların tüm renk paletiyle doğru görünmesi için terminalinizin **truecolor** (24-bit renk) desteklemesi gerekir. Çoğu modern terminal bunu varsayılan olarak destekler, ancak gerekirse etkinleştirmeniz gerekebilir: + +- **Desteği kontrol edin**: `echo $COLORTERM` çalıştırın - çıktı `truecolor` veya `24bit` olmalıdır +- **Truecolor etkinleştirin**: kabuk profilinizde `COLORTERM=truecolor` ortam değişkenini ayarlayın +- **Terminal uyumluluğu**: terminal emülatörünüzün 24-bit rengi desteklediğinden emin olun (iTerm2, Alacritty, Kitty, Windows Terminal ve GNOME Terminal'in yeni sürümleri gibi modern terminaller genelde destekler) + +Truecolor desteği yoksa temalar daha düşük renk doğruluğu ile görünebilir veya en yakın 256 renk yaklaşımına düşebilir. + +--- + +## Yerleşik temalar + +opencode birden fazla yerleşik temayla gelir. + +| Ad | Açıklama | +| ---------------------- | ----------------------------------------------------------------------------- | +| `system` | Terminalinizin arka plan rengine uyum sağlar | +| `tokyonight` | [tokyonight](https://github.com/folke/tokyonight.nvim) temasını temel alır | +| `everforest` | [Everforest](https://github.com/sainnhe/everforest) temasını temel alır | +| `ayu` | [Ayu](https://github.com/ayu-theme) koyu temasını temel alır | +| `catppuccin` | [Catppuccin](https://github.com/catppuccin) temasını temel alır | +| `catppuccin-macchiato` | [Catppuccin](https://github.com/catppuccin) temasını temel alır | +| `gruvbox` | [Gruvbox](https://github.com/morhetz/gruvbox) temasını temel alır | +| `kanagawa` | [Kanagawa](https://github.com/rebelot/kanagawa.nvim) temasını temel alır | +| `nord` | [Nord](https://github.com/nordtheme/nord) temasını temel alır | +| `matrix` | Hacker tarzı yeşil üzerine siyah tema | +| `one-dark` | [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark temasını temel alır | + +Ve daha fazlası; sürekli yeni temalar ekliyoruz. + +--- + +## Sistem teması + +`system` teması, terminalinizin renk düzenine otomatik uyum sağlamak için tasarlanmıştır. Sabit renk kullanan klasik temalardan farklı olarak _system_ teması: + +- **Gri ölçeği üretir**: En iyi kontrast için terminal arka planına göre özel gri tonları oluşturur +- **ANSI renkleri kullanır**: 0-15 arası standart ANSI renklerini syntax highlighting ve UI öğelerinde kullanır, böylece terminal paletinize uyar +- **Terminal varsayılanlarını korur**: Metin ve arka plan renklerinde `none` kullanarak terminalin yerel görünümünü korur + +Sistem teması şu kullanıcılar için idealdir: + +- opencode'un terminal görünümüyle birebir uyumlu olmasını isteyenler +- Özel terminal renk şemaları kullananlar +- Tüm terminal uygulamalarında tutarlı bir görünüm tercih edenler + +--- + +## Tema kullanımı + +`/theme` komutuyla tema seçicisini açıp tema seçebilirsiniz. İsterseniz [config](/docs/config) dosyanızda da belirtebilirsiniz. + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## Özel temalar + +opencode, kullanıcıların kolayca tema oluşturup özelleştirebilmesi için esnek bir JSON tabanlı tema sistemi sunar. + +--- + +### Hiyerarşi + +Temalar birden fazla dizinden şu sırayla yüklenir; daha sonra gelen dizin öncekini ezer: + +1. **Yerleşik temalar** - Binary içine gömülüdür +2. **Kullanıcı yapılandırma dizini** - `~/.config/opencode/themes/*.json` veya `$XDG_CONFIG_HOME/opencode/themes/*.json` +3. **Proje kök dizini** - `/.opencode/themes/*.json` +4. **Geçerli çalışma dizini** - `./.opencode/themes/*.json` + +Birden fazla dizinde aynı adlı tema varsa, önceliği daha yüksek dizindeki tema kullanılır. + +--- + +### Tema oluşturma + +Özel tema oluşturmak için tema dizinlerinden birinde bir JSON dosyası oluşturun. + +Kullanıcı geneli temalar için: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +Proje özel temalar için: + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### JSON formatı + +Temalar aşağıdaki özellikleri destekleyen esnek bir JSON formatı kullanır: + +- **Hex renkler**: `"#ffffff"` +- **ANSI renkler**: `3` (0-255) +- **Renk referansları**: `"primary"` veya özel tanımlar +- **Koyu/açık varyantlar**: `{"dark": "#000", "light": "#fff"}` +- **Renk yok**: `"none"` - Terminal varsayılan rengi veya şeffaflık kullanılır + +--- + +### Renk tanımları + +`defs` bölümü isteğe bağlıdır ve tema içinde tekrar kullanılabilir renkler tanımlamanızı sağlar. + +--- + +### Terminal varsayılanları + +Özel `"none"` değeri, terminalin varsayılan rengini miras almak için herhangi bir renkte kullanılabilir. Bu, terminalinizin renk şemasıyla doğal şekilde bütünleşen temalar oluştururken özellikle faydalıdır: + +- `"text": "none"` - Terminalin varsayılan ön plan rengini kullanır +- `"background": "none"` - Terminalin varsayılan arka plan rengini kullanır + +--- + +### Örnek + +Aşağıda özel bir tema örneği var: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/tr/tools.mdx b/packages/web/src/content/docs/tr/tools.mdx new file mode 100644 index 00000000000..2eded12d3cb --- /dev/null +++ b/packages/web/src/content/docs/tr/tools.mdx @@ -0,0 +1,379 @@ +--- +title: Araçlar +description: LLM'in kullanabileceği araçları yönetin. +--- + +Araçlar, LLM'in kod tabanınızda eylem gerçekleştirmesini sağlar. opencode yerleşik bir araç setiyle gelir, ancak bunu [özel araçlarla](/docs/custom-tools) veya [MCP sunucularıyla](/docs/mcp-servers) genişletebilirsiniz. + +Varsayılan olarak tüm araçlar **etkindir** ve çalışmak için izin istemez. Araç davranışını [izinler](/docs/permissions) üzerinden kontrol edebilirsiniz. + +--- + +## Yapılandırma + +Araç davranışını kontrol etmek için `permission` alanını kullanın. Her araç için izin verebilir, reddedebilir veya onay isteyebilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +Birden fazla aracı aynı anda kontrol etmek için joker karakterler de kullanabilirsiniz. Örneğin, bir MCP sunucusundan gelen tüm araçlar için onay istemek: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +İzin yapılandırması için [daha fazla bilgi alın](/docs/permissions). + +--- + +## Yerleşik + +opencode içinde bulunan tüm yerleşik araçlar aşağıdadır. + +--- + +### bash + +Proje ortamınızda kabuk komutları çalıştırır. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +Bu araç LLM'in `npm install`, `git status` gibi terminal komutlarını veya diğer kabuk komutlarını çalıştırmasını sağlar. + +--- + +### edit + +Birebir metin değiştirme ile mevcut dosyaları düzenler. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Bu araç dosyalarda kesin metin eşleşmelerini değiştirerek hassas düzenleme yapar. LLM'in kodu değiştirmek için kullandığı temel yöntemdir. + +--- + +### write + +Yeni dosyalar oluşturur veya mevcut dosyaları üzerine yazar. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +LLM'in yeni dosya oluşturmasına izin vermek için bunu kullanın. Dosya zaten varsa üzerine yazar. + +:::note +`write` aracı `edit` izniyle kontrol edilir; bu izin tüm dosya değişikliklerini kapsar (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### read + +Kod tabanınızdan dosya içeriği okur. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +Bu araç dosyaları okur ve içeriklerini döndürür. Büyük dosyalar için belirli satır aralıklarını okuma desteği vardır. + +--- + +### grep + +Düzenli ifadelerle dosya içeriğinde arama yapar. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +Kod tabanında hızlı içerik araması sunar. Tam regex sözdizimini ve dosya desen filtrelerini destekler. + +--- + +### glob + +Desen eşleştirme ile dosya bulur. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +`**/*.js` veya `src/**/*.ts` gibi glob desenleriyle dosya arar. Eşleşen dosya yollarını değişim zamanına göre sıralar. + +--- + +### list + +Verilen yoldaki dosya ve dizinleri listeler. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +Bu araç dizin içeriğini listeler. Sonuçları filtrelemek için glob desenlerini kabul eder. + +--- + +### lsp (deneysel) + +Tanım, referans, hover bilgisi ve çağrılar hiyerarşisi gibi kod zekası özellikleri için yapılandırdığınız LSP sunucularıyla etkileşir. + +:::note +Bu araç yalnızca `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (veya `OPENCODE_EXPERIMENTAL=true`) olduğunda kullanılabilir. +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +Desteklenen işlemler: `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls`, `outgoingCalls`. + +Projeniz için kullanılabilir LSP sunucularını ayarlamak için [LSP Sunucuları](/docs/lsp) sayfasına bakın. + +--- + +### patch + +Dosyalara patch uygular. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +Bu araç patch dosyalarını kod tabanınıza uygular. Farklı kaynaklardan gelen diff ve patch'leri uygulamak için kullanışlıdır. + +:::note +`patch` aracı `edit` izniyle kontrol edilir; bu izin tüm dosya değişikliklerini kapsar (`edit`, `write`, `patch`, `multiedit`). +::: + +--- + +### skill + +Bir [skill](/docs/skills) (`SKILL.md` dosyası) yükler ve içeriğini konuşmaya döndürür. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +Kodlama oturumlarında yapılacaklar listesini yönetir. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +Karmaşık işlemlerde ilerlemeyi takip etmek için görev listeleri oluşturur ve günceller. LLM bunu çok adımlı görevleri düzenlemek için kullanır. + +:::note +Bu araç alt agent'lar için varsayılan olarak devre dışıdır, ama manuel etkinleştirebilirsiniz. [Daha fazla bilgi](/docs/agents/#permissions) +::: + +--- + +### todoread + +Mevcut yapılacaklar listesini okur. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +Güncel todo listesi durumunu okur. LLM bunu hangi görevlerin beklediğini veya tamamlandığını takip etmek için kullanır. + +:::note +Bu araç alt agent'lar için varsayılan olarak devre dışıdır, ama manuel etkinleştirebilirsiniz. [Daha fazla bilgi](/docs/agents/#permissions) +::: + +--- + +### webfetch + +Web içeriği getirir. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +LLM'in web sayfalarını getirip okumasını sağlar. Dokümantasyon aramak veya çevrimiçi kaynakları incelemek için kullanışlıdır. + +--- + +### websearch + +Web'de bilgi arar. + +:::note +Bu araç yalnızca opencode provider kullanılırken veya `OPENCODE_ENABLE_EXA` ortam değişkeni doğru değerlerden birine ayarlandığında (örneğin `true` ya da `1`) kullanılabilir. + +opencode başlatırken etkinleştirmek için: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +Exa AI ile web araması yaparak ilgili bilgileri bulur. Eğitim verisi kesim tarihinin ötesindeki konuları araştırmak, güncel olayları bulmak veya genel araştırma yapmak için kullanışlıdır. + +API anahtarı gerekmez - araç Exa AI'nin barındırılan MCP hizmetine doğrudan kimlik doğrulaması olmadan bağlanır. + +:::tip +Bilgi keşfetmeniz gerekiyorsa `websearch`, belirli bir URL'den içerik çekmeniz gerekiyorsa `webfetch` kullanın. +::: + +--- + +### question + +Çalışma sırasında kullanıcıya soru sorar. + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +Bu araç LLM'in görev sırasında kullanıcıya soru sormasını sağlar. Şunlar için kullanışlıdır: + +- Kullanıcı tercihleri veya gereksinimleri toplamak +- Belirsiz talimatları netleştirmek +- Uygulama seçeneklerinde karar almak +- Hangi yöne gidileceğine dair seçenek sunmak + +Her soru bir başlık, soru metni ve seçenek listesi içerir. Kullanıcılar seçeneklerden birini seçebilir veya özel yanıt yazabilir. Birden fazla soru varsa tüm yanıtları göndermeden önce sorular arasında gezebilirler. + +--- + +## Özel araçlar + +Özel araçlar, LLM'in çağırabileceği kendi fonksiyonlarınızı tanımlamanızı sağlar. Bunlar config dosyanızda tanımlanır ve keyfi kod çalıştırabilir. + +Özel araç oluşturma için [daha fazla bilgi alın](/docs/custom-tools). + +--- + +## MCP sunucuları + +MCP (Model Context Protocol) sunucuları, harici araçları ve servisleri entegre etmenizi sağlar. Buna veritabanı erişimi, API entegrasyonları ve üçüncü taraf servisler dahildir. + +MCP sunucularını yapılandırma için [daha fazla bilgi alın](/docs/mcp-servers). + +--- + +## Dahili detaylar + +Dahilde `grep`, `glob` ve `list` gibi araçlar [ripgrep](https://github.com/BurntSushi/ripgrep) kullanır. Varsayılan olarak ripgrep `.gitignore` desenlerine uyar; yani `.gitignore` içindeki dosya ve dizinler arama ve listeleme sonucuna dahil edilmez. + +--- + +### Yoksayma desenleri + +Normalde yok sayılan dosyaları dahil etmek için proje kökünde bir `.ignore` dosyası oluşturun. Bu dosya belirli yolları açıkça izinli yapabilir. + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +Örneğin bu `.ignore` dosyası, `node_modules/` içinde olsalar bile ripgrep'in `dist/`, `build/` ve `.gitignore` dizinlerinde arama yapmasına izin verir. diff --git a/packages/web/src/content/docs/tr/troubleshooting.mdx b/packages/web/src/content/docs/tr/troubleshooting.mdx new file mode 100644 index 00000000000..24ef067ffab --- /dev/null +++ b/packages/web/src/content/docs/tr/troubleshooting.mdx @@ -0,0 +1,299 @@ +--- +title: Sorun giderme +description: Yaygin sorunlar ve cozum adimlari. +--- + +opencode ile ilgili bir sorunu ayiklamak icin once loglari ve diskte tuttugu yerel verileri kontrol edin. + +--- + +## Loglar + +Log dosyalari su konuma yazilir: + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: `WIN+R` tuslayip `%USERPROFILE%\.local\share\opencode\log` yapistirin + +Log dosyalari zaman damgasiyla adlandirilir (ornegin `2025-01-09T123456.log`) ve en yeni 10 log dosyasi tutulur. + +Daha ayrintili ayiklama bilgisi icin `--log-level` komut satiri secenegini kullanabilirsiniz. Ornek: `opencode --log-level DEBUG`. + +--- + +## Depolama + +opencode, oturum verilerini ve diger uygulama verilerini diskte su konumda saklar: + +- **macOS/Linux**: `~/.local/share/opencode/` +- **Windows**: `WIN+R` tuslayip `%USERPROFILE%\.local\share\opencode` yapistirin + +Bu dizin sunlari icerir: + +- `auth.json` - API anahtarlari, OAuth tokenlari gibi kimlik dogrulama verileri +- `log/` - Uygulama loglari +- `project/` - Oturum ve mesaj verileri gibi projeye ozel veriler + - Proje bir Git deposundaysa `.//storage/` altinda saklanir + - Git deposu degilse `./global/storage/` altinda saklanir + +--- + +## Masaüstü uygulaması + +opencode Desktop arka planda yerel bir opencode sunucusu (`opencode-cli` sidecar) calistirir. Sorunlarin cogu bozuk bir plugin, hasarli cache veya hatali sunucu ayarindan kaynaklanir. + +### Hızlı kontroller + +- Uygulamayi tamamen kapatip yeniden acin +- Uygulama hata ekrani gosteriyorsa **Restart**'a tiklayip hata detaylarini kopyalayin +- Yalnizca macOS: `opencode` menusu -> **Reload Webview** (arayuz bos/donukse yardimci olur) + +--- + +### Eklentileri devre dışı bırakın + +Desktop uygulamasi acilista cokuyorsa, takiliyorsa veya garip davranislar gosteriyorsa once pluginleri devre disi birakin. + +#### Global config'i kontrol edin + +Global config dosyanizi acin ve `plugin` anahtarini arayin. + +- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (veya `~/.config/opencode/opencode.json`) +- **macOS/Linux** (eski kurulumlar): `~/.local/share/opencode/opencode.jsonc` +- **Windows**: `WIN+R` tuslayip `%USERPROFILE%\.config\opencode\opencode.jsonc` yapistirin + +Plugin tanimliysa anahtari kaldirarak veya bos bir diziye cekerek gecici olarak devre disi birakin: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### Eklenti dizinlerini kontrol edin + +opencode diskten yerel plugin de yukleyebilir. Bu dizinleri gecici olarak tasiyin (veya klasoru yeniden adlandirin) ve uygulamayi yeniden baslatin: + +- **Global plugins** + - **macOS/Linux**: `~/.config/opencode/plugins/` + - **Windows**: `WIN+R` tuslayip `%USERPROFILE%\.config\opencode\plugins` yapistirin +- **Project plugins** (sadece proje bazli config kullaniyorsaniz) + - `/.opencode/plugins/` + +Uygulama duzelirse soruna neden olan plugini bulmak icin pluginleri tek tek yeniden etkinlestirin. + +--- + +### Cache'i temizleyin + +Pluginleri kapatmak ise yaramazsa (veya plugin kurulumu takili kaldiysa), opencode'un cache'i yeniden olusturmasi icin cache'i temizleyin. + +1. opencode Desktop'u tamamen kapatin +2. Cache dizinini silin: + +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/.cache/opencode` +- **Linux**: `~/.cache/opencode` dizinini silin (veya `rm -rf ~/.cache/opencode` calistirin) +- **Windows**: `WIN+R` tuslayip `%USERPROFILE%\.cache\opencode` yapistirin + +3. opencode Desktop'u yeniden baslatin + +--- + +### Sunucu bağlantı sorunlarını düzeltin + +opencode Desktop ya kendi yerel sunucusunu baslatir (varsayilan) ya da sizin tanimladiginiz bir sunucu URL'sine baglanir. + +**"Connection Failed"** penceresi goruyorsaniz (veya uygulama acilis ekranini gecemiyorsa), ozel bir sunucu URL'si olup olmadigini kontrol edin. + +#### Desktop varsayilan sunucu URL'sini temizleyin + +Ana ekranda sunucu adina (durum noktali) tiklayarak Server secicisini acin. **Default server** bolumunde **Clear**'a tiklayin. + +#### Config'ten `server.port` / `server.hostname` kaldirin + +`opencode.json(c)` dosyanizda `server` bolumu varsa gecici olarak kaldirin ve desktop uygulamasini yeniden baslatin. + +#### Ortam degiskenlerini kontrol edin + +Ortamda `OPENCODE_PORT` ayarliysa desktop uygulamasi yerel sunucu icin o portu kullanmaya calisir. + +- `OPENCODE_PORT` degerini kaldirin (veya bos bir port secin) ve yeniden baslatin + +--- + +### Linux: Wayland / X11 sorunları + +Linux'ta bazi Wayland kurulumlari bos pencere veya compositor hatalarina yol acabilir. + +- Wayland kullaniyorsaniz ve uygulama bos/acilmiyorsa `OC_ALLOW_WAYLAND=1` ile baslatin +- Bu daha kotu olursa kaldirip X11 oturumunda baslatmayi deneyin + +--- + +### Windows: WebView2 Çalışma Zamanı + +Windows'ta opencode Desktop, Microsoft Edge **WebView2 Runtime** gerektirir. Uygulama bos pencereyle aciliyorsa veya hic baslamiyorsa WebView2'yi kurup/guncelleyip tekrar deneyin. + +--- + +### Windows: Genel performans sorunları + +Windows'ta yavaslik, dosya erisim sorunlari veya terminal problemleri yasiyorsaniz [WSL (Windows Subsystem for Linux)](/docs/windows-wsl) kullanmayi deneyin. WSL, opencode ozellikleriyle daha sorunsuz calisan bir Linux ortami saglar. + +--- + +### Bildirimler görünmüyor + +opencode Desktop sistem bildirimlerini yalnizca su durumlarda gosterir: + +- Isletim sistemi ayarlarinizda opencode icin bildirimler etkinse +- Uygulama penceresi odakta degilse + +--- + +### Desktop depolamasını sıfırlayın (son çare) + +Uygulama acilmiyorsa ve ayarlari arayuz icinden temizleyemiyorsaniz, desktop uygulamasinin kayitli durumunu sifirlayin. + +1. opencode Desktop'u kapatin +2. Su dosyalari bulun ve silin (opencode Desktop uygulama veri dizininde yer alirlar): + +- `opencode.settings.dat` (desktop varsayilan sunucu URL'si) +- `opencode.global.dat` ve `opencode.workspace.*.dat` (son sunucular/projeler gibi UI durumu) + +Dizini hizlica bulmak icin: + +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (ardindan yukaridaki dosya adlarini aratin) +- **Linux**: `~/.local/share` altinda bu dosya adlarini aratin +- **Windows**: `WIN+R` -> `%APPDATA%` (ardindan bu dosya adlarini aratin) + +--- + +## Yardım alın + +opencode ile ilgili bir sorun yasiyorsaniz: + +1. **GitHub'da issue acin** + + Hata bildirmek veya ozellik talep etmek icin en iyi yol GitHub depomuzdur: + + [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + + Yeni issue acmadan once sorununuzun daha once raporlanip raporlanmadigini kontrol edin. + +2. **Discord'a katilin** + + Gercek zamanli yardim ve topluluk sohbeti icin Discord sunucumuza katilin: + + [**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## Yaygın sorunlar + +Asagida yaygin sorunlar ve cozumleri yer aliyor. + +--- + +### opencode başlamıyor + +1. Hata mesaji icin loglari kontrol edin +2. Terminalde cikti gormek icin `--print-logs` ile calistirin +3. `opencode upgrade` ile en guncel surumu kullandiginizdan emin olun + +--- + +### Kimlik doğrulama sorunları + +1. TUI'da `/connect` komutuyla yeniden kimlik dogrulamasi yapin +2. API anahtarlarinizin gecerli oldugunu kontrol edin +3. Aginizin provider API baglantilarina izin verdiginden emin olun + +--- + +### Model kullanılamıyor + +1. Provider ile kimlik dogrulamasi yaptiginizi kontrol edin +2. Config'teki model adinin dogru oldugunu dogrulayin +3. Bazi modeller ozel erisim veya abonelik gerektirebilir + +`ProviderModelNotFoundError` aliyorsaniz buyuk olasilikla bir yerde model referansi yanlistir. +Model referansi su formatta olmalidir: `/` + +Ornekler: + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +Erisiminiz olan modelleri gormek icin `opencode models` calistirin. + +--- + +### ProviderInitError + +`ProviderInitError` aliyorsaniz buyuk olasilikla config'iniz gecersiz veya bozulmustur. + +Cozum adimlari: + +1. Once [providers rehberini](/docs/providers) izleyerek provider kurulumunun dogru oldugunu dogrulayin +2. Sorun surerse kayitli konfigurasyonu temizlemeyi deneyin: + + ```bash + rm -rf ~/.local/share/opencode + ``` + + Windows'ta `WIN+R` tuslayip su konumu silin: `%USERPROFILE%\.local\share\opencode` + +3. TUI'da `/connect` komutuyla provider kimlik dogrulamasini tekrar yapin + +--- + +### AI_APICallError ve provider paket sorunlari + +API cagrisi hatalari aliyorsaniz bunun nedeni guncel olmayan provider paketleri olabilir. opencode, provider paketlerini (OpenAI, Anthropic, Google vb.) gerektikce dinamik yukler ve yerelde onbellekler. + +Provider paket sorunlarini gidermek icin: + +1. Provider paket cache'ini temizleyin: + + ```bash + rm -rf ~/.cache/opencode + ``` + + Windows'ta `WIN+R` tuslayip su konumu silin: `%USERPROFILE%\.cache\opencode` + +2. En guncel provider paketlerini yeniden kurmak icin opencode'u yeniden baslatin + +Bu, opencode'un en yeni provider paket surumlerini indirmesini zorlar ve model parametresi/API degisikliklerinden kaynakli uyumsuzluklari cogu zaman cozer. + +--- + +### Linux'ta kopyala/yapıştır çalışmıyor + +Linux kullanicilarinin kopyala/yapistir ozelliginin calismasi icin asagidaki pano araclarindan en az birini kurmasi gerekir: + +**X11 sistemleri icin:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**Wayland sistemleri icin:** + +```bash +apt install -y wl-clipboard +``` + +**Headless ortamlar icin:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +opencode, Wayland kullandiginizi algilarsa `wl-clipboard` tercihi yapar. Aksi halde sirayla `xclip` ve `xsel` araclarini arar. diff --git a/packages/web/src/content/docs/tr/tui.mdx b/packages/web/src/content/docs/tr/tui.mdx new file mode 100644 index 00000000000..2bd5db8f5df --- /dev/null +++ b/packages/web/src/content/docs/tr/tui.mdx @@ -0,0 +1,387 @@ +--- +title: TUI +description: opencode terminal arayuzunu kullanin. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +opencode, projelerinizde LLM ile calismak icin etkilesimli bir terminal arayuzu (TUI) sunar. + +opencode'u calistirdiginizda mevcut dizin icin TUI baslar. + +```bash +opencode +``` + +Isterseniz belirli bir calisma dizini icin de baslatabilirsiniz. + +```bash +opencode /path/to/project +``` + +TUI icinde bir mesaj yazarak istem gonderebilirsiniz. + +```text +Give me a quick summary of the codebase. +``` + +--- + +## Dosya referanslari + +Mesajlarinizda `@` kullanarak dosyalara referans verebilirsiniz. Bu, mevcut calisma dizininde bulanik dosya aramasi yapar. + +:::tip +Mesajlarinizda dosyalara referans vermek icin `@` 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. + +--- + +## Bash komutlari + +Bir mesaji `!` ile baslatarak shell komutu calistirin. + +```bash frame="none" +!ls -la +``` + +Komut ciktiisi bir arac sonucu olarak konusmaya eklenir. + +--- + +## Komutlar + +opencode TUI kullanirken `/` ve komut adini yazarak hizli eylemler calistirabilirsiniz. Ornek: + +```bash frame="none" +/help +``` + +Komutlarin cogu, lider tusu `ctrl+x` olan bir kisayola da sahiptir. [Daha fazla bilgi](/docs/keybinds). + +Mevcut slash komutlarinin tam listesi: + +--- + +### connect + +opencode'a bir provider ekler. Mevcut provider'lari secip API anahtarlari eklemenizi saglar. + +```bash frame="none" +/connect +``` + +--- + +### compact + +Guncel oturumu sikistirir. _Takma ad_: `/summarize` + +```bash frame="none" +/compact +``` + +**Kisayol:** `ctrl+x c` + +--- + +### details + +Arac calistirma detaylarini goster/gizle yapar. + +```bash frame="none" +/details +``` + +**Kisayol:** `ctrl+x d` + +--- + +### editor + +Mesaj yazmak icin harici editor acar. `EDITOR` ortam degiskeninde ayarli editoru kullanir. [Daha fazla bilgi](#editor-setup). + +```bash frame="none" +/editor +``` + +**Kisayol:** `ctrl+x e` + +--- + +### exit + +opencode'dan cikar. _Takma adlar_: `/quit`, `/q` + +```bash frame="none" +/exit +``` + +**Kisayol:** `ctrl+x q` + +--- + +### export + +Mevcut konusmayi Markdown olarak disa aktarir ve varsayilan editorunuzde acar. `EDITOR` ortam degiskenindeki editoru kullanir. [Daha fazla bilgi](#editor-setup). + +```bash frame="none" +/export +``` + +**Kisayol:** `ctrl+x x` + +--- + +### help + +Yardim penceresini gosterir. + +```bash frame="none" +/help +``` + +**Kisayol:** `ctrl+x h` + +--- + +### init + +`AGENTS.md` dosyasini olusturur veya gunceller. [Daha fazla bilgi](/docs/rules). + +```bash frame="none" +/init +``` + +**Kisayol:** `ctrl+x i` + +--- + +### models + +Kullanilabilir modelleri listeler. + +```bash frame="none" +/models +``` + +**Kisayol:** `ctrl+x m` + +--- + +### new + +Yeni bir oturum baslatir. _Takma ad_: `/clear` + +```bash frame="none" +/new +``` + +**Kisayol:** `ctrl+x n` + +--- + +### redo + +Geri alinan bir mesaji tekrar uygular. Yalnizca `/undo` kullanildiktan sonra kullanilabilir. + +:::tip +Dosya degisiklikleri de geri yuklenir. +::: + +Dahilde bu islem dosya degisikliklerini yonetmek icin Git kullanir. Bu nedenle projenizin **bir Git deposu olmasi gerekir**. + +```bash frame="none" +/redo +``` + +**Kisayol:** `ctrl+x r` + +--- + +### sessions + +Oturumlari listeler ve aralarinda gecis yapar. _Takma adlar_: `/resume`, `/continue` + +```bash frame="none" +/sessions +``` + +**Kisayol:** `ctrl+x l` + +--- + +### share + +Mevcut oturumu paylasir. [Daha fazla bilgi](/docs/share). + +```bash frame="none" +/share +``` + +**Kisayol:** `ctrl+x s` + +--- + +### themes + +Kullanilabilir temalari listeler. + +```bash frame="none" +/theme +``` + +**Kisayol:** `ctrl+x t` + +--- + +### thinking + +Konusmadaki thinking/reasoning bloklarinin gorunurlugunu degistirir. Etkin oldugunda, genisletilmis dusunmeyi destekleyen modellerin akil yurutmelerini gorebilirsiniz. + +:::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. +::: + +```bash frame="none" +/thinking +``` + +--- + +### undo + +Konusmadaki son mesaji geri alir. En son kullanici mesaji, sonraki tum yanitlar ve dosya degisiklikleri kaldirilir. + +:::tip +Yapilan dosya degisiklikleri de geri cevrilir. +::: + +Dahilde bu islem dosya degisikliklerini yonetmek icin Git kullanir. Bu nedenle projenizin **bir Git deposu olmasi gerekir**. + +```bash frame="none" +/undo +``` + +**Kisayol:** `ctrl+x u` + +--- + +### unshare + +Mevcut oturumun paylasimini kaldirir. [Daha fazla bilgi](/docs/share#paylasimi-kaldirma). + +```bash frame="none" +/unshare +``` + +--- + +## Editor kurulumu + +`/editor` ve `/export` komutlari, `EDITOR` ortam degiskeninde tanimli editoru kullanir. + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + + Kalici yapmak icin bunu kabuk profilinize ekleyin: + `~/.bashrc`, `~/.zshrc` vb. + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + + Kalici yapmak icin **System Properties** > **Environment Variables** yolunu kullanin. + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + + Kalici yapmak icin bunu PowerShell profilinize ekleyin. + + + + +Yaygin editor secenekleri: + +- `code` - Visual Studio Code +- `cursor` - Cursor +- `windsurf` - Windsurf +- `nvim` - Neovim editoru +- `vim` - Vim editoru +- `nano` - Nano editoru +- `notepad` - Windows Notepad +- `subl` - Sublime Text + +:::note +VS Code gibi bazi editorlerin `--wait` parametresiyle baslatilmasi gerekir. +::: + +Bazi editorler bloklayici modda calismak icin komut satiri argumanlari ister. `--wait` bayragi editor surecinin kapanana kadar beklemesini saglar. + +--- + +## Yapilandirin + +TUI davranisini opencode config dosyanizdan ozellestirebilirsiniz. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### Secenekler + +- `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.** + +--- + +## Ozellestirme + +TUI gorunumunun cesitli kisimlarini komut paletiyle (`ctrl+x h` veya `/help`) ozellestirebilirsiniz. Bu ayarlar yeniden baslatmalar arasinda korunur. + +--- + +#### Kullanici adi gorunumu + +Sohbet mesajlarinda kullanici adinizin gosterilip gosterilmeyecegini degistirir. Sunlardan erisebilirsiniz: + +- Komut paleti: "username" veya "hide username" aratin +- Ayar otomatik saklanir ve TUI oturumlarinda hatirlanir diff --git a/packages/web/src/content/docs/tr/web.mdx b/packages/web/src/content/docs/tr/web.mdx new file mode 100644 index 00000000000..4b9ae78eab4 --- /dev/null +++ b/packages/web/src/content/docs/tr/web.mdx @@ -0,0 +1,142 @@ +--- +title: Web +description: Tarayıcınızda opencode'u kullanma. +--- + +opencode, tarayıcınızda bir web uygulaması olarak çalışabilir ve bir terminale ihtiyaç duymadan aynı güçlü AI kodlama deneyimini sağlayabilir. + +![opencode Web - Yeni Oturum](../../../assets/web/web-homepage-new-session.png) + +## Başlarken + +Aşağıdakileri çalıştırarak web arayüzünü başlatın: + +```bash +opencode web +``` + +Bu, `127.0.0.1` üzerinde rastgele kullanılabilir bir bağlantı noktasına sahip yerel bir sunucuyu başlatır ve opencode'u varsayılan tarayıcınızda otomatik olarak açar. + +:::caution +`OPENCODE_SERVER_PASSWORD` ayarlanmadıysa sunucunun güvenliği kaldırılacaktır. Bu, yerel kullanım için iyidir ancak ağ erişimi için ayarlanmalıdır. +::: + +:::tip[Windows Kullanıcıları] +En iyi deneyim için PowerShell yerine `opencode web`'yi [WSL](/docs/windows-wsl)'den çalıştırın. Bu, uygun dosya sistemi erişimini ve terminal entegrasyonunu sağlar. +::: + +--- + +## Yapılandırma + +Web sunucusunu komut satırı bayraklarıyla veya [config dosyanızda](/docs/config) yapılandırabilirsiniz. + +### Port + +opencode varsayılan olarak kullanılabilir bir bağlantı noktasını seçer. Bir bağlantı noktası belirtebilirsiniz: + +```bash +opencode web --port 4096 +``` + +### Ana makine adı + +Varsayılan olarak sunucu `127.0.0.1` (yalnızca localhost) öğesine bağlanır. opencode'u ağınızda erişilebilir kılmak için: + +```bash +opencode web --hostname 0.0.0.0 +``` + +`0.0.0.0` kullanıldığında, opencode hem yerel hem de ağ adreslerini gösterecektir: + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### mDNS Keşfi + +Sunucunuzun yerel ağda bulunabilir olmasını sağlamak için mDNS'yi etkinleştirin: + +```bash +opencode web --mdns +``` + +Bu, ana bilgisayar adını otomatik olarak `0.0.0.0` olarak ayarlar ve sunucuyu `opencode.local` olarak tanıtır. + +Aynı ağ üzerinde birden fazla örneği çalıştıracak şekilde mDNS alan adını özelleştirebilirsiniz: + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +CORS'a yönelik ek alan adlarına izin vermek için (özel ön uçlar için kullanışlıdır): + +```bash +opencode web --cors https://example.com +``` + +### Kimlik Doğrulaması + +Erişimi korumak için `OPENCODE_SERVER_PASSWORD` ortam değişkenini kullanarak bir parola ayarlayın: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +Kullanıcı adı varsayılan olarak `opencode` şeklindedir ancak `OPENCODE_SERVER_USERNAME` ile değiştirilebilir. + +--- + +## Web Arayüzünü Kullanma + +Web arayüzü başlatıldığında opencode oturumlarınıza erişim sağlar. + +### Oturum + +Oturumlarınızı ana sayfadan görüntüleyin ve yönetin. Aktif oturumları görebilir ve yenilerini başlatabilirsiniz. + +![opencode Web - Etkin Oturum](../../../assets/web/web-homepage-active-session.png) + +### Sunucu Durumu + +Bağlı sunucuları ve durumlarını görüntülemek için "Sunucuları Gör" seçeneğini tıklayın. + +![opencode Web - Sunuculara bakın](../../../assets/web/web-homepage-see-servers.png) + +--- + +## Terminal Takma + +Çalışan bir web sunucusuna bir terminal TUI'si ekleyebilirsiniz: + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +Bu, aynı oturumları ve durumu paylaşarak hem web arayüzünü hem de terminali aynı anda kullanmanıza olanak tanır. + +--- + +## Yapılandırma Dosyası + +Sunucu ayarlarını `opencode.json` yapılandırma dosyanızda da yapılandırabilirsiniz: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +Komut satırı bayrakları yapılandırma dosyası ayarlarından önceliklidir. diff --git a/packages/web/src/content/docs/tr/windows-wsl.mdx b/packages/web/src/content/docs/tr/windows-wsl.mdx new file mode 100644 index 00000000000..7d0471682f3 --- /dev/null +++ b/packages/web/src/content/docs/tr/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: En iyi deneyim icin opencode'u WSL'de calistirin. +--- + +import { Steps } from "@astrojs/starlight/components" + +opencode Windows'ta dogrudan calisabilir, ancak en iyi deneyim icin [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) kullanmanizi oneriyoruz. WSL, opencode ozellikleriyle sorunsuz calisan bir Linux ortami saglar. + +:::tip[Neden WSL?] +WSL, daha iyi dosya sistemi performansi, tam terminal destegi ve opencode'un dayandigi gelistirme araclariyla uyumluluk sunar. +::: + +--- + +## Kurulum + + + +1. **WSL'i yukleyin** + + Henuz yuklemediyseniz resmi Microsoft rehberini kullanarak [WSL kurulumunu](https://learn.microsoft.com/en-us/windows/wsl/install) yapin. + +2. **opencode'u WSL icine yukleyin** + + WSL hazir olduktan sonra WSL terminalini acin ve opencode'u [kurulum yontemlerinden](/docs/) biriyle yukleyin. + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **opencode'u WSL icinden kullanin** + + Proje dizininize gidin (`/mnt/c/`, `/mnt/d/` vb. ile Windows dosyalarina erisebilirsiniz) ve opencode'u calistirin. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## Masaüstü uygulaması + WSL sunucusu + +opencode Desktop kullanmak isteyip sunucuyu WSL'de calistirmak istiyorsaniz: + +1. **Sunucuyu WSL'de baslatin** ve dis baglantilara izin vermek icin `--hostname 0.0.0.0` kullanin: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **Desktop uygulamasini** `http://localhost:4096` adresine baglayin + +:::note +Kurulumunuzda `localhost` calismiyorsa bunun yerine WSL IP adresini kullanin (WSL icinde: `hostname -I`) ve `http://:4096` adresine baglanin. +::: + +:::caution +`--hostname 0.0.0.0` kullaniyorsaniz sunucuyu guvene almak icin `OPENCODE_SERVER_PASSWORD` ayarlayin. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## Web istemcisi + WSL + +Windows'ta en iyi web deneyimi icin: + +1. **`opencode web` komutunu PowerShell yerine WSL terminalinde calistirin**: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Windows tarayicinizdan** `http://localhost:` adresini acin (opencode URL'yi yazdirir) + +`opencode web` komutunu WSL'den calistirmak, dosya sistemi erisimi ve terminal entegrasyonunu daha tutarli hale getirirken tarayicidan erisimi korur. + +--- + +## Windows dosyalarına erişin + +WSL, tum Windows dosyalariniza `/mnt/` dizini uzerinden erisebilir: + +- `C:` surucusu -> `/mnt/c/` +- `D:` surucusu -> `/mnt/d/` +- Ve digerleri... + +Ornek: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +En sorunsuz deneyim icin deponuzu WSL dosya sistemine (ornegin `~/code/` altina) klonlayip opencode'u orada calistirmayi dusunun. +::: + +--- + +## İpuçları + +- Windows suruculerinde duran projelerde opencode'u WSL icinde calistirin - dosya erisimi daha sorunsuz olur +- Butunlesik bir gelistirme akisi icin opencode ile birlikte VS Code [WSL eklentisini](https://code.visualstudio.com/docs/remote/wsl) kullanin +- opencode konfigurasyonunuz ve oturumlariniz WSL ortaminda `~/.local/share/opencode/` konumunda saklanir diff --git a/packages/web/src/content/docs/tr/zen.mdx b/packages/web/src/content/docs/tr/zen.mdx new file mode 100644 index 00000000000..b9978894193 --- /dev/null +++ b/packages/web/src/content/docs/tr/zen.mdx @@ -0,0 +1,238 @@ +--- +title: Zen +description: opencode ekibinin sundugu secili model 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. + +:::note +OpenCode Zen su anda beta asamasindadir. +::: + +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. + +--- + +## 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. + +:::tip +opencode ile iyi calisan belirli model/provider kombinasyonlarini test ettik. +::: + +Bu nedenle OpenRouter benzeri bir servis uzerinden model kullaniyorsaniz, istediginiz modelin en iyi surumunu alip almadiginizdan her zaman emin olamazsiniz. + +Bunu cozmeye yonelik olarak sunlari yaptik: + +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 + +OpenCode Zen, bu modellere erisim saglayan bir AI gateway'dir. + +--- + +## Nasil calisir + +OpenCode Zen, opencode'daki diger provider'lar gibi calisir. + +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 + +Ucretlendirme istek basina yapilir ve hesabiniza kredi yukleyebilirsiniz. + +--- + +## Endpoint'ler + +Modellerimize asagidaki API endpoint'leri uzerinden de erisebilirsiniz. + +| Model | Model ID | Endpoint | AI SDK Package | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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. + +--- + +### Modeller + +Mevcut modellerin tam listesini ve metadatasini su adresten cekebilirsiniz: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## Fiyatlandirma + +Kullandikca ode modelini destekliyoruz. Asagidaki fiyatlar **1M token basina** verilmistir. + +| Model | Input | Output | Cached Read | Cached Write | +| --------------------------------- | ------ | ------ | ----------- | ------------ | +| Big Pickle | Free | Free | Free | - | +| MiniMax M2.1 Free | Free | Free | Free | - | +| MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | +| GLM 4.7 Free | Free | Free | Free | - | +| 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 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 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.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 | Free | Free | Free | - | + +Kullanim gecmisinizde _Claude Haiku 3.5_ gorebilirsiniz. Bu, oturum basliklarini olusturmak icin kullanilan [dusuk maliyetli bir modeldir](/docs/config/#models). + +:::note +Kredi karti ucretleri maliyetine yansitilir (islem basina %4.4 + $0.30); bunun disinda ek ucret almiyoruz. +::: + +Ucretsiz 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 + +Sorunuz varsa bize ulasin. + +--- + +### Otomatik yukleme + +Bakiyeniz $5'in altina dustugunde Zen otomatik olarak $20 yukler. + +Otomatik yukleme tutarini degistirebilir veya bu ozelligi tamamen kapatabilirsiniz. + +--- + +### Aylik limitler + +Tum calisma alani ve ekip uyeleri icin aylik kullanim 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. + +--- + +## Gizlilik + +Tum modellerimiz ABD'de barindiriliyor. Provider'larimiz sifir saklama politikasini izler ve verilerinizi model egitimi icin kullanmaz; asagidaki istisnalar haric: + +- 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 + +--- + +## Ekipler icin + +Zen ekipler icin de guclu bir cozumdur. Ekip arkadaslarini davet edebilir, roller atayabilir, kullanilacak modelleri yonetebilir ve daha fazlasini yapabilirsiniz. + +:::note +Calisma alanlari beta kapsaminda su anda ekipler icin ucretsizdir. +::: + +Calisma alani yonetimi su anda beta kapsaminda ucretsizdir. Fiyatlandirma detaylarini yakinda paylasacagiz. + +--- + +### Roller + +Calisma alaniniza ekip arkadaslarini davet edip rol atayabilirsiniz: + +- **Admin**: Modelleri, uyeleri, API anahtarlarini ve faturalandirmayi yonetir +- **Member**: Yalnizca kendi API anahtarlarini yonetir + +Admin'ler maliyet kontrolu icin uye bazinda aylik harcama limitleri de ayarlayabilir. + +--- + +### Model erisimi + +Admin'ler calisma alani icin belirli modelleri acip kapatabilir. Devre disi bir modele yapilan istekler hata dondurur. + +Bu, veri toplayan bir modelin kullanimini kapatmak istediginiz durumlarda kullanislidir. + +--- + +### Kendi anahtarinizi kullanin + +Zen'deki diger modellere erisirken kendi OpenAI veya Anthropic API anahtarlarinizi da kullanabilirsiniz. + +Kendi anahtarinizi kullandiginizda token ucreti Zen yerine dogrudan provider tarafindan faturalandirilir. + +Ornegin kurulusunuzun zaten OpenAI veya Anthropic anahtari varsa Zen'in sagladigi anahtar yerine onu kullanabilirsiniz. + +--- + +## Hedefler + +OpenCode Zen'i su amaclarla olusturduk: + +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 diff --git a/packages/web/src/content/docs/windows-wsl.mdx b/packages/web/src/content/docs/windows-wsl.mdx new file mode 100644 index 00000000000..ca3b6a4e32d --- /dev/null +++ b/packages/web/src/content/docs/windows-wsl.mdx @@ -0,0 +1,112 @@ +--- +title: Windows (WSL) +description: Run OpenCode on Windows using WSL for the best experience. +--- + +import { Steps } from "@astrojs/starlight/components" + +While OpenCode can run directly on Windows, we recommend using [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) for the best experience. WSL provides a Linux environment that works seamlessly with OpenCode's features. + +:::tip[Why WSL?] +WSL offers better file system performance, full terminal support, and compatibility with development tools that OpenCode relies on. +::: + +--- + +## Setup + + + +1. **Install WSL** + + If you haven't already, [install WSL](https://learn.microsoft.com/en-us/windows/wsl/install) using the official Microsoft guide. + +2. **Install OpenCode in WSL** + + Once WSL is set up, open your WSL terminal and install OpenCode using one of the [installation methods](/docs/). + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **Use OpenCode from WSL** + + Navigate to your project directory (access Windows files via `/mnt/c/`, `/mnt/d/`, etc.) and run OpenCode. + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## Desktop App + WSL Server + +If you prefer using the OpenCode Desktop app but want to run the server in WSL: + +1. **Start the server in WSL** with `--hostname 0.0.0.0` to allow external connections: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **Connect the Desktop app** to `http://localhost:4096` + +:::note +If `localhost` does not work in your setup, connect using the WSL IP address instead (from WSL: `hostname -I`) and use `http://:4096`. +::: + +:::caution +When using `--hostname 0.0.0.0`, set `OPENCODE_SERVER_PASSWORD` to secure the server. +::: + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +--- + +## Web Client + WSL + +For the best web experience on Windows: + +1. **Run `opencode web` in the WSL terminal** rather than PowerShell: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **Access from your Windows browser** at `http://localhost:` (OpenCode prints the URL) + +Running `opencode web` from WSL ensures proper file system access and terminal integration while still being accessible from your Windows browser. + +--- + +## Accessing Windows Files + +WSL can access all your Windows files through the `/mnt/` directory: + +- `C:` drive → `/mnt/c/` +- `D:` drive → `/mnt/d/` +- And so on... + +Example: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +For the smoothest experience, consider cloning/copying your repo into the WSL filesystem (for example under `~/code/`) and running OpenCode there. +::: + +--- + +## Tips + +- Keep OpenCode running in WSL for projects stored on Windows drives - file access is seamless +- Use VS Code's [WSL extension](https://code.visualstudio.com/docs/remote/wsl) alongside OpenCode for an integrated development workflow +- Your OpenCode config and sessions are stored within the WSL environment at `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/zh-cn/acp.mdx b/packages/web/src/content/docs/zh-cn/acp.mdx new file mode 100644 index 00000000000..47e0f3e05ce --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/acp.mdx @@ -0,0 +1,156 @@ +--- +title: ACP 支持 +description: 在任何 ACP 兼容编辑器中使用 opencode。 +--- + +opencode 支持 [Agent Client Protocol](https://agentclientprotocol.com) (ACP),允许您直接在兼容的编辑器和 IDE 中使用它。 + +:::tip +有关支持 ACP 的编辑器和工具的列表,请查看 [Zed ACP progress report](https://zed.dev/blog/acp-progress-report#available-now)。 +::: + +ACP 是一种开放协议,用于标准化代码编辑器和 AI 编码代理之间的通信。 + +--- + +## 配置 + +要通过 ACP 使用 opencode,须编辑器配置为运行 `opencode acp` 命令。 + +该命令将 opencode 作为 ACP 兼容的子进程启动,通过 stdio 通过 JSON-RPC 与您的编辑器进行通信。 + +以下是支持 ACP 的流行编辑器的示例。 + +--- + +### Zed + +添加到您的 [Zed](https://zed.dev) 配置 (`~/.config/zed/settings.json`): + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +要打开它,请使用 **命令面板** 中的 `agent: new thread` 操作。 + +您还可以通过编辑 `keymap.json` 来绑定键盘快捷键: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### JetBrains IDE + +根据 [文档](https://www.jetbrains.com/help/ai-assistant/acp.html) 添加到你的 [JetBrains IDE](https://www.jetbrains.com/) `acp.json`: + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +要打开它,请在 AI Chat 代理选择器中使用新的 "opencode" 代理。 + +--- + +### Avante.nvim + +添加到您的 [Avante.nvim](https://github.com/yetone/avante.nvim) 配置: + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +如果需要传递环境变量: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +相当于 opencode 网关 [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim) 中的 ACP 代理,接下来将以下内容添加到 Neovim 配置中: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +此配置将 CodeCompanion.nvim 设置为使用 opencode 作为聊天的 ACP 代理。 + +如果您需要传递环境变量(如 `OPENCODE_API_KEY`),请参阅 CodeCompanion.nvim 文档中的 [Configuration: Adapters](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) 了解完整信息。 + +## 支持 + +opencode 通过 ACP 的工作方式与在终端中的工作方式相同。支持所有功能: + +:::note +目前不支持某些内置斜杠命令,例如 `/undo` 和 `/redo`。 +::: + +- 内置工具(文件操作、终端命令等) +- 自定义工具和斜杠命令 +- 在 opencode 配置中配置的 MCP 服务器 +- `AGENTS.md` 的项目特定规则 +- 自定义程序和 linter +- 代理和权限系统 diff --git a/packages/web/src/content/docs/zh-cn/agents.mdx b/packages/web/src/content/docs/zh-cn/agents.mdx new file mode 100644 index 00000000000..a94296f4525 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/agents.mdx @@ -0,0 +1,747 @@ +--- +title: 代理 +description: 配置和使用专门的代理。 +--- + +代理是专门的人工智能助手,可以针对特定任务和工作流程进行配置。它们允许您创建具有自定义提示、模型和工具访问权限的专用工具。 + +:::tip +使用 Plan 代理来分析代码并审查建议,而无需进行任何代码更改。 +::: + +您可以在会话期间在代理之间切换,或使用 `@` 提及来调用它们。 + +--- + +## 类型 + +OpenCode 有两种类型的代理;主代理和子代理。 + +--- + +### 主代理 + +主代理 (Primary) 是与您直接交互的主要助手。您可以使用 **Tab** 键或您配置的 `switch_agent` 键绑定循环浏览它们。这些代理处理您的主要对话。工具访问是通过权限配置的 - 例如,“Build”启用了所有工具,而“Plan”则受到限制。 + +:::tip +您可以在会话期间使用 **Tab** 键在主代理之间进行切换。 +::: + +OpenCode 附带两个内置的主代理:**Build** 和 **Plan**。 +看看下面这些。 + +--- + +### 子代理 + +子代理 (Subagents) 是主代理可以调用​​来执行特定任务的专业助手。您还可以通过在消息中 **@提及** 它们来手动调用它们。 + +OpenCode 附带两个内置子代理:**General** 和 **Explore**。我们将在下面看看这个。 + +--- + +## 内置 + +OpenCode 附带两个内置主代理和两个内置子代理。 + +--- + +### 使用 Build + +_模式_:`primary` + +Build 是启用所有工具的 **默认** Primary 代理。这是用于需要完全访问文件操作和系统命令的开发工作的标准代理。 + +--- + +### 使用 Plan + +_模式_:`primary` + +专为规划和分析而设计的受限代理。我们使用权限系统为您提供更多控制并防止意外更改。 +默认情况下,以下所有项均设置为 `ask`: + +- `file edits`:所有书写、修复和编辑 +- `bash`:所有 bash 命令 + +当您希望 LLM 分析代码、建议更改或创建计划而不是对代码库进行任何实际修改时,此代理非常有用。 + +--- + +### 使用 General + +_模式_:`subagent` + +用于研究复杂问题和执行多步骤任务的通用代理。它具有完整的工具访问权限(待办事项除外),因此可在需要时修改文件,并并行运行多个工作单元。 + +--- + +### 使用 Explore + +_模式_:`subagent` + +用于探索代码库的快速只读代理。无法修改文件。当您需要按模式快速查找文件、搜索代码中的关键字或回答有关代码库的问题时,请使用此功能。 + +--- + +### 使用 Compact + +_模式_:`primary` + +隐藏的系统代理,将长上下文压缩为更小的抽象。它会在需要时自动运行,并且无法在 UI 中选择。 + +--- + +### 使用 Title + +_模式_:`primary` + +生成短会话标题的隐藏系统代理。它会自动运行,并且无法在 UI 中选择。 + +--- + +### 使用 Summary + +_模式_:`primary` + +创建会话摘要的系统代理。它会自动运行,并且无法在 UI 中选择。 + +--- + +## 用法 + +1. 对于主代理,请在会话期间使用 **Tab** 键循环浏览它们。您还可以使用配置的 `switch_agent` 键绑定。 + +2. 可以调用子代理: + - **自动**由主代理根据其描述执行专门任务。 + - 通过在消息中 **@提及** 子代理手动进行。例如。 + + ```txt frame="none" + @general help me search for this function + ``` + +3. **会话之间导航**:当子代理创建自己的子会话时,您可以使用以下命令在父会话和所有子会话之间导航: + - **\+Right**(或您配置的 `session_child_cycle` 键绑定)向前循环父级 → 子级 1 → 子级 2 → ... → 父级 + - **\+Left**(或您配置的 `session_child_cycle_reverse` 键绑定)向后循环父级 ← 子级 1 ← 子级 2 ← ... ← 父级 + + 这使您可以在主要对话和专门的子代理工作之间无缝切换。 + +--- + +## 配置 + +您也可以自定义内置代理或通过配置创建您自己的代理。可以通过两种方式配置代理: + +--- + +### JSON + +在 `opencode.json` 配置文件中配置代理: + +```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 + +您还可以使用 Markdown 文件定义代理。将它们放入: + +- 全局:`~/.config/opencode/agents/` +- 每个项目:`.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 文件名成为代理名称。例如,`review.md` 创建 `review` 代理。 + +--- + +## 选项 + +让我们详细看看这些配置选项。 + +--- + +### 描述 + +使用 `description` 选项提供代理的作用以及使用时的简要描述。 + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +这是一个 **必需的** 配置选项。 + +--- + +### 温度 + +使用 `temperature` 配置控制 LLM 响应的随机性和创意。 + +较低的值使响应更加集中和确定,而较高的值则增加创造力和可变性。 + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +温度值范围通常为 0.0 到 1.0: + +- **0.0-0.2**:响应更集中、确定性更高,适合代码分析和规划 +- **0.3-0.5**:平衡型响应,兼顾稳定性与创造力 +- **0.6-1.0**:响应更有创意和多样性,适合头脑风暴和探索 + +```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}" + } + } +} +``` + +如果未指定温度,OpenCode 将使用特定于模型的默认值;大多数模型通常为 0,Qwen 模型为 0.55。 + +--- + +### 最大步数 + +控制代理在被迫仅使用文本响应之前可以执行的最大代理迭代次数。这允许希望控制成本的用户对代理操作设置限制。 + +如果未设置,代理将继续迭代,直到模型选择停止或用户中断会话。 + +```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 + } + } +} +``` + +当达到限制时,代理会收到特殊的系统提示,指示其响应其工作摘要和建议的剩余任务。 + +:::caution +旧版 `maxSteps` 字段已废弃。请改用 `steps`。 +::: + +--- + +### 禁用 + +设置为 `true` 以取消代理。 + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### 提示 + +使用 `prompt` 配置为代理指定自定义系统提示文件。提示文件应包含特定于代理目的的说明。 + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +该路径相对于文件所在位置的配置。因此,这适用于全局 OpenCode 配置和项目特定配置。 + +--- + +### 模型 + +使用 `model` 配置此代理的模型。对于使用针对不同任务优化的不同模型很有帮助。例如,更快的规划模型、更强大的实施模型。 + +:::tip +如果您不指定模型,主代理将使用 [全局配置的模型](/docs/config#models),而子代理将使用调用子代理的主代理的模型。 +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +OpenCode 配置中的模型 ID 使用格式 `provider/model-id`。例如,如果您使用 [OpenCode Zen](/docs/zen),则您将使用 `opencode/gpt-5.1-codex` 来表示 GPT 5.1 Codex。 + +--- + +### 工具 + +使用 `tools` 配置控制此代理中可用的工具。您可以通过将特定工具设置为 `true` 或 `false` 来启用或禁用特定工具。 + +```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 +特定于代理的配置会覆盖全局配置。 +::: + +您还可以使用通配符同时控制多个工具。例如,要禁用 MCP 服务器中的所有工具: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[了解有关工具的更多信息](/docs/tools)。 + +--- + +### 权限 + +您可以配置权限来管理代理可以执行的操作。 目前,`edit`、`bash` 和 `webfetch` 工具的权限可以配置为: + +- `"ask"` — 运行工具提示批准之前 +- `"allow"` — 尚未批准所有操作 +- `"deny"` — 取消该工具 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +您可以覆盖每个代理的这些权限。 + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +您还可以在 Markdown 代理中设置权限。 + +```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. +``` + +您可以设置特定的 bash 命令的权限。 + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +这可以采用全局模式。 + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +您还可以使用 `*` 通配符来管理所有命令的权限。 +由于最后一个匹配规则优先,因此将 `*` 通配符放在前面,将特定规则放在后面。 + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[了解有关权限的更多信息](/docs/permissions)。 + +--- + +### 模式 + +使用 `mode` 配置控制代理的模式。 `mode` 选项用于确定如何使用代理。 + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +`mode` 选项可设置为 `primary`、`subagent` 或 `all`。如果未指定 `mode`,则默认为 `all`。 + +--- + +### 隐藏 + +使用 `hidden: true` 从 `@` 自动完成菜单隐藏子代理。对于只能由其他代理通过任务工具以编程方式调用的内部子代理很有帮助。 + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +这仅影响自动完成菜单中的用户可见性。如果权限允许,模型仍然可以通过任务工具调用隐藏代理。 + +:::note +仅适用于 `mode: subagent` 代理。 +::: + +--- + +### 任务权限 + +使用 `permission.task` 控制代理可以通过任务工具调用哪些子代理。使用 glob 模式进行灵活匹配。 + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +当设置为 `deny` 时,子代理社区任务工具描述中因此完全删除,模型不会尝试调用它。 + +:::tip +规则按顺序评估,**最后匹配的规则触发**。在上面的示例中,`orchestrator-planner` 匹配 `*`(拒绝)和 `orchestrator-*`(允许),但由于 `orchestrator-*` 位于 `*` 之后,因此结果为 `allow`。 +::: + +:::tip +用户始终可以通过 `@` 自动完成菜单直接调用任何子代理,即使代理的任务权限会拒绝它。 +::: + +--- + +### 颜色 + +在 UI 中的界面外观中使用 `color` 选项自定义代理。这会影响代理在界面中的显示方式。 + +使用有效的十六进制颜色(例如 `#FF5733`)或主题颜色:`primary`、`secondary`、`accent`、`success`、`warning`、`error`、`info`。 + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +使用 `top_p` 选项控制响应多样性。控制随机性的温度替代方案。 + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +值范围从 0.0 到 1.0。较低的值更加集中,较高的值更加多样化。 + +--- + +### 其他 + +您在代理配置中指定的任何其他选项都将作为模型选项 **直接** 传递给提供商。这允许您使用特定于提供商的功能和参数。 + +例如,使用 OpenAI 的推理模型,您可以控制推理工作: + +```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" + } + } +} +``` + +这些附加选项是特定于模型和提供商的。检查提供商的文档以获取可用参数。 + +:::tip +运行 `opencode models` 查看可用模型的列表。 +::: + +--- + +## 创建代理 + +您可以使用以下命令创建新代理: + +```bash +opencode agent create +``` + +此交互式命令将: + +1. 询问代理保存在哪里;全局或特定项目。 +2. 描述代理应该做什么。 +3. 生成适当的系统提示和标识符。 +4. 让您选择代理可以访问哪些工具。 +5. 最后,使用代理配置创建一个 markdown 文件。 + +--- + +## 使用案例 + +以下是不同代理的一些常见用例。 + +- **Build Agent**:启用所有工具的完整开发工作 +- **Plan Agent**:分析规划,不做改动 +- **Review Agent**:具有只读访问权限和文档工具的代码审查 +- **Debug Agent**:专注于启用 bash 和读取工具的调查 +- **Docs Agent**:使用文件操作但不使用系统命令的文档编写 + +--- + +## 示例 + +以下是一些您可能会觉得有用的示例代理。 + +:::tip +您有想要分享的代理吗? [提交 PR](https://github.com/anomalyco/opencode)。 +::: + +--- + +### 文档代理 + +```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 +``` + +--- + +### 安全审计员 + +```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/zh-cn/cli.mdx b/packages/web/src/content/docs/zh-cn/cli.mdx new file mode 100644 index 00000000000..6d2ea032d11 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/cli.mdx @@ -0,0 +1,603 @@ +--- +title: CLI +description: opencode CLI 选项和命令。 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +默认情况下,opencode CLI 在不带任何参数运行时启动 [TUI](/docs/tui)。 + +```bash +opencode +``` + +但它也接受本页记录的命令。这允许您以编程方式与 opencode 交互。 + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +启动 opencode 终端用户界面。 + +```bash +opencode [project] +``` + +#### 标志 + +| 标志 | 简写 | 描述 | +| ------------ | ---- | --------------------------------------------------------- | +| `--continue` | `-c` | 继续上一个会话 | +| `--session` | `-s` | 继续的会话 ID | +| `--fork` | | 继续时分叉会话(与 `--continue` 或 `--session` 一起使用) | +| `--prompt` | | 使用的提示 | +| `--model` | `-m` | 使用的模型 (provider/model) | +| `--agent` | | 使用的代理 | +| `--port` | | 监听端口 | +| `--hostname` | | 监听的主机名 | + +--- + +## 命令 + +opencode CLI 还具有以下命令。 + +--- + +### agent + +管理 opencode 代理。 + +```bash +opencode agent [command] +``` + +--- + +### attach + +将终端附加到通过 `serve` 或 `web` 命令启动的已运行 opencode 后端服务器。 + +```bash +opencode attach [url] +``` + +这允许将 TUI 与远程 opencode 后端一起使用。例如: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### 标志 + +| 标志 | 简写 | 描述 | +| ----------- | ---- | ------------------- | +| `--dir` | | 启动 TUI 的工作目录 | +| `--session` | `-s` | 继续的会话 ID | + +--- + +#### create + +使用自定义配置创建新代理。 + +```bash +opencode agent create +``` + +此命令将指导您使用自定义系统提示和工具配置创建新代理。 + +--- + +#### list + +列出所有可用的代理。 + +```bash +opencode agent list +``` + +--- + +### auth + +用于管理提供商的凭据和登录的命令。 + +```bash +opencode auth [command] +``` + +--- + +#### login + +opencode 由 [Models.dev](https://models.dev) 上的提供商列表支持,因此您可以使用 `opencode auth login` 来为您想要使用的任何提供商配置 API 密钥。它存储在 `~/.local/share/opencode/auth.json` 中。 + +```bash +opencode auth login +``` + +当 opencode 启动时,它会从凭据文件加载提供商。以及如果在您的环境或项目中的 `.env` 文件中定义了任何密钥。 + +--- + +#### list + +列出凭据文件中存储的所有经过身份验证的提供商。 + +```bash +opencode auth list +``` + +或者简短的版本。 + +```bash +opencode auth ls +``` + +--- + +#### logout + +通过从凭据文件中清除提供商,将您从提供商中注销。 + +```bash +opencode auth logout +``` + +--- + +### github + +管理 GitHub 代理以实现存储库自动化。 + +```bash +opencode github [command] +``` + +--- + +#### install + +在您的存储库中安装 GitHub 代理。 + +```bash +opencode github install +``` + +这将设置必要的 GitHub Actions 工作流程并指导您完成配置过程。 [了解更多](/docs/github)。 + +--- + +#### run + +运行 GitHub 代理。这通常用在 GitHub Actions 中。 + +```bash +opencode github run +``` + +#### 标志 + +| 标志 | 描述 | +| --------- | ------------------------------ | +| `--event` | 用于运行代理的 GitHub 模拟事件 | +| `--token` | GitHub 个人访问 Token | + +--- + +### mcp + +管理模型上下文协议 (MCP) 服务器。 + +```bash +opencode mcp [command] +``` + +--- + +#### add + +将 MCP 服务器添加到您的配置中。 + +```bash +opencode mcp add +``` + +此命令将指导您添加本地或远程 MCP 服务器。 + +--- + +#### list + +列出所有已配置的 MCP 服务器及其连接状态。 + +```bash +opencode mcp list +``` + +或者使用简短版本。 + +```bash +opencode mcp ls +``` + +--- + +#### auth + +使用启用 OAuth 的 MCP 服务器进行身份验证。 + +```bash +opencode mcp auth [name] +``` + +如果您不提供服务器名称,系统将提示您从可用的支持 OAuth 的服务器中进行选择。 + +您还可以列出支持 OAuth 的服务器及其身份验证状态。 + +```bash +opencode mcp auth list +``` + +或者使用简短版本。 + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +删除 MCP 服务器的 OAuth 凭据。 + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +调试 MCP 服务器的 OAuth 连接问题。 + +```bash +opencode mcp debug +``` + +--- + +### models + +列出已配置提供商的所有可用模型。 + +```bash +opencode models [provider] +``` + +此命令以 `provider/model` 格式显示您配置的提供商中可用的所有模型。 + +这对于确定 [你的配置](/docs/config/) 中使用的确切模型名称很有帮助。 + +您可以选择提供提供商 ID 并按该提供商筛选模型。 + +```bash +opencode models anthropic +``` + +#### 标志 + +| 标志 | 描述 | +| ----------- | ---------------------------------------- | +| `--refresh` | 从 models.dev 刷新模型缓存 | +| `--verbose` | 使用更详细的模型输出(包括成本等元数据) | + +使用 `--refresh` 标志来更新服务器的模型列表。当新模型已添加到提供商并且您希望在 opencode 中查看它们时,这非常有用。 + +```bash +opencode models --refresh +``` + +--- + +### run + +通过直接传递提示以非交互模式运行 opencode。 + +```bash +opencode run [message..] +``` + +这对于编写脚本、自动化,或者当您想要快速获得答案而不是完整的 TUI 时非常有用。例如。 + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +您还可以附加到正在运行的 `opencode serve` 实例,以避免每次运行时 MCP 服务器冷启动时间: + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### 标志 + +| 标志 | 简写 | 描述 | +| ------------ | ---- | --------------------------------------------------------------- | +| `--command` | | 要运行的命令,使用消息作为参数 | +| `--continue` | `-c` | 继续上一个会话 | +| `--session` | `-s` | 继续的会话 ID | +| `--fork` | | 继续时分叉会话(与 `--continue` 或 `--session` 一起使用) | +| `--share` | | 分享会话 | +| `--model` | `-m` | 使用的模型 (provider/model) | +| `--agent` | | 使用的代理 | +| `--file` | `-f` | 要附加到消息的文件 | +| `--format` | | 格式:default(格式化)或 json(原始 JSON 事件) | +| `--title` | | 会话标题(如果未提供值,则使用截断的提示) | +| `--attach` | | 连接到正在运行的 opencode 服务器(例如,http://localhost:4096) | +| `--port` | | 本地服务器的端口(默认为随机端口) | + +--- + +### serve + +启动无头 opencode 服务器以进行 API 访问。查看 [服务器文档](/docs/server) 以获取完整的 HTTP 接口。 + +```bash +opencode serve +``` + +这将启动一个 HTTP 服务器,该服务器提供对 opencode 功能的 API 访问,无需 TUI 界面。设置 `OPENCODE_SERVER_PASSWORD` 以启用 HTTP 基本身份验证(用户名默认为 `opencode`)。 + +#### 标志 + +| 标志 | 描述 | +| ------------ | ------------------------ | +| `--port` | 监听端口 | +| `--hostname` | 监听的主机名 | +| `--mdns` | 启用 mDNS 发现 | +| `--cors` | 允许 CORS 的其他浏览器源 | + +--- + +### session + +管理 opencode 会话。 + +```bash +opencode session [command] +``` + +--- + +#### list + +列出所有 opencode 会话。 + +```bash +opencode session list +``` + +##### 标志 + +| 标志 | 简写 | 描述 | +| ------------- | ---- | ------------------------------ | +| `--max-count` | `-n` | 限制为最近的 N 个会话 | +| `--format` | | 输出格式:table 或 json(table) | + +--- + +### stats + +显示 opencode 会话的 Token 使用情况和成本统计信息。 + +```bash +opencode stats +``` + +#### 标志 + +| 标志 | 描述 | +| ----------- | -------------------------------------------------------- | +| `--days` | 显示过去 N 天(所有时间)的统计数据 | +| `--tools` | 显示工具数量(全部) | +| `--models` | 显示模型使用情况细分(默认隐藏)。输入一个数字来显示前 N | +| `--project` | 按项目过滤(所有项目,空字符串:当前项目) | + +--- + +### export + +将会话数据导出为 JSON。 + +```bash +opencode export [sessionID] +``` + +如果您不提供会话 ID,系统将提示您从可用的会话中进行选择。 + +--- + +### import + +从 JSON 文件或 opencode 共享 URL 导入会话数据。 + +```bash +opencode import +``` + +您可以从本地文件或 opencode 共享 URL 导入。 + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +使用 Web 界面启动无头 opencode 服务器。 + +```bash +opencode web +``` + +这将启动 HTTP 服务器并打开 Web 浏览器以通过 Web 界面访问 opencode。设置 `OPENCODE_SERVER_PASSWORD` 以启用 HTTP 基本身份验证(用户名默认为 `opencode`)。 + +#### 标志 + +| 标志 | 描述 | +| ------------ | ------------------------ | +| `--port` | 监听端口 | +| `--hostname` | 监听的主机名 | +| `--mdns` | 启用 mDNS 发现 | +| `--cors` | 允许 CORS 的其他浏览器源 | + +--- + +### acp + +启动 ACP (Agent Client Protocol) 服务器。 + +```bash +opencode acp +``` + +此命令启动一个 ACP 服务器,该服务器使用 nd-JSON 通过 stdin/stdout 进行通信。 + +#### 标志 + +| 标志 | 描述 | +| ------------ | ------------ | +| `--cwd` | 工作目录 | +| `--port` | 监听端口 | +| `--hostname` | 监听的主机名 | + +--- + +### uninstall + +卸载 opencode 并删除所有相关文件。 + +```bash +opencode uninstall +``` + +#### 标志 + +| 标志 | 简写 | 描述 | +| --------------- | ---- | ---------------------------- | +| `--keep-config` | `-c` | 保留配置文件 | +| `--keep-data` | `-d` | 保留会话数据和快照 | +| `--dry-run` | | 显示将删除的内容但不实际删除 | +| `--force` | `-f` | 跳过确认提示 | + +--- + +### upgrade + +将 opencode 更新到最新版本或特定版本。 + +```bash +opencode upgrade [target] +``` + +升级到最新版本。 + +```bash +opencode upgrade +``` + +升级到特定版本。 + +```bash +opencode upgrade v0.1.48 +``` + +#### 标志 + +| 标志 | 简写 | 描述 | +| ---------- | ---- | ------------------------------------------ | +| `--method` | `-m` | 使用的安装方法;curl, npm, pnpm, bun, brew | + +--- + +## 全局标志 + +opencode CLI 接受以下全局标志。 + +| 标志 | 简写 | 描述 | +| -------------- | ---- | ----------------------------------- | +| `--help` | `-h` | 显示帮助 | +| `--version` | `-v` | 打印版本号 | +| `--print-logs` | | 将日志打印到 stderr | +| `--log-level` | | 日志级别 (DEBUG, INFO, WARN, ERROR) | + +--- + +## 环境变量 + +可以使用环境变量配置 opencode。 + +| 变量 | 类型 | 描述 | +| ------------------------------------- | ------- | ----------------------------------------- | +| `OPENCODE_AUTO_SHARE` | boolean | 自动共享会话 | +| `OPENCODE_GIT_BASH_PATH` | string | Windows 上 Git Bash 可执行文件的路径 | +| `OPENCODE_CONFIG` | string | 配置文件路径 | +| `OPENCODE_CONFIG_DIR` | string | 配置目录的路径 | +| `OPENCODE_CONFIG_CONTENT` | string | 内联 json 配置内容 | +| `OPENCODE_DISABLE_AUTOUPDATE` | boolean | 禁用自动更新检查 | +| `OPENCODE_DISABLE_PRUNE` | boolean | 禁用数据的修剪 | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | 禁用自动终端标题更新 | +| `OPENCODE_PERMISSION` | string | 内联 json 权限配置 | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | 禁用默认插件 | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | 禁用自动 LSP 服务器下载 | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | 启用实验模型 | +| `OPENCODE_DISABLE_AUTOCOMPACT` | boolean | 禁用自动上下文压缩 | +| `OPENCODE_DISABLE_CLAUDE_CODE` | boolean | 禁用从 `.claude` 读取(提示+技能) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | 禁用读取 `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | 禁用加载 `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | boolean | 禁用从远程源获取模型 | +| `OPENCODE_FAKE_VCS` | string | 用于测试目的的伪造 VCS | +| `OPENCODE_DISABLE_FILETIME_CHECK` | boolean | 禁用文件时间检查以进行优化 | +| `OPENCODE_CLIENT` | string | 客户端标识符(默认为 `cli`) | +| `OPENCODE_ENABLE_EXA` | boolean | 启用 Exa 网络搜索工具 | +| `OPENCODE_SERVER_PASSWORD` | string | 为 `serve`/`web` 启用基本身份验证 | +| `OPENCODE_SERVER_USERNAME` | string | 覆盖基本身份验证用户名(默认 `opencode`) | +| `OPENCODE_MODELS_URL` | string | 用于获取模型配置的自定义 URL | + +--- + +### 实验性功能 + +这些环境变量启用可能会更改或删除的实验性功能。 + +| 变量 | 类型 | 描述 | +| ----------------------------------------------- | ------- | ----------------------------------- | +| `OPENCODE_EXPERIMENTAL` | boolean | 启用所有实验性功能 | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | 启用图标发现 | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | 在 TUI 中禁用选择时复制 | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number | bash 命令的默认超时(以毫秒为单位) | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | number | LLM 响应的最大输出 Token | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolean | 为整个目录启用文件观察器 | +| `OPENCODE_EXPERIMENTAL_OXFMT` | boolean | 启用 oxfmt 格式化程序 | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolean | 启用实验性 LSP 工具 | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | 禁用文件观察器 | +| `OPENCODE_EXPERIMENTAL_EXA` | boolean | 启用实验性 Exa 功能 | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolean | 启用实验性 LSP 类型检查 | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolean | 启用实验性 Markdown 功能 | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolean | 启用计划模式 | diff --git a/packages/web/src/content/docs/zh-cn/commands.mdx b/packages/web/src/content/docs/zh-cn/commands.mdx new file mode 100644 index 00000000000..548b681b0b7 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/commands.mdx @@ -0,0 +1,323 @@ +--- +title: 命令 +description: 为重复任务创建自定义命令。 +--- + +自定义命令允许您指定在 TUI 中执行该命令时要运行的提示。 + +```bash frame="none" +/my-command +``` + +除了 `/init`、`/undo`、`/redo`、`/share`、`/help` 等内置命令之外,还有自定义命令。 [了解更多](/docs/tui#commands)。 + +--- + +## 创建命令文件 + +在 `commands/` 目录中创建 markdown 文件来定义自定义命令。 + +创建 `.opencode/commands/test.md`: + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +frontmatter 定义命令属性。内容成为模板。 + +通过键入 `/` 后跟命令名称来使用该命令。 + +```bash frame="none" +"/test" +``` + +--- + +## 配置 + +您可以通过 opencode 配置或通过在 `commands/` 目录中创建 markdown 文件来添加自定义命令。 + +--- + +### JSON + +在 opencode [配置](/docs/config) 中使用 `command` 选项: + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +现在您可以在 TUI 中运行这个命令: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +您还可以使用 Markdown 文件定义命令。将它们放入: + +- 全局:`~/.config/opencode/commands/` +- 每个项目:`.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Markdown 文件名成为命令名。例如,`test.md` 让 +你运行: + +```bash frame="none" +/test +``` + +--- + +## 提示配置 + +自定义命令的提示支持几个特殊的占位符和语法。 + +--- + +### 参数 + +使用 `$ARGUMENTS` 占位符将参数提交给命令。 + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +使用参数运行命令: + +```bash frame="none" +/component Button +``` + +`$ARGUMENTS` 将替换为 `Button`。 + +您还可以使用位置参数访问各个参数: + +- `$1` - 第一个参数 +- `$2` - 第二个参数 +- `$3` - 第三个参数 +- 等等... + +例如: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +运行命令: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +这取代了: + +- `$1` 与 `config.json` +- `$2` 与 `src` +- `$3` 与 `{ "key": "value" }` + +--- + +### Shell 输出 + +使用 _!`command`_ 将 [bash 命令](/docs/tui#bash-commands) 输出注入到提示符中。 + +例如,要创建分析测试覆盖率的自定义命令: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +或者查看最近的更改: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +命令在项目的根目录中运行,其输出成为提示的一部分。 + +--- + +### 文件引用 + +使用 `@` 后跟文件名将文件包含在命令中。 + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +文件内容会自动包含在提示中。 + +--- + +## 选项 + +让我们详细看看配置选项。 + +--- + +### template + +`template` 选项定义执行命令时将发送到 LLM 的提示。 + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +这是一个 **必需的** 配置选项。 + +--- + +### description + +使用 `description` 选项提供命令功能的简要描述。 + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +当您输入命令时,这将在 TUI 中显示为描述。 + +--- + +### agent + +使用 `agent` 配置选择指定哪个 [Agent](/docs/agents) 应执行此命令。 +如果是 [Subagents](/docs/agents/#subagents) 该命令将默认触发子代理调用。 +要取消此行为,则将 `subtask` 设置为 `false`。 + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +这是一个 **可选** 配置选项。如果未指定,则默认为您当前的代理。 + +--- + +### subtask + +使用 `subtask` 布尔值强制命令触发 [Subagents](/docs/agents/#subagents) 调用。 +如果您希望命令不污染您的主要上下文并且将 **强制** 代理充当子代理,那么这非常有用, +即使 `mode` 在 [Agent](/docs/agents) 配置上设置为 `primary`。 + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +这是一个 **可选** 配置选项。 + +--- + +### model + +使用 `model` 配置覆盖此命令的默认模型。 + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +这是一个 **可选** 配置选项。 + +--- + +## 内置 + +opencode 包含 `/init`、`/undo`、`/redo`、`/share`、`/help` 等内置命令;[了解更多](/docs/tui#commands)。 + +:::note +自定义命令可以覆盖内置命令。 +::: + +如果您定义同名的自定义命令,它将覆盖内置命令。 diff --git a/packages/web/src/content/docs/zh-cn/config.mdx b/packages/web/src/content/docs/zh-cn/config.mdx new file mode 100644 index 00000000000..e07e4601f69 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/config.mdx @@ -0,0 +1,680 @@ +--- +title: 配置 +description: 使用 opencode JSON 配置。 +--- + +您可以使用 JSON 配置文件配置 opencode。 + +--- + +## 格式 + +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, +} +``` + +--- + +## 位置 + +您可以将配置放置在几个不同的位置,它们有一个不同的优先顺序。 + +:::note +配置文件**合并在一起**,而不是替换。 +::: + +配置文件被合并在一起,而不是被替换。以下配置位置的设置被合并。仅当密钥冲突时,后面的配置才会覆盖前面的配置。保留所有配置中的非冲突设置。 + +例如,如果您的全局配置设置 `theme: "opencode"` 和 `autoupdate: true`,并且您的项目配置设置 `model: "anthropic/claude-sonnet-4-5"`,则最终配置将包括所有三个设置。 + +--- + +### 优先级 + +配置源按以下顺序加载(后面的源覆盖前面的源): + +1. **Remote config** (来自 `.well-known/opencode`) - 组织默认值 +2. **Global config** (`~/.config/opencode/opencode.json`) - 用户首选项 +3. **Custom config** (`OPENCODE_CONFIG` env var) - 自定义覆盖 +4. **Project config** (项目中的 `opencode.json`) - 项目特定的设置 +5. **`.opencode` 目录** - 代理、命令、插件 +6. **Inline config** (`OPENCODE_CONFIG_CONTENT` env var) - 运行时覆盖 + +这意味着项目配置可以覆盖全局默认值,全局配置可以覆盖远程组织默认值。 + +:::note +`.opencode` 和 `~/.config/opencode` 目录对子目录使用 **复数名称**:`agents/`、`commands/`、`modes/`、`plugins/`、`skills/`、`tools/` 和 `themes/`。为了向后兼容,还支持单数名称(例如 `agent/`)。 +::: + +--- + +### 远程 + +组织可以通过 `.well-known/opencode` 端点提供默认配置。当您向支持的提供商进行身份验证时,会自动获取该信息。 + +首先加载远程配置,作为基础层。所有其他配置源(全局、项目)都可以覆盖这些默认值。 + +例如,如果您的组织提供默认禁用的 MCP 服务器: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +您可以在本地配置中启用特定服务器: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### 全局 + +将全局 opencode 配置放在 `~/.config/opencode/opencode.json` 中。使用全局配置来实现用户范围的首选项,例如主题、提供商或按键绑定。 + +全局配置覆盖远程组织默认值。 + +--- + +### 项目级 + +在项目根目录中添加 `opencode.json`。项目配置在标准配置文件中具有最高优先级 - 它覆盖全局配置和远程配置。 + +:::tip +将项目特定配置放在项目的根目录中。 +::: + +当 opencode 启动时,它会在当前目录中查找配置文件或向上遍历到最近的 Git 目录。 + +这也可以安全地签入 Git 并使用与全局模式相同的架构。 + +--- + +### 自定义路径 + +使用 `OPENCODE_CONFIG` 环境变量指定自定义配置文件路径。 + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +自定义配置按优先顺序在全局配置和项目配置之间加载。 + +--- + +### 自定义目录 + +使用 `OPENCODE_CONFIG_DIR` 环境变量指定自定义配置目录。将在该目录中搜索代理、命令、模式和插件,就像标准 `.opencode` 目录一样,并且应该遵循相同的结构。 + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +自定义目录在全局配置和 `.opencode` 目录加载后,因此 **可以覆盖** 它们的设置。 + +--- + +## 模式 + +配置文件具有在 [**`opencode.ai/config.json`**](https://opencode.ai/config.json) 中定义的架构。 + +您的编辑器应该能够根据架构进行验证和自动完成。 + +--- + +### TUI + +您可以通过 `tui` 选项配置特定于 TUI 的设置。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +可用选项: + +- `scroll_acceleration.enabled` - 启用 macOS 风格的滚动加速。 **优先于 `scroll_speed`。** +- `scroll_speed` - 自定义滚动速度倍增(默认值:`3`,最小值:`1`)。如果 `scroll_acceleration.enabled` 是 `true`,则忽略。 +- `diff_style` - 控制差异渲染。 `"auto"` 适应终端宽度,`"stacked"` 始终显示单列。 + +[在此处了解有关使用 TUI 的更多信息](/docs/tui)。 + +--- + +### 服务器 + +您可以通过 `opencode serve` 选项为 `opencode web` 和 `server` 命令配置服务器设置。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +可用选项: + +- `port` - 监听端口。 +- `hostname` - 监听的主机名。当 `mdns` 启用且未设置主机名时,默认为 `0.0.0.0`。 +- `mdns` - 启用 mDNS 服务发现。这允许网络上的其他设备发现您的 opencode 服务器。 +- `mdnsDomain` - mDNS 服务的自定义域名。默认为 `opencode.local`。对于在同一个网络上运行多个实例很有帮助。 +- `cors` - 从基于浏览器的客户端使用 HTTP 服务器时允许 CORS 的其他来源。值必须是完整来源(协议+主机+可选端口),例如 `https://app.example.com`。 + +[在此处了解有关服务器的更多信息](/docs/server)。 + +--- + +### 工具 + +您可以通过 `tools` 选项管理 LLM 可以使用的工具。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[在此处了解有关工具的更多信息](/docs/tools)。 + +--- + +### 模型 + +您可以通过 `provider`、`model` 和 `small_model` 选项来配置要在 opencode 配置中使用的提供商和模型。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +`small_model` 选项为标题生成等轻量级任务配置单独的模型。默认情况下,如果您的提供商可以提供更便宜的模型,opencode 会尝试使用更便宜的模型,否则它会退回到您的主模型。 + +提供商选项可以包括 `timeout` 和 `setCacheKey`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` - 请求超时以毫秒为单位(默认值:300000)。设置为 `false` 以禁用。 +- `setCacheKey` - 确保始终为指定的提供商设置缓存键。 + +您还可以配置 [本地模型](/docs/models#local)。[了解更多](/docs/models)。 + +--- + +#### 特定于提供商的选项 + +有些提供商支持除通用 `timeout` 和 `apiKey` 之外的其他配置选项。 + +##### Amazon Bedrock + +Amazon Bedrock 支持 AWS 特定配置: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` - Bedrock 的 AWS 区域(默认为 `AWS_REGION` env var 或 `us-east-1`) +- `profile` - 来自 `~/.aws/credentials` 的 AWS 命名配置文件(默认为 `AWS_PROFILE` env var) +- `endpoint` - VPC 终端节点的自定义节点 URL。这是使用 AWS 特定术语的通用 `baseURL` 选项的别名。如果两者都指定,`endpoint` 优先。 + +:::note +Bearer Tokens (`AWS_BEARER_TOKEN_BEDROCK` 或 `/connect`) 优先于基于配置文件的身份验证。详情请参见 [身份验证优先级](/docs/providers#authentication-precedence)。 +::: + +[了解有关 Amazon Bedrock 配置的更多信息](/docs/providers#amazon-bedrock)。 + +--- + +### 主题 + +您可以通过 opencode 配置中的 `theme` 选项配置要使用的主题。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[在这里了解更多](/docs/themes)。 + +--- + +### 代理 + +您可以通过 `agent` 选项为特定任务配置专用代理。 + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +您还可以使用 `~/.config/opencode/agents/` 或 `.opencode/agents/` 中的 markdown 文件定义代理。 [在这里了解更多](/docs/agents)。 + +--- + +### 默认代理 + +您可以使用 `default_agent` 选项设置默认代理。当没有明确指定时,这将确定使用哪个代理。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +默认代理必须是 Primary 代理(不是 Subagent)。这可以是内置代理(如 `"build"` 或 `"plan"`),也可以是您定义的 [Custom Agent](/docs/agents)。如果指定的代理不存在或者是子代理,opencode 将回退到 `"build"` 并发出警告。 + +此设置适用于所有界面:TUI、CLI (`opencode run`)、桌面应用程序和 GitHub Action。 + +--- + +### 分享 + +您可以通过 `share` 选项配置 [分享](/docs/share) 功能。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +这需要: + +- `"manual"` - 允许通过命令手动共享(默认) +- `"auto"` - 自动分享新对话 +- `"disabled"` - 完全禁用共享 + +默认情况下,共享设置为手动模式,您需要使用 `/share` 命令显式共享对话。 + +--- + +### 命令 + +您可以通过 `command` 选项为重复任务配置自定义命令。 + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +您还可以使用 `~/.config/opencode/commands/` 或 `.opencode/commands/` 中的 Markdown 文件定义命令。 [在这里了解更多](/docs/commands)。 + +--- + +### 快捷键 + +您可以通过 `keybinds` 选项自定义您的按键绑定。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[在这里了解更多](/docs/keybinds)。 + +--- + +### 自动更新 + +opencode 将在启动时自动下载任何新的更新。您可以使用 `autoupdate` 选项禁用此功能。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +如果您不想更新但希望在新版本可用时收到通知,则需将 `autoupdate` 设置为 `"notify"`。 +请注意,这仅在未使用 Homebrew 等包管理器安装时才有效。 + +--- + +### 格式化程序 + +您可以通过 `formatter` 选项配置代码格式化程序。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[在这里了解有关格式化程序的更多信息](/docs/formatters)。 + +--- + +### 权限 + +默认情况下,opencode **允许所有操作**,无需明确批准。您可以使用 `permission` 选项更改此设置。 + +例如,要确保 `edit` 和 `bash` 工具需要用户批准: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[在此处了解有关权限的更多信息](/docs/permissions)。 + +--- + +### 压缩 + +您可以通过 `compaction` 选项控制上下文压缩行为。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto` - 当上下文已满时自动压缩会话(默认值:`true`)。 +- `prune` - 删除旧工具输出以保存 Tokens(默认值:`true`)。 + +--- + +### 观察器 + +您可以通过 `watcher` 选项配置文件观察器忽略模式。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +模式遵循 glob 语法。使用它可以从文件监视中排除嘈杂的目录。 + +--- + +### MCP 服务器 + +您可以通过 `mcp` 选项配置要使用的 MCP 服务器。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[在这里了解更多](/docs/mcp-servers)。 + +--- + +### 插件 + +[Plugins](/docs/plugins) 使用自定义工具、挂钩和集成扩展 opencode。 + +将插件文件放置在 `.opencode/plugins/` 或 `~/.config/opencode/plugins/` 中。您还可以通过 `plugin` 选项从 npm 加载插件。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[在这里了解更多](/docs/plugins)。 + +--- + +### 指令 + +您可以通过 `instructions` 选项配置您正在使用的模型的说明。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +这需要指令文件的路径和 glob 模式数组。 [在此处了解有关规则的更多信息](/docs/rules)。 + +--- + +### 禁用提供商 + +您可以通过 `disabled_providers` 选项禁用自动加载的提供商。当您想要阻止加载某些提供商(即使其凭据可用)时,这非常有用。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +`disabled_providers` 优先于 `enabled_providers`。 +::: + +`disabled_providers` 选项接受提供商 ID 数组。当提供商被禁用时: + +- 即使设置了环境变量也不会加载。 +- 即使通过 `/connect` 命令配置 API 密钥,也不会加载它。 +- 提供商的模型不会出现在模型选择列表中。 + +--- + +### 启用提供商 + +您可以通过 `enabled_providers` 选项指定允许的提供商列表。设置后,仅启用指定的提供商,所有其他提供商将被忽略。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +当您想要限制 opencode 仅使用特定的提供商而不是逐一禁用它们时,这非常有用。 + +:::note +`disabled_providers` 优先于 `enabled_providers`。 +::: + +如果提供商同时出现在 `enabled_providers` 和 `disabled_providers` 中,则 `disabled_providers` 优先以保持一致性。 + +--- + +### 实验性功能 + +`experimental` 键包含正在积极开发的选项。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +实验选项不稳定。它们可能会更改或被删除,恕不另行通知。 +::: + +--- + +## 变量 + +您可以在配置文件中使用变量替换来引用环境变量和文件内容。 + +--- + +### 环境变量 + +使用 `{env:VARIABLE_NAME}` 替换环境变量: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +如果未设置环境变量,它将被替换为空字符串。 + +--- + +### 文件 + +使用 `{file:path/to/file}` 替换文件的内容: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +文件路径可以是: + +- 相对于配置文件目录 +- 或者以 `/` 或 `~` 开头的绝对路径 + +这些对于: + +- 将 API 密钥等敏感数据保存在单独的文件中。 +- 包含大型指令文件,而不会弄乱您的配置。 +- 跨多个配置文件共享通用配置片段。 diff --git a/packages/web/src/content/docs/zh-cn/custom-tools.mdx b/packages/web/src/content/docs/zh-cn/custom-tools.mdx new file mode 100644 index 00000000000..211df7c0146 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: 自定义工具 +description: 创建 LLM 可以在 opencode 中调用的工具。 +--- + +自定义工具是您创建的函数,LLM 可以在对话期间调用。它们与 opencode 的 [Built-in Tools](/docs/tools) 一起工作,例如 `read`、`write` 和 `bash`。 + +--- + +## 创建工具 + +工具定义为 **TypeScript** 或 **JavaScript** 文件。但是,工具定义调用可以使用 **任何语言** 编写的脚本 - TypeScript 或 JavaScript 仅用于工具定义本身。 + +--- + +### 位置 + +它们可以定义为: + +- 通过将它们放在项目的 `.opencode/tools/` 目录中来本地进行。 +- 或者在全局范围内,将它们放在 `~/.config/opencode/tools/` 中。 + +--- + +### 结构 + +创建工具最简单的方法是使用 `tool()` 帮助程序,它提供类型安全和验证。 + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +**文件名** 成为 **工具名称**。以上创建了一个 `database` 工具。 + +--- + +#### 每个文件多个工具 + +您还可以从单个文件导出多个工具。每个导出都会成为 **一个单独的工具**,名称为 **`_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +这将创建两个工具:`math_add` 和 `math_multiply`。 + +--- + +### 参数 + +您可以使用 `tool.schema`(即 [Zod](https://zod.dev))来定义参数类型。 + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +您还可以直接导入 [Zod](https://zod.dev) 并返回一个普通对象: + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### 上下文 + +工具接收有关当前会话的上下文: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +使用 `context.directory` 作为会话工作目录。 +使用 `context.worktree` 作为 git 工作树根。 + +--- + +## 示例 + +### 使用 Python 编写工具 + +您可以使用任何您想要的语言编写工具。下面是一个使用 Python 将两个数字相加的示例。 + +首先,使用创建 Python 脚本的工具: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +然后创建调用它的工具定义: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +这里我们使用 [`Bun.$`](https://bun.com/docs/runtime/shell) 实用程序来运行 Python 脚本。 diff --git a/packages/web/src/content/docs/zh-cn/ecosystem.mdx b/packages/web/src/content/docs/zh-cn/ecosystem.mdx new file mode 100644 index 00000000000..25689beb11c --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: 生态系统 +description: 使用 opencode 构建的项目和集成。 +--- + +基于 opencode 的社区项目集合。 + +:::note +想要将您的 opencode 相关项目添加到此列表中吗?提交 PR。 +::: + +您还可以查看 [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) 和 [opencode.cafe](https://opencode.cafe),这是一个聚合生态系统和社区的社区。 + +--- + +## 插件 + +| 名称 | 描述 | +| --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | 在隔离的 Daytona 沙箱中自动运行 opencode 会话,并使用 git 同步和实时预览 | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | 自动注入 Helicone 会话标头以进行请求包 | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | 使用查找工具将 TypeScript/Svelte 类型自动注入到文件读取中 | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | 使用您的 ChatGPT Plus 或 Pro 订阅而不是 API 积分 | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | 使用您现有的 Gemini 计划而不是 API 密钥 | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | 使用 Antigravity 的免费模型代替 API | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | 具有浅克隆和自动分配端口的多分支开发容器隔离 | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Google Antigravity OAuth 插件,支持 Google 搜索和更强大的 API 处理 | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | 通过修剪过时的工具输出来优化 token 使用 | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | 为具有 Google 接地风格的受支持增加本机网络搜索支持 | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | 使 AI 代理能够在 PTY 中运行后台进程,末端发送其交互输入。 | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | 非交互式 shell 命令指令 - 防止依赖 TTY 的操作挂起 | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | 使用 Wakatime 跟踪 opencode 使用情况 | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | 清理 LLM 生成的 markdown 表 | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | 使用 Morph Fast Apply API 和取消编辑标记将代码编辑速度提高 10 倍 | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | 后台代理、预构建的 LSP/AST/MCP 工具、精选代理、兼容 Claude Code | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | opencode 会话的桌面通知和声音警报 | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | 针对权限、完成和错误事件的桌面通知和声音警报 | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | 基于 opencode 上下文的 AI 支持的自动 Zellij 会话命名 | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | 允许 opencode 代理通过技能发现和注入失败延迟加载提示 | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | 使用 Supermemory 跨会话持久内存 | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | 具有视觉注释和私人/离线共享的交互式计划审查 | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | 将 opencode/命令扩展为具有精细流程控制的强大编排系统 | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | 使用带 cron 语法的 launchd (Mac) 或 systemd (Linux) 安排重复作业 | +| [micode](https://github.com/vtemian/micode) | 塑造头脑风暴 → 计划 → 实施具有会议连续性的工作流程 | +| [octto](https://github.com/vtemian/octto) | 用于通过多问题形式进行 AI 头脑风暴的交互式浏览器 UI | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | 具有异步委托和上下文持久性的 Claude Code 风格后台代理 | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | opencode 的本机操作系统通知 – 了解任务何时完成 | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | 一堆多代理编排工具 – 16个,组件一次安装 | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | opencode 的零难度 git 工作树 | + +--- + +## 项目 + +| 名称 | 描述 | +| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------- | +| [kimaki](https://github.com/remorses/kimaki) | 用于控制 opencode 会话的 Discord 机器人,基于 SDK 构建 | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Neovim 插件,用于编辑器采集提示,基于 API 构建 | +| [portal](https://github.com/hosenur/portal) | 通过 Tailscale/VPN 实现 opencode 的移动优先 Web UI | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | 用于构建 opencode 插件的模板 | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Neovim opencode 前端 - 基于终端的 AI 编码代理 | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Vercel AI SDK 提供商,用于通过 @opencode-ai/sdk 使用 opencode | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | opencode 的 Web/桌面应用程序和 VS Code 扩展 | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | 在 Obsidian 的 UI 中嵌入 opencode 的 Obsidian 插件 | +| [OpenWork](https://github.com/different-ai/openwork) | Claude Cowork 的替代开源方案,由 opencode 提供支持 | +| [ocx](https://github.com/kdcokenny/ocx) | opencode 扩展管理器具有可移植、隔离的配置文件。 | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | opencode 的桌面、Web、移动和远程客户端应用程序 | + +--- + +## 代理 + +| 名称 | 描述 | +| ----------------------------------------------------------------- | ---------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | 用于格式化开发的 Agentic AI 代理和命令 | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | 用于增强工作流程的配置、提示、代理和插件 | diff --git a/packages/web/src/content/docs/zh-cn/enterprise.mdx b/packages/web/src/content/docs/zh-cn/enterprise.mdx new file mode 100644 index 00000000000..d4ababa2d6d --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/enterprise.mdx @@ -0,0 +1,165 @@ +--- +title: 企业版 +description: 在您的组织中安全地使用 opencode。 +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +opencode 企业版适用于希望确保其代码和数据永远不会离开其基础设施的组织。它可以通过使用与 SSO 和内部 AI 网关集成的集中方式配置来实现此目的。 + +:::note +opencode 不存储您的任何代码或上下文数据。 +::: + +要开始使用 opencode 企业版: + +1. 与您的团队进行内部试用。 +2. **联系我们** 讨论定价和实施选项。 + +--- + +## 试用 + +opencode 是开源的,不存储您的任何代码或上下文数据,因此您的开发人员只需 [开始吧](/docs/) 并进行试用。 + +--- + +### 数据处理 + +**opencode 不会存储您的代码或上下文数据。** 所有处理都在本地进行或通过直接 API 调用您的 AI 提供商。 + +这意味着只要您使用您信任的提供商或内部 AI 网关,您就可以安全使用 opencode。 + +这里唯一需要注意的是可选的 `/share` 功能。 + +--- + +#### 分享对话 + +如果用户启用 `/share` 功能,对话和关联的数据将被发送到我们用于在 opencode.ai 上托管这些共享页面的服务。 + +数据当前通过我们的 CDN 边缘网络提供服务,并缓存在用户附近的边缘。 + +我们建议您在试用时禁用此功能。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[了解更多关于分享的信息](/docs/share)。 + +--- + +### 代码所有权 + +**您拥有 opencode 生成的所有代码。** 没有许可限制或所有权主张。 + +--- + +## 定价 + +我们对 opencode Enterprise 使用按席位模型。如果您有自己的 LLM 网关,我们不会对使用的 Token 收取费用。有关定价和实施选项的更多详细信息,请 **联系我们**。 + +--- + +## 部署 + +完成试用并准备好在您的组织中使用 opencode 后,您可以 **联系我们** 进行讨论定价和实施选项。 + +--- + +### 中央配置 + +我们可以将 opencode 设置为您的整个组织使用单一的中央配置。 + +这种集中式配置可以与您的 SSO 提供商集成,并确保所有用户仅访问您的内部 AI 网关。 + +--- + +### SSO 集成 + +通过中央配置,opencode 可以与您组织的 SSO 提供商集成以进行身份验证。 + +这使得 opencode 能够通过现有的身份管理系统获取内部 AI 网关的凭据。 + +--- + +### 内部 AI 网关 + +通过中央配置,opencode 还可以配置为仅使用您的内部 AI 网关。 + +您还可以禁用所有其他 AI 提供商,确保所有请求都通过组织批准的基础设施。 + +--- + +### 自托管 + +虽然我们建议禁用共享页面以确保您的数据永远不会离开您的组织,我们还可以帮助您在您的基础设施上自行托管它们。 + +目前这已在我们的路线图上。如果您有兴趣,**让我们知道**。 + +--- + +## 常见问题 + +

+什么是 opencode 企业版? + +opencode 企业版适用于希望确保其代码和数据永远不会离开其基础设施的组织。它可以通过使用与 SSO 和内部 AI 网关集成的集中方式配置来实现此目的。 + +
+ +
+如何开始使用 opencode 企业版? + +与您的团队进行内部实验即可。opencode 默认情况下不存储您的代码或上下文数据,可以轻松上手。 + +然后 **联系我们** 讨论定价和实施选项。 + +
+ +
+企业定价如何运作? + +我们提供按席位企业定价。如果您有自己的 LLM 网关,我们不会对使用的 Token 收取费用。如需了解更多详情,请 **联系我们**,获取根据您组织的需求定制的报价。 + +
+ +
+opencode 企业版保证我的数据安全吗? + +是的。opencode 不存储您的代码或上下文数据。所有处理都在本地进行或通过直接 API 调用您的 AI 提供商。通过中央配置和 SSO 集成,您的数据在组织的基础架构中保持安全。 + +
+ +
+我们可以使用自己的私有 npm 注册表吗? + +opencode 通过 Bun 的本机 `.npmrc` 文件支持来支持私有 npm 注册表。如果您的组织使用私有注册表,例如 JFrog Artifactory、Nexus 或类似的,请确保开发人员在运行 opencode 之前经过身份验证。 + +要使用您的私有注册表设置身份验证: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +这将创建带有身份验证详细信息的 `~/.npmrc`。 opencode 会自动读取这个。 + +:::caution +在运行 opencode 之前,您必须登录私有注册表。 +::: + +或者,您可以手动配置 `.npmrc` 文件: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +开发人员必须在运行 opencode 之前登录私有注册表,以确保可以从您的企业注册表安装软件包。 + +
diff --git a/packages/web/src/content/docs/zh-cn/formatters.mdx b/packages/web/src/content/docs/zh-cn/formatters.mdx new file mode 100644 index 00000000000..8e080d85f8f --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: 格式化程序 +description: opencode 使用特定于语言的格式化程序。 +--- + +使用特定于语言的格式化程序编写或编辑文件后,opencode 会自动格式化文件。这可以确保生成的代码遵循项目的代码风格。 + +--- + +## 内置 + +opencode 附带了多个适用于流行语言和框架的内置格式化程序。下面是格式化程序、支持的文件扩展名以及所需的命令或配置选项的列表。 + +| 格式化程序 | 扩展名 | 要求 | +| -------------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| 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 | +| 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 | + +因此,如果您的项目的 `prettier` 中有 `package.json`,opencode 将自动使用它。 + +--- + +## 它是如何工作的 + +当 opencode 写入或编辑文件时,它: + +1. 根据所有启用的格式化程序检查文件扩展名。 +2. 对文件运行适当的格式化程序命令。 +3. 自动应用格式更改。 + +此过程在后台进行,确保无需任何手动步骤即可维护您的代码样式。 + +--- + +## 配置 + +您可以通过 opencode 配置中的 `formatter` 部分自定义格式化程序。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +每个格式化程序配置支持以下内容: + +| 属性 | 类型 | 描述 | +| ------------- | -------- | ---------------------------------- | +| `disabled` | boolean | 将其设置为 `true` 以禁用格式化程序 | +| `command` | string[] | 格式化运行的命令 | +| `environment` | object | 运行格式化程序时要设置的环境变量 | +| `extensions` | string[] | 此格式化程序应处理的文件扩展名 | + +让我们看一些例子。 + +--- + +### 禁用格式化程序 + +要全局禁用 **所有** 格式化程序,将 `formatter` 设置为 `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +要禁用 **特定** 格式化程序,将 `disabled` 设置为 `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### 自定义格式化程序 + +您可以覆盖内置格式化程序或通过指定命令、环境变量和文件扩展名添加新格式化程序: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +命令中的 **`$FILE` 占位符** 将替换为正在格式化的文件的路径。 diff --git a/packages/web/src/content/docs/zh-cn/github.mdx b/packages/web/src/content/docs/zh-cn/github.mdx new file mode 100644 index 00000000000..b9b80d0dd6f --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/github.mdx @@ -0,0 +1,321 @@ +--- +title: GitHub +description: 在 GitHub 问题和拉取请求中使用 opencode。 +--- + +opencode 与您的 GitHub 工作流程集成。在评论中提及 `/opencode` 或 `/oc`,opencode 将在您的 GitHub Actions 运行器中执行任务。 + +--- + +## 功能 + +- **Triage issues**: 要求 opencode 调查问题并向您解释。 +- **Fix and implement**: 要求 opencode 修复问题或实施功能。将在一个新的分支中工作并提交包含所有更改的 PR。 +- **Secure**: opencode 在 GitHub 的运行器中运行。 + +--- + +## 安装 + +在 GitHub 存储库中的项目中运行以下命令: + +```bash +opencode github install +``` + +这将引导您完成安装 GitHub 应用程序、创建工作流程和设置机密。 + +--- + +### 手动设置 + +或者您可以手动设置。 + +1. **Install the GitHub app** + + 前往 [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent)。确保它​​已安装在目标存储库上。 + +2. **Add the workflow** + + 将以下工作流程文件添加到存储库中的 `.github/workflows/opencode.yml` 中。确保在 `model` 中设置适当的 `env` 和所需的 API 密钥。 + + ```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx + ``` + +3. **Store the API keys in secrets** + + 在您的组织或项目的 **Settings** 中,展开左侧的 **Secrets and variables**,然后选择 **Actions**。并添加所需的 API 密钥。 + +--- + +## 配置 + +- `model`:与 opencode 一起使用的模型。采用 `provider/model` 格式。这是 **必需的**。 +- `agent`:要使用的代理。必须是一级代理。如果未找到,则从配置回退到 `default_agent` 或 `"build"`。 +- `share`:是否共享 opencode 会话。对于公共存储库,默认为 **true**。 +- `prompt`:可选的自定义提示以覆盖默认行为。使用它来自定义 opencode 处理请求的方式。 +- `token`:可选的 GitHub 访问 Token,用于执行创建评论、提交更改和打开拉取请求等操作。默认情况下,opencode 使用来自 opencode GitHub 应用程序的安装访问 Token,因此提交、评论和拉取请求显示为来自应用。 + + 或者,您可以使用 GitHub Action 运行程序的 [内置 `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token),而无需安装 opencode GitHub 应用程序。只需确保在您的工作流程中所需的权限: + + ```yaml + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + ``` + + 您可以在 GitHub Actions 文档中了解有关配置工作流程的更多信息。 + +--- + +## 支持的事件 + +opencode 可以由以下 GitHub 事件触发: + +| 事件类型 | 触发方式 | 详情 | +| ----------------------------- | ---------------------------- | --------------------------------------------------------------------------------------- | +| `issue_comment` | 对问题或 PR 发表评论 | 在评论中提及 `/opencode` 或 `/oc`。 opencode 读取上下文并可以创建分支、打开 PR 或回复。 | +| `pull_request_review_comment` | 对 PR 中的特定代码行进行评论 | 在检查代码时提及 `/opencode` 或 `/oc`。 opencode 接收文件路径、行号和 diff 上下文。 | +| `issues` | 问题已打开或已编辑 | 创建或修改问题时自动触发 opencode。需要 `prompt` 输入。 | +| `pull_request` | PR 已开启或已更新 | 当 PR 打开、同步或重新打开时自动触发 opencode。对于自动评论很有帮助。 | +| `schedule` | 基于 Cron 的计划 | 按计划运行 opencode。需要 `prompt` 输入。输出进入日志和 PR(没有可评论的问题)。 | +| `workflow_dispatch` | 从 GitHub UI 手动触发 | 通过“操作”选项卡触发 opencode。需要 `prompt` 输入。输出进入日志和 PR。 | + +### 计划示例 + +按计划运行 opencode 以执行自动化任务: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +对于计划事件,`prompt` 输入是 **必需的**,因为没有注释可以从中提取指令。希望计划工作流在没有用户上下文的情况下运行并进行权限检查,因此如果您 opencode 创建分支或 PR,工作流必须支持 `contents: write` 和 `pull-requests: write`。 + +--- + +### Pull Request 示例 + +或更新 PR 时自动审核: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +对于 `pull_request` 事件,如果未提供 `prompt`,opencode 将默认审核拉取请求。 + +--- + +### Issue 分类示例 + +自动分类新问题。此示例过滤超过 30 天的账户以减少垃圾邮件: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +对于 `issues` 事件,`prompt` 输入是 **必需的**,因为没有注释可以从中提取指令。 + +--- + +## 自定义提示 + +覆盖默认提示,为您的工作流程自定义 opencode 的行为。 + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +这对于执行与您的项目相关的特定审查标准、编码标准或重点领域非常有用。 + +--- + +## 示例 + +以下是如何在 GitHub 中使用 opencode 的一些示例。 + +- **Explain an issue** + + 在 GitHub 问题中添加此评论。 + + ``` + /opencode explain this issue + ``` + + opencode 将阅读整个线程,包括所有评论,并回复并提供清晰的解释。 + +- **Fix an issue** + + 在 GitHub 问题中,说: + + ``` + /opencode fix this + ``` + + opencode 将创建一个新分支,实施更改,并使用更改打开 PR。 + +- **Review PRs and make changes** + + 在 GitHub PR 上留下以下评论。 + + ``` + Delete the attachment from S3 when the note is removed /oc + ``` + + opencode 将实施请求的更改并提交到同一个 PR。 + +- **Review specific code lines** + + 直接在 PR 的“文件”选项卡中的代码行上留下评论。opencode 自动检测文件、行号和差异上下文以提供准确的响应。 + + ``` + [Comment on specific lines in Files tab] + /oc add error handling here + ``` + + 当评论特定行时,opencode 接收: + - 正在审查的确切文件 + - 具体代码行 + - 周围的差异上下文 + - 行号信息 + + 这允许更有针对性的请求,而无需手动指定文件路径或行号。 diff --git a/packages/web/src/content/docs/zh-cn/gitlab.mdx b/packages/web/src/content/docs/zh-cn/gitlab.mdx new file mode 100644 index 00000000000..e9c474e62fe --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: 在 GitLab 问题和合并请求中使用 opencode。 +--- + +opencode 通过 GitLab CI/CD 管道或与 GitLab Duo 与您的 GitLab 工作流程集成。 + +在这两种情况下,opencode 都会在您的 GitLab 运行器上运行。 + +--- + +## GitLab CI + +opencode 在常规 GitLab 管道中工作。您可以将其构建为管道 [CI 组件](https://docs.gitlab.com/ee/ci/components/) + +在这里,我们使用社区创建的 opencode CI/CD 组件 — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode)。 + +--- + +### 功能 + +- **Use custom configuration per job**: 使用自定义配置目录配置 opencode,例如 `./config/#custom-directory` 以启用或禁用 opencode 调用的功能。 +- **Authentication**: Uses OIDC for secure authentication +- **Flexible**: CI 组件支持多种输入来自定义其行为 + +--- + +### 设置 + +1. 将 opencode 身份验证 JSON 作为文件类型 CI 环境变量存储在 **Settings** > **CI/CD** > **Variables** 下。确保将它们标记为“隐藏和隐藏”。 +2. 将以下内容添加到您的 `.gitlab-ci.yml` 文件中。 + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +有关此组件的更多输入和示例[查看文档](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode)。 + +--- + +## GitLab Duo + +opencode 与您的 GitLab 工作流程集成。 +在评论中提及 `@opencode`,opencode 将在您的 GitLab CI 管道中执行任务。 + +--- + +### 功能 + +- **Triage issues**: 要求 opencode 调查问题并向您解释。 +- **Fix and implement**: 要求 opencode 修复问题或实施功能。 + 它将创建一个新分支并提出包含更改的合并请求。 +- **Secure**: opencode 在您的 GitLab 运行器上运行。 + +--- + +### 设置 + +opencode 在您的 GitLab CI/CD 管道中运行,您需要进行以下设置: + +:::tip +查看 [**GitLab docs**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) 获取最新说明。 +::: + +1. 配置您的 GitLab 环境 +2. 设置 CI/CD +3. 获取 AI 模型提供商 API 密钥 +4. 创建服务账户 +5. 配置 CI/CD 变量 +6. 创建一个流配置文件,这是一个示例: + +
+ + Flow configuration + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +详细说明可以参考 [GitLab CLI agents docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/)。 + +--- + +### 示例 + +以下是如何在 GitLab 中使用 opencode 的一些示例。 + +:::tip +您可以配置使用与 `@opencode` 不同的触发词。 +::: + +- **Explain an issue** + + 在 GitLab 问题中添加此评论。 + + ``` + @opencode explain this issue + ``` + + opencode 将阅读该问题并回复并提供清晰的解释。 + +- **Fix an issue** + + 在 GitLab 问题中,说: + + ``` + @opencode fix this + ``` + + opencode 将创建一个新分支,实施更改,并打开包含更改的合并请求。 + +- **Review merge requests** + + 对 GitLab 合并请求留下以下评论。 + + ``` + @opencode review this merge request + ``` + + opencode 将审核合并请求并提供反馈。 diff --git a/packages/web/src/content/docs/zh-cn/ide.mdx b/packages/web/src/content/docs/zh-cn/ide.mdx new file mode 100644 index 00000000000..fb3a92bec7c --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: VS Code、Cursor 等 IDE 的 opencode 扩展 +--- + +opencode 与 VS Code、Cursor 或任何支持终端的 IDE 集成。只需在终端中运行 `opencode` 即可开始。 + +--- + +## 用法 + +- **快速启动**:使用 `Cmd+Esc` (Mac) 或 `Ctrl+Esc` (Windows/Linux) 在分割终端视图中打开 opencode,或者聚焦现有终端会话(如果现有终端会话正在运行)。 +- **新会话**:使用 `Cmd+Shift+Esc` (Mac) 或 `Ctrl+Shift+Esc` (Windows/Linux) 启动新的 opencode 终端会话,即使该会话已打开。您还可以单击 UI 中的 opencode 按钮。 +- **上下文获取**:自动与 opencode 共享您当前的选择或选项卡。 +- **文件引用快捷方式**:使用 `Cmd+Option+K` (Mac) 或 `Alt+Ctrl+K` (Linux/Windows) 插入文件引用。例如,`@File#L37-42`。 + +--- + +## 安装 + +要在 VS Code 和 Cursor、Windsurf、VSCodium 等流行分支上安装 opencode: + +1. 打开 VS Code +2. 打开集成终端 +3. 运行 `opencode` - 扩展会自动安装 + +另一方面,如果您想在从 TUI 运行 `/editor` 或 `/export` 时使用自己的 IDE,则需要设置 `export EDITOR="code --wait"`。 [了解更多](/docs/tui/#editor-setup)。 + +--- + +### 手动安装 + +在扩展市场中搜索 **opencode**,然后单击 **Install**。 + +--- + +### 故障排除 + +如果扩展无法自动安装: + +- 确定您在集成终端中运行 `opencode`。 +- 确认您的 IDE 和 CLI 已安装: + - 对于 VS Code:`code` 命令 + - 对于 Cursor:`cursor` 命令 + - 对于 Windsurf:`windsurf` 命令 + - 对于 VSCodium:`codium` 命令 + - 如果没有,请运行 `Cmd+Shift+P` (Mac) 或 `Ctrl+Shift+P` (Windows/Linux) 并搜索 “Shell Command: Install 'code' command in PATH”(或适用于您的 IDE 的对应命令) +- 确保 VS Code 能够安装扩展 diff --git a/packages/web/src/content/docs/zh-cn/index.mdx b/packages/web/src/content/docs/zh-cn/index.mdx new file mode 100644 index 00000000000..bc71221372d --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/index.mdx @@ -0,0 +1,352 @@ +--- +title: 介绍 +description: 开始使用 opencode。 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**opencode**](/) 是一个开源人工智能编码代理。它可用于基于终端的界面、桌面应用程序或 IDE 扩展。 + +![具有 opencode 主题的 opencode TUI](../../../assets/lander/screenshot.png) + +让我们开始吧。 + +--- + +#### 先决条件 + +要在终端中使用 opencode,您需要: + +1. 现代终端模拟器,例如: + - [WezTerm](https://wezterm.org),跨平台 + - [Alacritty](https://alacritty.org),跨平台 + - [Ghostty](https://ghostty.org),Linux 和 macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/),Linux 和 macOS + +2. 你要使用的 LLM 提供商 API 密钥。 + +--- + +## 安装 + +安装 opencode 最简单的方法是通过安装脚本。 + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +您还可以使用以下命令安装它: + +- **使用 Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **在 macOS 和 Linux 上使用 Homebrew** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > 我们使用 opencode Tap 来获取最新版本。官方 `brew install opencode` 公式由 Homebrew 团队建议,维护频率较低。 + +- **在 Arch Linux 上使用 Paru** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[推荐:使用 WSL] +为了在 Windows 上获得最佳体验,我们建议使用 [Windows Subsystem for Linux (WSL)](/docs/windows-wsl)。它提供了更好的性能并与 opencode 的功能完全兼容。 +::: + +- **使用 Chocolatey** + + ```bash + choco install opencode + ``` + +- **使用 Scoop** + + ```bash + scoop install opencode + ``` + +- **使用 npm** + + ```bash + npm install -g opencode-ai + ``` + +- **使用 Mise** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **使用 Docker** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +目前正在支持在 Windows 上安装 opencode 时使用 Bun。 + +您还可以从 [Releases](https://github.com/anomalyco/opencode/releases) 获取二进制文件。 + +--- + +## 配置 + +借助 opencode,你可以通过配置 API 使用任意 LLM 提供商。 + +如果你刚开始使用 LLM 提供商,我们建议使用 [OpenCode Zen](/docs/zen)。 +这是经过 opencode 团队测试和验证的精选模型列表。 + +1. 在 TUI 中运行 `/connect` 命令,选择 opencode,然后前往 [opencode.ai/auth](https://opencode.ai/auth)。 + + ```txt + /connect + ``` + +2. 登录,添加您的账单信息,然后复制您的详细 API 密钥。 + +3. 粘贴您的 API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +或者,你也可以选择其他提供商之一。[了解更多](/docs/providers#directory)。 + +--- + +## 初始化 + +现在您已经配置了提供商,您可以导航到一个项目 +你想继续工作。 + +```bash +cd /path/to/project +``` + +并运行 opencode。 + +```bash +opencode +``` + +接下来,通过运行以下命令来初始化项目的 opencode。 + +```bash frame="none" +/init +``` + +这涉及 opencode 分析您的项目并在以下位置创建 `AGENTS.md` 文件 +项目根。 + +:::tip +您应该将项目的 `AGENTS.md` 文件提交到 Git。 +::: + +这有助于 opencode 理解项目结构和使用的编码模式。 + +--- + +## 用法 + +您现在已准备好使用 opencode 来处理您的项目。请轻松询问任何事物! + +如果您不熟悉使用 AI 编码代理,以下是一些可能会有所帮助的示例。 + +--- + +### 提问 + +您可以要求 opencode 向您解释代码库。 + +:::tip +使用 `@` 键模糊搜索工程中的文件。 +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +如果您没有处理代码库的一部分,这会很有帮助。 + +--- + +### 添加功能 + +您可以要求 opencode 向您的项目添加新功能。但是我们首先建议要求它制定一个计划。 + +1. **创建计划** + + opencode 有一个 _计划模式_,该模式禁止其进行更改和 + 相反,建议 _如何_ 实现该功能。 + + 使用 **Tab** 键切换到它。您会在右下角有一个指示符。 + + ```bash frame="none" title="Switch to Plan mode" + + ``` + + 现在让我们描述一下我们想要它做什么。 + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + 您需要为 opencode 提供足够的详细信息才能了解您想要的内容。它有帮助 + 就像与团队中的初级开发人员交谈一样与它交谈。 + + :::tip + 为 opencode 提供大量上下文和示例,以帮助其理解您的内容 + 想。 + ::: + +2. **迭代计划** + + 一旦它为您提供了计划,您就可以提供反馈或添加更多详细信息。 + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + + :::tip + 将图像拖放到终端中以将其添加到提示中。 + ::: + + opencode 可以扫描您提供的任何图像并将其添加到提示中。您可以 + 通过将图像拖放到终端中来完成此操作。 + +3. **构建功能** + + 一旦您对计划感到满意,请切换回 _构建模式_ + 再次按 **Tab** 键。 + + ```bash frame="none" + + ``` + + 并要求它做出改变。 + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### 进行更改 + +对于更直接的更改,您可以要求 opencode 直接构建它 +无需先审查计划。 + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +您需要确保提供大量详细信息,以便 opencode 做出正确的决定变化。 + +--- + +### 撤消更改 + +假设您要求 opencode 进行一些更改。 + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +但你意识到这不是你想要的。您 **可以撤消** 更改 +使用 `/undo` 命令。 + +```bash frame="none" +/undo +``` + +opencode 现在将恢复您所做的更改并再次显示您的原始消息。 + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +您可以从这里调整提示并要求 opencode 重试。 + +:::tip +您可以多次运行 `/undo` 以撤销多次更改。 +::: + +或者您 **可以使用 `/redo` 命令重做** 更改。 + +```bash frame="none" +/redo +``` + +--- + +## 分享 + +您与 opencode 的对话可以 [与您的团队分享](/docs/share)。 + +```bash frame="none" +/share +``` + +这会创建当前对话的链接并复制到剪贴板。 + +:::note +默认情况下不共享对话。 +::: + +这是带有 opencode 的 [示例对话](https://opencode.ai/s/4XP1fce5)。 + +--- + +## 定制 + +就是这样!你现在已经是 opencode 高手了。 + +要让您成为自己的,我们建议 [选择一个主题](/docs/themes)、[自定义交互绑定](/docs/keybinds)、[配置代码整理程序](/docs/formatters)、[创建自定义命令](/docs/commands) 或使用 [opencode 配置](/docs/config)。 diff --git a/packages/web/src/content/docs/zh-cn/keybinds.mdx b/packages/web/src/content/docs/zh-cn/keybinds.mdx new file mode 100644 index 00000000000..0ecd7c9bf66 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/keybinds.mdx @@ -0,0 +1,192 @@ +--- +title: 快捷键 +description: 自定义您的按键绑定。 +--- + +opencode 有一个按键绑定列表,您可以通过 opencode 配置进行自定义。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## Leader 键 + +opencode 对大多数按键绑定使用 `leader` 键。这可以避免终端中的冲突。 + +默认情况下,`ctrl+x` 是主键,大多数操作要求您先按主键,再按快捷键。例如,要开始新会话,请先按 `ctrl+x`,然后按 `n`。 + +您不需要为键绑定使用主键,但我们建议您这样做。 + +--- + +## 禁用按键绑定 + +您可以通过将按键添加到您的配置中并使用值“none”来禁用按键绑定。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## 桌面提示快捷键 + +opencode 桌面应用程序提示输入支持常见的 Readline/Emacs 风格的文本编辑快捷方式。这些是内置的,目前无法通过 `opencode.json` 进行配置。 + +| 快捷键 | 动作 | +| -------- | ------------------------- | +| `ctrl+a` | 移至当前行起点 | +| `ctrl+e` | 移至当前行尾 | +| `ctrl+b` | 将光标向后移动一个字符 | +| `ctrl+f` | 将光标向前移动一个字符 | +| `alt+b` | 将光标向后移动一个单词 | +| `alt+f` | 将光标向前移动一个单词 | +| `ctrl+d` | 删除光标下的字符 | +| `ctrl+k` | 删除到行尾 | +| `ctrl+u` | 删除到行首 | +| `ctrl+w` | 删除前一个单词 | +| `alt+d` | 删除下一个单词 | +| `ctrl+t` | 转置字符 | +| `ctrl+g` | 取消弹出窗口/中止运行响应 | + +--- + +## Shift+Enter + +默认情况下,某些终端不发送带有 Enter 的修饰键。您可能需要配置终端发送 `Shift+Enter` 作为转义序列。 + +### Windows Terminal + +打开您的 `settings.json`: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +将其添加到根级 `actions` 数组: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +将其添加到根级 `keybindings` 数组: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +保存文件并重新启动 Windows Terminal 或打开新选项卡。 diff --git a/packages/web/src/content/docs/zh-cn/lsp.mdx b/packages/web/src/content/docs/zh-cn/lsp.mdx new file mode 100644 index 00000000000..cc81810cc79 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: LSP 服务器 +description: opencode 与您的 LSP 服务器集成。 +--- + +opencode 与您的语言服务器协议 (LSP) 集成,以帮助 LLM 与您的代码库交互。它使用诊断向 LLM 提供反馈。 + +--- + +## 内置 + +opencode 附带了多种适用于流行语言的内置 LSP 服务器: + +| 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+)` 已安装 | +| 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-language-server | +| zls | .zig, .zon | `zig` 命令可用 | + +当检测到上述文件扩展名之一并且满足要求时,LSP 服务器将自动启用。 + +:::note +您可以通过将 `OPENCODE_DISABLE_LSP_DOWNLOAD` 环境变量设置为 `true` 来取消自动 LSP 服务器下载。 +::: + +--- + +## 它是如何工作的 + +当 opencode 打开一个文件时,它: + +1. 根据所有启用的 LSP 服务器检查文件扩展名。 +2. 如果尚未运行,则启动相应的 LSP 服务器。 + +--- + +## 配置 + +您可以通过 opencode 配置中的 `lsp` 部分自定义 LSP 服务器。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +每个 LSP 服务器支持以下功能: + +| 属性 | 类型 | 描述 | +| ---------------- | -------- | ----------------------------------- | +| `disabled` | boolean | 将其设置为 `true` 以禁用 LSP 服务器 | +| `command` | string[] | 启动 LSP 服务器的命令 | +| `extensions` | string[] | 此 LSP 服务器应处理的文件扩展名 | +| `env` | object | 启动服务器时设置的环境变量 | +| `initialization` | object | 发送到 LSP 服务器的初始化选项 | + +让我们看一些例子。 + +--- + +### 环境变量 + +启动 LSP 服务器时使用 `env` 参数设置环境变量: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### 初始化选项 + +使用 `initialization` 属性将初始化选项传递给 LSP 服务器。这些是在 LSP `initialize` 请求发送期间的服务器特定设置: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +初始化选项因 LSP 服务器而异。检查 LSP 服务器的文档以获得可用选项。 +::: + +--- + +### 禁用 LSP 服务器 + +要全局禁用 **所有** LSP 服务,将 `lsp` 设置为 `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +要禁用 **特定** LSP 服务器,将 `disabled` 设置为 `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### 自定义 LSP 服务器 + +您可以通过指定命令和文件扩展名来添加自定义 LSP 服务器: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## 其他信息 + +### PHP Intelephense + +PHP Intelephense 通过许可证密钥提供高级功能。您可以通过将(仅)密钥放置在以下位置的文本文件中来提供许可证密钥: + +- 在 macOS/Linux 上:`$HOME/intelephense/license.txt` +- 在 Windows 上:`%USERPROFILE%/intelephense/license.txt` + +该文件应仅包含许可证密钥,不包含其他内容。 diff --git a/packages/web/src/content/docs/zh-cn/mcp-servers.mdx b/packages/web/src/content/docs/zh-cn/mcp-servers.mdx new file mode 100644 index 00000000000..eb001563874 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/mcp-servers.mdx @@ -0,0 +1,511 @@ +--- +title: MCP 服务器 +description: 添加本地和远程MCP工具。 +--- + +您可以使用“模型上下文协议”或MCP将外部工具添加到opencode。opencode支持本地和远程服务器。 + +添加使用后,MCP工具将自动与内置工具一起供LLM。 + +--- + +#### 注意事项 + +当您使用 MCP 服务器时,它会添加到上下文中。如果您有很多工具,这会很快增加。因此,我们建议您选择使用哪些 MCP 服务器。 + +:::tip +MCP服务器会添加到您的上下文中,因此您需要小心启用哪些服务器。 +::: + +某些MCP服务器(例如GitHub MCP服务器)往往会添加大量代币,并且很容易超出上下文限制。 + +--- + +## 启用 + +您可以在`mcp`下的[opencode配置](https://opencode.ai/docs/config/)中定义MCP服务器。为每个MCP添加唯一的名称。当提示LLM时,您可以通过名称引用该MCP。 + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +您还可以通过将`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 + } + } +} +``` + +您的本地配置值会覆盖远程默认值。有关更多详细信息,请参阅[配置优先级](/docs/config#precedence-order)。 + +--- + +## 本地 + +使用`type`将本地MCP服务器添加到MCP对像中的`"local"`。 + +```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` | 字符串 | 是 | MCP 服务器连接类型,必须是`"local"`。 | +| `command` | 数据库 | 是 | 运行 MCP 服务器的命令和参数。 | +| `environment` | 对象 | | 运行服务器时设置的环境变量。 | +| `enabled` | 布尔 | | 在启动时启用或禁用MCP 服务器。 | +| `timeout` | 数量 | | 从MCP服务器获取工具的超时(以毫秒为单位)。默认为5000(5秒)。 | + +--- + +## 远程 + +通过将`type`设置为ZZPH1Z添加远程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" + } + } + } +} +``` + +`"remote"` 是远程MCP服务器的URL,使用`url`选项您可以创建标头列表。 + +--- + +#### 选项 + +| 选项 | 类型 | 必填 | 描述 | +| ---------- | ------ | ---- | -------------------------------------------------------------- | +| `headers` | 字符串 | 是 | MCP 服务器连接类型,必须是`type`。 | +| `"remote"` | 字符串 | 是 | 远程 MCP 服务器的 URL。 | +| `url` | 布尔 | | 在启动时启用或禁用MCP 服务器。 | +| `enabled` | 对象 | | 随请求一起发送的标头。 | +| `headers` | 对象 | | OAuth 身份验证。请参阅下面的配置[开放认证](#oauth) 部分。 | +| `oauth` | 数量 | | 从MCP服务器获取工具的超时(以毫秒为单位)。默认为5000(5秒)。 | + +--- + +## OAuth + +opencode自动处理远程MCP服务器的OAuth身份验证。当服务器需要身份验证时,opencode将: + +1. 检测 401 响应并启动 OAuth 流程 +2. 如果服务器支持,请使用**动态客户端注册 (RFC 7591)** +3. 安全地存儲Tokens以供将來的请求 + +--- + +### 自动 + +对于大多数支持 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 将在您第一次嘗試使用它時提示您进行身份验证。如果沒有,您可以使用 `timeout`[手动觸發流量](#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 +``` + +`opencode mcp auth ` 命令将打开您的浏览器进行授权。授权后,opencode Tokens安全地存储在 `mcp auth` 中。 + +--- + +#### 禁用 OAuth + +如果要禁用服务器的自动OAuth(例如,对于使用API密钥的服务器),则`~/.local/share/opencode/mcp-auth.json`设置为`oauth`: + +```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 选项 + +| 选项 | 类型 | 描述 | +| -------------- | --------------- | --------------------------------------------------- | +| `false` | 对象 \| `oauth` | OAuth 配置对象,或 `false` 以取消 OAuth 自动检测。 | +| `clientId` | 字符串 | OAuth 客户端 ID。如果未提供,将尝试动态客户端注册。 | +| `clientSecret` | 字符串 | OAuth客户端密钥(如果需要授权服务器)。 | +| `scope` | 字符串 | 授权期间请求的 OAuth 范围。 | + +#### 调试 + +如果远程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 配置来管理它们。 + +--- + +### 全局 + +这意味著您可以全局启用或禁用它們。 + +```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 + } +} +``` + +我们还可以使用 glob 模式来取消所有匹配的 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 + } +} +``` + +这里我们使用 glob 模式 `my-mcp*` 来取消所有 MCP。 + +--- + +### 每个代理人 + +如果您有大量 MCP 服务器,您可以选择为每个代理启用它们并全局取消它们。因此: + +1. 全局禁用它作为工具。 +2. 在您的[代理配置](/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 + } + } + } +} +``` + +--- + +#### 全局模式 + +glob 模式使用简单的正则表达式 globbing 模式: + +- `*` 匹配零个或多个任意字符(例如,`"my-mcp*"` 匹配 `my-mcp_search`、`my-mcp_list` 等) +- `?` 恰好匹配一个字符 +- 所有其他字符均按字面意思匹配 + +:::note +MCP服务器工具以名称服务器作为出口进行注册,要因此禁用服务器的所有工具,只需使用: + +``` +"mymcpservername_*": false +``` + +::: + +--- + +## 示例 + +以下是一些常见的 MCP 服务器的示例。如果您想记录其他服务器,您可以提交 PR。 + +--- + +### 哨兵 + +添加[哨兵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 +``` + +--- + +### 背景7 + +添加[Context7 MCP 服务器](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` 环境变量。 + +将 `use context7` 添加到提示中以使用 Context7 MCP 服务器。 + +```txt "use context7" +Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 +``` + +或者,您可以将类似的内容添加到您的[代理.md](/docs/rules/)。 + +```md title="AGENTS.md" +When you need to search docs, use `context7` tools. +``` + +--- + +### Vercel 的 Grep + +添加 [Vercel 的 Grep](https://grep.app) MCP 服务器正在搜索 GitHub 上的代码片段。 + +```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 +``` + +或者,您可以将类似的内容添加到您的[代理.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/zh-cn/models.mdx b/packages/web/src/content/docs/zh-cn/models.mdx new file mode 100644 index 00000000000..1a9b5b4c07a --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/models.mdx @@ -0,0 +1,223 @@ +--- +title: 模型 +description: 配置 LLM 提供商和模型。 +--- + +opencode 使用 [AI SDK](https://ai-sdk.dev/) 和 [Models.dev](https://models.dev) 支持 **75+ LLM 提供商**,并支持运行本地模型。 + +--- + +## 提供商 + +默认会预加载大多数流行的提供商。如果您已通过 `/connect` 命令添加了提供商的凭据,那么它们将在您启动 opencode 时可用。 + +了解有关[提供商](/docs/providers) 的更多信息。 + +--- + +## 选择模型 + +配置完提供商後,您可以通过輸入以下內容來选择您想要的模型: + +```bash frame="none" +/models +``` + +--- + +## 推荐模型 + +那裡有很多模型,每週都会有新模型問世。 + +:::tip +考慮使用我们推薦的模型之一。 +::: + +然而,既擅長生成代碼又擅長工具调用的只有少數。 + +以下是与 opencode 配合良好的几个模型,排名不分前面。(这不是好看的列表,也不一定是最新的): + +- GPT 5.2 +- GPT 5.1 法典 +- 近距離工作4.5 +- 克勞德十四行詩 4.5 +- 极小极M2.1 +- 雙子座 3 专業版 + +--- + +## 设置默认值 + +要将其中之一设置为默認模型,您可以在您的 +打開代碼配置。 + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +这里完整的ID是`provider_id/model_id`。例如,如果您使用[OpenCode Zen](/docs/zen),则您将使用`opencode/gpt-5.1-codex`来表示GPT 5.1 Codex。 + +如果您配置了[定制生产](/docs/providers#custom),则`provider_id` 是配​​置中`provider` 部分的按键,`model_id` 是`provider.models` 中的按键。 + +--- + +## 配置模型 + +您可以通过 config.json 全局配置模型的选项。 + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +在这里,我们为两个内置模型配置全局设置:`gpt-5`(通过 `openai` 提供商访问)和 `claude-sonnet-4-20250514`(通过 `anthropic` 提供商访问)。 +内置结构和模型名称可以在[Models.dev](https://models.dev) 上找到。 + +您还可以为您正在使用的任何代理配置这些选项。代理配置会覆盖此处的所有全局选项。 [了解更多](/docs/agents/#additional)。 + +你还可以定义扩展内置 variants 的自定义 variants。variants 允许你为同一模型配置不同设置,而无需创建重复条目: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## 变体 + +许多模型支持具有不同配置的多种变体。opencode附带了流行建设的内置默认变体。 + +### 内置变体 + +opencode 附带了许多重大的默认变体: + +**人擇**: + +- `high` - 高思维预算(默认) +- `max` - 最大预算规划 + +**OpenAI**: + +因模型而異,但大致如下: + +- `none` - 没有推理 +- `minimal` - 最少的推理工作 +- `low` - 推理工作量低 +- `medium` - 中等推理努力 +- `high` - 高推理能力 +- `xhigh` - 极高的推理能力 + +**谷歌**: + +- `low` - 降低工作量/Tokens預算 +- `high` - 更高的努力/Tokens預算 + +:::tip +该列表并不全面。許多其他提供商也有内置的默認值。 +::: + +### 自定义变体 + +您可以覆盖現有變體或添加您自己的變體: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### 循环变体 + +使用按键绑定`variant_cycle`在变体之间快速切换。 [了解更多](/docs/keybinds)。 + +--- + +## 加载模型 + +当opencode启动时,它会按以下优先顺序检查模型: + +1. `--model` 或 `-m` 配置命令行标志。格式与文件中的相同:`provider_id/model_id`。 + +2. opencode 配置中的模型列表。 + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + + 这里的格式是`provider/model`。 + +3. 最后使用的模型。 + +4. 第一个模型使用内部优先級。 diff --git a/packages/web/src/content/docs/zh-cn/modes.mdx b/packages/web/src/content/docs/zh-cn/modes.mdx new file mode 100644 index 00000000000..f4c2c78fdd8 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/modes.mdx @@ -0,0 +1,331 @@ +--- +title: 模式 +description: 不同的模式適用于不同的用例。 +--- + +:::caution +现在通过opencode配置中的`agent`选项配置模式。这 +`mode` 选项现已废弃。 [了解更多](/docs/agents)。 +::: + +opencode 中的模式允许自定义不同的示例行为、工具和提示。 + +它具有两种内置模式:**构建**和**计划**。您可以定制 +这些或通过 opencode 配置配置您自己的。 + +您可以在会话期間在模式之間切換或在配置文件中配置它們。 + +--- + +## 内置 + +opencode 有两种内置模式。 + +--- + +### 构建 + +構建是启用所有工具的**默認**模式。这是開發工作的標準模式,您需要完全访问文件操作和系統命令。 + +--- + +### 计划 + +专为規劃和分析而設計的受限模式。在計劃模式下,默認情况下禁用以下工具: + +- `write` - 无法创建新文件 +- `edit` - 无法修改现有文件,位于 `.opencode/plans/*.md` 的用于详细说明计划本身的文件另外 +- `patch` - 无法应用补丁 +- `bash` - 无法执行 shell 命令 + +当您希望人工智能分析代码、建议更改或创建计划而不对代码库进行任何实际修改时,此模式非常有用。 + +--- + +## 切换 + +您可以在会话期间使用 _Tab_ 键在模式之间切换。或者您配置的 `switch_mode` 键绑定。 + +另请参见:[格式化程序](/docs/formatters)相关代码配置的信息。 + +--- + +## 配置 + +您可以自定義内置模式或通过配置创建自己的模式。可以通过两种方式配置模式: + +### JSON 配置 + +在 `opencode.json` 配置文件中配置模式: + +```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 配置 + +您还可以使用 Markdown 文件定义模式。将它们放入: + +- 全球:`~/.config/opencode/modes/` +- 项目:`.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. +``` + +Markdown 文件名成为模式名称(例如,`review.md` 创建`review` 模式)。 + +讓我们詳細看看这些配置選項。 + +--- + +### 模型 + +使用`model`配置覆盖此模式的默认模型。对于使用针对不同任务优化的不同模型很有帮助。例如,更快的规划模型、更强大的实施模型。 + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### 温度 + +使用`temperature`配置控制AI响应的随机性和创造。较低的值使响应更加集中和确定,而较高的值则增加创造力和可变性。 + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +温度值范围通常为 0.0 到 1.0: + +- **0.0-0.2**:响应更集中、确定性更高,适合代码分析和规划 +- **0.3-0.5**:平衡型响应,兼顾稳定性与创造力 +- **0.6-1.0**:响应更有创意和多样性,适合头脑风暴和探索 + +```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}" + } + } +} +``` + +如果未指定温度,opencode将使用特定于模型的默认值(大多数模型通常为0,Qwen模型为0.55)。 + +--- + +### 提示词 + +使用 `prompt` 配置为模式指定自定义系统提示文件。提示文件应包含特定于该模式用途的指令。 + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +该路徑是相对于配置文件所在位置的。所以这適用于 +全局opencode配置和项目特定配置。 + +--- + +### 工具 + +使用 `tools` 配置控制模式下可用的工具。您可以通过将特定工具设置为 `true` 或 `false` 来启用或禁用特定工具。 + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +如果未指定任何工具,则默認启用所有工具。 + +--- + +#### 可用工具 + +这裡是所有可以通过模式配置控制的工具。 + +| 工具 | 描述 | +| ----------- | ---------------- | +| `bash` | 执行shell命令 | +| `edit` | 修改现有文件 | +| `write` | 创建新文件 | +| `read` | 读取文件内容 | +| `grep` | 搜索文件内容 | +| `glob` | 按模式查找文件 | +| `list` | 上市目录内容 | +| `patch` | 对文件应用补丁 | +| `todowrite` | 管理待办事项列表 | +| `todoread` | 阅读待办事项列表 | +| `webfetch` | 获取网页内容 | + +--- + +## 自定义模式 + +您可以通过将自定義模式添加到配置來创建自己的自定義模式。以下是使用这两种方法的示例: + +### 使用 JSON 配置 + +```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 + } + } + } +} +``` + +### 使用 Markdown 文件 + +在`.opencode/modes/`中为项目特定模式创建模式文件,在`~/.config/opencode/modes/`中为全局模式创建模式文件: + +```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 +``` + +--- + +### 使用案例 + +以下是不同模式的一些常見用例。 + +- **构建模式**:启用所有工具的完整開發工作 +- **计划模式**:分析和計劃,無需更改 +- **审阅模式**:使用只讀访问权限和文档工具進行代碼审阅 +- **调试模式**:专注于启用bash和读取工具的调查 +- **文档模式**:使用文件操作但不使用系統命令的文档編寫 + +您可能还会發現不同的模型適用于不同的用例。 diff --git a/packages/web/src/content/docs/zh-cn/network.mdx b/packages/web/src/content/docs/zh-cn/network.mdx new file mode 100644 index 00000000000..f64d099c653 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/network.mdx @@ -0,0 +1,57 @@ +--- +title: 网络 +description: 配置代理和自定義證書。 +--- + +opencode支持企业网络环境的标准代理环境变量和自定义证书。 + +--- + +## 代理 + +opencode 尊重标准代理环境变量。 + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +TUI 与本地 HTTP 服务器通信。您必须绕过此连接的代理以防止路由循环。 +::: + +您可以使用[CLI 标志](/docs/cli#run)配置服务器的端口和主机名。 + +--- + +### 认证 + +如果您的代理需要基本身份验证,请在 URL 中包含凭据。 + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +避免对密碼進行硬編碼。使用環境變量或安全憑證存儲。 +::: + +对于需要高级身份验证(例如 NTLM 或 Kerberos)的代理,请考虑使用支持您的身份验证方法的 LLM 网关。 + +--- + +## 自定义证书 + +如果您的企业使用自定义 CA 进行 HTTPS 连接,请配置 opencode 以信任它们。 + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +这适用于代理连接和直接 API 访问。 diff --git a/packages/web/src/content/docs/zh-cn/permissions.mdx b/packages/web/src/content/docs/zh-cn/permissions.mdx new file mode 100644 index 00000000000..47f7ef95dfe --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: 权限 +description: 控制哪些操作需要批准才能運行。 +--- + +opencode 使用`permission` 配置来决定给定的操作是否应自动运行、提示您或被阻止。 + +从 `v1.1.1` 开始,旧版配置 `tools` 布尔已被废弃,并已合并到 `permission` 中。仍支持旧版的 `tools` 配置以实现平滑兼容。 + +--- + +## 动作 + +每个权限规则解析为以下之一: + +- `"allow"` — 尚未批准运行 +- `"ask"` — 提示批准 +- `"deny"` — 阻止该操作 + +--- + +## 配置 + +您可以全局设置权限(使用`*`),并覆盖特定工具。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +您还可以一次设置所有权限: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## 粒度规则(对象语法) + +对于大多數权限,您可以使用对像根據工具輸入应用不同的操作。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +规则通过模式匹配進行評估,**最后匹配的规则獲勝**。常見的模式是将包羅万象的 `"*"` 规则放在前面,然後再放置更具體的规则。 + +### 通配符 + +权限模式使用簡單的通配符匹配: + +- `*` 匹配零个或多个任意字符 +- `?` 恰好匹配一个字符 +- 所有其他字符均按字面意思匹配 + +### 主目录扩展 + +您可以在模式目录中使用 `~` 或 `$HOME` 来引用您的主目录。这对于 [`external_directory`](#external-directories) 规则特别有用。 + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### 外部目录 + +使用 `external_directory` 允许工具调用启动 opencode 的工作目录之外的路径。这适用于任何采用路径作为输入的工具(例如 `read`、`edit`、`list`、`glob`、`grep` 和许多Z`bash` 命令)。 + +主扩展(如`~/...`)仅影响模式的编写方式。它不会使外部路径成为当前工作空间的一部分,因此仍然必须通过 `external_directory` 允许工作目录之外的路径。 + +例如,这允许访问`~/projects/personal/`下的所有内容: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +这里允许的任何目录都会继承与当前工作空间默认相同的值。自[`read`默认为`allow`](#defaults)起,也允许读取`external_directory`下面的边界,除非被覆盖。当工具应在这些路径中时添加显式规则,例如在保留读取的同时阻止编辑: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +将列表重点放在受信任的路径上,并根据其他工具的需要分层额外的允许或拒绝规则(例如`bash`)。 + +--- + +## 可用权限 + +opencode权限由工具名称和一些安全防护措施决定: + +- `read` — 读取文件(与文件路径匹配) +- `edit` — 所有文件修改(头部`edit`、`write`、`patch`、`multiedit`) +- `glob` — 文件通配符(匹配通配符模式) +- `grep` — 内容搜索(匹配正则表达式模式) +- `list` — 上市目录中的文件(与目录路径匹配) +- `bash` — 运行 shell 命令(匹配 `git status --porcelain` 等解析命令) +- `task` — 启动子代理(与子代理类型匹配) +- `skill` — 加载技能(与技能名称匹配) +- `lsp` — 运行 LSP 查询(当前非粒度) +- `todoread`、`todowrite` — 讀取/更新待辦事項列表 +- `webfetch` — 获取 URL(与 URL 匹配) +- `websearch`、`codesearch` — 網頁/代碼搜索(与查询匹配) +- `external_directory` — 当工具访问项目工作目录外部的路径时触发 +- `doom_loop` — 当相同的工具调用相同的输入重复 3 次时触发 + +--- + +## 默认值 + +如果您未指定任何内容,opencode分散许可的默认值开始: + +- 大部分权限默认为`"allow"`。 +- `doom_loop`和`external_directory`默认为`"ask"`。 +- `read` 是 `"allow"`,但 `.env` 文件默认被拒绝: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## “询问”的作用是什么 + +当 opencode 提示批准时,UI 会提供清晰的结果: + +- `once` — 仅批准此请求 +- `always` — 批准与建议模式匹配的未来请求(对于当前 opencode 会话的其余部分) +- `reject` — 拒绝请求 + +`always` 将批准的模式集由该工具提供(例如,bash 批准通常将安全端口(如 `git status*`)列入白名单)。 + +--- + +## 代理 + +您可以覆盖每个代理的权限。代理权限与全局​​配置合并,代理规则优先。 [了解更多](/docs/agents#permissions)关于代理权限。 + +:::note +有关更详细的模式匹配示例,请参见上面的 [粒度规则(对象语法)](#granular-rules-object-syntax) 部分。 +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +您还可以在 Markdown 中配置代理权限: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +对参数的命令使用模式匹配。 `"grep *"` 允许 `grep pattern file.txt`,而 `"grep"` 单独会阻止它。像 `git status` 这样的命令适用于默认行为,但在传递参数时需要显式许可(如 `"git status *"`)。 +::: diff --git a/packages/web/src/content/docs/zh-cn/plugins.mdx b/packages/web/src/content/docs/zh-cn/plugins.mdx new file mode 100644 index 00000000000..3a4a80753c2 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/plugins.mdx @@ -0,0 +1,385 @@ +--- +title: 插件 +description: 编写您自己的插件来扩展 opencode。 +--- + +插件允许您通过挂钩各种事件和自定义行为来扩展 opencode。您可以创建插件来添加新功能、与外部服务集成或修改 opencode 的默认行为。 + +例如,查看社区创建的[插件](/docs/ecosystem#plugins)。 + +--- + +## 使用插件 + +有两种加載插件的方法。 + +--- + +### 从本地文件 + +将 JavaScript 或 TypeScript 文件放置在插件目录中。 + +- `.opencode/plugins/` - 项目级插件 +- `~/.config/opencode/plugins/` - 全局插件 + +这些目录中的文件会在启动時自动加載。 + +--- + +### 来自 npm + +在配置文件中指定 npm 包。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +支持常规和范围的 npm 包。 + +浏览[生态系统](/docs/ecosystem#plugins)中的可用插件。 + +--- + +### 插件是如何安装的 + +**npm 插件** 在启动时使用 Bun 自动安装。包及其依赖项缓存在 `~/.cache/opencode/node_modules/` 中。 + +**本地插件**直接从插件目录加载。要使用外部包,您必须在配置目录中创建`package.json`(请参阅[依赖关系](#dependencies)),或将插件发布到npm和[将其添加到您的配置中](/docs/config#plugins)。 + +--- + +### 加载顺序 + +插件從所有源加載,所有掛鉤按顺序運行。加載顺序为: + +1. 全局配置 (`~/.config/opencode/opencode.json`) +2. 项目配置(`opencode.json`) +3. 插件全局目录 (`~/.config/opencode/plugins/`) +4. 项目插件目录(`.opencode/plugins/`) + +具有相同的名称和版本,但是重复的 npm 包将被加载一次。,本地插件和名称相似的 npm 插件都是分开加载的。 + +--- + +## 创建一个插件 + +插件是一个 **JavaScript/TypeScript 模块多个**,它导出一个或插件 +功能。每个函數接收一个上下文对象并返回一个鉤子对象。 + +--- + +### 依赖关系 + +本地插件和自定义工具可以使用外部 npm 包。将 `package.json` 添加到您的配置目录,其中包含您需要的依赖项。 + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +opencode 在启动时运行 `bun install` 来安装这些。然后你的插件和工具就可以导入它们了。 + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### 基本结构 + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +插件函數接收: + +- `project`:当前项目信息。 +- `directory`:当前工作目录。 +- `worktree`:git 工作树路径。 +- `client`:用于与AI交互的opencodeSDK客户端。 +- `$`:Bun的[外壳API](https://bun.com/docs/runtime/shell)用于执行命令。 + +--- + +### TypeScript 支持 + +对于 TypeScript 插件,您可以从插件包中导入类型: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### 事件 + +插件可以訂閱事件,如下面的示例部分所示。以下是可用的不同事件的列表。 + +#### 命令事件 + +- `command.executed` + +#### 文件事件 + +- `file.edited` +- `file.watcher.updated` + +#### 安装事件 + +- `installation.updated` + +#### LSP 事件 + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### 消息事件 + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### 权限事件 + +- `permission.asked` +- `permission.replied` + +#### 服务器事件 + +- `server.connected` + +#### 会话事件 + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### 待办事项事件 + +- `todo.updated` + +#### Shell 事件 + +- `shell.env` + +#### 工具事件 + +- `tool.execute.after` +- `tool.execute.before` + +#### TUI 事件 + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## 示例 + +以下是一些可用于扩展 opencode 的插件示例。 + +--- + +### 发送通知 + +当某些事件發生時發送通知: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +我们在 macOS 上使用 `osascript` AppleScript。这里我们用它运行来发送通知。 + +:::note +如果您使用 opencode 桌面应用程序,它可以在响应准备就绪或会话错误时自动发送系统通知。 +::: + +--- + +### .env 保护 + +阻止opencode读取`.env`文件: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### 注入环境变量 + +将环境变量注入所有shell执行(AI工具和用户终端): + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### 自定义工具 + +插件还可以向 opencode 添加自定义工具: + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +`tool` 帮助器创建一个可以调用的自定义工具的opencode。它采用 Zod 模式函数并返回一个工具定义: + +- `description`:该工具的作用 +- `args`:Zod 模式的工具参数 +- `execute`:调用工具时运行的函数 + +您的自定義工具将可与内置工具一起用于opencode。 + +--- + +### 日志 + +使用 `client.app.log()` 而不是 `console.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` 内存将被忽略。 diff --git a/packages/web/src/content/docs/zh-cn/providers.mdx b/packages/web/src/content/docs/zh-cn/providers.mdx new file mode 100644 index 00000000000..b9b35d6195f --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/providers.mdx @@ -0,0 +1,1888 @@ +--- +title: 提供商 +description: 在 opencode 中使用任意 LLM 提供商。 +--- + +import config from "../../../../config.mjs" +export const console = config.console + +opencode 使用 [AI SDK](https://ai-sdk.dev/) 和 [Models.dev](https://models.dev),支持 **75+ LLM 提供商**,也支持运行本地模型。 + +要添加提供商,你需要: + +1. 使用 `/connect` 命令添加提供商的 API 密钥。 +2. 在 opencode 配置中设置该提供商。 + +--- + +### 凭据 + +当你使用 `/connect` 命令添加提供商 API 后,凭据会存储在 +`~/.local/share/opencode/auth.json`。 + +--- + +### 配置 + +你可以使用 opencode 配置中的 `provider` 部分自定义提供商配置。 + +--- + +#### 基本网址 + +您可以通过设置 `baseURL` 选项来自定义任何提供商的基本 URL。这在使用代理服务或自定义端点时非常有用。 + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen 是opencode团队提供的模型列表,这些模型已被 +经测试和验证可与opencode良好配合。 [了解更多](/docs/zen)。 + +:::tip +如果您是新手,我们建议您从 OpenCode Zen 开始。 +::: + +1. Run the `/connect` command in the TUI, select opencode, and head to [opencode.ai/auth](https://opencode.ai/auth). + + ```txt + /connect + ``` + +2. 登录,添加您的账单详细信息,然后复制您的 API 密钥。 + +3. 贴上您的 API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 在 TUI 中执行 `/models` 以查看我们推荐的模型列表。 + + ```txt + /models + ``` + +它的工作方式与 opencode 中的任何其他提供的程序相同,并且完全可以选择使用。 + +--- + +## 目录 + +讓我们詳細瞭解一些提供商。如果您想将提供商添加到 +列表,请随时开启PR。 + +:::note +没看到你要的提供商?欢迎提交 PR。 +::: + +--- + +### 302.AI + +1. Head over to the [302.AI console](https://302.ai/), create an account, and generate an API key. + +2. 执行`/connect`命令并搜索**302.AI**。 + + ```txt + /connect + ``` + +3. 输入您的 302.AI API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令选择模型。 + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +相当于 Amazon Bedrock 与 opencode 结合使用: + +1. 前往 Amazon Bedrock 控制台中的 **模型目录** 并请求 + 访问您想要的模型。 + + :::提示 + 您需要能够在 Amazon Bedrock 中访问所需的模型。 + ::: + +2. **使用以下方法之一配置身份验证**: + + #### 环境变量(快速启动) + + 执行 opencode 时设置以下环境变量之一: + + ```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode + ``` + + 或者将它们添加到您的 bash 配置文件中: + + ```bash title="~/.bash_profile" + export AWS_PROFILE=my-dev-profile + export AWS_REGION=us-east-1 + ``` + + #### 配置文件(推薦) + + For project-specific or persistent configuration, use `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` 选项的别名) + + :::提示 + 配置文件選項优先于环境变量。 + ::: + + #### 高阶: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" + } + } + } + } + ``` + + :::笔记 + `endpoint` 选项是通用 `baseURL` 选项的别名,使用 AWS 术语特定。如果同时指定了 `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 自动注入。 + + #### 認證优先顺序 + + Amazon Bedrock 使用以下身份验证优先顺序: + 1. **不记名Tokens** - `AWS_BEARER_TOKEN_BEDROCK`环境变化数据或来自`/connect`Tokens的Tokens + 2. **AWS 凭证链** - 配置档案、访问密钥、共享凭证、IAM 角色、Web 身份Tokens (EKS IRSA)、实例项后设置资料 + + :::笔记 + 设置不记名Tokens(使用 `/connect` 或 `AWS_BEARER_TOKEN_BEDROCK`)时,其优先于所有 AWS 凭证方法(包括配置的配置文件)。 + ::: + +3. 执行`/models`命令选择所需的模型。 + + ```txt + /models + ``` + +:::note +对于自定义推理配置文件,请在按键中使用模型并提供商名称,并将 `id` 属性设置为 arn。这确保了正确的缓存: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. 注册后,执行`/connect`命令并选择Anthropic。 + + ```txt + /connect + ``` + +2. 您可以在此处选择 **Claude Pro/Max** 选项,就会打开您的浏览器 + 并要求您进行身份验证。 + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. 现在,当您使用 `/models` 命令时,所有人类模型都应该可用。 + + ```txt + /models + ``` + +:::info +Using your Claude Pro/Max subscription in opencode is not officially supported by [Anthropic](https://anthropic.com). +::: + +##### 使用 API 键 + +如果您没有 Pro/Max 订阅,您还可以选择 **创建 API 密钥**。它还会开启您的浏览器并要求您登录 Anthropic 并为您提供一个可以粘贴到终端中的代码。 + +或者,如果您已安装 API 密钥,则可以选择 **手动输入 API 密钥** 将其贴到终端中。 + +--- + +### Azure OpenAI + +:::note +如果遇到“抱歉,但我无法协助该请求”错误,请尝试将 Azure 资源中的内容筛选器从 **DefaultV2** 更改为 **Default**。 +::: + +1. Head over to the [Azure portal](https://portal.azure.com/) and create an **Azure OpenAI** resource. You'll need: + - **资源名称**:这将成为您的 API 端点 (`https://RESOURCE_NAME.openai.azure.com/`) 的一部分 + - **API 密钥**:来自您资源的 `KEY 1` 或 `KEY 2` + +2. Go to [Azure AI Foundry](https://ai.azure.com/) and deploy a model. + + :::笔记 + 部署名称必须与模型名称匹配,opencode才能正常工作。 + ::: + +3. 执行 `/connect` 命令并搜索 **Azure**。 + + ```txt + /connect + ``` + +4. 输入您的 API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. 将您的资源名称设置为环境变量: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + 或者将其添加内容添加到您的 bash 配置文件中: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. 执行 `/models` 命令以选择您部署的模型。 + + ```txt + /models + ``` + +--- + +### Azure 认知服务 + +1. Head over to the [Azure portal](https://portal.azure.com/) and create an **Azure OpenAI** resource. You'll need: + - **资源名称**:这将成为您的 API 端点 (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) 的一部分 + - **API 密钥**:来自您资源的 `KEY 1` 或 `KEY 2` + +2. Go to [Azure AI Foundry](https://ai.azure.com/) and deploy a model. + + :::笔记 + 部署名称必须与模型名称匹配,opencode才能正常工作。 + ::: + +3. 执行 `/connect` 命令并搜索 **Azure 认知服务**。 + + ```txt + /connect + ``` + +4. 输入您的 API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. 将您的资源名称设置为环境变量: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + 或者将其添加内容添加到您的 bash 配置文件中: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. 执行 `/models` 命令以选择您部署的模型。 + + ```txt + /models + ``` + +--- + +### Baseten + +1. Head over to the [Baseten](https://app.baseten.co/), create an account, and generate an API key. + +2. 执行 `/connect` 命令并搜索 **Baseten**。 + + ```txt + /connect + ``` + +3. 输入您的 Baseten API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令选择模型。 + + ```txt + /models + ``` + +--- + +### Cerebras + +1. Head over to the [Cerebras console](https://inference.cerebras.ai/), create an account, and generate an API key. + +2. 执行 `/connect` 命令并搜索 **Cerebras**。 + + ```txt + /connect + ``` + +3. 输入您的 Cerebras API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令选择*Qwen 3 Coder 480B*等模型。 + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +Cloudflare AI Gateway lets you access models from OpenAI, Anthropic, Workers AI, and more through a unified endpoint. With [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) you don't need separate API keys for each provider. + +1. Head over to the [Cloudflare dashboard](https://dash.cloudflare.com/), navigate to **AI** > **AI Gateway**, and create a new gateway. + +2. 将您的账户ID和闸道器ID设定为环境变量。 + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. 执行 `/connect` 命令并搜索 **Cloudflare AI Gateway**。 + + ```txt + /connect + ``` + +4. 输入您的 Cloudflare API Tokens。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + 或者将其设置为环境变量。 + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. 执行`/models`命令选择模型。 + + ```txt + /models + ``` + + 您还可以使用opencode配置添加模型。 + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +### Cortecs + +1. Head over to the [Cortecs console](https://cortecs.ai/), create an account, and generate an API key. + +2. 执行 `/connect` 命令并搜索 **Cortecs**。 + + ```txt + /connect + ``` + +3. 输入您的 Cortecs API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行 `/models` 命令以选择类似 _Kimi K2 Instruct_ 的模型。 + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. Head over to the [DeepSeek console](https://platform.deepseek.com/), create an account, and click **Create new API key**. + +2. 执行 `/connect` 命令并搜索 **DeepSeek**。 + + ```txt + /connect + ``` + +3. 输入您的 DeepSeek API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令以选择DeepSeek模型,例如*DeepSeek Reasoner*。 + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. Head over to the [Deep Infra dashboard](https://deepinfra.com/dash), create an account, and generate an API key. + +2. 执行 `/connect` 命令并搜索 **Deep Infra**。 + + ```txt + /connect + ``` + +3. 输入您的深层基础设施 API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令选择模型。 + + ```txt + /models + ``` + +--- + +### Firmware + +1. Head over to the [Firmware dashboard](https://app.firmware.ai/signup), create an account, and generate an API key. + +2. 执行`/connect`命令并搜索**韧体**。 + + ```txt + /connect + ``` + +3. 输入您的韧体API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令选择模型。 + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. Head over to the [Fireworks AI console](https://app.fireworks.ai/), create an account, and click **Create API Key**. + +2. 执行 `/connect` 命令并搜索 **Fireworks AI**。 + + ```txt + /connect + ``` + +3. 输入您的 Fireworks AI API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行 `/models` 命令以选择类似 _Kimi K2 Instruct_ 的模型。 + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo 通过 GitLab 的人工代理提供具有本机工具呼叫功能的人工智慧代理聊天。 + +1. 执行`/connect`命令并选择GitLab。 + + ```txt + /connect + ``` + +2. 选择您的身份验证方法: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + └ + ``` + + #### 使用OAuth(推荐) + + 选择**OAuth**,您的浏览器将开启并进行授权。 + + #### 使用个人访问Tokens + 1. Go to [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens) + 2. 单击**添加新Tokens** + 3. Name: `OpenCode`, Scopes: `api` + 4. 复制Tokens(以 `glpat-` 发起人) + 5. 在终端中輸入 + +3. 执行 `/models` 命令查看可用模型。 + + ```txt + /models + ``` + + 提供基于 Claude 的模型: + - **duo-chat-haiku-4-5**(默认)- 快速任务的快速响应 + - **duo-chat-sonnet-4-5** - 大多数工作流程的平衡失败 + - **duo-chat-opus-4-5** - 最有能力进行复杂分析 + +:::note +如果您不愿意,也可以指定“GITLAB_TOKEN”环境变量 +将Tokens存储在opencode身份验证存储中。 +::: + +##### 自托管 GitLab + +:::note[合规笔记] +opencode 使用一个小模型来执行一些 AI 任务,例如生成会话标题。 +情况下,其配置为使用 gpt-5-nano,由 Zen 托管。默认 opencode +只需使用您自己的 GitLab 托管示例项,即可将以下内容添加到您的 +`opencode.json` file. It is also recommended to disable session sharing. + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +对于自托管 GitLab 示例项目: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +如果您的示例项执行自定义AI闸道器: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +或者添加到您的 bash 配置文件中: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +您的 GitLab 管理员必须启用以下功能: + +1. [Duo Agent Platform](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) for the user, group, or instance +2. 功能标志(通过Rails控制台): + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: + +##### 用于自托管项目的 OAuth + +为了使 Oauth 适用于您的自托管项目,您需要建立 +一个新的应用程序(设置→应用程序) +回调 URL `http://127.0.0.1:8080/callback` 和以下范围: + +- api(您代表访问API) +- read_user(读取您的个人信息) +- read_repository(允许对存储库进行只读访问) + +然后将应用程序ID公开为环境变量: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +More documentation on [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth) homepage. + +##### 配置 + +Customize through `opencode.json`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### GitLab API 工具(可选,但强烈推荐) + +要访问GitLab工具(合并请求、问题、管道、CI/CD等): + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +该外挂提供全面的GitLab存储库管理功能,包括MR审查、问题跟踪、管道监控等。 + +--- + +### GitHub Copilot + +相当于您的 GitHub Copilot 订阅与 opencode 一起使用: + +:::note +某些模型可能需要 [Pro+ +订阅](https://github.com/features/copilot/plans)使用。 + +Some models need to be manually enabled in your [GitHub Copilot settings](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use). +::: + +1. 执行 `/connect` 命令并搜索 GitHub Copilot。 + + ```txt + /connect + ``` + +2. Navigate to [github.com/login/device](https://github.com/login/device) and enter the code. + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + └ Waiting for authorization... + ``` + +3. 现在执行 `/models` 命令来选择您想要的模型。 + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +Google Vertex AI 与 opencode 结合使用: + +1. 前往 Google Cloud Console 中的 **模型花园** 并检查 + 您所在地区提供的模型。 + + :::笔记 + 您需要有一个启用了 Vertex AI API 的 Google Cloud 专案。 + ::: + +2. 设置所需的环境变量: + - `GOOGLE_CLOUD_PROJECT`:您的Google云专案ID + - `VERTEX_LOCATION`(可选):Vertex AI的区域(默认为`global`) + - 身份验证(选择一項): + - `GOOGLE_APPLICATION_CREDENTIALS`:服务帐户 JSON 密钥文件的路径 + - 使用 gcloud CLI 进行身份验证:`gcloud auth application-default login` + + 在执行 opencode 时设置它们。 + + ```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode + ``` + + 或者将它们添加到您的 bash 配置文件中。 + + ```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 +The `global` region improves availability and reduces errors at no extra cost. Use regional endpoints (e.g., `us-central1`) for data residency requirements. [Learn more](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. 执行`/models`命令选择所需的模型。 + + ```txt + /models + ``` + +--- + +### Groq + +1. Head over to the [Groq console](https://console.groq.com/), click **Create API Key**, and copy the key. + +2. 执行 `/connect` 命令并搜索 Groq。 + + ```txt + /connect + ``` + +3. 输入结构的API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令来选择您想要的。 + + ```txt + /models + ``` + +--- + +### Hugging Face + +[Hugging Face Inference Providers](https://huggingface.co/docs/inference-providers) provides access to open models supported by 17+ providers. + +1. Head over to [Hugging Face settings](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained) to create a token with permission to make calls to Inference Providers. + +2. 执行 `/connect` 命令并搜索 **拥抱脸**。 + + ```txt + /connect + ``` + +3. 輸入您的擁抱臉標記。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令选择*Kimi-K2-Instruct* 或 _GLM-4.6_ 等模型。 + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) is an LLM observability platform that provides logging, monitoring, and analytics for your AI applications. The Helicone AI Gateway routes your requests to the appropriate provider automatically based on the model. + +1. Head over to [Helicone](https://helicone.ai), create an account, and generate an API key from your dashboard. + +2. 执行 `/connect` 命令并搜索 **Helicone**。 + + ```txt + /connect + ``` + +3. 输入您的 Helicone API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令选择模型。 + + ```txt + /models + ``` + +For more providers and advanced features like caching and rate limiting, check the [Helicone documentation](https://docs.helicone.ai). + +#### 可選配置 + +如果您发现Helicone的某些功能或模型未通过opencode自动配置,您始终可以自行配置。 + +Here's [Helicone's Model Directory](https://helicone.ai/models), you'll need this to grab the IDs of the models you want to add. + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### 自定義標頭 + +Helicone 支持快速获取、用户跟踪和会话管理等功能的自定义标头。使用 `options.headers` 将它们添加到您提供的方案配置中: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### 会话跟蹤 + +Helicone's [Sessions](https://docs.helicone.ai/features/sessions) feature lets you group related LLM requests together. Use the [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) plugin to automatically log each opencode conversation as a session in Helicone. + +```bash +npm install -g opencode-helicone-session +``` + +将其添加到您的配置中。 + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +该外挂将 `Helicone-Session-Id` 和 `Helicone-Session-Name` 标头注入您的请求中。在 Helicone 的会话页面中,您将看到每个 opencode 对话都是单独的会话。 + +##### 常见螺旋接头 + +| 標題 | 描述 | +| -------------------------- | ----------------------------------------------------- | +| `Helicone-Cache-Enabled` | Enable response caching (`true`/`false`) | +| `Helicone-User-Id` | 点击用户跟踪指标 | +| `Helicone-Property-[Name]` | 添加自定义属性(例如`Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | 将请求与提示版本相关联 | + +See the [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory) for all available headers. + +--- + +### llama.cpp + +You can configure opencode to use local models through [llama.cpp's](https://github.com/ggml-org/llama.cpp) llama-server utility + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +在这个例子中: + +- `llama.cpp` 是自定义创建 ID。这可以是您想要的任何字符串。 +- `npm` specifies the package to use for this provider. Here, `@ai-sdk/openai-compatible` is used for any OpenAI-compatible API. +- `name` 是 UI 中提供商的显示名称。 +- `options.baseURL` 是本地服务器器的端点。 +- `models` 是模型 ID 以及配置的对应映射。模型名称将显示在模型选择列表中。 + +--- + +### IO.NET + +IO.NET提供了17种针对各种例子进行优化的模型: + +1. Head over to the [IO.NET console](https://ai.io.net/), create an account, and generate an API key. + +2. 执行`/connect`命令并搜索**IO.NET**。 + + ```txt + /connect + ``` + +3. 输入您的 IO.NET API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令选择模型。 + + ```txt + /models + ``` + +--- + +### LM Studio + +您可以通过使用本地模型来使用 LM Studio 配置opencode。 + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +在这个例子中: + +- `lmstudio` 是自定义创建 ID。这可以是您想要的任何字符串。 +- `npm` specifies the package to use for this provider. Here, `@ai-sdk/openai-compatible` is used for any OpenAI-compatible API. +- `name` 是 UI 中提供商的显示名称。 +- `options.baseURL` 是本地服务器器的端点。 +- `models` 是模型 ID 以及配置的对应映射。模型名称将显示在模型选择列表中。 + +--- + +### Moonshot AI + +要使用 Moonshot AI 中的 Kimi K2: + +1. Head over to the [Moonshot AI console](https://platform.moonshot.ai/console), create an account, and click **Create API key**. + +2. 执行 `/connect` 命令并搜索 **Moonshot AI**。 + + ```txt + /connect + ``` + +3. 输入您的 Moonshot API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令以选择*Kimi K2*。 + + ```txt + /models + ``` + +--- + +### MiniMax + +1. Head over to the [MiniMax API Console](https://platform.minimax.io/login), create an account, and generate an API key. + +2. 执行 `/connect` 命令并搜索 **MiniMax**。 + + ```txt + /connect + ``` + +3. 输入您的 MiniMax API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令选择*M2.1*等模型。 + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. Head over to the [Nebius Token Factory console](https://tokenfactory.nebius.com/), create an account, and click **Add Key**. + +2. 执行`/connect`命令并搜索**NebiusTokens工厂**。 + + ```txt + /connect + ``` + +3. 输入您的 Nebius Tokens工厂 API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行 `/models` 命令以选择类似 _Kimi K2 Instruct_ 的模型。 + + ```txt + /models + ``` + +--- + +### Ollama + +您可以使用 Ollama 配置 opencode 本地模型。 + +:::tip +Ollama can automatically configure itself for opencode. See the [Ollama integration docs](https://docs.ollama.com/integrations/opencode) for details. +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +在这个例子中: + +- `ollama` 是自定义创建 ID。这可以是您想要的任何字符串。 +- `npm` specifies the package to use for this provider. Here, `@ai-sdk/openai-compatible` is used for any OpenAI-compatible API. +- `name` 是 UI 中提供商的显示名称。 +- `options.baseURL` 是本地服务器器的端点。 +- `models` 是模型 ID 以及配置的对应映射。模型名称将显示在模型选择列表中。 + +:::tip +如果工具暂停,请尝试增加 Ollama 中的 `num_ctx`。从 16k - 32k 左右开始。 +::: + +--- + +### Ollama Cloud + +相当于 Ollama Cloud 与 opencode 一起使用: + +1. 前往 [https://ollama.com/](https://ollama.com/) 并登录或建立账户。 + +2. 导航至**设置** > **API 密钥**,然后单击**添加API 密钥**以生成新的API 密钥。 + +3. 复制 API 密钥以在 opencode 中使用。 + +4. 执行 `/connect` 命令并搜索 **Ollama Cloud**。 + + ```txt + /connect + ``` + +5. 输入您的 Ollama Cloud API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **重要**:在opencode中使用云模型之前,必须将模型信息拉取到本地: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. 执行 `/models` 命令以选择您的 Ollama Cloud 模型。 + + ```txt + /models + ``` + +--- + +### OpenAI + +We recommend signing up for [ChatGPT Plus or Pro](https://chatgpt.com/pricing). + +1. 注册后,执行`/connect`命令并选择OpenAI。 + + ```txt + /connect + ``` + +2. 您可以选择 **ChatGPT Plus 或 Pro** 选项,就会在这里开启您的浏览器 + 并要求您进行身份验证。 + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. 现在,当您使用 `/models` 命令时,所有 OpenAI 模型都应该可用。 + + ```txt + /models + ``` + +##### 使用 API 键 + +如果您已安装 API 密钥,则可以选择 **手动输入 API 密钥** 将其贴到终端中。 + +--- + +### OpenCode Zen + +OpenCode Zen 是 opencode 团队提供的经过测试和验证的模型列表。 [了解更多](/docs/zen)。 + +1. 登录 **OpenCode Zen** 并单击 **创建 API 密钥**。 + +2. 执行 `/connect` 命令并搜索 **OpenCode Zen**。 + + ```txt + /connect + ``` + +3. 输入您的 opencode API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令选择*Qwen 3 Coder 480B*等模型。 + + ```txt + /models + ``` + +--- + +### OpenRouter + +1. Head over to the [OpenRouter dashboard](https://openrouter.ai/settings/keys), click **Create API Key**, and copy the 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跨统一平台提供对OpenAI、Anthropic、Google、Amazon、Meta、Mistral和AI21的40多个模型的访问。 + +1. Go to your [SAP BTP Cockpit](https://account.hana.ondemand.com/), navigate to your SAP AI Core service instance, and create a service key. + + :::提示 + The service key is a JSON object containing `clientid`, `clientsecret`, `url`, and `serviceurls.AI_API_URL`. You can find your AI Core instance under **Services** > **Instances and Subscriptions** in the 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 配置文件中: + + ```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' + ``` + +4. (可选)设置部署ID和资源组: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::笔记 + 这些设置是可选的,应根据 SAP AI Core 设置进行配置。 + ::: + +5. 执行 `/models` 命令从 40 个多个可用模型中进行选择。 + + ```txt + /models + ``` + +--- + +### OVHcloud AI Endpoints + +1. Head over to the [OVHcloud panel](https://ovh.com/manager). Navigate to the `Public Cloud` section, `AI & Machine Learning` > `AI Endpoints` and in `API Keys` tab, click **Create a new API key**. + +2. 执行 `/connect` 命令并搜索 **OVHcloud AI 端点**。 + + ```txt + /connect + ``` + +3. 输入您的 OVHcloud AI 端点 API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令选择*gpt-oss-120b*等模型。 + + ```txt + /models + ``` + +--- + +### Scaleway + +To use [Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/) with Opencode: + +1. Head over to the [Scaleway Console IAM settings](https://console.scaleway.com/iam/api-keys) to generate a new API key. + +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. Head over to the [Together AI console](https://api.together.ai), create an account, and click **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. Head over to the [Venice AI console](https://venice.ai), create an account, and generate an API key. + +2. 执行 `/connect` 命令并搜索 **Venice AI**。 + + ```txt + /connect + ``` + +3. 输入您的威尼斯 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. Head over to the [Vercel dashboard](https://vercel.com/), navigate to the **AI Gateway** tab, and click **API keys** to create a new API key. + +2. 执行 `/connect` 命令并搜索 **Vercel AI Gateway**。 + + ```txt + /connect + ``` + +3. 输入您的 Vercel AI 网关 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. Head over to the [xAI console](https://console.x.ai/), create an account, and generate an API key. + +2. 执行 `/connect` 命令并搜索 **xAI**。 + + ```txt + /connect + ``` + +3. 输入您的 xAI API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行 `/models` 命令来选择类似 _Grok Beta_ 的模型。 + + ```txt + /models + ``` + +--- + +### Z.AI + +1. Head over to the [Z.AI API console](https://z.ai/manage-apikey/apikey-list), create an account, and click **Create a new API key**. + +2. 执行 `/connect` 命令并搜索 **Z.AI**。 + + ```txt + /connect + ``` + + 如果您订阅了**GLM编码计划**,请选择**Z.AI编码计划**。 + +3. 输入您的 Z.AI API 密钥。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 执行`/models`命令选择*GLM-4.7*等模型。 + + ```txt + /models + ``` + +--- + +### ZenMux + +1. Head over to the [ZenMux dashboard](https://zenmux.ai/settings/keys), click **Create API Key**, and copy the 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": {} + } + } + } + } + ``` + +--- + +## 自定义提供商 + +要添加 `/connect` 命令中未列出的任何 **OpenAI 兼容**提供商: + +:::tip +您可以将任何 OpenAI 兼容的提供商与 opencode 一起使用。大多数 AI 提供商都提供 OpenAI 兼容 API。 +::: + +1. 执行`/connect`命令并逐步升级到**其他**。 + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. 输入企业的唯一ID。 + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::笔记 + 选择一个容易记住的 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. Create or update your `opencode.json` file in your project directory: + + ```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兼容的事业 + - **名称**:UI中的显示名称。 + - **模型**:可用模型。 + - **options.baseURL**:API 端点 URL。 + - **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**:模型可以生成的最大Tokens。 + +`limit` 栏位允许 opencode 了解您还剩下多少上下文。标准提供商会自动从 models.dev 中提取这些内容。 + +--- + +## 故障排除 + +如果您在配置提供商時遇到問題,请检查以下內容: + +1. **Check the auth setup**: Run `opencode auth list` to see if the credentials + 提供商的配置已添加到您的配置中。 + + 这并不利于 Amazon Bedrock 等依赖环境变数进行身份验证的工作。 + +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/zh-cn/rules.mdx b/packages/web/src/content/docs/zh-cn/rules.mdx new file mode 100644 index 00000000000..c9135c2994d --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/rules.mdx @@ -0,0 +1,180 @@ +--- +title: 规则 +description: 设置opencode的自定義指令。 +--- + +您可以通过 `AGENTS.md` 文件创建 opencode 的自定义指令。这和 Cursor 的规则类似。它包含将包含在 LLM 上下文中的说明,方便您的特定项目自定义其行为。 + +--- + +## 初始化 + +要创建新的`AGENTS.md`文件,您可以在opencode中运行`/init`命令。 + +:::tip +您应该将项目的 `AGENTS.md` 文件提交到 Git。 +::: + +这将扫描您的项目及其所有内容,以了解该项目的内容并生成一个 `AGENTS.md` 文件。这有助于更好地打开代码导航项目。 + +如果您已有现有的 `AGENTS.md` 文件,将尝试添加到其中。 + +--- + +## 例子 + +您也可以手动创建此文件。以下是您可以导入 `AGENTS.md` 文件中的一些内容的示例。 + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +我们在此處添加特定于項目的說明,这将在您的團隊中共享。 + +--- + +## 类型 + +opencode 还支持从多个位置读取 `AGENTS.md` 文件。这有不同的目的。 + +### 项目 + +将 `AGENTS.md` 放置在项目根目录中以获取特定于项目的规则。这些仅适用于您在此目录或子目录中工作时。 + +### 全局 + +您还可以在 `~/.config/opencode/AGENTS.md` 文件中包含全局规则。这适用于所有opencode会话。 + +由于此未提交给 Git 或与您的团队共享,因此我们建议使用它来指定 LLM 应遵循的任何个人规则。 + +### 克勞德代碼兼容性 + +Error 500 (Server Error)!!1500.That’s an error.There was an error. Please try again later.That’s all we know. + +- **项目规则**:项目目录中的`CLAUDE.md`(如果`AGENTS.md`不存在则使用) +- **全局规则**:`~/.claude/CLAUDE.md`(如果不存在`~/.config/opencode/AGENTS.md`则使用) +- **技能**:`~/.claude/skills/` — 详情请参见[代理技巧](/docs/skills/) + +要取消Claude Code兼容性,请设置以下环境变量之一: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## 优先级 + +当opencode启动时,它会按以下顺序查找规则文件: + +1. **本地文件**,从当前目录向上浏览(`AGENTS.md`,`CLAUDE.md`) +2. **全局文件** `~/.config/opencode/AGENTS.md` +3. **克劳德代码文件**位于`~/.claude/CLAUDE.md`(禁用禁用) + +第一个匹配的文件每个在类别中触发。例如,如果您同时拥有`AGENTS.md`和`CLAUDE.md`,则仅使用`AGENTS.md`。同样,`~/.config/opencode/AGENTS.md`优先于`~/.claude/CLAUDE.md`。 + +--- + +## 自定义指令 + +您可以在 `opencode.json` 或全局 `~/.config/opencode/opencode.json` 中指定自定义指令文件。这允许您和您的团队重用现有规则,而不必将它们复制到 AGENTS.md。 + +例子: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +您还可以使用远程URL从Web加载说明。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +遠程指令的获取有 5 秒的超時時間。 + +所有说明文件均与您的`AGENTS.md`文件合并。 + +--- + +## 引用外部文件 + +虽然opencode不会自动解析`AGENTS.md`中的文件引用,但您可以通过两种方式实现类似的功能: + +### 使用 opencode.json + +推荐的方法是在`instructions`中使用`opencode.json`字段: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### AGENTS.md 中的手册说明 + +您可以通过在 `AGENTS.md` 中明确提供的指令来教 opencode 读取外部文件。这是一个实际的示例: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +这種方法允许您: + +- 创建模塊化、可重用的规则文件 +- 通过符号链接或git子模块在项目之间共享规则 +- 保持 AGENTS.md 简洁,同时参考详细指南 +- 确保opencode仅在特定任务需要时加载文件 + +:::tip +对于 monorepos 或具有共享标准的项目,使用 `opencode.json` 和 glob 模式(如 `packages/*/AGENTS.md`)比手动指令更易于维护。 +::: diff --git a/packages/web/src/content/docs/zh-cn/sdk.mdx b/packages/web/src/content/docs/zh-cn/sdk.mdx new file mode 100644 index 00000000000..0a8f63fa175 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: opencode 服务器的类型不同于安全 JS 客户端。 +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +opencode JS/TS SDK 提供类型其他安全的客户端用于与服务器交互。 +使用它以程序设计方式构建集成和控制opencode。 + +[了解更多关于服务器如何工作的](/docs/server)。例如,查看社区构建的[projects](/docs/ecosystem#projects)。 + +--- + +## 安装 + +从npm安装SDK: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## 创建客户端 + +创建opencode的示例项: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +这会同時启动服务器和客戶端 + +#### 选项 + +| 选项 | 型别 | 描述 | 默认 | +| ---------- | ------------- | ------------------------------ | ----------- | +| `hostname` | `string` | 服务器主机名 | `127.0.0.1` | +| `port` | `number` | 服务器埠 | `4096` | +| `signal` | `AbortSignal` | 取消的中止讯号 | `undefined` | +| `timeout` | `number` | 服务器启动超时(以毫秒为单位) | `5000` | +| `config` | `Config` | 放置的财产 | `{}` | + +--- + +## 配置 + +You can pass a configuration object to customize behavior. The instance still picks up your `opencode.json`, but you can override or add configuration inline: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## 仅限客户端 + +如果您已经有 opencode 的正在执行示例项,则可以创建一个客户端示例项来连线到它: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### 选项 + +| 选项 | 型别 | 描述 | 默认 | +| --------------- | ---------- | ---------------------------- | ----------------------- | +| `baseUrl` | `string` | 服务器的 URL | `http://localhost:4096` | +| `fetch` | `function` | 习俗获取实现 | `globalThis.fetch` | +| `parseAs` | `string` | 响应解析方法 | `auto` | +| `responseStyle` | `string` | 返回样式:`data` 或 `fields` | `fields` | +| `throwOnError` | `boolean` | 掷骰错误而不是返回 | `false` | + +--- + +## 类型 + +SDK 包括所有 API 型以外的 TypeScript 定义。直接汇入其中: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +所有型別均根據服务器的 OpenAPI 規範生成,并可在 型別文件 中找到。 + +--- + +## 错误 + +SDK 可能会丢掷错误,您可以捕获并处理这些错误: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## API + +SDK跨越型别安全客户端公开所有服务器API。 + +--- + +### 全局 + +| 方法 | 描述 | 回应 | +| ----------------- | ------------------------ | ------------------------------------ | +| `global.health()` | 检查服务器健康状况和版本 | `{ healthy: true, version: string }` | + +--- + +#### 示例 + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### 应用程序 + +| 方法 | 描述 | 回应 | +| -------------- | ------------------ | ------------------------------------------ | +| `app.log()` | 登录日志 | `boolean` | +| `app.agents()` | 列出所有可用的代理 | 代理[] | + +--- + +#### 示例 + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### 项目 + +| 方法 | 描述 | 回应 | +| ------------------- | ------------ | ------------------------------------------ | +| `project.list()` | 列出所有专案 | 专案[] | +| `project.current()` | 获取当前专案 | 专案 | + +--- + +#### 示例 + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### 路径 + +| 方法 | 描述 | 回应 | +| ------------ | ------------ | ---------------------------------------- | +| `path.get()` | 获取当前路徑 | 路徑 | + +--- + +#### 示例 + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### 配置 + +| 方法 | 描述 | 回应 | +| -------------------- | -------------------- | --------------------------------------------------------------------------------------------------- | +| `config.get()` | 获取配置資訊 | 配置 | +| `config.providers()` | 列出提供商和默认模型 | `{ providers: `提供商[]`, default: { [key: string]: string } }` | + +--- + +#### 示例 + +```javascript +const config = await client.config.get() + +const { providers, default: defaults } = await client.config.providers() +``` + +--- + +### 会话 + +| 方法 | 描述 | 筆記 | +| ---------------------------------------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| `session.list()` | 列出会话 | 返回 Session[] | +| `session.get({ path })` | 获取会话 | 返回 会话 | +| `session.children({ path })` | 列出子会话 | 返回 Session[] | +| `session.create({ body })` | 建立会话 | 返回 会话 | +| `session.delete({ path })` | 离开会话 | 返回`boolean` | +| `session.update({ path, body })` | 更新会话屬性 | 返回 会话 | +| `session.init({ path, body })` | Analyze app and create `AGENTS.md` | Returns `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` | + +--- + +#### 示例 + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### 文件 + +| 方法 | 描述 | 回应 | +| ------------------------- | -------------------- | ----------------------------------------------------------------------------------- | +| `find.text({ query })` | 搜索档案中文字 | 具有 `path`、`lines`、`line_number`、`absolute_offset`、`submatches` 的匹配对象数组 | +| `find.files({ query })` | 按名称查询档案和目录 | `string[]`(路径) | +| `find.symbols({ query })` | 查询工作区符號 | 符號[] | +| `file.read({ query })` | 读取档案 | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | 获取跟蹤文件的狀態 | 文件[] | + +`find.files` 支持一些可选的查询栏位: + +- `type`:`"file"` 或 `"directory"` +- `directory`:覆盖搜索的专案根目录 +- `limit`:最大结果 (1–200) + +--- + +#### 示例 + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| 方法 | 描述 | 回应 | +| ------------------------------ | ---------------- | --------- | +| `tui.appendPrompt({ body })` | 将文字附加到提示 | `boolean` | +| `tui.openHelp()` | 开启帮助对话方块 | `boolean` | +| `tui.openSessions()` | 开启会话选择器 | `boolean` | +| `tui.openThemes()` | 开启主题选择器 | `boolean` | +| `tui.openModels()` | 开启模型选择器 | `boolean` | +| `tui.submitPrompt()` | 提交当前提示 | `boolean` | +| `tui.clearPrompt()` | 清除提示 | `boolean` | +| `tui.executeCommand({ body })` | 执行命令 | `boolean` | +| `tui.showToast({ body })` | 显示吐司通知 | `boolean` | + +--- + +#### 示例 + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### 授权 + +| 方法 | 描述 | 回应 | +| ------------------- | ---------------- | --------- | +| `auth.set({ ... })` | 设定身份验证凭据 | `boolean` | + +--- + +#### 示例 + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### 事件 + +| 方法 | 描述 | 回应 | +| ------------------- | ------------------ | ------------------ | +| `event.subscribe()` | 服务器传送的事件流 | 服务器传送的事件流 | + +--- + +#### 示例 + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/zh-cn/server.mdx b/packages/web/src/content/docs/zh-cn/server.mdx new file mode 100644 index 00000000000..27604021a00 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/server.mdx @@ -0,0 +1,287 @@ +--- +title: 服务器 +description: 通过 HTTP 与 opencode 服务器交互。 +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +The `opencode serve` command runs a headless HTTP server that exposes an OpenAPI endpoint that an opencode client can use. + +--- + +### 用法 + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### 选项 + +| 标志 | 描述 | 默认 | +| --------------- | ----------------------------------- | ---------------- | +| `--port` | 监听音频 | `4096` | +| `--hostname` | 监听的主机名 | `127.0.0.1` | +| `--mdns` | 启用 mDNS 发现 | `false` | +| `--mdns-domain` | Custom domain name for mDNS service | `opencode.local` | +| `--cors` | 允许的其他浏览器来源 | `[]` | + +`--cors` 可以多次交付: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### 验证 + +Set `OPENCODE_SERVER_PASSWORD` to protect the server with HTTP basic auth. The username defaults to `opencode`, or set `OPENCODE_SERVER_USERNAME` to override it. This applies to both `opencode serve` and `opencode web`. + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### 它是如何運作的 + +When you run `opencode` it starts a TUI and a server. Where the TUI is the +与服务器器对话的客户端。服务器器公开 OpenAPI 3.1 规范 +该端点还用于生成 [SDK](/docs/sdk)。 + +:::tip +使用opencode服务器以程序设计方式与opencode交互。 +::: + +该架构让 opencode 支持客户端,并允许您以多种设计方式与 opencode 交互。 + +You can run `opencode serve` to start a standalone server. If you have the +opencode TUI running, `opencode serve` will start a new server. + +--- + +#### 连接到現有服务器 + +当您启动 TUI 时,它会随机分配端口和主机名。您可以重新设置 `--hostname` 和 `--port` [flags](/docs/cli)。使用它连线到其服务器然后器。 + +[**_T2_**](#tui) 端点可用于跨境服务器驱动 TUI。例如,您可以预填充或执行提示。此设置由 opencode [IDE](/docs/ide) 外挂使用。 + +--- + +## 規格 + +服务器发布了OpenAPI 3.1规范,可以在以下位置查看: + +``` +http://:/doc +``` + +例如,`http://localhost:4096/doc`。使用规范生成客户端或检查请求和响应类型其他。或者在 Swagger 浏览器中查看它。 + +--- + +## API + +opencode服务器公开以下API。 + +--- + +### 全局 + +| 方法 | 路徑 | 描述 | 回应 | +| ----- | ---------------- | ------------------------ | ------------------------------------ | +| `GET` | `/global/health` | 获取服务器运行状况和版本 | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | 获取全域性事件(SSE 流) | 事件流 | + +--- + +### 项目 + +| 方法 | 路徑 | 描述 | 回应 | +| ----- | ------------------ | ------------ | ------------------------------------------ | +| `GET` | `/project` | 列出所有专案 | 专案[] | +| `GET` | `/project/current` | 获取当前专案 | 专案 | + +--- + +### 路径和VCS + +| 方法 | 路徑 | 描述 | 回应 | +| ----- | ------- | ----------------------- | ------------------------------------------- | +| `GET` | `/path` | 获取当前路徑 | 路徑 | +| `GET` | `/vcs` | 获取当前专案的 VCS 資訊 | VcsInfo | + +--- + +### 例項 + +| 方法 | 路徑 | 描述 | 回应 | +| ------ | ------------------- | -------------- | --------- | +| `POST` | `/instance/dispose` | 执行当前实例项 | `boolean` | + +--- + +### 配置 + +| 方法 | 路徑 | 描述 | 回应 | +| ------- | ------------------- | -------------------- | -------------------------------------------------------------------------------------- | +| `GET` | `/config` | 获取配置資訊 | 配置 | +| `PATCH` | `/config` | 更新配置 | 配置 | +| `GET` | `/config/providers` | 列出提供商和默认模型 | `{ providers: `提供商[]`, default: { [key: string]: string } }` | + +--- + +### 提供商 + +| 方法 | 路徑 | 描述 | 回应 | +| ------ | -------------------------------- | ----------------------- | --------------------------------------------------------------------------------- | +| `GET` | `/provider` | 列出所有提供商 | `{ all: `提供商[]`, default: {...}, connected: string[] }` | +| `GET` | `/provider/auth` | 获取提供商身份验证方法 | `{ [providerID: string]: `ProviderAuthMethod[]` }` | +| `POST` | `/provider/{id}/oauth/authorize` | 使用 OAuth 授權提供商 | ProviderAuthAuthorization | +| `POST` | `/provider/{id}/oauth/callback` | 处理提供商的 OAuth 回调 | `boolean` | + +--- + +### 会话 + +| 方法 | 路徑 | 描述 | 筆記 | +| -------- | ---------------------------------------- | ---------------------------------- | -------------------------------------------------------------------------------- | +| `GET` | `/session` | 列出所有会话 | 返回 Session[] | +| `POST` | `/session` | 建立新会话 | 正文: `{ parentID?, title? }`,返回 Session | +| `GET` | `/session/status` | 获取所有会话的会话狀態 | 返回 `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | 获取会话详细信息 | 返回会话 | +| `DELETE` | `/session/:id` | 删除会话及所有资料 | 返回`boolean` | +| `PATCH` | `/session/:id` | 更新会话屬性 | 正文: `{ title? }`,返回 Session | +| `GET` | `/session/:id/children` | 获取会话的子会话 | 返回 Session[] | +| `GET` | `/session/:id/todo` | 获取会话的待辦事項列表 | 返回 Todo[] | +| `POST` | `/session/:id/init` | Analyze app and create `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returns `boolean` | +| `POST` | `/session/:id/fork` | 在消息中分叉現有会话 | 正文: `{ messageID? }`,返回 Session | +| `POST` | `/session/:id/abort` | 中止正在执行的会话 | 返回`boolean` | +| `POST` | `/session/:id/share` | 分享会话 | 返回会话 | +| `DELETE` | `/session/:id/share` | 取消共享会话 | 返回会话 | +| `GET` | `/session/:id/diff` | 获取本次会话的差異 | 查询:`messageID?`,返回 FileDiff[] | +| `POST` | `/session/:id/summarize` | 会议总结 | 正文:`{ providerID, modelID }`,返回 `boolean` | +| `POST` | `/session/:id/revert` | 回复讯息 | 正文:`{ messageID, partID? }`,返回 `boolean` | +| `POST` | `/session/:id/unrevert` | 恢复所有已恢复的消息 | 返回`boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | 回复许可权限请求 | 正文:`{ response, remember? }`,返回 `boolean` | + +--- + +### 留言 + +| 方法 | 路徑 | 描述 | 筆記 | +| ------ | --------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `GET` | `/session/:id/message` | 列出会话中的消息 | 查询: `limit?`,返回 `{ info: `消息`, parts: `Part[]`}[]` | +| `POST` | `/session/:id/message` | 发送消息并等待回复 | 正文: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`,返回 `{ info: `消息`, parts: `部分[]`}` | +| `GET` | `/session/:id/message/:messageID` | 获取消息详情 | 返回 `{ info: `消息`, parts: `部分[]`}` | +| `POST` | `/session/:id/prompt_async` | 非同步传送消息(休眠等待) | 主体:与 `/session/:id/message` 相同,返回 `204 No Content` | +| `POST` | `/session/:id/command` | 执行斜槓命令 | 正文: `{ messageID?, agent?, model?, command, arguments }`,返回 `{ info: `消息`, parts: `部分[]`}` | +| `POST` | `/session/:id/shell` | 执行 shell 命令 | 正文: `{ agent, model?, command }`,返回 `{ info: `消息`, parts: `部分[]`}` | + +--- + +### 命令 + +| 方法 | 路徑 | 描述 | 回应 | +| ----- | ---------- | ------------ | ------------------------------------------ | +| `GET` | `/command` | 列出所有命令 | 命令[] | + +--- + +### 文件 + +| 方法 | 路徑 | 描述 | 回应 | +| ----- | ------------------------ | -------------------- | ----------------------------------------------------------------------------------- | +| `GET` | `/find?pattern=` | 搜索文件中的文字 | 具有 `path`、`lines`、`line_number`、`absolute_offset`、`submatches` 的匹配对像数组 | +| `GET` | `/find/file?query=` | 按名称查询文件和目录 | `string[]`(路徑) | +| `GET` | `/find/symbol?query=` | 查询工作区符號 | 符號[] | +| `GET` | `/file?path=` | 列出文件和目录 | FileNode[] | +| `GET` | `/file/content?path=

` | 讀取文件 | 文件內容 | +| `GET` | `/file/status` | 获取跟蹤文件的狀態 | 文件[] | + +#### `/find/file` 查询参数 + +- `query`(必需)—搜寻字符串(模糊匹配) +- `type`(可选)— 将结果限制为 `"file"` 或 `"directory"` +- `directory` (任选) — 覆盖搜索的专案根目录 +- `limit`(任选)— 最大结果 (1–200) +- `dirs`(任选)— 旧标志(`"false"`仅返回档案) + +--- + +### 工具(實驗) + +| 方法 | 路徑 | 描述 | 回应 | +| ----- | ------------------------------------------- | ---------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | 列出所有工具 ID | 工具ID | +| `GET` | `/experimental/tool?provider=

&model=` | 列出具有模型 JSON 模式的工具 | 工具列表 | + +--- + +### LSP、格式化程式和 MCP + +| 方法 | 路徑 | 描述 | 回应 | +| ------ | ------------ | ------------------- | ------------------------------------------------------ | +| `GET` | `/lsp` | 获取 LSP 服务器狀態 | LSPStatus[] | +| `GET` | `/formatter` | 获取格式化程式狀態 | FormatterStatus[] | +| `GET` | `/mcp` | 获取 MCP 服务器狀態 | `{ [name: string]: `MCP狀態` }` | +| `POST` | `/mcp` | 动态添加 MCP 服务器 | 主体:`{ name, config }`,返回 MCP 状态对象 | + +--- + +### 代理商 + +| 方法 | 路徑 | 描述 | 回应 | +| ----- | -------- | ------------------ | ------------------------------------------ | +| `GET` | `/agent` | 列出所有可用的代理 | 代理[] | + +--- + +### 日志 + +| 方法 | 路徑 | 描述 | 回应 | +| ------ | ------------------------------------------- | ------ | -------------------- | +| `POST` | 身体:`{ service, level, message, extra? }` | `/log` | 写入日志。 `boolean` | + +--- + +### TUI + +| 方法 | 路徑 | 描述 | 回应 | +| ------ | ----------------------- | ----------------------------------------- | ------------ | +| `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` | 设置身份验证凭据。正文必须与提供商架构匹配 | `boolean` | + +--- + +### 活动 + +| 方法 | 路徑 | 描述 | 回应 | +| ----- | -------- | ------------------------------------------------------------------- | ------------------ | +| `GET` | `/event` | 服务器发送事件流。第一个事件是 `server.connected`,之后是总线事件。 | 服务器发送事件流。 | + +--- + +### 文档 + +| 方法 | 路徑 | 描述 | 回应 | +| ----- | ------ | --------------- | ------------------------- | +| `GET` | `/doc` | 开启API 3.1规范 | 具有OpenAPI规范的HTML页面 | diff --git a/packages/web/src/content/docs/zh-cn/share.mdx b/packages/web/src/content/docs/zh-cn/share.mdx new file mode 100644 index 00000000000..e73eac373d1 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/share.mdx @@ -0,0 +1,128 @@ +--- +title: 分享 +description: 分享您的 opencode 对话。 +--- + +opencode 的共享功能允许您建立指向 opencode 对话的公共链接,以便您可以与蓝牙进行战斗或从其他人那里获得帮助。 + +:::note +任何知道链接的人都可以公開访问共享对话。 +::: + +--- + +## 它是如何運作的 + +当您分享对话时,opencode: + +1. 为您的会话建立唯一的公共 URL +2. 将您的对话歷史記錄同步到我们的服务器 +3. 通过可共享链接访问对话 — `opncd.ai/s/` + +--- + +## 分享 + +opencode 支持清晰控制对话共享方式的共享模式: + +--- + +### 手动(默认) + +在默认情况下,opencode 使用手动共享模式。会话不会自动共享,但您可以使用 `/share` 命令手动共享它们: + +``` +/share +``` + +这将生成一个唯一的 URL,将其复制到您的剪贴簿中。 + +要在[配置文件](/docs/config) 中显式设置手动模式: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### 自动分享 + +您可以通过将 [config file](/docs/config) 中的 `share` 选项设置为 `"auto"` 来为所有新对话启用自动共享: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +启用自动共享後,每个新对话都会自动共享并生成链接。 + +--- + +### 已禁用 + +您可以通过将 [config file](/docs/config) 中的 `share` 选项设置为 `"disabled"` 来完全禁用共享: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +To enforce this across your team for a given project, add it to the `opencode.json` in your project and check into Git. + +--- + +## 取消共享 + +要停止共享对话并将其從公共访问中删除: + +``` +/unshare +``` + +这将删除共享链接并删除与对话相关的数据。 + +--- + +## 隱私 + +分享对话時需要記住一些事項。 + +--- + +### 数据保留 + +共享对话仍然可以访问,直到您明確取消共享。这 +包括: + +- 完整的对话歷史記錄 +- 所有消息和回复 +- 会话元数据 + +--- + +### 建議 + +- 仅共享不包含敏感資訊的对话。 +- 分享之前查看对话內容。 +- 協作完成後取消共享对话。 +- 避免与专有程式碼或機密数据共享对话。 +- 对于敏感专案,完全禁用共享。 + +--- + +## 对于企業 + +对于企業部署,共享功能可以是: + +- **出于安全合規性完全禁用** +- **仅限** 仅通过 SSO 进行身份验证的用户 +- **在您自己的基礎設施上自行託管** + +[了解更多关于在您的组织中使用opencode的](/docs/enterprise)。 diff --git a/packages/web/src/content/docs/zh-cn/skills.mdx b/packages/web/src/content/docs/zh-cn/skills.mdx new file mode 100644 index 00000000000..f5c588d1ed2 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/skills.mdx @@ -0,0 +1,222 @@ +--- +title: 《代理技巧》 +description: “贯穿 SKILL.md 定义可重用行为” +--- + +代理让 opencode 技能从您的存储库或主目录中找到可重用的指令。 +技能贯穿本机 `skill` 工具输入导入 - 代理可以查看可用技能并可以在需要时加载完整内容。 + +--- + +## 放置文件 + +为每个技能名称建立一个资料夹,并在其中放入`SKILL.md`。 +opencode 搜索这些位置: + +- Project config: `.opencode/skills//SKILL.md` +- Global config: `~/.config/opencode/skills//SKILL.md` +- 专案Claude兼容:`.claude/skills//SKILL.md` +- 全域性 Claude 兼容: `~/.claude/skills//SKILL.md` +- 专案代理兼容:`.agents/skills//SKILL.md` +- 全球代理兼容:`~/.agents/skills//SKILL.md` + +--- + +## 了解发现 + +对于专案本地路径, opencode 从当前工作目录向上走,直到到达 git 工作树。 +It loads any matching `skills/*/SKILL.md` in `.opencode/` and any matching `.claude/skills/*/SKILL.md` or `.agents/skills/*/SKILL.md` along the way. + +Global definitions are also loaded from `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md`, and `~/.agents/skills/*/SKILL.md`. + +--- + +## 编写 Frontmatter + +每个 `SKILL.md` 必须以 YAML frontmatter 。 +仅識別这些欄位: + +- `name`(必填) +- `description`(必填) +- `license`(任选) +- `compatibility`(任选) +- `metadata`(任选,字符串到字符串对映) + +未知的 frontmatter 栏位将被忽略。 + +--- + +## 验证名称 + +`name` 必须: + +- 長度为 1–64 个字元 +- 为小寫字母數字并带有單个連字元分隔符 +- 不以 `-` 開始或結束 +- 不包含連續的 `--` +- 匹配包含 `SKILL.md` 的目录名 + +等效的正規表示式: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## 遵循长度规则 + +`description` 必须是 1-1024 个字元。 +保持足夠具體,以便代理能夠正确选择。 + +--- + +## 使用一个例子 + +Create `.opencode/skills/git-release/SKILL.md` like this: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## 识别工具说明 + +opencode 列出了 `skill` 工具描述中的可用技能。 +每个条目都包含技能名称和描述: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +代理通过呼叫工具來載入技能: + +``` +skill({ name: "git-release" }) +``` + +--- + +## 配置权限 + +Control which skills agents can access using pattern-based permissions in `opencode.json`: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| 許可 | 行为 | +| ------- | -------------------------- | +| `allow` | 技能立即加载 | +| `deny` | 对特工隐藏技能,访问被拒绝 | +| `ask` | 加载前提示用户批准 | + +模式支持万用字元:`internal-*` 匹配 `internal-docs`、`internal-tools` 等。 + +--- + +## 覆盖每个代理 + +为特定代理授予与全域性默认权限不同的权限。 + +**对于自定義代理**(在代理前言中): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**For built-in agents** (in `opencode.json`): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## 禁用技能工具 + +完全禁用不应该使用技能的特工: + +**对于定製代理**: + +```yaml +--- +tools: + skill: false +--- +``` + +**对于內建代理**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +禁用後,`` 部分将被完全省略。 + +--- + +## 解决加载问题 + +如果某項技能沒有显示: + +1. 验证 `SKILL.md` 拼写为全部大写 +2. 检查 frontmatter 是否包括 `name` 和 `description` +3. 確保技能名称在所有位置都是唯一的 +4. 查询权限——具有`deny`的代理隐藏技能 diff --git a/packages/web/src/content/docs/zh-cn/themes.mdx b/packages/web/src/content/docs/zh-cn/themes.mdx new file mode 100644 index 00000000000..2f28f15d55b --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/themes.mdx @@ -0,0 +1,369 @@ +--- +title: 主题 +description: 选择內建主题或定義您自己的主题。 +--- + +使用 opencode,您可以从多个内建主题中进行选择,使用适合您的终端主题的主题,或定义您自己的自定义主题。 + +By default, opencode uses our own `opencode` theme. + +--- + +## 终端要求 + +为了使主题能夠正确显示完整的调色板,您的终端必須支持**真彩色**(24 位顏色)。大多數现代终端默认支持此功能,但您可能需要启用它: + +- **检查支持**:执行 `echo $COLORTERM` - 它应该输出 `truecolor` 或 `24bit` +- **启用真彩色**:在shell配置文件中设置环境变量`COLORTERM=truecolor` +- **您的终端兼容性**:确保终端模拟器支持24位颜色(大多数现代终端,​​​​如iTerm2、Alacritty、Kitty、Windows终端和最新版本的GNOME终端都支持) + +如果沒有真彩色支持,主题的顏色精度可能会降低或回落到最接近的 256 色近似值。 + +--- + +## 内置主题 + +opencode 带有几个内建主题。 + +| 名称 | 描述 | +| ---------------------- | ---------------------------------------------------------------------------- | +| `system` | 适应您所处的背景颜色 | +| `tokyonight` | Based on the [Tokyonight](https://github.com/folke/tokyonight.nvim) theme | +| `everforest` | Based on the [Everforest](https://github.com/sainnhe/everforest) theme | +| `ayu` | Based on the [Ayu](https://github.com/ayu-theme) dark theme | +| `catppuccin` | Based on the [Catppuccin](https://github.com/catppuccin) theme | +| `catppuccin-macchiato` | Based on the [Catppuccin](https://github.com/catppuccin) theme | +| `gruvbox` | Based on the [Gruvbox](https://github.com/morhetz/gruvbox) theme | +| `kanagawa` | Based on the [Kanagawa](https://github.com/rebelot/kanagawa.nvim) theme | +| `nord` | Based on the [Nord](https://github.com/nordtheme/nord) theme | +| `matrix` | 骇客风格黑底绿主题 | +| `one-dark` | Based on the [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark theme | + +此外,我们还在不斷添加新主题。 + +--- + +## 系统主题 + +`system` 主题旨在自动适应您的最终方案。与使用固定颜色的传统主题不同,_system_ 主题: + +- **生成灰度**:根據终端的背景顏色建立自定義灰度,確保最佳对比度。 +- **使用 ANSI 颜色**:使用标准 ANSI 颜色 (0-15) 进行语法突出显示和 UI 元素,尊重 Windows 的调色盘。 +- **保留默认设置**:使用 `none` 作为文字和背景颜色以保持本机的外观。 + +系統主题適合以下用户: + +- 希望 opencode 与终端的外观相匹配 +- 使用自定義终端配色方案 +- 希望所有终端应用程序具有一致的外觀 + +--- + +## 使用主题 + +您可以通过使用 `/theme` 命令调出主题选择来选择主题。或者您可以在 [config](/docs/config) 中指定它。 + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## 自定义主题 + +opencode 支持灵活的基于 JSON 的主题系统,允许用户轻松创建和自定义主题。 + +--- + +### 优先级 + +主题按以下顺序從多个目录載入,其中后面的目录覆盖前面的目录: + +1. **內建主题** - 这些主题嵌入在二進製文件中 +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` + +如果多个目录包含同名主题,则将使用优先顺序較高的目录中的主题。 + +--- + +### 创建主题 + +要创建自定义主题,请在主题目录中创建 JSON 档案。 + +对于用户范围的主题: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +以及針对特定专案的主题。 + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### JSON 格式 + +主题使用灵活的 JSON 格式,支持: + +- **十六进位制造颜色**: `"#ffffff"` +- **ANSI 颜色**: `3` (0-255) +- **颜色参考**: `"primary"` 或自定义定义 +- **深色/light 变体**: `{"dark": "#000", "light": "#fff"}` +- **无颜色**: `"none"` - 使用终端的默认颜色或透明 + +--- + +### 颜色定义 + +`defs` 部分是可选的,它允许您定义可在主题中引用的可重用颜色。 + +--- + +### 终端默认值 + +特殊值 `"none"` 可用于任何颜色以继承默认的默认颜色。这对于建立与终端方案无缝的融合主题特别有用: + +- `"text": "none"` - 使用遥控器的预设前景色 +- `"background": "none"` - 使用桌面的背景颜色 + +--- + +### 例子 + +以下是自定義主题的示例: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/zh-cn/tools.mdx b/packages/web/src/content/docs/zh-cn/tools.mdx new file mode 100644 index 00000000000..1be9d669012 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/tools.mdx @@ -0,0 +1,379 @@ +--- +title: 工具 +description: 管理 LLM 可以使用的工具。 +--- + +Tools allow the LLM to perform actions in your codebase. opencode comes with a set of built-in tools, but you can extend it with [custom tools](/docs/custom-tools) or [MCP servers](/docs/mcp-servers). + +默认情况下,所有工具都是**启用**并且不需要执行权限。您可以交叉[permissions](/docs/permissions) 控制工具行为。 + +--- + +## 配置 + +使用 `permission` 栏位控制工具行为。您可以允许、拒绝或要求批准每个工具。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +您还可以使用万用字元同时控制多个工具。例如,要求 MCP 服务器批准所有工具: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[了解更多](/docs/permissions)关于配置许可权。 + +--- + +## 內建 + +以下是 opencode 中可用的所有内置工具。 + +--- + +### 巴什 + +在专案环境中执行shell命令。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +This tool allows the LLM to run terminal commands like `npm install`, `git status`, or any other shell command. + +--- + +### 編輯 + +使用精確的字符串替換修改現有文件。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +该工具取消替换精确的文字来匹配对文件执行精确编辑。这是 LLM 修改代码的主要方式。 + +--- + +### 寫 + +建立新文件或覆盖現有文件。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +使用它允许 LLM 创建新文件。如果现有文件已经存在,将会覆盖它们。 + +:::note +`write`工具由`edit`许可权控制,该许可权主题所有文件修改(`edit`、`write`、`patch`、`multiedit`)。 +::: + +--- + +### 讀 + +從程式碼庫中讀取文件內容。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +该工具讀取文件并返回其內容。它支持讀取大文件的特定行范围。 + +--- + +### grep + +使用正規表示式搜索文件內容。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +在您的程式碼庫中快速進行內容搜索。支持完整的正規表示式語法和文件模式过濾。 + +--- + +### 全域性 + +通过模式匹配查询文件。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +使用 `**/*.js` 或 `src/**/*.ts` 等全域性模式搜索档案。返回按时间排序的匹配档案路径修改。 + +--- + +### 列表 + +列出給定路徑中的文件和目录。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +该工具列出目录內容。它接受全域性模式來过濾結果。 + +--- + +### lsp(实验性) + +与您配置的LSP服务器交互,通知计划码智慧功能,例如定义、引用、悬停资讯和呼叫层次结构。 + +:::note +This tool is only available when `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (or `OPENCODE_EXPERIMENTAL=true`). +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +支持的操作包括 `goToDefinition`、`findReferences`、`hover`、`documentSymbol`、`workspaceSymbol`、`goToImplementation`、`prepareCallHierarchy`、`incomingCalls` 和 `outgoingCalls`。 + +To configure which LSP servers are available for your project, see [LSP Servers](/docs/lsp). + +--- + +### 修補 + +对文件应用補丁。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +该工具将補丁文件应用到您的程式碼庫。对于应用來自各種來源的差異和補丁很有帮助。 + +:::note +`patch`工具由`edit`许可权控制,该许可权主题所有文件修改(`edit`、`write`、`patch`、`multiedit`)。 +::: + +--- + +### 技能 + +加载[skill](/docs/skills)(`SKILL.md` 档案)并在对话中返回其内容。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### 待辦寫入 + +在編碼会话期間管理待辦事項列表。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +建立和更新任务列表以跟踪复杂操作期间的详细信息。LLM 使用它来组织多步骤任务。 + +:::note +默认情况下,子代理取消此工具,但您可以手动启用它。 [了解更多](/docs/agents/#permissions) +::: + +--- + +### 託多雷德 + +閱讀現有的待辦事項列表。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +读取当前完成待办事项列表状态。由 LLM 用于跟踪哪些任务待处理或已已。 + +:::note +默认情况下,子代理取消此工具,但您可以手动启用它。 [了解更多](/docs/agents/#permissions) +::: + +--- + +### 網頁抓取 + +获取網頁內容。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +允许 LLM 获取和读取网页。对于查询文件或研究线上资源很有帮助。 + +--- + +### 網路搜索 + +在網路上搜索資訊。 + +:::note +仅当使用 opencode 提供或 `OPENCODE_ENABLE_EXA` 程序环境变量设置为任何真值(例如 `true` 或 `1`)时,此工具才可用。 + +要在启动 opencode 时启用: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +使用 Exa AI 执行网路搜索以线上查询相关资讯。对于研究主题、查询时事或收集训练超出数据范围的资讯很有帮助。 + +不需要 API 密钥 — 该工具消耗身份验证即可直接连线到 Exa AI 的托管 MCP 服务。 + +:::tip +当您需要查询资讯(发现)时,请使用 `websearch`;当您需要从特定 URL 检索内容(搜索)时,请使用 `webfetch`。 +::: + +--- + +### 問題 + +在执行过程中詢問用户問題。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +该工具允许 LLM 在任务期间询问用户问题。它适用于: + +- 收集用户偏好或要求 +- 澄清不明確的指令 +- 就實施选择做出決策 +- 提供选择方向 + +每个問題都包含標題、問題文字和選項列表。用户可以從提供的選項中進行选择或輸入自定義答案。当存在多个問題時,用户可以在提交所有答案之前在这些問題之间导航。 + +--- + +## 定製工具 + +自定义工具可以让您定义LLM可以调用自己的函式。这些是在您的配置文件中定义的并且可以执行任何代码。 + +[了解更多](/docs/custom-tools)关于创建自定义工具。 + +--- + +## MCP 服务器 + +MCP(模型上下文协议)服务器允许您集成外部工具和服务。这包括数据库访问、API 集成和第三方服务。 + +[了解更多](/docs/mcp-servers)关于配置MCP服务器。 + +--- + +## 内部結構 + +Internally, tools like `grep`, `glob`, and `list` use [ripgrep](https://github.com/BurntSushi/ripgrep) under the hood. By default, ripgrep respects `.gitignore` patterns, which means files and directories listed in your `.gitignore` will be excluded from searches and listings. + +--- + +### 忽略模式 + +要包含通常会被忽略的文件,请在专案根目录中建立 `.ignore` 文件。该文件可以明确允许某些路径。 + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +例如,此 `.ignore` 档案允许 ripgrep 在 `node_modules/`、`dist/` 和 `build/` 目录中搜索,即使它们列在 `.gitignore` 中。 diff --git a/packages/web/src/content/docs/zh-cn/troubleshooting.mdx b/packages/web/src/content/docs/zh-cn/troubleshooting.mdx new file mode 100644 index 00000000000..b658f6938e1 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/troubleshooting.mdx @@ -0,0 +1,300 @@ +--- +title: 故障排除 +description: 常見問題以及如何解決它們。 +--- + +要排除 opencode 的问题,请首先检查其存储在磁碟上的日志和本地数据。 + +--- + +## 日志 + +日誌文件寫入: + +- **macOS/Linux**: `~/.local/share/opencode/log/` +- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.local\share\opencode\log` + +日志档案以时间命名(例如`2025-01-09T123456.log`),并保留最近10个日志档案。 + +You can set the log level with the `--log-level` command-line option to get more detailed debug information. For example, `opencode --log-level DEBUG`. + +--- + +## 存储 + +opencode程序将会话数据和其他应用程序数据存储在磁碟上: + +- **macOS/Linux**: `~/.local/share/opencode/` +- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.local\share\opencode` + +该目录包含: + +- `auth.json` - 身份验证凭据,例如 API 密钥、OAuth Tokens +- `log/` - 应用日志 +- `project/` - 项目特定数据,例如会话和消息数据 + - 如果项目位于 Git 仓库中,则存储在 `.//storage/` 中 + - 如果不是 Git 存储库,则存储在 `./global/storage/` 中 + +--- + +## 桌面应用程序 + +opencode Desktop runs a local opencode server (the `opencode-cli` sidecar) in the background. Most issues are caused by a misbehaving plugin, a corrupted cache, or a bad server setting. + +### 快速检查 + +- 完全退出并重新启动应用程序。 +- 如果应用程序显示错误界面,请单击“**重新启动**”并复制错误详细信息。 +- macOS only: `OpenCode` menu -> **Reload Webview** (helps if the UI is blank/frozen). + +--- + +### 禁用插件 + +如果桌面应用程序在启动時崩潰、掛起或行为異常,请首先禁用插件。 + +#### 检查全域性配置 + +开启全域性文件并查询`plugin`键。 + +- **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` + +如果您配置了插件,请通过删除密钥或将其设置为空数组來暂时禁用它們: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### 检查插件目录 + +opencode 还可以从磁碟加载本地外挂。暂时将它们移开(或重新命名资料夹)并重新启动桌面应用程序: + +- **全域性插件** + - **macOS/Linux**: `~/.config/opencode/plugins/` + - **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.config\opencode\plugins` +- **专案插件**(仅当您使用每个专案配置時) + - `/.opencode/plugins/` + +如果应用程序再次開始工作,请一次重新启用一个插件,以找出導致問題的插件。 + +--- + +### 清除缓存 + +如果取消外挂没有帮助(或者外挂安装被卡住),请清除缓存,方便opencode可以重建它。 + +1. 完全退出 opencode 桌面。 +2. 删除缓存目录: + +- **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` + +3. 重新启动 opencode 桌面。 + +--- + +### 修復服务器连接問題 + +opencode Desktop 可以启动自己的本地服务器(默认配置)或连线到您的服务器 URL。 + +如果您看到**“连线失败”**对话中断(或者应用程序永远无法穿透启动萤幕),请检查自定义服务器URL。 + +#### 清除桌面桌面服务器 URL + +在主屏幕中,单击服务器名称(带有状态点)以打开服务器选择器。在“**默认服务器**”部分中,单击“**清除**”。 + +#### 从配置中删除 `server.port` / `server.hostname` + +If your `opencode.json(c)` contains a `server` section, temporarily remove it and restart the desktop app. + +#### 检查环境变量 + +如果您在环境中设置了 `OPENCODE_PORT`,桌面应用程序将尝试将交换机用于本地服务器。 + +- 取消设置`OPENCODE_PORT`(或选择一个休闲摊)并重新启动。 + +--- + +### Linux:Wayland / X11 问题 + +在 Linux 上,某些 Wayland 设置可能会导致空白视窗或合成器错误。 + +- 如果您在 Wayland 程序上并且应用的是 blank/crashing,请尝试使用 `OC_ALLOW_WAYLAND=1` 启动。 +- 如果这让事情变得更糟糕,请完成其删除并尝试在 X11 会话下启动。 + +--- + +### Windows:WebView2执行时 + +在 Windows 上,opencode 桌面需要 Microsoft Edge **WebView2 执行时**。如果应用程序打开为空白视窗或无法启动,请 install/update WebView2 并重试。 + +--- + +### Windows:一般问题 + +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. + +--- + +### 通知不显示 + +opencode 桌面仅在以下情况下显示系统通知: + +- 在您的作业系统中设置为 opencode 启用了通知,并且 +- 应用程序視窗未聚焦。 + +--- + +### 重置桌面应用程序儲存(最后的手段) + +如果应用程序无法并且启动您无法从 UI 内部清除设置,请重置桌面应用程序的存储状态。 + +1. 退出 opencode 桌面。 +2. 查询并删除这些文件(它们位于 opencode 桌面应用程序数据目录中): + +- `opencode.settings.dat` (desktop default server URL) +- `opencode.global.dat` and `opencode.workspace.*.dat` (UI state like recent servers/projects) + +快速找到目录: + +- **macOS**:Finder -> `Cmd+Shift+G` -> `~/Library/Application Support`(然后搜索上面的档名) +- **Linux**:在`~/.local/share`下搜索上述档名 +- **Windows**:按 `WIN+R` -> `%APPDATA%` (然后搜索上面的档名) + +--- + +## 寻求帮助 + +如果您遇到 opencode 问题: + +1. **报告 GitHub** 上的问题 + + 报告错误或请求功能的最佳方式是利用我们的 GitHub 存储库: + + [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + + 在建立新問題之前,请搜索現有問題以查看您的問題是否已被報告。 + +2. **加入我们的不和諧** + + 获得实时帮助和社群讨论,请加入我们的Discord服务器: + + [**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## 常见问题 + +以下是一些常見問題以及解決方法。 + +--- + +### opencode 无法启动 + +1. 检查日誌中是否有错误消息 +2. 尝试使用 `--print-logs` 执行以查看终端中的输出 +3. Ensure you have the latest version with `opencode upgrade` + +--- + +### 身份验证問題 + +1. 尝试使用 TUI 中的 `/connect` 命令重新进行身份验证 +2. 检查您的API 密钥是否有效 +3. 保证您的网路允许连线到达辉煌的API + +--- + +### 模型不可用 + +1. 检查您是否已通过提供商的身份验证 +2. 驗證配置中的模型名称是否正确 +3. 某些模型可能需要特定的访问权限或訂閱 + +如果您遇到 `ProviderModelNotFoundError` 您很可能是错误的 +在某處引用模型。 +模型应该像这樣引用:`/` + +示例: + +- `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` + +--- + +### 提供商初始化错误 + +如果遇到 ProviderInitError,您的配置可能无效或损坏。 + +要解決这个問題: + +1. 首先,按照[提供商指南](/docs/providers) 验证您的事业是否已正确设置 +2. 如果問題仍然存在,请嘗試清除儲存的配置: + + ```bash + rm -rf ~/.local/share/opencode + ``` + + On Windows, press `WIN+R` and delete: `%USERPROFILE%\.local\share\opencode` + +3. 使用 TUI 中的 `/connect` 命令指示您的企业重新进行身份验证。 + +--- + +### AI_API_CallError 和提供包问题 + +如果您遇到 API 呼叫错误,这可能是由于过去提供包造成的。 opencode 根据需要动态安装提供包(OpenAI、Anthropic、Google 等)将其缓存放在本地。 + +要解決provider 包問題: + +1. 清除provider 包缓存: + + ```bash + rm -rf ~/.cache/opencode + ``` + + On Windows, press `WIN+R` and delete: `%USERPROFILE%\.cache\opencode` + +2. 重新启动 opencode 以重新安装最新的提供包 + +这将需要 opencode 下载最新版本的提供包,这通常可以解决模型参数和 API 更改的兼容性问题。 + +--- + +### 复制/粘贴在 Linux 上不可用 + +Linux 用户需要安装以下剪贴簿实用程序之一才能使 copy/paste 功能正常工作: + +**对于X11系统:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +** 对于 Wayland 系统:** + +```bash +apt install -y wl-clipboard +``` + +**对于無頭環境:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +opencode 将检测您是否正在使用 Wayland 并更喜欢 `wl-clipboard`,否则将尝试按以下顺序剪贴簿工具:`xclip` 和 `xsel`。 diff --git a/packages/web/src/content/docs/zh-cn/tui.mdx b/packages/web/src/content/docs/zh-cn/tui.mdx new file mode 100644 index 00000000000..e1beb9abff7 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/tui.mdx @@ -0,0 +1,390 @@ +--- +title: TUI +description: 使用 opencode 终端用户界面。 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +opencode 提供交互式终端介面或 TUI,以便使用 LLM 处理您的专案。 + +执行opencode启动当前目录的TUI。 + +```bash +opencode +``` + +或者您可以为特定的工作目录启动它。 + +```bash +opencode /path/to/project +``` + +进入TUI后,您可以查看消息进行提示。 + +```text +Give me a quick summary of the codebase. +``` + +--- + +## 文件引用 + +您可以使用 `@` 在消息中引用文件。这会在当前工作目录中進行模糊文件搜索。 + +:::tip +您还可以使用 `@` 來引用消息中的文件。 +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +文件的內容会自动添加到对话中。 + +--- + +## Bash 命令 + +以`!`开始一条消息以执行shell命令。 + +```bash frame="none" +!ls -la +``` + +命令的輸出将作为工具結果添加到对话中。 + +--- + +## 命令 + +使用 opencode TUI 时,您可以输入 `/` 后跟命令名称来快速执行操作。例如: + +```bash frame="none" +/help +``` + +大多数命令还是以使用 `ctrl+x` 作为主键的键系结,其中 `ctrl+x` 是默认主键。 [了解更多](/docs/keybinds)。 + +以下是所有可用的斜槓命令: + +--- + +### 连接 + +将提供商添加到 opencode。你可以从可用提供商中选择,并添加它们的 API 密钥。 + +```bash frame="none" +/connect +``` + +--- + +### 紧凑 + +压缩当前会话。_别名_: `/summarize` + +```bash frame="none" +/compact +``` + +** 快捷键:** `ctrl+x c` + +--- + +### 細節 + +切換工具执行详细信息。 + +```bash frame="none" +/details +``` + +** 快捷键:** `ctrl+x d` + +--- + +### 編輯 + +开启外部编辑器来编写消息。使用`EDITOR`环境变量中设定的编辑器。 [了解更多](#editor-setup)。 + +```bash frame="none" +/editor +``` + +** 快捷键:** `ctrl+x e` + +--- + +### 退出 + +退出opencode。 _别名_:`/quit`、`/q` + +```bash frame="none" +/exit +``` + +** 快捷键:** `ctrl+x q` + +--- + +### 导出 + +将当前对话汇出到 Markdown 并在默认编辑器中开启。使用 `EDITOR` 环境变数中设定的编辑器。 [了解更多](#editor-setup)。 + +```bash frame="none" +/export +``` + +** 快捷键:** `ctrl+x x` + +--- + +### 幫助 + +显示幫助对话方塊。 + +```bash frame="none" +/help +``` + +** 快捷键:** `ctrl+x h` + +--- + +### 初始化 + +Create or update `AGENTS.md` file. [Learn more](/docs/rules). + +```bash frame="none" +/init +``` + +** 快捷键:** `ctrl+x i` + +--- + +### 模型 + +列出可用模型。 + +```bash frame="none" +/models +``` + +** 快捷键:** `ctrl+x m` + +--- + +### 新的 + +开始新的会话。 _别名_: `/clear` + +```bash frame="none" +/new +``` + +** 快捷键:** `ctrl+x n` + +--- + +### 重做 + +删除之前重做消除的讯息。仅在使用`/undo`后可用。 + +:::tip +任何文件更改也将被恢复。 +::: + +在内部,这使用 Git 来管理文件更改。所以你的专案**需要 +是一个Git存储库**。 + +```bash frame="none" +/redo +``` + +** 快捷键:** `ctrl+x r` + +--- + +### 会话 + +上市会话并在会话之间切换。 _别名_:`/resume`、`/continue` + +```bash frame="none" +/sessions +``` + +** 快捷键:** `ctrl+x l` + +--- + +### 分享 + +共享当前会话。 [了解更多](/docs/share)。 + +```bash frame="none" +/share +``` + +** 快捷键:** `ctrl+x s` + +--- + +### 主题 + +列出可用的主题。 + +```bash frame="none" +/theme +``` + +** 快捷键:** `ctrl+x t` + +--- + +### 思維 + +切换对话中 thinking/reasoning 块的可视性。启用后,您可以看到支持增强套件思维的模型的推理过程。 + +:::note +该命令仅控制是否**显示** - 不启用或取消模型的推理功能。要切换实际推理功能,请使用 `ctrl+t` 回圈切换模型变体。 +::: + +```bash frame="none" +/thinking +``` + +--- + +### 撤消 + +撤消对话中的最后一条消息。删除最近的用户消息、所有后续響应以及任何文件更改。 + +:::tip +所做的任何文件更改也将被恢复。 +::: + +在内部,这使用 Git 来管理文件更改。所以你的专案**需要 +是一个Git存储库**。 + +```bash frame="none" +/undo +``` + +** 快捷键:** `ctrl+x u` + +--- + +### 取消共享 + +取消共享当前会话。 [了解更多](/docs/share#un-sharing)。 + +```bash frame="none" +/unshare +``` + +--- + +## 编辑器设置 + +`/editor` 和 `/export` 命令都使用 `EDITOR` 环境变量中指定的编辑器。 + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + + 要使其永久存在,请将其添加到您的 shell 配置文件中; + `~/.bashrc`、`~/.zshrc` 等 + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + + 要使其永久化,请使用 **系统属性** > **环境 + 变量**。 + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + + 要使其永久化,请将其添加到您的 PowerShell 配置文件中。 + + + + +流行的编辑器選項包括: + +- `code` - Visual Studio Code +- `cursor` - 游标 +- `windsurf` - 风帆冲浪 +- `nvim` - Neovim 编辑器 +- `vim` - Vim 编辑器 +- `nano` - 奈米编辑器 +- `notepad` - Windows 文章书 +- `subl` - 崇高文字 + +:::note +一些编辑器如 VS Code 需要以 `--wait` 标志启动。 +::: + +某些编辑器需要命令列参数才能在阻止模式下执行。 `--wait` 标志使编辑器程序阻塞直至关闭。 + +--- + +## 配置 + +您可以使用 opencode 配置文件自定义 TUI 行为。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### 選項 + +- `scroll_acceleration` - 启用 macOS 式滚动加速以实现平滑、自然的滚动。启用后,滚动速度会随着快速滚动滚动而增加,并在较慢的移动时保持精确。 **此设定优先于 `scroll_speed` 并在启用时覆盖它。 ** +- `scroll_speed` - 控制使用滚动控制器时 TUI 滚动的速度(简单:`1`)。默认为 `3`。 **注意:如果 `scroll_acceleration.enabled` 设置为 `true`,则忽略此设置。 ** + +--- + +## 自定义 + +您可以使用命令选项板(`ctrl+x h` 或 `/help`)自定义 TUI 查看的各个方面。这些设置在重新启动后仍然存在。 + +--- + +#### 用户名称显示 + +切換您的用户名称是否出現在聊天消息中。通过以下方式访问: + +- 命令面板:搜索“用户名称”或“隐藏用户名称” +- 该设置会自动保留,放在 TUI 会话中被记住 diff --git a/packages/web/src/content/docs/zh-cn/web.mdx b/packages/web/src/content/docs/zh-cn/web.mdx new file mode 100644 index 00000000000..efb55aaab5f --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/web.mdx @@ -0,0 +1,142 @@ +--- +title: 網路 +description: 在浏览器中使用opencode。 +--- + +opencode 可以在浏览器中作为 Web 应用程序执行,消耗终端可以提供同样强大的 AI 编码体验。 + +![opencode Web - New Session](../../../assets/web/web-homepage-new-session.png) + +## 入門 + +绕过执行以下命令启动 Web 简介: + +```bash +opencode web +``` + +这将在 `127.0.0.1` 上启动一个具有随机可用端口的本地服务器,并自动在默认浏览器中开启 opencode。 + +:::caution +如果未设置`OPENCODE_SERVER_PASSWORD`,服务器将不安全。这对于本地使用来说很好,但应该针对网路访问进行设置。 +::: + +:::tip[Windows 用户] +For the best experience, run `opencode web` from [WSL](/docs/windows-wsl) rather than PowerShell. This ensures proper file system access and terminal integration. +::: + +--- + +## 配置 + +您可以使用命令列标志或在[config file](/docs/config).conf 中配置Web服务器。 + +### 端口 + +默认情况下,opencode 选择一个可用的端口。您可以指定一个端口: + +```bash +opencode web --port 4096 +``` + +### 主機名 + +情况默认下,服务器系结到`127.0.0.1`(仅限本地主机)。要使opencode在您的网路上可访问: + +```bash +opencode web --hostname 0.0.0.0 +``` + +使用`0.0.0.0`时,opencode将显示本地地址和网络地址: + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### mDNS 发现 + +启用 mDNS 使您的服务器在本地网上可以发现: + +```bash +opencode web --mdns +``` + +This automatically sets the hostname to `0.0.0.0` and advertises the server as `opencode.local`. + +您可以自定义 mDNS 域名以在同一网路上执行多个示例: + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +允许CORS使用其他域(对于自定义前缀有用): + +```bash +opencode web --cors https://example.com +``` + +### 驗證 + +要保护访问,请使用 `OPENCODE_SERVER_PASSWORD` 环境变数设置密码: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +The username defaults to `opencode` but can be changed with `OPENCODE_SERVER_USERNAME`. + +--- + +## 使用网络界面 + +启动后,网路界面将提供对您的 opencode 会话的访问。 + +### 会话 + +從主頁查看和管理您的会话。您可以查看活动会话并開始新会话。 + +![opencode Web - Active Session](../../../assets/web/web-homepage-active-session.png) + +### 服务器狀態 + +单击“查看服务器”可查看连接的服务器及其狀態。 + +![opencode Web - See Servers](../../../assets/web/web-homepage-see-servers.png) + +--- + +## 连接终端 + +您可以将终端 TUI 连线到正在执行的 Web 服务器: + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +这允许您同时使用 Web 界面和终端,共享相同的会话和状态。 + +--- + +## 配置文件 + +You can also configure server settings in your `opencode.json` config file: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +命令行标志优先于配置文件设置。 diff --git a/packages/web/src/content/docs/zh-cn/windows-wsl.mdx b/packages/web/src/content/docs/zh-cn/windows-wsl.mdx new file mode 100644 index 00000000000..95ef1bd6d81 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: 在 Windows 上通过 WSL 使用 opencode。 +--- + +import { Steps } from "@astrojs/starlight/components" + +虽然 opencode 可以直接在 Windows 上运行,但为了获得最佳体验,我们推荐使用 [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install)。WSL 提供了一个与 opencode 功能无缝协作的 Linux 环境。 + +:::tip[为什么使用 WSL?] +WSL 提供更好的文件系统性能、完整的终端支持,以及与 opencode 依赖的开发工具的兼容性。 +::: + +--- + +## 设置 + + + +1. **安装 WSL** + + 如果你还没有安装,请按照 Microsoft 官方指南 [安装 WSL](https://learn.microsoft.com/en-us/windows/wsl/install)。 + +2. **在 WSL 中安装 opencode** + + 完成 WSL 设置后,打开 WSL 终端并使用任一[安装方式](/docs/)安装 opencode。 + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **从 WSL 使用 opencode** + + 进入你的项目目录(可通过 `/mnt/c/`、`/mnt/d/` 等访问 Windows 文件)并运行 opencode。 + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## 桌面应用 + WSL 服务器 + +如果你想使用 opencode 桌面应用,但希望在 WSL 中运行服务器: + +1. **在 WSL 中启动服务器**,并使用 `--hostname 0.0.0.0` 以允许外部连接: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **将桌面应用连接到** `http://localhost:4096` + +:::note +如果你的环境中 `localhost` 不可用,请改用 WSL 的 IP 地址连接(在 WSL 中执行:`hostname -I`),并使用 `http://:4096`。 +::: + +:::caution +使用 `--hostname 0.0.0.0` 时,请设置 `OPENCODE_SERVER_PASSWORD` 来保护服务器。 + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## Web 客户端 + WSL + +在 Windows 上获得最佳 Web 体验: + +1. **请在 WSL 终端中运行 `opencode web`**,而不是在 PowerShell 中运行: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **在 Windows 浏览器中访问** `http://localhost:`(opencode 会打印该 URL) + +从 WSL 运行 `opencode web` 可以确保正确的文件系统访问和终端集成,同时仍可在 Windows 浏览器中访问。 + +--- + +## 访问 Windows 文件 + +WSL 可以通过 `/mnt/` 目录访问你所有的 Windows 文件: + +- `C:` drive → `/mnt/c/` +- `D:` drive → `/mnt/d/` +- 其他盘符同理 + +示例: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +为了获得更流畅的体验,建议将仓库克隆或复制到 WSL 文件系统中(例如 `~/code/`),并在那里运行 opencode。 +::: + +--- + +## 提示 + +- 即使项目存放在 Windows 盘符中,也建议在 WSL 中运行 opencode,文件访问会更顺畅 +- 可将 opencode 与 VS Code 的 [WSL 扩展](https://code.visualstudio.com/docs/remote/wsl)配合使用,形成一体化开发流程 +- opencode 的配置和会话会保存在 WSL 环境中的 `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/zh-cn/zen.mdx b/packages/web/src/content/docs/zh-cn/zen.mdx new file mode 100644 index 00000000000..1a2e77aabc6 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/zen.mdx @@ -0,0 +1,254 @@ +--- +title: 禪 +description: 由 opencode 提供的精选模型列表。 +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +Error 500 (Server Error)!!1500.That’s an error.There was an error. Please try again later.That’s all we know. + +:::note +OpenCode Zen 目前处于一个测试阶段。 +::: + +Zen 的工作方式与 opencode 中的任何其他提供商相同。您登录 OpenCode Zen 并获得 +你的API钥匙。它是**完全可选的**,你不需要使用它即可使用 +opencode。 + +--- + +## 背景 + +市面上有很多模型,但其中只有少數幾个 +这些模型可以很好地用作編碼代理。此外,大多數提供商都 +配置非常不同;所以你会得到截然不同的效能和質量。 + +:::tip +我们测试了一组与 opencode 配合良好的模型并提供商。 +::: + +因此,如果您使用 OpenRouter 之类的东西使用模型,您永远无法 +確定您是否獲得了您想要的模型的最佳版本。 + +为瞭解決这个問題,我们做了幾件事: + +1. 我们測試了一組選定的模型,并与他們的團隊討論瞭如何 + 最好执行它們。 +2. 然後我们与一些提供商合作以確保这些服務得到服務 + 正确。 +3. 最后,我们对 model/provider 的组合进行了基准测试,总结了 + 并附上一份我们覺得不錯的推薦清單。 + +OpenCode Zen 是一个AI闸道器,可以让您访问这些模型。 + +--- + +## 它是如何運作的 + +OpenCode Zen 的工作方式与 opencode 中的任何其他功能相同。 + +1. 您登录 **OpenCode Zen**,添加您的账单 + 详细信息,然后复制您的 API 密钥。 +2. 您在 TUI 中执行 `/connect` 命令,选择 OpenCode Zen,然后贴上 API 密钥。 +3. 在 TUI 中执行 `/models` 以查看我们推荐的模型列表。 + +您需要按请求付費,并且您可以将積分添加到您的账户中。 + +--- + +## 端点 + +您还可以通过以下 API 端点访问我们的模型。 + +| 模型 | 模型ID | 端点 | 人工智慧SDK包 | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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 配置中的 [model id](/docs/config/#models) +uses the format `opencode/`. For example, for GPT 5.2 Codex, you would +use `opencode/gpt-5.2-codex` in your config. + +--- + +### 模型 + +您可以從以下位置获取可用模型及其元数据的完整列表: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## 定价 + +我们支持即用即付模式。以下是**每 100 万Tokens的价格**。 + +| 模型 | 輸入 | 輸出 | 缓存讀取 | 缓存寫入 | +| ---------------------------------- | ---------- | ---------- | ---------- | ---------- | +| 大泡菜 | 免費 | 免費 | 免費 | - | +| MiniMax M2.1 免费 | 免费 | 免费 | 免费 | - | +| 迷你最大M2.1 | 0.30 美元 | 1.20 美元 | 0.10 美元 | - | +| GLM 4.7 免费 | 免费 | 免费 | 免费 | - | +| GLM 4.7 | 0.60 美元 | 2.20 美元 | 0.10 美元 | - | +| GLM 4.6 | 0.60 美元 | 2.20 美元 | 0.10 美元 | - | +| Kimi K2.5 免费 | 免费 | 免费 | 免费 | - | +| 作为K2.5 | 0.60 美元 | $3.00 | 0.08 美元 | - | +| Kimi K2 思考 | 0.40 美元 | 2.50 美元 | - | - | +| 作为K2 | 0.40 美元 | 2.50 美元 | - | - | +| Qwen3 编码器 480B | 0.45 美元 | 1.50 美元 | - | - | +| Claude Sonnet 4.5(≤ 200K Tokens) | $3.00 | 15.00 美元 | 0.30 美元 | 3.75 美元 | +| 克劳德十四行诗 4.5(> 200K 代币) | 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 俳句 4.5 | 1.00 美元 | 5.00 美元 | 0.10 美元 | 1.25 美元 | +| Claude 俳句 3.5 | 0.80 美元 | 4.00 美元 | 0.08 美元 | 1.00 美元 | +| 克劳德作品4.6(≤ 200K 代币) | 5.00 美元 | 25.00 美元 | 0.50 美元 | 6.25 美元 | +| Claude Opus 4.6(> 200K Tokens) | 10.00 美元 | 37.50 美元 | 1.00 美元 | 12.50 美元 | +| Claude 工作 4.5 | 5.00 美元 | 25.00 美元 | 0.50 美元 | 6.25 美元 | +| Claude 工作 4.1 | 15.00 美元 | 75.00 美元 | 1.50 美元 | 18.75 美元 | +| Gemini 3 Pro(≤20万代币) | 2.00 美元 | 12.00 美元 | 0.20 美元 | - | +| Gemini 3 Pro(>20万代币) | 4.00 美元 | 18.00 美元 | 0.40 美元 | - | +| 双子座 3 闪光 | 0.50 美元 | $3.00 | 0.05 美元 | - | +| GPT 5.2 | 1.75 美元 | 14.00 美元 | 0.175 美元 | - | +| GPT 5.2 法典 | 1.75 美元 | 14.00 美元 | 0.175 美元 | - | +| GPT 5.1 | 1.07 美元 | 8.50 美元 | 0.107 美元 | - | +| GPT 5.1 法典 | 1.07 美元 | 8.50 美元 | 0.107 美元 | - | +| GPT 5.1 法典最大 | 1.25 美元 | 10.00 美元 | 0.125 美元 | - | +| GPT 5.1 迷你版 | 0.25 美元 | 2.00 美元 | 0.025 美元 | - | +| GPT 5 | 1.07 美元 | 8.50 美元 | 0.107 美元 | - | +| GPT 5 法典 | 1.07 美元 | 8.50 美元 | 0.107 美元 | - | +| GPT 5 奈米 | 免费 | 免费 | 免费 | - | + +您可能会在您的使用历史记录中注意到*Claude Haiku 3.5*。这是一个[低成本模型](/docs/config/#models),用于生成会话标题。 + +:::note +信用卡费用按成本轉嫁(4.4% + 每筆交易 0.30 美元);除此之外我们不收取任何费用。 +::: + +免費模型: + +- GLM 4.7 免费版本在 opencode 上限时提供。团队正在利用这段时间收集反馈并改进模型。 +- Kimi K2.5 在 opencode 限时免费发布。团队正在利用这段时间收集反馈并改进模型。 +- MiniMax M2.1 在 opencode 限时免费供应。团队正在利用这段时间收集反馈并改进模型。 +- Big Pickle 是一个隐形模型,在 opencode 上限时免费。团队正在利用这个临时收集反馈并改进模型。 + +如果您有任何疑問,请聯絡我们。 + +--- + +### 自动重新載入 + +如果您的余额低于 5 美元,Zen 将自动充值 20 美元。 + +您可以更改自动充值金額。您还可以完全禁用自动重新載入。 + +--- + +### 每月限额 + +您还可以为整个工作区和每个工作区设置每月使用限制 +你的團隊成员。 + +例如,假设您将每月使用中断设置为 20 美元,Zen 将不会使用 +一个月超过 20 美元。但如果你启用了自动重新加载,Zen 可能会结束 +如果您的余额低于 5 美元,则向您收取超过 20 美元的费用。 + +--- + +## 隐私 + +我们所有的模型都在美国託管。我们的提供商遵循零保留政策,不会将您的数据用于模型训练,但以下情况除外: + +- Big Pickle:在免费期间,收集可用于改进模型的数据。 +- GLM 4.7 免费:在免费期间,收集可用于改进模型的数据。 +- Kimi K2.5 免费:在免费期间,收集可用于改进模型的数据。 +- MiniMax M2.1 免费:在免费期间,收集可用于改进模型的数据。 +- 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). + +--- + +## 对于团队 + +Zen 对团队也很有效。您可以参与第三方、角色、策划 +您的團隊使用的模型等等。 + +:::note +作为測試版的一部分,工作空間目前对團隊免費。 +::: + +作为測試版的一部分,管理工作空間目前对團隊免費。我们将会 +很快就会分享更多有關定價的細節。 + +--- + +### 角色 + +您可以邀请團隊成员到您的工作区并分配角色: + +- **管理员**:管理模型、成员、API 密钥和设备 +- **成员**:仅管理自己的API 金? + +管理员还可以为每个成员设置每月支出限额,以控制成本。 + +--- + +### 模型访问 + +管理员可以启用或禁用工作区的特定模型。对禁用模型发出的请求会返回错误。 + +这对于您想要禁用以下模型的情况很有帮助: +收集数据。 + +--- + +### 使用你自己的密钥 + +你可以使用自己的 OpenAI 或 Anthropic API 密钥,同时继续使用 Zen 的其他模型。 + +使用你自己的 API 密钥时,Tokens 会直接由对应提供商计费,而不是由 Zen 计费。 + +例如,你的组织可能已经有 OpenAI 或 Anthropic 的 API 密钥, +你希望优先使用它们,而不是 Zen 提供的密钥。 + +--- + +## 为什么使用 Zen + +我们构建 OpenCode Zen 是为了: + +1. **基准测试**最适合编码代理的 models/providers。 +2. 可以优先使用 **高质量** 选项,而不是被迫降级性能或改用更便宜的提供商。 +3. 通过按成本价计费传递任何**降价收益**,额外费用仅为处理费。 +4. 通过可与其他编码代理一起使用实现 **无锁定**,你也始终可以把其他提供商与 opencode 组合使用。 diff --git a/packages/web/src/content/docs/zh-tw/acp.mdx b/packages/web/src/content/docs/zh-tw/acp.mdx new file mode 100644 index 00000000000..26ddcff9003 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/acp.mdx @@ -0,0 +1,156 @@ +--- +title: ACP 支援 +description: 在任何 ACP 相容編輯器中使用 OpenCode。 +--- + +OpenCode 支援 [Agent Client Protocol](https://agentclientprotocol.com) 或 (ACP),允許您直接在相容的編輯器和 IDE 中使用它。 + +:::tip +有關支援 ACP 的編輯器和工具的列表,請查看 [ACP progress report](https://zed.dev/blog/acp-progress-report#available-now)。 +::: + +ACP 是一種開放協議,用於標準化程式碼編輯器和 AI 程式碼代理之間的通訊。 + +--- + +## 設定 + +要透過 ACP 使用 OpenCode,請將編輯器設定為執行 `opencode acp` 指令。 + +該指令將 OpenCode 作為 ACP 相容的子程序啟動,透過 stdio 透過 JSON-RPC 與您的編輯器進行通訊。 + +以下是支援 ACP 的流行編輯器的範例。 + +--- + +### Zed + +新增到您的 [Zed](https://zed.dev) 設定 (`~/.config/zed/settings.json`): + +```json title="~/.config/zed/settings.json" +{ + "agent_servers": { + "OpenCode": { + "command": "opencode", + "args": ["acp"] + } + } +} +``` + +要打開它,請使用 **命令面板** 中的 `agent: new thread` 操作。 + +您還可以透過編輯 `keymap.json` 來綁定鍵盤快速鍵: + +```json title="keymap.json" +[ + { + "bindings": { + "cmd-alt-o": [ + "agent::NewExternalAgentThread", + { + "agent": { + "custom": { + "name": "OpenCode", + "command": { + "command": "opencode", + "args": ["acp"] + } + } + } + } + ] + } + } +] +``` + +--- + +### JetBrains IDE + +根據 [文件](https://www.jetbrains.com/help/ai-assistant/acp.html) 新增到你的 [JetBrains IDE](https://www.jetbrains.com/) acp.json: + +```json title="acp.json" +{ + "agent_servers": { + "OpenCode": { + "command": "/absolute/path/bin/opencode", + "args": ["acp"] + } + } +} +``` + +要打開它,請在 AI Chat 代理選擇器中使用新的「opencode」代理。 + +--- + +### Avante.nvim + +新增到您的 [Avante.nvim](https://github.com/yetone/avante.nvim) 設定: + +```lua +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" } + } + } +} +``` + +如果需要傳遞環境變數: + +```lua {6-8} +{ + acp_providers = { + ["opencode"] = { + command = "opencode", + args = { "acp" }, + env = { + OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY") + } + } + } +} +``` + +--- + +### CodeCompanion.nvim + +要將 OpenCode 用作 [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim) 中的 ACP 代理,請將以下內容新增到 Neovim 設定中: + +```lua +require("codecompanion").setup({ + interactions = { + chat = { + adapter = { + name = "opencode", + model = "claude-sonnet-4", + }, + }, + }, +}) +``` + +此設定將 CodeCompanion 設定為使用 OpenCode 作為聊天的 ACP 代理。 + +如果您需要傳遞環境變數(如 `OPENCODE_API_KEY`),請參閱 CodeCompanion.nvim 文件中的 [設定適配器:環境變數](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) 了解完整詳細資訊。 + +## 支援 + +OpenCode 透過 ACP 的工作方式與在終端機中的工作方式相同。支援所有功能: + +:::note +目前不支援某些內建斜線指令,例如 `/undo` 和 `/redo`。 +::: + +- 內建工具(檔案操作、終端機指令等) +- 自定義工具和斜線指令 +- 在 OpenCode 設定中設定的 MCP 伺服器 +- `AGENTS.md` 的專案特定規則 +- 自定義格式化程式和 linter +- 代理和權限系統 diff --git a/packages/web/src/content/docs/zh-tw/agents.mdx b/packages/web/src/content/docs/zh-tw/agents.mdx new file mode 100644 index 00000000000..c4d3d656bca --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/agents.mdx @@ -0,0 +1,746 @@ +--- +title: 代理 +description: 設定和使用專門的代理。 +--- + +代理是專門的 AI 助理,可以針對特定任務和工作流程進行設定。它們允許您建立具有自定義提示、模型和工具存取權限的專用工具。 + +:::tip +使用計畫代理來分析程式碼並審閱建議,而無需進行任何程式碼變更。 +::: + +您可以在工作階段期間在代理之間切換,或使用 `@` 提及來呼叫它們。 + +--- + +## 類型 + +opencode 中有兩種類型的代理;主要代理和子代理。 + +--- + +### 主要代理 + +主要代理是與您直接互動的主要助理。您可以使用 **Tab** 鍵或您設定的 `switch_agent` 鍵綁定循環切換它們。這些代理處理您的主要對話。工具存取是透過權限設定的 - 例如,「Build」啟用了所有工具,而「Plan」則受到限制。 + +:::tip +您可以在工作階段期間使用 **Tab** 鍵在主要代理之間切換。 +::: + +opencode 附帶兩個內建的主要代理:**Build** 和 **Plan**。我們將在下面看看這些。 + +--- + +### 子代理 + +子代理是主要代理可以呼叫來執行特定任務的專業助理。您也可以透過在訊息中 **@提及** 它們來手動呼叫它們。 + +opencode 附帶兩個內建子代理:**General** 和 **Explore**。我們將在下面看看這個。 + +--- + +## 內建 + +opencode 附帶兩個內建主代理和兩個內建子代理。 + +--- + +### 使用 Build (構建) + +_模式_:`primary` + +Build 是啟用所有工具的**預設**主要代理。這是用於需要完全存取檔案操作和系統指令的開發工作的標準代理。 + +--- + +### 使用 Plan (計畫) + +_模式_:`primary` + +專為規劃和分析而設計的受限代理。我們使用權限系統為您提供更多控制並防止意外變更。 +預設情況下,以下所有項均設定為 `ask`: + +- `file edits`:所有寫入、修補和編輯 +- `bash`:所有 bash 指令 + +當您希望 LLM 分析程式碼、建議變更或建立計畫而不對程式碼庫進行任何實際修改時,此代理非常有用。 + +--- + +### 使用 General (一般) + +_模式_:`subagent` + +用於研究複雜問題和執行多步驟任務的通用代理。具有完整的工具存取權限(待辦事項除外),因此可以在需要時變更檔案。使用它可以並行執行多個工作單元。 + +--- + +### 使用 Explore (探索) + +_模式_:`subagent` + +用於探索程式碼庫的快速唯讀代理。無法修改檔案。當您需要按模式快速尋找檔案、搜尋程式碼中的關鍵字或回答有關程式碼庫的問題時,請使用此功能。 + +--- + +### 使用 Compact (壓縮) + +_模式_:`primary` + +隱藏的系統代理,將長上下文壓縮為較小的摘要。它會在需要時自動執行,並且無法在 UI 中選擇。 + +--- + +### 使用 Title (標題) + +_模式_:`primary` + +生成短工作階段標題的隱藏系統代理。它會自動執行,並且無法在 UI 中選擇。 + +--- + +### 使用 Summarize (摘要) + +_模式_:`primary` + +建立工作階段摘要的隱藏系統代理。它會自動執行,並且無法在 UI 中選擇。 + +--- + +## 用法 + +1. 對於主要代理,請在工作階段期間使用 **Tab** 鍵循環切換它們。您也可以使用設定的 `switch_agent` 鍵綁定。 + +2. 可以呼叫子代理: + - **自動**由主要代理根據其描述執行專門任務。 + - 透過在訊息中 **@提及** 子代理手動進行。例如: + + ```txt frame="none" + @general help me search for this function + ``` + +3. **工作階段之間導航**:當子代理建立自己的子工作階段時,您可以使用以下指令在父工作階段和所有子工作階段之間導航: + - **\+Right**(或您設定的 `session_child_cycle` 鍵綁定)向前循環父級 → 子級 1 → 子級 2 → ... → 父級 + - **\+Left**(或您設定的 `session_child_cycle_reverse` 鍵綁定)向後循環父級 ← 子級 1 ← 子級 2 ← ... ← 父級 + + 這使您可以在主要對話和專門的子代理工作之間無縫切換。 + +--- + +## 設定 + +您可以自定義內建代理或透過設定建立您自己的代理。可以透過兩種方式設定代理: + +--- + +### JSON + +在 `opencode.json` 設定檔中設定代理: + +```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 + +您也可以使用 Markdown 檔案定義代理。將它們放入: + +- 全域:`~/.config/opencode/agents/` +- 每個專案:`.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 檔名成為代理名稱。例如,`review.md` 建立 `review` 代理。 + +--- + +## 選項 + +讓我們詳細看看這些設定選項。 + +--- + +### 描述 (Description) + +使用 `description` 選項提供代理的作用以及何時使用它的簡要描述。 + +```json title="opencode.json" +{ + "agent": { + "review": { + "description": "Reviews code for best practices and potential issues" + } + } +} +``` + +這是一個**必需的**設定選項。 + +--- + +### 溫度 (Temperature) + +使用 `temperature` 設定控制 LLM 回應的隨機性和創造性。 + +較低的值使回應更加集中和確定,而較高的值則增加創造力和可變性。 + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +溫度值的範圍通常為 0.0 到 1.0: + +- **0.0-0.2**:非常集中且確定的回應,非常適合程式碼分析和規劃 +- **0.3-0.5**:具有一定創造力的平衡回應,適合一般開發任務 +- **0.6-1.0**:更有創意和多樣化的反應,有助於腦力激盪和探索 + +```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}" + } + } +} +``` + +如果未指定溫度,opencode 將使用特定於模型的預設值;大多數模型通常為 0,Qwen 模型為 0.55。 + +--- + +### 最大步數 (Steps) + +控制代理在被迫僅使用文字回應之前可以執行的最大代理迭代次數。這允許希望控制成本的使用者對代理操作設定限制。 + +如果未設定,代理將繼續迭代,直到模型選擇停止或使用者中斷工作階段。 + +```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 + } + } +} +``` + +當達到限制時,代理會收到特殊的系統提示,指示其回應其工作摘要和建議的剩餘任務。 + +:::caution +舊版 `maxSteps` 欄位已棄用。請改用 `steps`。 +::: + +--- + +### 禁用 (Disable) + +設定為 `true` 以禁用代理。 + +```json title="opencode.json" +{ + "agent": { + "review": { + "disable": true + } + } +} +``` + +--- + +### 提示 (Prompt) + +使用 `prompt` 設定為此代理指定自定義系統提示檔案。提示檔案應包含特定於代理目的的說明。 + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +該路徑是相對於設定檔所在位置的。因此,這適用於全域 opencode 設定和專案特定設定。 + +--- + +### 模型 (Model) + +使用 `model` 設定覆蓋此代理的模型。對於使用針對不同任務最佳化的不同模型很有用。例如,更快的規劃模型、更強大的實作模型。 + +:::tip +如果您不指定模型,主代理將使用 [全域設定的模型](/docs/config#models),而子代理將使用呼叫子代理的主代理的模型。 +::: + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +opencode 設定中的模型 ID 使用格式 `provider/model-id`。例如,如果您使用 [OpenCode Zen](/docs/zen),則您將使用 `opencode/gpt-5.1-codex` 來表示 GPT 5.1 Codex。 + +--- + +### 工具 (Tools) + +使用 `tools` 設定控制此代理中可用的工具。您可以透過將特定工具設定為 `true` 或 `false` 來啟用或禁用特定工具。 + +```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 +特定於代理的設定會覆蓋全域設定。 +::: + +您也可以使用萬用字元同時控制多個工具。例如,要禁用 MCP 伺服器中的所有工具: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "readonly": { + "tools": { + "mymcp_*": false, + "write": false, + "edit": false + } + } + } +} +``` + +[了解有關工具的更多資訊](/docs/tools)。 + +--- + +### 權限 (Permissions) + +您可以設定權限來管理代理可以執行的操作。目前,`edit`、`bash` 和 `webfetch` 工具的權限可以設定為: + +- `"ask"` — 執行工具之前提示批准 +- `"allow"` — 未經批准允許所有操作 +- `"deny"` — 禁用該工具 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + } +} +``` + +您可以覆蓋每個代理的這些權限。 + +```json title="opencode.json" {3-5,8-10} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny" + }, + "agent": { + "build": { + "permission": { + "edit": "ask" + } + } + } +} +``` + +您還可以在 Markdown 代理中設定權限。 + +```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. +``` + +您可以設定特定 bash 指令的權限。 + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git push": "ask", + "grep *": "allow" + } + } + } + } +} +``` + +這可以採用全域模式。 + +```json title="opencode.json" {7} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "git *": "ask" + } + } + } + } +} +``` + +您也可以使用 `*` 萬用字元來管理所有指令的權限。 +由於最後一個匹配規則優先,因此將 `*` 萬用字元放在前面,將特定規則放在後面。 + +```json title="opencode.json" {8} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git status *": "allow" + } + } + } + } +} +``` + +[了解有關權限的更多資訊](/docs/permissions)。 + +--- + +### 模式 (Mode) + +使用 `mode` 設定控制代理的模式。 `mode` 選項用於確定如何使用代理。 + +```json title="opencode.json" +{ + "agent": { + "review": { + "mode": "subagent" + } + } +} +``` + +`mode` 選項可設定為 `primary`、`subagent` 或 `all`。如果未指定 `mode`,則預設為 `all`。 + +--- + +### 隱藏 (Hidden) + +使用 `@` 從 `hidden: true` 自動完成選單隱藏子代理。對於只能由其他代理透過任務工具以程式化方式呼叫的內部子代理很有用。 + +```json title="opencode.json" +{ + "agent": { + "internal-helper": { + "mode": "subagent", + "hidden": true + } + } +} +``` + +這僅影響自動完成選單中的使用者可見性。如果權限允許,模型仍然可以透過任務工具呼叫隱藏代理。 + +:::note +僅適用於 `mode: subagent` 代理。 +::: + +--- + +### 任務權限 (Task Permissions) + +使用 `permission.task` 控制代理可以透過任務工具呼叫哪些子代理。使用 glob 模式進行靈活匹配。 + +```json title="opencode.json" +{ + "agent": { + "orchestrator": { + "mode": "primary", + "permission": { + "task": { + "*": "deny", + "orchestrator-*": "allow", + "code-reviewer": "ask" + } + } + } + } +} +``` + +當設定為 `deny` 時,子代理將從任務工具描述中完全刪除,因此模型不會嘗試呼叫它。 + +:::tip +規則按順序評估,**最後匹配的規則獲勝**。在上面的範例中,`orchestrator-planner` 匹配 `*`(拒絕)和 `orchestrator-*`(允許),但由於 `orchestrator-*` 位於 `*` 之後,因此結果為 `allow`。 +::: + +:::tip +使用者始終可以透過 `@` 自動完成選單直接呼叫任何子代理,即使代理的任務權限會拒絕它。 +::: + +--- + +### 顏色 (Color) + +使用 `color` 選項自定義代理在 UI 中的視覺外觀。這會影響代理在介面中的顯示方式。 + +使用有效的十六進位顏色(例如 `#FF5733`)或主題顏色:`primary`、`secondary`、`accent`、`success`、`warning`、`error`、`info`。 + +```json title="opencode.json" +{ + "agent": { + "creative": { + "color": "#ff6b6b" + }, + "code-reviewer": { + "color": "accent" + } + } +} +``` + +--- + +### Top P + +使用 `top_p` 選項控制回應多樣性。控制隨機性的溫度替代方案。 + +```json title="opencode.json" +{ + "agent": { + "brainstorm": { + "top_p": 0.9 + } + } +} +``` + +值範圍從 0.0 到 1.0。較低的值更加集中,較高的值更加多樣化。 + +--- + +### 額外選項 (Extra) + +您在代理設定中指定的任何其他選項都將作為模型選項**直接**傳遞給供應商。這允許您使用特定於供應商的功能和參數。 + +例如,使用 OpenAI 的推理模型,您可以控制推理工作: + +```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" + } + } +} +``` + +這些附加選項是特定於模型和供應商的。檢查供應商的文件以獲取可用參數。 + +:::tip +執行 `opencode models` 查看可用模型的列表。 +::: + +--- + +## 建立代理 + +您可以使用以下指令建立新代理: + +```bash +opencode agent create +``` + +此互動式指令將: + +1. 詢問代理保存在哪裡;全域或特定專案。 +2. 描述代理應該做什麼。 +3. 生成適當的系統提示和標識符。 +4. 讓您選擇代理可以存取哪些工具。 +5. 最後,使用代理設定建立一個 markdown 檔案。 + +--- + +## 使用案例 + +以下是不同代理的一些常見使用案例。 + +- **Build 代理**:啟用所有工具的完整開發工作 +- **Plan 代理**:分析規劃,不做改動 +- **Review 代理**:具有唯讀存取權限和文件工具的程式碼審查 +- **Debug 代理**:專注於啟用 bash 和讀取工具的調查 +- **Docs 代理**:使用檔案操作但不使用系統指令的文件編寫 + +--- + +## 範例 + +以下是一些您可能會覺得有用的範例代理。 + +:::tip +您有想要分享的代理嗎? [提交 PR](https://github.com/anomalyco/opencode)。 +::: + +--- + +### 文件代理 + +```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 +``` + +--- + +### 安全稽核員 + +```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/zh-tw/cli.mdx b/packages/web/src/content/docs/zh-tw/cli.mdx new file mode 100644 index 00000000000..580526524bf --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/cli.mdx @@ -0,0 +1,603 @@ +--- +title: 命令列介面 +description: opencode CLI 選項和指令。 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +預設情況下,OpenCode CLI 在不帶任何參數執行時啟動 [TUI](/docs/tui)。 + +```bash +opencode +``` + +但它也接受本頁記錄的指令。這允許您以程式化方式與 OpenCode 互動。 + +```bash +opencode run "Explain how closures work in JavaScript" +``` + +--- + +### tui + +啟動 OpenCode TUI。 + +```bash +opencode [project] +``` + +#### 旗標 (Flags) + +| 旗標 | 簡寫 | 說明 | +| ------------ | ---- | ------------------------------------------------------------- | +| `--continue` | `-c` | 繼續上一個工作階段 | +| `--session` | `-s` | 繼續指定的工作階段 ID | +| `--fork` | | 繼續時分岔工作階段(與 `--continue` 或 `--session` 一起使用) | +| `--prompt` | | 使用的提示 | +| `--model` | `-m` | 使用的模型 (provider/model) | +| `--agent` | | 使用的代理 | +| `--port` | | 監聽連接埠 | +| `--hostname` | | 監聽的主機名稱 | + +--- + +## 指令 + +OpenCode CLI 還具有以下指令。 + +--- + +### agent + +管理 OpenCode 代理。 + +```bash +opencode agent [command] +``` + +--- + +### attach + +將終端機連接到透過 `serve` 或 `web` 指令啟動的已執行的 OpenCode 後端伺服器。 + +```bash +opencode attach [url] +``` + +這允許將 TUI 與遠端 OpenCode 後端一起使用。例如: + +```bash +# Start the backend server for web/mobile access +opencode web --port 4096 --hostname 0.0.0.0 + +# In another terminal, attach the TUI to the running backend +opencode attach http://10.20.30.40:4096 +``` + +#### 旗標 + +| 旗標 | 簡寫 | 說明 | +| ----------- | ---- | --------------------- | +| `--dir` | | 啟動 TUI 的工作目錄 | +| `--session` | `-s` | 繼續指定的工作階段 ID | + +--- + +#### create + +使用自定義設定建立新代理。 + +```bash +opencode agent create +``` + +此指令將指導您使用自定義系統提示和工具設定建立新代理。 + +--- + +#### list + +列出所有可用的代理。 + +```bash +opencode agent list +``` + +--- + +### auth + +用於管理供應商的憑證和登入的指令。 + +```bash +opencode auth [command] +``` + +--- + +#### login + +OpenCode 由 [Models.dev](https://models.dev) 上的供應商列表提供支援,因此您可以使用 `opencode auth login` 為您想要使用的任何供應商設定 API 金鑰。它儲存在 `~/.local/share/opencode/auth.json` 中。 + +```bash +opencode auth login +``` + +當 OpenCode 啟動時,它會從憑證檔案載入供應商。如果您的環境中定義了任何金鑰或專案中的 `.env` 檔案。 + +--- + +#### list + +列出憑證檔案中儲存的所有經過身分驗證的供應商。 + +```bash +opencode auth list +``` + +或者簡短的版本。 + +```bash +opencode auth ls +``` + +--- + +#### logout + +透過從憑證檔案中清除供應商,將您從供應商中登出。 + +```bash +opencode auth logout +``` + +--- + +### github + +管理 GitHub 代理以實現儲存庫自動化。 + +```bash +opencode github [command] +``` + +--- + +#### install + +在您的儲存庫中安裝 GitHub 代理。 + +```bash +opencode github install +``` + +這將設定必要的 GitHub Actions 工作流程並指導您完成設定過程。 [了解更多](/docs/github)。 + +--- + +#### run + +執行 GitHub 代理。這通常用在 GitHub Actions 中。 + +```bash +opencode github run +``` + +##### 旗標 + +| 旗標 | 說明 | +| --------- | ------------------------------ | +| `--event` | 用於執行代理的 GitHub 模擬事件 | +| `--token` | GitHub 個人存取權杖 | + +--- + +### mcp + +管理模型上下文協議 (MCP) 伺服器。 + +```bash +opencode mcp [command] +``` + +--- + +#### add + +將 MCP 伺服器新增到您的設定中。 + +```bash +opencode mcp add +``` + +此指令將指導您新增本地或遠端 MCP 伺服器。 + +--- + +#### list + +列出所有已設定的 MCP 伺服器及其連線狀態。 + +```bash +opencode mcp list +``` + +或者使用簡短版本。 + +```bash +opencode mcp ls +``` + +--- + +#### auth + +使用啟用 OAuth 的 MCP 伺服器進行身分驗證。 + +```bash +opencode mcp auth [name] +``` + +如果您不提供伺服器名稱,系統將提示您從可用的支援 OAuth 的伺服器中進行選擇。 + +您還可以列出支援 OAuth 的伺服器及其身分驗證狀態。 + +```bash +opencode mcp auth list +``` + +或者使用簡短版本。 + +```bash +opencode mcp auth ls +``` + +--- + +#### logout + +刪除 MCP 伺服器的 OAuth 憑證。 + +```bash +opencode mcp logout [name] +``` + +--- + +#### debug + +除錯 MCP 伺服器的 OAuth 連線問題。 + +```bash +opencode mcp debug +``` + +--- + +### models + +列出已設定供應商的所有可用模型。 + +```bash +opencode models [provider] +``` + +此指令以 `provider/model` 格式顯示您設定的供應商中可用的所有模型。 + +這對於確定 [你的設定](/docs/config/) 中使用的確切模型名稱很有用。 + +您可以選擇傳遞供應商 ID 以按該供應商篩選模型。 + +```bash +opencode models anthropic +``` + +#### 旗標 + +| 旗標 | 說明 | +| ----------- | ---------------------------------------- | +| `--refresh` | 從 models.dev 刷新模型快取 | +| `--verbose` | 使用更詳細的模型輸出(包括成本等元資料) | + +使用 `--refresh` 旗標來更新快取的模型列表。當新模型已新增到供應商並且您希望在 OpenCode 中查看它們時,這非常有用。 + +```bash +opencode models --refresh +``` + +--- + +### run + +透過直接傳遞提示以非互動模式執行 opencode。 + +```bash +opencode run [message..] +``` + +這對於撰寫指令碼、自動化,或者當您想要快速得到答案而不啟動完整的 TUI 時非常有用。例如: + +```bash "opencode run" +opencode run Explain the use of context in Go +``` + +您還可以附加到正在執行的 `opencode serve` 實例,以避免每次執行時 MCP 伺服器冷啟動時間: + +```bash +# Start a headless server in one terminal +opencode serve + +# In another terminal, run commands that attach to it +opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" +``` + +#### 旗標 + +| 旗標 | 短 | 說明 | +| ------------ | ---- | --------------------------------------------------------------- | +| `--command` | | 要執行的指令,使用訊息作為參數 | +| `--continue` | `-c` | 繼續上一個工作階段 | +| `--session` | `-s` | 繼續指定的工作階段 ID | +| `--fork` | | 繼續時分岔工作階段(與 `--continue` 或 `--session` 一起使用) | +| `--share` | | 分享工作階段 | +| `--model` | `-m` | 使用的模型 (provider/model) | +| `--agent` | | 使用的代理 | +| `--file` | `-f` | 要附加到訊息的檔案 | +| `--format` | | 格式:預設 (formatted) 或 json (原始 JSON 事件) | +| `--title` | | 工作階段標題(如果未提供值,則使用截斷的提示) | +| `--attach` | | 連接到正在執行的 opencode 伺服器(例如,http://localhost:4096) | +| `--port` | | 本地伺服器的連接埠(預設為隨機連接埠) | + +--- + +### serve + +啟動無介面 opencode 伺服器以進行 API 存取。查看 [伺服器文件](/docs/server) 以獲取完整的 HTTP 介面。 + +```bash +opencode serve +``` + +這將啟動一個 HTTP 伺服器,該伺服器提供對 opencode 功能的 API 存取,而無需 TUI 介面。設定 `OPENCODE_SERVER_PASSWORD` 以啟用 HTTP 基本身分驗證(使用者名稱預設為 `opencode`)。 + +#### 旗標 + +| 旗標 | 說明 | +| ------------ | -------------------------- | +| `--port` | 監聽連接埠 | +| `--hostname` | 監聽的主機名稱 | +| `--mdns` | 啟用 mDNS 探索 | +| `--cors` | 允許 CORS 的其他瀏覽器來源 | + +--- + +### session + +管理 opencode 工作階段。 + +```bash +opencode session [command] +``` + +--- + +#### list + +列出所有 opencode 工作階段。 + +```bash +opencode session list +``` + +##### 旗標 + +| 旗標 | 短 | 說明 | +| ------------- | ---- | ------------------------------ | +| `--max-count` | `-n` | 限制為最近 N 個工作階段 | +| `--format` | | 輸出格式:table 或 json(table) | + +--- + +### stats + +顯示 opencode 工作階段的 Tokens 使用情況和成本統計資訊。 + +```bash +opencode stats +``` + +#### 旗標 + +| 旗標 | 說明 | +| ----------- | -------------------------------------------------------- | +| `--days` | 顯示過去 N 天(所有時間)的統計數據 | +| `--tools` | 顯示的工具數量(全部) | +| `--models` | 顯示模型使用情況細分(預設隱藏)。傳遞一個數字來顯示前 N | +| `--project` | 按專案過濾(所有專案,空字串:當前專案) | + +--- + +### export + +將工作階段數據導出為 JSON。 + +```bash +opencode export [sessionID] +``` + +如果您不提供工作階段 ID,系統將提示您從可用工作階段中進行選擇。 + +--- + +### import + +從 JSON 檔案或 opencode 分享 URL 匯入工作階段數據。 + +```bash +opencode import +``` + +您以從本地檔案或 opencode 分享 URL 匯入。 + +```bash +opencode import session.json +opencode import https://opncd.ai/s/abc123 +``` + +--- + +### web + +使用 Web 介面啟動無介面 opencode 伺服器。 + +```bash +opencode web +``` + +這將啟動 HTTP 伺服器並打開網頁瀏覽器以透過 Web 介面存取 opencode。設定 `OPENCODE_SERVER_PASSWORD` 以啟用 HTTP 基本身分驗證(使用者名稱預設為 `opencode`)。 + +#### 旗標 + +| 旗標 | 說明 | +| ------------ | -------------------------- | +| `--port` | 監聽連接埠 | +| `--hostname` | 監聽的主機名稱 | +| `--mdns` | 啟用 mDNS 探索 | +| `--cors` | 允許 CORS 的其他瀏覽器來源 | + +--- + +### acp + +啟動 ACP (Agent Client Protocol) 伺服器。 + +```bash +opencode acp +``` + +此指令啟動一個 ACP 伺服器,該伺服器使用 nd-JSON 透過 stdin/stdout 進行通訊。 + +#### 旗標 + +| 旗標 | 說明 | +| ------------ | -------------- | +| `--cwd` | 工作目錄 | +| `--port` | 監聽連接埠 | +| `--hostname` | 監聽的主機名稱 | + +--- + +### uninstall + +解除安裝 opencode 並刪除所有相關檔案。 + +```bash +opencode uninstall +``` + +#### 旗標 + +| 旗標 | 短 | 說明 | +| --------------- | ---- | -------------------------------- | +| `--keep-config` | `-c` | 保留設定檔 | +| `--keep-data` | `-d` | 保留工作階段數據和快照 | +| `--dry-run` | | 顯示在不刪除的情況下將刪除的內容 | +| `--force` | `-f` | 跳過確認提示 | + +--- + +### upgrade + +將 opencode 更新到最新版本或特定版本。 + +```bash +opencode upgrade [target] +``` + +升級到最新版本。 + +```bash +opencode upgrade +``` + +升級到特定版本。 + +```bash +opencode upgrade v0.1.48 +``` + +#### 旗標 + +| 旗標 | 簡寫 | 說明 | +| ---------- | ---- | ------------------------------------------ | +| `--method` | `-m` | 使用的安裝方法;curl、npm、pnpm、bun、brew | + +--- + +## 全域旗標 + +opencode CLI 採用以下全域旗標。 + +| 旗標 | 短 | 說明 | +| -------------- | ---- | ------------------------------------ | +| `--help` | `-h` | 顯示說明 | +| `--version` | `-v` | 列印版本號 | +| `--print-logs` | | 將記錄列印到 stderr | +| `--log-level` | | 記錄等級(debug, info, warn, error) | + +--- + +## 環境變數 + +可以使用環境變數設定 opencode。 + +| 變數 | 類型 | 說明 | +| ------------------------------------- | ------- | --------------------------------------------- | +| `OPENCODE_AUTO_SHARE` | boolean | 自動分享工作階段 | +| `OPENCODE_GIT_BASH_PATH` | string | Windows 上 Git Bash 可執行檔案的路徑 | +| `OPENCODE_CONFIG` | string | 設定檔路徑 | +| `OPENCODE_CONFIG_DIR` | string | 設定目錄的路徑 | +| `OPENCODE_CONFIG_CONTENT` | string | 內聯 json 設定內容 | +| `OPENCODE_DISABLE_AUTOUPDATE` | boolean | 禁用自動更新檢查 | +| `OPENCODE_DISABLE_PRUNE` | boolean | 禁用舊數據的修剪 | +| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | 禁用自動終端機標題更新 | +| `OPENCODE_PERMISSION` | string | 內聯 json 權限設定 | +| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | 禁用預設外掛 | +| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | 禁用自動 LSP 伺服器下載 | +| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | 啟用實驗模型 | +| `OPENCODE_DISABLE_AUTOCOMPACT` | boolean | 禁用自動上下文壓縮 | +| `OPENCODE_DISABLE_CLAUDE_CODE` | boolean | 禁止從 `.claude` 讀取(提示+技巧) | +| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | 禁用讀取 `~/.claude/CLAUDE.md` | +| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | 禁用載入 `.claude/skills` | +| `OPENCODE_DISABLE_MODELS_FETCH` | boolean | 禁用從遠端來源獲取模型 | +| `OPENCODE_FAKE_VCS` | string | 用於測試目的的假 VCS 供應商 | +| `OPENCODE_DISABLE_FILETIME_CHECK` | boolean | 禁用檔案時間檢查以進行最佳化 | +| `OPENCODE_CLIENT` | string | 客戶端標識符(預設為 `cli`) | +| `OPENCODE_ENABLE_EXA` | boolean | 啟用 Exa 網路搜尋工具 | +| `OPENCODE_SERVER_PASSWORD` | string | 為 `serve`/`web` 啟用基本身分驗證 | +| `OPENCODE_SERVER_USERNAME` | string | 覆蓋基本身分驗證使用者名稱(預設 `opencode`) | +| `OPENCODE_MODELS_URL` | string | 用於獲取模型設定的自定義 URL | + +--- + +### 實驗性的 + +這些環境變數啟用可能會更改或刪除的實驗性功能。 + +| 變數 | 類型 | 說明 | +| ----------------------------------------------- | ------- | ----------------------------------- | +| `OPENCODE_EXPERIMENTAL` | boolean | 啟用所有實驗性功能 | +| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | 啟用圖示探索 | +| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | 在 TUI 中禁用選擇時複製 | +| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number | bash 指令的預設超時(以毫秒為單位) | +| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | number | LLM 回應的最大輸出 tokens | +| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolean | 為整個目錄啟用檔案觀察器 | +| `OPENCODE_EXPERIMENTAL_OXFMT` | boolean | 啟用 oxfmt 格式化程式 | +| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolean | 啟用實驗性 LSP 工具 | +| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | 禁用檔案觀察器 | +| `OPENCODE_EXPERIMENTAL_EXA` | boolean | 啟用實驗性 Exa 功能 | +| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolean | 啟用實驗性 LSP 類型檢查 | +| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolean | 啟用實驗性 Markdown 功能 | +| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolean | 啟用計畫模式 | diff --git a/packages/web/src/content/docs/zh-tw/commands.mdx b/packages/web/src/content/docs/zh-tw/commands.mdx new file mode 100644 index 00000000000..88069e27196 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/commands.mdx @@ -0,0 +1,322 @@ +--- +title: 指令 +description: 為重複任務建立自定義指令。 +--- + +自定義指令允許您指定在 TUI 中執行該指令時要執行的提示。 + +```bash frame="none" +/my-command +``` + +除了 `/init`、`/undo`、`/redo`、`/share`、`/help` 等內建指令之外,還有自定義指令。 [了解更多](/docs/tui#commands)。 + +--- + +## 建立指令檔案 + +在 `commands/` 目錄中建立 markdown 檔案來定義自定義指令。 + +建立 `.opencode/commands/test.md`: + +```md title=".opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +frontmatter 定義指令屬性。內容成為範本。 + +透過輸入 `/` 後跟指令名稱來使用該指令。 + +```bash frame="none" +"/test" +``` + +--- + +## 設定 + +您 可以透過 opencode 設定或透過在 `commands/` 目錄中建立 markdown 檔案來新增自定義指令。 + +--- + +### JSON + +在 opencode [設定](/docs/config) 中使用 `command` 選項: + +```json title="opencode.jsonc" {4-12} +{ + "$schema": "https://opencode.ai/config.json", + "command": { + // This becomes the name of the command + "test": { + // This is the prompt that will be sent to the LLM + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + // This is shown as the description in the TUI + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +現在您可以在 TUI 中執行此指令: + +```bash frame="none" +/test +``` + +--- + +### Markdown + +您也可以使用 Markdown 檔案定義指令。將它們放入: + +- 全域:`~/.config/opencode/commands/` +- 每個專案:`.opencode/commands/` + +```markdown title="~/.config/opencode/commands/test.md" +--- +description: Run tests with coverage +agent: build +model: anthropic/claude-3-5-sonnet-20241022 +--- + +Run the full test suite with coverage report and show any failures. +Focus on the failing tests and suggest fixes. +``` + +Markdown 檔名成為指令名。例如,`test.md` 讓您執行: + +```bash frame="none" +/test +``` + +--- + +## 提示設定 + +自定義指令的提示支援幾個特殊的預留位置和語法。 + +--- + +### 參數 (Arguments) + +使用 `$ARGUMENTS` 預留位置將參數傳遞給指令。 + +```md title=".opencode/commands/component.md" +--- +description: Create a new component +--- + +Create a new React component named $ARGUMENTS with TypeScript support. +Include proper typing and basic structure. +``` + +使用參數執行指令: + +```bash frame="none" +/component Button +``` + +`$ARGUMENTS` 將替換為 `Button`。 + +您也可以使用位置參數存取各個參數: + +- `$1` - 第一個參數 +- `$2` - 第二個參數 +- `$3` - 第三個參數 +- 等等... + +例如: + +```md title=".opencode/commands/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +執行指令: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +這取代了: + +- `$1` 與 `config.json` +- `$2` 與 `src` +- `$3` 與 `{ "key": "value" }` + +--- + +### Shell 輸出 + +使用 _!`command`_ 將 [bash 指令](/docs/tui#bash-commands) 輸出注入到提示中。 + +例如,要建立分析測試覆蓋率的自定義指令: + +```md title=".opencode/commands/analyze-coverage.md" +--- +description: Analyze test coverage +--- + +Here are the current test results: +!`npm test` + +Based on these results, suggest improvements to increase coverage. +``` + +或者查看最近的變更: + +```md title=".opencode/commands/review-changes.md" +--- +description: Review recent changes +--- + +Recent git commits: +!`git log --oneline -10` + +Review these changes and suggest any improvements. +``` + +指令在專案的根目錄中執行,其輸出成為提示的一部分。 + +--- + +### 檔案參考 + +使用 `@` 後跟檔名將檔案包含在指令中。 + +```md title=".opencode/commands/review-component.md" +--- +description: Review component +--- + +Review the component in @src/components/Button.tsx. +Check for performance issues and suggest improvements. +``` + +檔案內容會自動包含在提示中。 + +--- + +## 選項 + +讓我們詳細看看設定選項。 + +--- + +### 範本 (Template) + +`template` 選項定義執行指令時將發送到 LLM 的提示。 + +```json title="opencode.json" +{ + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." + } + } +} +``` + +這是一個**必需的**設定選項。 + +--- + +### 描述 (Description) + +使用 `description` 選項提供指令功能的簡要描述。 + +```json title="opencode.json" +{ + "command": { + "test": { + "description": "Run tests with coverage" + } + } +} +``` + +當您輸入指令時,這將在 TUI 中顯示為描述。 + +--- + +### 代理 (Agent) + +使用 `agent` 設定可選擇指定哪個 [代理](/docs/agents) 應執行此指令。 +如果這是 [子代理](/docs/agents/#subagents),該指令將預設觸發子代理呼叫。 +要禁用此行為,請將 `subtask` 設定為 `false`。 + +```json title="opencode.json" +{ + "command": { + "review": { + "agent": "plan" + } + } +} +``` + +這是一個**可選**設定選項。如果未指定,則預設為您當前的代理。 + +--- + +### 子任務 (Subtask) + +使用 `subtask` 布林值強制指令觸發 [子代理](/docs/agents/#subagents) 呼叫。 +如果您希望指令不污染您的主要上下文並且將**強制**代理充當子代理,那麼這非常有用, +即使 `mode` 在 [代理](/docs/agents) 設定上設定為 `primary`。 + +```json title="opencode.json" +{ + "command": { + "analyze": { + "subtask": true + } + } +} +``` + +這是一個**可選**設定選項。 + +--- + +### 模型 (Model) + +使用 `model` 設定覆寫此指令的預設模型。 + +```json title="opencode.json" +{ + "command": { + "analyze": { + "model": "anthropic/claude-3-5-sonnet-20241022" + } + } +} +``` + +這是一個**可選**設定選項。 + +--- + +### 內建 + +opencode 包含 `/init`、`/undo`、`/redo`、`/share`、`/help` 等內建指令; [了解更多](/docs/tui#commands)。 + +:::note +自定義指令可以覆寫內建指令。 +::: + +如果您定義同名的自定義指令,它將覆寫內建指令。 diff --git a/packages/web/src/content/docs/zh-tw/config.mdx b/packages/web/src/content/docs/zh-tw/config.mdx new file mode 100644 index 00000000000..817b08673b1 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/config.mdx @@ -0,0 +1,680 @@ +--- +title: 設定 +description: 使用 opencode JSON 設定。 +--- + +您可以使用 JSON 設定檔設定 opencode。 + +--- + +## 格式 + +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, +} +``` + +--- + +## 位置 + +您可以將設定放置在幾個不同的位置,它們有一個不同的優先順序。 + +:::note +設定檔**合併在一起**,而不是取代。 +::: + +設定檔被合併在一起,而不是被取代。以下設定位置的設定被合併。僅當鍵值衝突時,後面的設定才會覆寫前面的設定。保留所有設定中的非衝突設定。 + +例如,如果您的全域設定設定 `theme: "opencode"` 和 `autoupdate: true`,並且您的專案設定設定 `model: "anthropic/claude-sonnet-4-5"`,則最終設定將包括所有三個設定。 + +--- + +### 優先順序 + +設定來源按以下順序載入(後面的來源覆寫前面的來源): + +1. **遠端設定**(來自 `.well-known/opencode`)- 組織預設值 +2. **全域設定** (`~/.config/opencode/opencode.json`) - 使用者偏好設定 +3. **自定義設定** (`OPENCODE_CONFIG` env var) - 自定義覆寫 +4. **專案設定**(專案中的 `opencode.json`)- 專案特定的設定 +5. **`.opencode` 目錄** - 代理、指令、外掛 +6. **內聯設定** (`OPENCODE_CONFIG_CONTENT` env var) - 執行時覆寫 + +這意味著專案設定可以覆寫全域預設值,全域設定可以覆寫遠端組織預設值。 + +:::note +`.opencode` 和 `~/.config/opencode` 目錄對子目錄使用**複數名稱**:`agents/`、`commands/`、`modes/`、`plugins/`、`skills/`、`tools/` 和 `themes/`。為了向後相容,也支援單數名稱(例如 `agent/`)。 +::: + +--- + +### 遠端 + +組織可以透過 `.well-known/opencode` 端點提供預設設定。當您向支援它的供應商進行身分驗證時,會自動取得該資訊。 + +首先載入遠端設定,作為基礎層。所有其他設定來源(全域、專案)都可以覆寫這些預設值。 + +例如,如果您的組織提供預設禁用的 MCP 伺服器: + +```json title="Remote config from .well-known/opencode" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": false + } + } +} +``` + +您可以在本地設定中啟用特定伺服器: + +```json title="opencode.json" +{ + "mcp": { + "jira": { + "type": "remote", + "url": "https://jira.example.com/mcp", + "enabled": true + } + } +} +``` + +--- + +### 全域 + +將全域 opencode 設定放在 `~/.config/opencode/opencode.json` 中。使用全域設定來實現使用者範圍的偏好設定,例如主題、供應商或按鍵綁定。 + +全域設定覆寫遠端組織預設值。 + +--- + +### 每個專案 + +在專案根目錄中新增 `opencode.json`。專案設定在標準設定檔中具有最高優先級 - 它覆寫全域設定和遠端設定。 + +:::tip +將專案特定設定放在專案的根目錄中。 +::: + +當 opencode 啟動時,它會在當前目錄中尋找設定檔或遍歷到最近的 Git 目錄。 + +這也可以安全地簽入 Git 並使用與全域模式相同的模式。 + +--- + +### 自定義路徑 + +使用 `OPENCODE_CONFIG` 環境變數指定自定義設定檔路徑。 + +```bash +export OPENCODE_CONFIG=/path/to/my/custom-config.json +opencode run "Hello world" +``` + +自定義設定按優先順序在全域設定和專案設定之間載入。 + +--- + +### 自定義目錄 + +使用 `OPENCODE_CONFIG_DIR` 環境變數指定自定義設定目錄。將在該目錄中搜尋代理、指令、模式和外掛,就像標準 `.opencode` 目錄一樣,並且應該遵循相同的結構。 + +```bash +export OPENCODE_CONFIG_DIR=/path/to/my/config-directory +opencode run "Hello world" +``` + +自定義目錄在全域設定和 `.opencode` 目錄之後載入,因此它**可以覆寫**它們的設定。 + +--- + +## 架構 + +設定檔具有在 [**`opencode.ai/config.json`**](https://opencode.ai/config.json) 中定義的架構。 + +您的編輯器應該能夠根據架構進行驗證和自動完成。 + +--- + +### TUI + +您可以透過 `tui` 選項設定特定於 TUI 的設定。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" + } +} +``` + +可用選項: + +- `scroll_acceleration.enabled` - 啟用 macOS 風格的捲動加速。 **優先於 `scroll_speed`。** +- `scroll_speed` - 自定義捲動速度倍數(預設值:`3`,最小值:`1`)。如果 `scroll_acceleration.enabled` 是 `true`,則忽略。 +- `diff_style` - 控制差異顯示。 `"auto"` 適應終端機寬度,`"stacked"` 始終顯示單列。 + +[在此處了解有關使用 TUI 的更多資訊](/docs/tui)。 + +--- + +### 伺服器 + +您可以透過 `opencode serve` 選項為 `opencode web` 和 `server` 指令設定伺服器設定。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "mdnsDomain": "myproject.local", + "cors": ["http://localhost:5173"] + } +} +``` + +可用選項: + +- `port` - 監聽的連接埠。 +- `hostname` - 要監聽的主機名稱。當 `mdns` 啟用且未設定主機名稱時,預設為 `0.0.0.0`。 +- `mdns` - 啟用 mDNS 服務探索。這允許網路上的其他設備發現您的 opencode 伺服器。 +- `mdnsDomain` - mDNS 服務的自定義網域名稱。預設為 `opencode.local`。對於在同一網路上執行多個實例很有用。 +- `cors` - 從基於瀏覽器的客戶端使用 HTTP 伺服器時允許 CORS 的其他來源。值必須是完整來源(通訊協定+主機+可選連接埠),例如 `https://app.example.com`。 + +[在此處了解有關伺服器的更多資訊](/docs/server)。 + +--- + +### 工具 + +您可以透過 `tools` 選項管理 LLM 可以使用的工具。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tools": { + "write": false, + "bash": false + } +} +``` + +[在此處了解有關工具的更多資訊](/docs/tools)。 + +--- + +### 模型 + +您可以透過 `provider`、`model` 和 `small_model` 選項來設定要在 opencode 設定中使用的供應商和模型。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": {}, + "model": "anthropic/claude-sonnet-4-5", + "small_model": "anthropic/claude-haiku-4-5" +} +``` + +`small_model` 選項為標題生成等輕量級任務設定單獨的模型。預設情況下,如果您的供應商可以提供更便宜的模型,opencode 會嘗試使用更便宜的模型,否則它會退回到您的主模型。 + +供應商選項可以包括 `timeout` 和 `setCacheKey`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "timeout": 600000, + "setCacheKey": true + } + } + } +} +``` + +- `timeout` - 請求超時以毫秒為單位(預設值:300000)。設定為 `false` 以禁用。 +- `setCacheKey` - 確保始終為指定的供應商設定快取金鑰。 + +您也可以設定 [本地模型](/docs/models#local)。 [了解更多](/docs/models)。 + +--- + +#### 特定於供應商的選項 + +某些供應商支援除通用 `timeout` 和 `apiKey` 設定之外的其他設定選項。 + +##### Amazon Bedrock + +Amazon Bedrock 支援 AWS 特定設定: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } +} +``` + +- `region` - Bedrock 的 AWS 區域(預設為 `AWS_REGION` env var 或 `us-east-1`) +- `profile` - 來自 `~/.aws/credentials` 的 AWS 命名設定檔(預設為 `AWS_PROFILE` env var) +- `endpoint` - VPC 終端節點的自定義終端節點 URL。這是使用 AWS 特定術語的通用 `baseURL` 選項的別名。如果兩者都指定,`endpoint` 優先。 + +:::note +Bearer Token (`AWS_BEARER_TOKEN_BEDROCK` 或 `/connect`) 優先於基於設定檔的身分驗證。詳情請參閱 [認證優先級](/docs/providers#authentication-precedence)。 +::: + +[了解有關 Amazon Bedrock 設定的更多資訊](/docs/providers#amazon-bedrock)。 + +--- + +### 主題 + +您可以透過 `theme` 選項在 opencode 設定中設定要使用的主題。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "theme": "" +} +``` + +[在這裡了解更多](/docs/themes)。 + +--- + +### 代理 + +您可以透過 `agent` 選項為特定任務設定專用代理。 + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "code-reviewer": { + "description": "Reviews code for best practices and potential issues", + "model": "anthropic/claude-sonnet-4-5", + "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", + "tools": { + // Disable file modification tools for review-only agent + "write": false, + "edit": false, + }, + }, + }, +} +``` + +您也可以使用 `~/.config/opencode/agents/` 或 `.opencode/agents/` 中的 markdown 檔案定義代理。 [在這裡了解更多](/docs/agents)。 + +--- + +### 預設代理 + +您可以使用 `default_agent` 選項設定預設代理。當沒有明確指定時,這將決定使用哪個代理。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +預設代理必須是主代理(而不是子代理)。這可以是內建代理,例如 `"build"` 或 `"plan"`,或者您定義的 [自定義代理](/docs/agents)。如果指定的代理不存在或者是子代理,opencode 將退回到 `"build"` 並發出警告。 + +此設定適用於所有介面:TUI、CLI (`opencode run`)、桌面應用程式和 GitHub Action。 + +--- + +### 分享 + +您可以透過 `share` 選項設定 [分享](/docs/share) 功能。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "manual" +} +``` + +這需要: + +- `"manual"` - 允許透過指令手動分享(預設) +- `"auto"` - 自動分享新對話 +- `"disabled"` - 完全禁用分享 + +預設情況下,分享設定為手動模式,您需要使用 `/share` 指令明確分享對話。 + +--- + +### 指令 + +您可以透過 `command` 選項為重複任務設定自定義指令。 + +```jsonc title="opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "command": { + "test": { + "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", + "description": "Run tests with coverage", + "agent": "build", + "model": "anthropic/claude-haiku-4-5", + }, + "component": { + "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", + "description": "Create a new component", + }, + }, +} +``` + +您也可以使用 `~/.config/opencode/commands/` 或 `.opencode/commands/` 中的 Markdown 檔案定義指令。 [在這裡了解更多](/docs/commands)。 + +--- + +### 按鍵綁定 + +您可以透過 `keybinds` 選項自定義您的按鍵綁定。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": {} +} +``` + +[在這裡了解更多](/docs/keybinds)。 + +--- + +### 自動更新 + +opencode 將在啟動時自動下載任何新的更新。您可以使用 `autoupdate` 選項禁用此功能。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false +} +``` + +如果您不想更新但希望在新版本可用時收到通知,請將 `autoupdate` 設定為 `"notify"`。 +請注意,這僅在未使用 Homebrew 等套件管理器安裝時才有效。 + +--- + +### 格式化程式 + +您可以透過 `formatter` 選項設定程式碼格式化程式。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + }, + "custom-prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + } + } +} +``` + +[在此處了解有關格式化程式的更多資訊](/docs/formatters)。 + +--- + +### 權限 + +預設情況下,opencode **允許所有操作**,無需明確批准。您可以使用 `permission` 選項更改此設定。 + +例如,要確保 `edit` 和 `bash` 工具需要使用者批准: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} +``` + +[在此處了解有關權限的更多資訊](/docs/permissions)。 + +--- + +### 壓縮 + +您可以透過 `compaction` 選項控制上下文壓縮行為。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "compaction": { + "auto": true, + "prune": true + } +} +``` + +- `auto` - 當上下文已滿時自動壓縮工作階段(預設值:`true`)。 +- `prune` - 刪除舊工具輸出以節省 tokens(預設值:`true`)。 + +--- + +### 觀察者 (Watcher) + +您可以透過 `watcher` 選項設定檔案觀察器忽略模式。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "watcher": { + "ignore": ["node_modules/**", "dist/**", ".git/**"] + } +} +``` + +模式遵循 glob 語法。使用它可以從檔案監視中排除嘈雜的目錄。 + +--- + +### MCP 伺服器 + +您可以透過 `mcp` 選項設定要使用的 MCP 伺服器。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mcp": {} +} +``` + +[在這裡了解更多](/docs/mcp-servers)。 + +--- + +### 外掛 + +[外掛](/docs/plugins) 使用自定義工具、掛鉤和整合擴展 opencode。 + +將外掛檔案放置在 `.opencode/plugins/` 或 `~/.config/opencode/plugins/` 中。您也可以透過 `plugin` 選項從 npm 載入外掛。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"] +} +``` + +[在這裡了解更多](/docs/plugins)。 + +--- + +### 指示 (Instructions) + +您可以透過 `instructions` 選項設定您正在使用的模型的指示。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +這需要指示檔案的路徑和全域模式陣列。 [了解更多關於規則在這裡](/docs/rules)。 + +--- + +### 禁用供應商 + +您可以透過 `disabled_providers` 選項禁用自動載入的供應商。當您想要阻止載入某些供應商(即使其憑證可用)時,這非常有用。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "disabled_providers": ["openai", "gemini"] +} +``` + +:::note +`disabled_providers` 優先於 `enabled_providers`。 +::: + +`disabled_providers` 選項接受供應商 ID 陣列。當供應商被禁用時: + +- 即使設定了環境變數也不會載入。 +- 即使透過 `/connect` 指令設定 API 金鑰,也不會載入它。 +- 供應商的模型不會出現在模型選擇列表中。 + +--- + +### 啟用的供應商 + +您可以透過 `enabled_providers` 選項指定供應商的允許清單。設定後,僅啟用指定的供應商,所有其他供應商將被忽略。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["anthropic", "openai"] +} +``` + +當您想要限制 opencode 僅使用特定的供應商而不是一一禁用它們時,這非常有用。 + +:::note +`disabled_providers` 優先於 `enabled_providers`。 +::: + +如果某個供應商同時出現在 `enabled_providers` 和 `disabled_providers` 中,則 `disabled_providers` 優先考慮向後相容性。 + +--- + +### 實驗性的 + +`experimental` 鍵包含正在積極開發的選項。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "experimental": {} +} +``` + +:::caution +實驗選項不穩定。它們可能會更改或被刪除,恕不另行通知。 +::: + +--- + +## 變數 + +您可以在設定檔中使用變數替換來引用環境變數和檔案內容。 + +--- + +### 環境變數 + +使用 `{env:VARIABLE_NAME}` 替換環境變數: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "model": "{env:OPENCODE_MODEL}", + "provider": { + "anthropic": { + "models": {}, + "options": { + "apiKey": "{env:ANTHROPIC_API_KEY}" + } + } + } +} +``` + +如果未設定環境變數,它將被替換為空字串。 + +--- + +### 檔案 + +使用 `{file:path/to/file}` 替換檔案的內容: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["./custom-instructions.md"], + "provider": { + "openai": { + "options": { + "apiKey": "{file:~/.secrets/openai-key}" + } + } + } +} +``` + +檔案路徑可以是: + +- 相對於設定檔目錄 +- 或者以 `/` 或 `~` 開頭的絕對路徑 + +這些對於: + +- 將 API 金鑰等敏感數據保存在單獨的檔案中。 +- 包含大型指示檔案,而不會弄亂您的設定。 +- 跨多個設定檔共享通用設定片段。 diff --git a/packages/web/src/content/docs/zh-tw/custom-tools.mdx b/packages/web/src/content/docs/zh-tw/custom-tools.mdx new file mode 100644 index 00000000000..29db4675e2f --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/custom-tools.mdx @@ -0,0 +1,170 @@ +--- +title: 自定義工具 +description: 建立 LLM 可以在 opencode 中呼叫的工具。 +--- + +自定義工具是您建立的函式,LLM 可以在對話期間呼叫。它們與 opencode 的 [內建工具](/docs/tools) 一起工作,例如 `read`、`write` 和 `bash`。 + +--- + +## 建立工具 + +工具定義為 **TypeScript** 或 **JavaScript** 檔案。但是,工具定義可以呼叫用 **任何語言** 編寫的指令碼 - TypeScript 或 JavaScript 僅用於工具定義本身。 + +--- + +### 位置 + +它們可以定義為: + +- 透過將它們放在專案的 `.opencode/tools/` 目錄中來本地進行。 +- 或者在全域範圍內,將它們放置在 `~/.config/opencode/tools/` 中。 + +--- + +### 結構 + +建立工具的最簡單方法是使用 `tool()` 輔助程式,它提供類型安全和驗證。 + +```ts title=".opencode/tools/database.ts" {1} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Query the project database", + args: { + query: tool.schema.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +}) +``` + +**檔名**成為**工具名稱**。以上建立了一個 `database` 工具。 + +--- + +#### 每個檔案多個工具 + +您也可以從單個檔案匯出多個工具。每個匯出都會成為**一個單獨的工具**,名稱為 **`_`**: + +```ts title=".opencode/tools/math.ts" +import { tool } from "@opencode-ai/plugin" + +export const add = tool({ + description: "Add two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a + args.b + }, +}) + +export const multiply = tool({ + description: "Multiply two numbers", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args) { + return args.a * args.b + }, +}) +``` + +這將建立兩個工具:`math_add` 和 `math_multiply`。 + +--- + +### 參數 (Arguments) + +您可以使用 `tool.schema`(即 [Zod](https://zod.dev))來定義參數類型。 + +```ts "tool.schema" +args: { + query: tool.schema.string().describe("SQL query to execute") +} +``` + +您也可以直接匯入 [Zod](https://zod.dev) 並返回一個一般物件: + +```ts {6} +import { z } from "zod" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +--- + +### 上下文 (Context) + +工具接收有關當前工作階段的上下文: + +```ts title=".opencode/tools/project.ts" {8} +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { agent, sessionID, messageID, directory, worktree } = context + return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` + }, +}) +``` + +使用 `context.directory` 作為工作階段工作目錄。 +使用 `context.worktree` 作為 git 工作樹根。 + +--- + +## 範例 + +### 用 Python 編寫一個工具 + +您可以用任何您想要的語言編寫工具。下面是一個使用 Python 將兩個數字相加的範例。 + +首先,將該工具建立為 Python 指令碼: + +```python title=".opencode/tools/add.py" +import sys + +a = int(sys.argv[1]) +b = int(sys.argv[2]) +print(a + b) +``` + +然後建立呼叫它的工具定義: + +```ts title=".opencode/tools/python-add.ts" {10} +import { tool } from "@opencode-ai/plugin" +import path from "path" + +export default tool({ + description: "Add two numbers using Python", + args: { + a: tool.schema.number().describe("First number"), + b: tool.schema.number().describe("Second number"), + }, + async execute(args, context) { + const script = path.join(context.worktree, ".opencode/tools/add.py") + const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() + return result.trim() + }, +}) +``` + +這裡我們使用 [`Bun.$`](https://bun.com/docs/runtime/shell) 公用程式來執行 Python 指令碼。 diff --git a/packages/web/src/content/docs/zh-tw/ecosystem.mdx b/packages/web/src/content/docs/zh-tw/ecosystem.mdx new file mode 100644 index 00000000000..ca0d8bf15d6 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/ecosystem.mdx @@ -0,0 +1,76 @@ +--- +title: 生態系統 +description: 使用 opencode 構建的專案和整合。 +--- + +基於 opencode 的社群專案集合。 + +:::note +想要將您的 opencode 相關專案添加到此列表中嗎?提交 PR。 +::: + +您也可以查看 [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) 和 [opencode.cafe](https://opencode.cafe),這是一個聚合生態系統和社群的社群。 + +--- + +## 外掛 + +| 名稱 | 描述 | +| --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | 使用 git 同步和即時預覽在隔離的 Daytona 沙箱中自動執行 opencode 工作階段 | +| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | 自動注入 Helicone 工作階段標頭以進行請求分組 | +| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | 使用搜尋工具將 TypeScript/Svelte 類型自動注入到檔案讀取中 | +| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | 使用您的 ChatGPT Plus/Pro 訂閱而不是 API 額度 | +| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | 使用您現有的 Gemini 計畫而不是 API 計費 | +| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | 使用 Antigravity 的免費模型代替 API 計費 | +| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | 具有淺層複製和自動分配連接埠的多分支開發容器隔離 | +| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Google Antigravity OAuth 外掛,支援 Google 搜尋和更強大的 API 處理 | +| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | 透過修剪過時的工具輸出來最佳化代幣使用 | +| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | 為具有 Google Grounding 風格的受支援供應商添加原生網路搜尋支援 | +| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | 使 AI 代理能夠在 PTY 中執行背景處理程序,並向其發送互動式輸入。 | +| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | 非互動式 shell 指令說明 - 防止依賴 TTY 的操作卡住 | +| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | 使用 Wakatime 追蹤 opencode 使用情況 | +| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | 清理 LLM 生成的 Markdown 表格 | +| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | 使用 Morph Fast Apply API 和惰性編輯標記將程式碼編輯速度提高 10 倍 | +| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | 背景代理、預先建置的 LSP/AST/MCP 工具、精選代理、相容 Claude Code | +| [opencode-notificator](https://github.com/panta82/opencode-notificator) | opencode 工作階段的桌面通知和聲音警報 | +| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | 針對權限、完成和錯誤事件的桌面通知和聲音警報 | +| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | 基於 opencode 上下文的 AI 支援的自動 Zellij 工作階段命名 | +| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | 允許 opencode 代理透過技能發現和注入按需延遲載入提示 | +| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | 使用超級記憶體跨工作階段持久記憶體 | +| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | 具有視覺註釋和私人/離線分享的互動式計畫審查 | +| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | 將 opencode/指令擴展為具有精細流程控制的強大編排系統 | +| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | 使用帶有 cron 語法的 launchd (Mac) 或 systemd (Linux) 安排重複作業 | +| [micode](https://github.com/vtemian/micode) | 結構化腦力激盪 → 計畫 → 實作具有會議連續性的工作流程 | +| [octto](https://github.com/vtemian/octto) | 用於透過多問題形式進行 AI 腦力激盪的互動式瀏覽器 UI | +| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | 具有非同步委託和上下文持久性的 Claude Code 風格背景代理 | +| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | opencode 的原生作業系統通知 – 了解任務何時完成 | +| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | 捆綁的多代理編排工具 – 16 個組件,一次安裝 | +| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | opencode 的零摩擦 git 工作樹 | + +--- + +## 專案 + +| 名稱 | 描述 | +| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------- | +| [kimaki](https://github.com/remorses/kimaki) | 用於控制 opencode 工作階段的 Discord 機器人,基於 SDK 構建 | +| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Neovim 外掛,用於編輯器感知提示,基於 API 構建 | +| [portal](https://github.com/hosenur/portal) | 透過 Tailscale/VPN 實現 opencode 的行動優先 Web UI | +| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | 用於構建 opencode 外掛的範本 | +| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Neovim opencode 前端 - 基於終端機的 AI 程式碼代理 | +| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Vercel AI SDK 供應商,用於透過 @opencode-ai/sdk 使用 opencode | +| [OpenChamber](https://github.com/btriapitsyn/openchamber) | opencode 的 Web/桌面應用程式和 VS Code 擴充功能 | +| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | 在 Obsidian 的 UI 中嵌入 opencode 的 Obsidian 外掛 | +| [OpenWork](https://github.com/different-ai/openwork) | Claude Cowork 的開源替代方案,由 opencode 提供支援 | +| [ocx](https://github.com/kdcokenny/ocx) | opencode 擴充功能管理器具有可攜式、隔離的設定檔。 | +| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | opencode 的桌面、Web、行動和遠端客戶端應用程式 | + +--- + +## 代理 + +| 名稱 | 描述 | +| ----------------------------------------------------------------- | ---------------------------------------- | +| [Agentic](https://github.com/Cluster444/agentic) | 用於結構化開發的模組化 AI 代理和指令 | +| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | 用於增強工作流程的設定、提示、代理和外掛 | diff --git a/packages/web/src/content/docs/zh-tw/enterprise.mdx b/packages/web/src/content/docs/zh-tw/enterprise.mdx new file mode 100644 index 00000000000..c4e5451b5ef --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/enterprise.mdx @@ -0,0 +1,167 @@ +--- +title: 企業版 +description: 在您的組織中安全地使用 opencode。 +--- + +import config from "../../../../config.mjs" +export const email = `mailto:${config.email}` + +opencode Enterprise 適用於希望確保其程式碼和資料永遠不會離開其基礎架構的組織。它可以透過使用與 SSO 和內部 AI 閘道整合的集中式設定來實現此目的。 + +:::note +opencode 不儲存您的任何程式碼或上下文資料。 +::: + +要開始使用 opencode Enterprise: + +1. 與您的團隊進行內部試用。 +2. **聯絡我們**討論定價和實作選項。 + +--- + +## 試用 + +opencode 是開源的,不儲存您的任何程式碼或上下文資料,因此您的開發人員只需 [開始使用](/docs/) 並進行試用。 + +--- + +### 資料處理 + +**opencode 不會儲存您的程式碼或上下文資料。** 所有處理都在本地進行或透過直接 API 呼叫您的 AI 供應商。 + +這意味著只要您使用您信任的供應商或內部 AI 閘道,您就可以安全使用 opencode。 + +這裡唯一需要注意的是可選的 `/share` 功能。 + +--- + +#### 分享對話 + +如果使用者啟用 `/share` 功能,對話和與之關聯的資料將被發送到我們用於在 opencode.ai 上託管這些分享頁面的服務。 + +資料當前透過我們的 CDN 邊緣網路提供服務,並快取在使用者附近的邊緣。 + +我們建議您在試用時禁用此功能。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "share": "disabled" +} +``` + +[了解更多關於分享的資訊](/docs/share)。 + +--- + +### 程式碼所有權 + +**您擁有 opencode 生成的所有程式碼。** 沒有授權限制或所有權聲明。 + +--- + +## 定價 + +我們對 opencode Enterprise 使用按席位計費模式。如果您有自己的 LLM 閘道,我們不會對使用的 Tokens 收取費用。有關定價和實作選項的更多詳細資訊,請**聯絡我們**。 + +--- + +## 部署 + +完成試用並準備好使用 opencode 後,請訪問: +您的組織,您可以**聯絡我們**進行討論 +定價和實作選項。 + +--- + +### 中央設定 + +我們可以將 opencode 設定為為您的整個組織使用單一的中央設定。 + +這種集中式設定可以與您的 SSO 供應商整合,並確保所有使用者僅存取您的內部 AI 閘道。 + +--- + +### 單一登入整合 + +透過中央設定,opencode 可以與您組織的 SSO 供應商整合以進行身分驗證。 + +這使得 opencode 能夠透過現有的身分管理系統取得內部 AI 閘道的憑證。 + +--- + +### 內部 AI 閘道 + +透過中央設定,opencode 還可以設定為僅使用您的內部 AI 閘道。 + +您還可以禁用所有其他 AI 供應商,確保所有請求都通過組織核准的基礎架構。 + +--- + +### 自行託管 + +雖然我們建議禁用分享頁面以確保您的資料永遠不會離開您的組織,我們還可以幫助您在您的基礎架構上自行託管它們。 + +目前這已在我們的路線圖上。如果您有興趣,**讓我們知道**。 + +--- + +## 常見問題 + +

+什麼是 opencode Enterprise? + +opencode Enterprise 適用於希望確保其程式碼和資料永遠不會離開其基礎架構的組織。它可以透過使用與 SSO 和內部 AI 閘道整合的集中式設定來實現此目的。 + +
+ +
+如何開始使用 opencode Enterprise? + +只需與您的團隊進行內部試用即可。 opencode 預設情況下不儲存您的程式碼或上下文資料,因此可以輕鬆上手。 + +然後**聯絡我們**討論定價和實作選項。 + +
+ +
+企業定價如何運作? + +我們提供按席位企業定價。如果您有自己的 LLM 閘道,我們不會對使用的 Tokens 收取費用。如需了解更多詳情,請**聯絡我們**,獲取根據您組織的需求客製化的報價。 + +
+ +
+opencode Enterprise 保證我的資料安全嗎? + +是的。 opencode 不儲存您的程式碼或上下文資料。所有處理都在本地進行或透過直接 API 呼叫您的 AI 供應商。透過中央設定和 SSO 整合,您的資料在組織的基礎架構中保持安全。 + +
+ +
+我們可以使用自己的私有 NPM Registry 嗎? + +opencode 透過 Bun 的原生 `.npmrc` 檔案支援來支援私有 npm Registry。如果您的組織使用私有 Registry,例如 JFrog Artifactory、Nexus 或類似的 Registry,請確保開發人員在執行 opencode 之前經過身分驗證。 + +要使用您的私有 Registry 設定身分驗證: + +```bash +npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +``` + +這將建立帶有身分驗證詳細資訊的 `~/.npmrc`。 opencode 會自動讀取這個。 + +:::caution +在執行 opencode 之前,您必須登入私有 Registry。 +::: + +或者,您可以手動設定 `.npmrc` 檔案: + +```bash title="~/.npmrc" +registry=https://your-company.jfrog.io/api/npm/npm-virtual/ +//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} +``` + +開發人員必須在執行 opencode 之前登入私有 Registry,以確保可以從企業 Registry 安裝套件。 + +
diff --git a/packages/web/src/content/docs/zh-tw/formatters.mdx b/packages/web/src/content/docs/zh-tw/formatters.mdx new file mode 100644 index 00000000000..2ded1419de1 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/formatters.mdx @@ -0,0 +1,130 @@ +--- +title: 格式化程式 +description: opencode 使用特定於語言的格式化程式。 +--- + +使用特定於語言的格式化程式編寫或編輯檔案後,opencode 會自動格式化檔案。這可確保生成的程式碼遵循專案的程式碼風格。 + +--- + +## 內建 + +opencode 附帶了多個適用於流行語言和框架的內建格式化程式。下面是格式化程式、支援的檔案副檔名以及所需的指令或設定選項的列表。 + +| 格式化程式 | 副檔名 | 要求 | +| -------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | +| gofmt | .go | `gofmt` 指令可用 | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | `mix` 指令可用 | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, 和 [更多](https://prettier.io/docs/en/index.html) | `prettier` 中有 `package.json` 相依套件 | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, 和 [更多](https://biomejs.dev/) | `biome.json(c)` 設定檔 | +| zig | .zig, .zon | `zig` 指令可用 | +| clang-format | .c, .cpp, .h, .hpp, .ino, 和 [更多](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` 設定檔 | +| ktlint | .kt, .kts | `ktlint` 指令可用 | +| ruff | .py, .pyi | `ruff` 指令可用並設定完成 | +| rustfmt | .rs | `rustfmt` 指令可用 | +| cargofmt | .rs | `cargo fmt` 指令可用 | +| uv | .py, .pyi | `uv` 指令可用 | +| rubocop | .rb, .rake, .gemspec, .ru | `rubocop` 指令可用 | +| standardrb | .rb, .rake, .gemspec, .ru | `standardrb` 指令可用 | +| htmlbeautifier | .erb, .html.erb | `htmlbeautifier` 指令可用 | +| air | .R | `air` 指令可用 | +| dart | .dart | `dart` 指令可用 | +| ocamlformat | .ml, .mli | `ocamlformat` 指令可用,且存在 `.ocamlformat` 設定檔 | +| terraform | .tf, .tfvars | `terraform` 指令可用 | +| gleam | .gleam | `gleam` 指令可用 | +| nixfmt | .nix | `nixfmt` 指令可用 | +| shfmt | .sh, .bash | `shfmt` 指令可用 | +| pint | .php | `laravel/pint` 中有 `composer.json` 相依套件 | +| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | `oxfmt` 中有 `package.json` 相依套件且啟用[實驗環境變數旗標](/docs/cli/#experimental) | +| ormolu | .hs | `ormolu` 指令可用 | + +因此,如果您的專案的 `package.json` 中有 `prettier`,opencode 將自動使用它。 + +--- + +## 它是如何運作的 + +當 opencode 寫入或編輯檔案時,它: + +1. 根據所有啟用的格式化程式檢查檔案副檔名。 +2. 對檔案執行適當的格式化程式指令。 +3. 自動套用格式變更。 + +此過程在背景進行,確保無需任何手動步驟即可維護您的程式碼樣式。 + +--- + +## 設定 + +您可以透過 opencode 設定中的 `formatter` 部分自定義格式化程式。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "formatter": {} +} +``` + +每個格式化程式設定支援以下內容: + +| 屬性 | 類型 | 描述 | +| ------------- | ------ | ---------------------------------- | +| `disabled` | 布林值 | 將其設定為 `true` 以禁用格式化程式 | +| `command` | 字串[] | 格式化執行的指令 | +| `environment` | 物件 | 執行格式化程式時要設定的環境變數 | +| `extensions` | 字串[] | 此格式化程式應處理的檔案副檔名 | + +讓我們看一些例子。 + +--- + +### 禁用格式化程式 + +要全域禁用**所有**格式化程式,請將 `formatter` 設定為 `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": false +} +``` + +要禁用**特定**格式化程式,請將 `disabled` 設定為 `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "disabled": true + } + } +} +``` + +--- + +### 自定義格式化程式 + +您可以覆寫內建格式化程式或透過指定指令、環境變數和檔案副檔名新增新格式化程式: + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "formatter": { + "prettier": { + "command": ["npx", "prettier", "--write", "$FILE"], + "environment": { + "NODE_ENV": "development" + }, + "extensions": [".js", ".ts", ".jsx", ".tsx"] + }, + "custom-markdown-formatter": { + "command": ["deno", "fmt", "$FILE"], + "extensions": [".md"] + } + } +} +``` + +指令中的 **`$FILE` 預留位置** 將替換為正在格式化的檔案的路徑。 diff --git a/packages/web/src/content/docs/zh-tw/github.mdx b/packages/web/src/content/docs/zh-tw/github.mdx new file mode 100644 index 00000000000..32d3f005e55 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/github.mdx @@ -0,0 +1,321 @@ +--- +title: GitHub +description: 在 GitHub Issues 和拉取請求中使用 opencode。 +--- + +opencode 與您的 GitHub 工作流程整合。在評論中提及 `/opencode` 或 `/oc`,opencode 將在您的 GitHub Actions Runner 中執行任務。 + +--- + +## 功能 + +- **分類問題**:要求 opencode 調查問題並向您解釋。 +- **修復和實作**:要求 opencode 修復問題或實作功能。它將在一個新分支中工作並提交包含所有變更的 PR。 +- **安全**:opencode 在 GitHub 的 Runner 中執行。 + +--- + +## 安裝 + +在 GitHub 儲存庫中的專案中執行以下指令: + +```bash +opencode github install +``` + +這將引導您完成安裝 GitHub 應用程式、建立工作流程和設定 Secrets。 + +--- + +### 手動設定 + +或者您可以手動設定。 + +1. **安裝 GitHub 應用程式** + + 前往 [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent)。確保它已安裝在目標儲存庫上。 + +2. **新增工作流程** + + 將以下工作流程檔案新增到儲存庫中的 `.github/workflows/opencode.yml` 中。確保在 `env` 中設定適當的 `model` 和所需的 API 金鑰。 + + ```yml title=".github/workflows/opencode.yml" {24,26} + name: opencode + + on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + + jobs: + opencode: + if: | + contains(github.event.comment.body, '/oc') || + contains(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + # share: true + # github_token: xxxx + ``` + +3. **設定 Secrets** + + 在您的組織或專案的 **Settings** 中,展開左側的 **Secrets and variables**,然後選擇 **Actions**。並新增所需的 API 金鑰。 + +--- + +## 設定 + +- `model`:與 opencode 一起使用的模型。採用 `provider/model` 格式。這是**必需的**。 +- `agent`: 使用的代理。必須是主要代理。如果未找到,則從設定退回到 `default_agent` 或 `"build"`。 +- `share`:是否分享 opencode 工作階段。對於公共儲存庫,預設為 **true**。 +- `prompt`:可選的自定義提示以覆寫預設行為。使用它來自定義 opencode 處理請求的方式。 +- `token`:可選的 GitHub 存取權杖,用於執行建立評論、提交變更和打開拉取請求等操作。預設情況下,opencode 使用來自 opencode GitHub 應用程式的安裝存取權杖,因此提交、評論和拉取請求顯示為來自應用程式。 + + 或者,您可以使用 GitHub Action Runner 的 [內建 `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token),而無需安裝 opencode GitHub 應用程式。只需確保在您的工作流程中授予所需的權限: + + ```yaml + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + ``` + + **注意**:使用 `GITHUB_TOKEN` 時,opencode 執行的操作(如提交和評論)將不會觸發其他工作流程。 + +--- + +## 支援的事件 + +opencode 可以由以下 GitHub 事件觸發: + +| 事件類型 | 觸發條件 | 詳情 | +| ----------------------------- | ------------------------------ | --------------------------------------------------------------------------------------- | +| `issue_comment` | 對問題或 PR 發表評論 | 在評論中提及 `/opencode` 或 `/oc`。 opencode 讀取上下文並可以建立分支、打開 PR 或回覆。 | +| `pull_request_review_comment` | 對 PR 中的特定程式碼行進行評論 | 在檢查程式碼時提及 `/opencode` 或 `/oc`。 opencode 接收檔案路徑、行號和 diff 上下文。 | +| `issues` | 問題已打開或已編輯 | 建立或修改問題時自動觸發 opencode。需要 `prompt` 輸入。 | +| `pull_request` | PR 已開啟或已更新 | 當 PR 被開啟、同步或重新開啟時自動觸發 opencode。對於自動評論很有用。 | +| `schedule` | 基於 Cron 的排程 | 按排程執行 opencode。需要 `prompt` 輸入。輸出進入日誌和 PR(沒有可評論的問題)。 | +| `workflow_dispatch` | 從 GitHub UI 手動觸發 | 透過「Actions」標籤按需觸發 opencode。需要 `prompt` 輸入。輸出進入日誌和 PR。 | + +### 排程範例 + +按排程執行 opencode 以執行自動化任務: + +```yaml title=".github/workflows/opencode-scheduled.yml" +name: Scheduled OpenCode Task + +on: + schedule: + - cron: "0 9 * * 1" # Every Monday at 9am UTC + +jobs: + opencode: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run OpenCode + uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review the codebase for any TODO comments and create a summary. + If you find issues worth addressing, open an issue to track them. +``` + +對於排程事件,`prompt` 輸入是**必需的**,因為沒有註釋可從中提取指令。排程工作流程在沒有使用者上下文的情況下執行以進行權限檢查,因此如果您希望 opencode 建立分支或 PR,工作流程必須授予 `contents: write` 和 `pull-requests: write`。 + +--- + +### 拉取請求範例 + +打開或更新 PR 時自動審閱: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: anthropic/claude-sonnet-4-20250514 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +對於 `pull_request` 事件,如果未提供 `prompt`,opencode 將預設審閱拉取請求。 + +--- + +### 問題分類範例 + +自動分類新問題。此範例過濾超過 30 天的帳號以減少垃圾訊息: + +```yaml title=".github/workflows/opencode-triage.yml" +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + issues: write + steps: + - name: Check account age + id: check + uses: actions/github-script@v7 + with: + script: | + const user = await github.rest.users.getByUsername({ + username: context.payload.issue.user.login + }); + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string + + - uses: actions/checkout@v6 + if: steps.check.outputs.result == 'true' + with: + persist-credentials: false + + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this issue. If there's a clear fix or relevant docs: + - Provide documentation links + - Add error handling guidance for code examples + Otherwise, do not comment. +``` + +對於 `issues` 事件,`prompt` 輸入是**必需的**,因為沒有評論可從中提取指令。 + +--- + +## 自定義提示 + +覆寫預設提示,為您的工作流程自定義 opencode 的行為。 + +```yaml title=".github/workflows/opencode.yml" +- uses: anomalyco/opencode/github@latest + with: + model: anthropic/claude-sonnet-4-5 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +這對於執行與您的專案相關的特定審閱標準、編碼標準或重點領域非常有用。 + +--- + +## 範例 + +以下是如何在 GitHub 中使用 opencode 的一些範例。 + +- **解釋一個問題** + + 在 GitHub Issue 中添加此評論。 + + ``` + /opencode explain this issue + ``` + + opencode 將閱讀整個討論串,包括所有評論,並回覆並提供清晰的解釋。 + +- **解決問題** + + 在 GitHub Issue 中,說: + + ``` + /opencode fix this + ``` + + opencode 將建立一個新分支,實作變更,並使用變更打開 PR。 + +- **審閱 PR 並進行變更** + + 在 GitHub PR 上留下以下評論。 + + ``` + Delete the attachment from S3 when the note is removed /oc + ``` + + opencode 將實作請求的變更並將其推送到分支。 + +- **查看特定程式碼行** + + 直接在 PR 的「Files」標籤中的程式碼行上留下評論。 opencode 自動檢測檔案、行號和 diff 上下文以提供精確的回應。 + + ``` + [Comment on specific lines in Files tab] + /oc add error handling here + ``` + + opencode 將查看: + - 正在審閱的確切檔案 + - 具體程式碼行 + - 周圍的 diff 上下文 + - 行號資訊 + + 這允許更有針對性的請求,而無需手動指定檔案路徑或行號。 diff --git a/packages/web/src/content/docs/zh-tw/gitlab.mdx b/packages/web/src/content/docs/zh-tw/gitlab.mdx new file mode 100644 index 00000000000..a96618fd1c0 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/gitlab.mdx @@ -0,0 +1,195 @@ +--- +title: GitLab +description: 在 GitLab 問題和合併請求中使用 opencode。 +--- + +opencode 透過 GitLab CI/CD 管線或與 GitLab Duo 與您的 GitLab 工作流程整合。 + +在這兩種情況下,opencode 都將在您的 GitLab Runner 上執行。 + +--- + +## GitLab + +opencode 在常規 GitLab 管線中工作。您可以將其構建為管線作為 [CI 組件](https://docs.gitlab.com/ee/ci/components/) + +在這裡,我們使用社群建立的 opencode CI/CD 組件 — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode)。 + +--- + +### 功能 + +- **每個作業使用自定義設定**:使用自定義設定目錄設定 opencode,例如 `./config/#custom-directory` 以啟用或禁用每個 opencode 呼叫的功能。 +- **無狀態**:opencode 的狀態(訊息歷史記錄等)儲存在合併請求評論線程中,使其完全無狀態。 +- **靈活**:CI 組件支援多種輸入來自定義其行為 + +--- + +### 設定 + +1. 將 opencode 身分驗證 JSON 作為檔案類型 CI 環境變數儲存在 **Settings** > **CI/CD** > **Variables** 下。確保將它們標記為「Masked and hidden」。 +2. 將以下內容新增到您的 `.gitlab-ci.yml` 檔案中。 + + ```yaml title=".gitlab-ci.yml" + include: + - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2 + inputs: + config_dir: ${CI_PROJECT_DIR}/opencode-config + auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON + command: optional-custom-command + message: "Your prompt here" + ``` + +有關此組件的更多輸入和使用案例[查看文件](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode)。 + +--- + +## GitLab Duo + +opencode 與您的 GitLab 工作流程整合。 +在評論中提及 `@opencode`,opencode 將在您的 GitLab CI 管線中執行任務。 + +--- + +### 功能 + +- **分類問題**:要求 opencode 調查問題並向您解釋。 +- **修復和實作**:要求 opencode 修復問題或實作功能。 + 它將建立一個新分支並提出包含變更的合併請求。 +- **安全**:opencode 在您的 GitLab Runner 上執行。 + +--- + +### 設定 + +opencode 在您的 GitLab CI/CD 管線中執行,您需要進行以下設定: + +:::tip +查看 [**GitLab 文件**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) 以獲取最新說明。 +::: + +1. 設定您的 GitLab 環境 +2. 設定 CI/CD +3. 取得 AI 模型供應商 API 金鑰 +4. 建立服務帳號 +5. 設定 CI/CD 變數 +6. 建立一個流程設定檔,這是一個範例: + +
+ + Flow configuration + + ```yaml + image: node:22-slim + commands: + - echo "Installing opencode" + - npm install --global opencode-ai + - echo "Installing glab" + - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE + - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* + - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash + - apt-get install --yes glab + - echo "Configuring glab" + - echo $GITLAB_HOST + - echo "Creating OpenCode auth configuration" + - mkdir --parents ~/.local/share/opencode + - | + cat > ~/.local/share/opencode/auth.json << EOF + { + "anthropic": { + "type": "api", + "key": "$ANTHROPIC_API_KEY" + } + } + EOF + - echo "Configuring git" + - git config --global user.email "opencode@gitlab.com" + - git config --global user.name "OpenCode" + - echo "Testing glab" + - glab issue list + - echo "Running OpenCode" + - | + opencode run " + You are an AI assistant helping with GitLab operations. + + Context: $AI_FLOW_CONTEXT + Task: $AI_FLOW_INPUT + Event: $AI_FLOW_EVENT + + Please execute the requested task using the available GitLab tools. + Be thorough in your analysis and provide clear explanations. + + + Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. + + If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. + You don't need to commit or push up changes, those will be done automatically based on the file changes you make. + + " + - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF + - echo "Checking for git changes and pushing if any exist" + - | + if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then + echo "Git changes detected, adding and pushing..." + git add . + if git diff --cached --quiet; then + echo "No staged changes to commit" + else + echo "Committing changes to branch: $CI_WORKLOAD_REF" + git commit --message "Codex changes" + echo "Pushing changes up to $CI_WORKLOAD_REF" + git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF + echo "Changes successfully pushed" + fi + else + echo "No git changes detected, skipping push" + fi + variables: + - ANTHROPIC_API_KEY + - GITLAB_TOKEN_OPENCODE + - GITLAB_HOST + ``` + +
+ +詳細說明可以參考 [GitLab CLI 代理文件](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/)。 + +--- + +### 範例 + +以下是如何在 GitLab 中使用 opencode 的一些範例。 + +:::tip +您可以設定使用與 `@opencode` 不同的觸發短語。 +::: + +- **解釋一個問題** + + 在 GitLab 問題中添加此評論。 + + ``` + @opencode explain this issue + ``` + + opencode 將閱讀該問題並回覆並提供清晰的解釋。 + +- **解決問題** + + 在 GitLab 問題中,說: + + ``` + @opencode fix this + ``` + + opencode 將建立一個新分支,實作變更,並打開包含變更的合併請求。 + +- **審閱合併請求** + + 對 GitLab 合併請求留下以下評論。 + + ``` + @opencode review this merge request + ``` + + opencode 將審閱合併請求並提供回饋。 diff --git a/packages/web/src/content/docs/zh-tw/ide.mdx b/packages/web/src/content/docs/zh-tw/ide.mdx new file mode 100644 index 00000000000..11275318f7f --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/ide.mdx @@ -0,0 +1,48 @@ +--- +title: IDE +description: VS Code、Cursor 和其他 IDE 的 OpenCode 擴充功能 +--- + +OpenCode 與 VS Code、Cursor 或任何支援終端機的 IDE 整合。只需在終端機中執行 `opencode` 即可開始。 + +--- + +## 用法 + +- **快速啟動**:使用 `Cmd+Esc` (Mac) 或 `Ctrl+Esc` (Windows/Linux) 在分割終端機視圖中打開 OpenCode,或者聚焦現有終端機工作階段(如果已有終端機工作階段正在執行)。 +- **新工作階段**:使用 `Cmd+Shift+Esc` (Mac) 或 `Ctrl+Shift+Esc` (Windows/Linux) 啟動新的 OpenCode 終端機工作階段,即使該工作階段已打開。您還可以單擊 UI 中的 OpenCode 按鈕。 +- **上下文感知**:自動與 OpenCode 分享您當前的選擇或分頁。 +- **檔案引用快速鍵**:使用 `Cmd+Option+K` (Mac) 或 `Alt+Ctrl+K` (Linux/Windows) 插入檔案引用。例如,`@File#L37-42`。 + +--- + +## 安裝 + +要在 VS Code 和 Cursor、Windsurf、VSCodium 等流行 Fork 上安裝 OpenCode: + +1. 打開 VS Code +2. 打開整合終端機 +3. 執行 `opencode` - 擴充功能會自動安裝 + +另一方面,如果您想在從 TUI 執行 `/editor` 或 `/export` 時使用自己的 IDE,則需要設定 `export EDITOR="code --wait"`。 [了解更多](/docs/tui/#editor-setup)。 + +--- + +### 手動安裝 + +在擴充功能市集中搜尋 **OpenCode**,然後單擊 **安裝**。 + +--- + +### 疑難排解 + +如果擴充功能無法自動安裝: + +- 確保您在整合終端機中執行 `opencode`。 +- 確認您的 IDE 的 CLI 已安裝: + - 對於 VS Code:`code` 指令 + - 對於 Cursor:`cursor` 指令 + - 對於 Windsurf:`windsurf` 指令 + - 對於 VSCodium:`codium` 指令 + - 如果沒有,請執行 `Cmd+Shift+P` (Mac) 或 `Ctrl+Shift+P` (Windows/Linux) 並搜尋「Shell Command: Install 'code' command in PATH」(或適用於您的 IDE 的等效指令) +- 確保 VS Code 有權安裝擴充功能 diff --git a/packages/web/src/content/docs/zh-tw/index.mdx b/packages/web/src/content/docs/zh-tw/index.mdx new file mode 100644 index 00000000000..ab22bfb5c7b --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/index.mdx @@ -0,0 +1,343 @@ +--- +title: 簡介 +description: 開始使用 OpenCode。 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" +import config from "../../../../config.mjs" +export const console = config.console + +[**OpenCode**](/) 是一個開源 AI 程式碼代理。它可用作基於終端機的介面、桌面應用程式或 IDE 擴充功能。 + +![具有 OpenCode 主題的 OpenCode TUI](../../../assets/lander/screenshot.png) + +讓我們開始吧。 + +--- + +#### 先決條件 + +要在終端機中使用 OpenCode,您需要: + +1. 現代終端機模擬器,例如: + - [WezTerm](https://wezterm.org),跨平台 + - [Alacritty](https://alacritty.org),跨平台 + - [Ghostty](https://ghostty.org),Linux 和 macOS + - [Kitty](https://sw.kovidgoyal.net/kitty/),Linux 和 macOS + +2. 您想要使用的 LLM 供應商的 API 金鑰。 + +--- + +## 安裝 + +安裝 OpenCode 最簡單的方法是透過安裝指令碼。 + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + +您也可以使用以下指令安裝: + +- **使用 Node.js** + + + + + ```bash + npm install -g opencode-ai + ``` + + + + + ```bash + bun install -g opencode-ai + ``` + + + + + ```bash + pnpm install -g opencode-ai + ``` + + + + + ```bash + yarn global add opencode-ai + ``` + + + + + +- **在 macOS 和 Linux 上使用 Homebrew** + + ```bash + brew install anomalyco/tap/opencode + ``` + + > 我們建議使用 OpenCode tap 來獲取最新版本。官方 `brew install opencode` formula 由 Homebrew 團隊維護,更新頻率較低。 + +- **在 Arch Linux 上使用 Paru** + + ```bash + paru -S opencode-bin + ``` + +#### Windows + +:::tip[建議:使用 WSL] +為了在 Windows 上獲得最佳體驗,我們建議使用[適用於 Linux 的 Windows 子系統 (WSL)](/docs/windows-wsl)。它提供了更好的效能並與 OpenCode 的功能完全相容。 +::: + +- **使用 Chocolatey** + + ```bash + choco install opencode + ``` + +- **使用 Scoop** + + ```bash + scoop install opencode + ``` + +- **使用 NPM** + + ```bash + npm install -g opencode-ai + ``` + +- **使用 Mise** + + ```bash + mise use -g github:anomalyco/opencode + ``` + +- **使用 Docker** + + ```bash + docker run -it --rm ghcr.io/anomalyco/opencode + ``` + +目前正在支援使用 Bun 在 Windows 上安裝 OpenCode。 + +您還可以從 [Releases](https://github.com/anomalyco/opencode/releases) 獲取二進位檔案。 + +--- + +## 設定 + +借助 OpenCode,您可以透過設定 API 金鑰來使用任何 LLM 供應商。 + +如果您不熟悉使用 LLM 供應商,我們建議使用 [OpenCode Zen](/docs/zen)。 +這是經過 OpenCode 團隊測試和驗證的精選模型列表。 + +1. 在 TUI 中執行 `/connect` 指令,選擇 opencode,然後前往 [opencode.ai/auth](https://opencode.ai/auth)。 + + ```txt + /connect + ``` + +2. 登入,新增您的帳單詳細資訊,然後複製您的 API 金鑰。 + +3. 貼上您的 API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +或者,您可以選擇其他供應商之一。[了解更多](/docs/providers#directory)。 + +--- + +## 初始化 + +現在您已經設定了供應商,您可以導航到一個您想繼續工作的專案。 + +```bash +cd /path/to/project +``` + +並執行 OpenCode。 + +```bash +opencode +``` + +接下來,透過執行以下指令來初始化專案的 OpenCode。 + +```bash frame="none" +/init +``` + +這將使 OpenCode 分析您的專案並在專案根目錄下建立 `AGENTS.md` 檔案。 + +:::tip +您應該將專案的 `AGENTS.md` 檔案提交到 Git。 +::: + +這有助於 OpenCode 理解專案結構和使用的編碼模式。 + +--- + +## 用法 + +您現在已準備好使用 OpenCode 來處理您的專案。請隨意詢問任何事物! + +如果您不熟悉使用 AI 程式碼代理,以下是一些可能會有所幫助的範例。 + +--- + +### 提出問題 + +您可以用 OpenCode 向您解釋程式碼庫。 + +:::tip +使用`@`鍵模糊搜尋專案中的檔案。 +::: + +```txt frame="none" "@packages/functions/src/api/index.ts" +How is authentication handled in @packages/functions/src/api/index.ts +``` + +如果您沒有處理程式碼庫的一部分,這會很有幫助。 + +--- + +### 新增功能 + +您可以用 OpenCode 向您的專案新增新功能。不過我們首先建議要求它制定一個計畫。 + +1. **制定計畫** + + OpenCode 有一個*計畫模式*,該模式禁用其進行變更,而是建議*如何*實作該功能。 + + 使用 **Tab** 鍵切換到它。您會在右下角看到一個指示符。 + + ```bash frame="none" title="Switch to Plan mode" + + ``` + + 現在讓我們描述一下我們想要它做什麼。 + + ```txt frame="none" + When a user deletes a note, we'd like to flag it as deleted in the database. + Then create a screen that shows all the recently deleted notes. + From this screen, the user can undelete a note or permanently delete it. + ``` + + 您需要為 OpenCode 提供足夠的詳細資訊以了解您想要的內容。這有幫助,就像與團隊中的初級開發人員交談一樣與它交談。 + + :::tip + 為 OpenCode 提供大量上下文和範例,以幫助其理解您的想法。 + ::: + +2. **迭代計畫** + + 一旦它為您提供了計畫,您可以提供回饋或新增更多詳細資訊。 + + ```txt frame="none" + We'd like to design this new screen using a design I've used before. + [Image #1] Take a look at this image and use it as a reference. + ``` + + :::tip + 將影像拖放到終端機中以將其新增到提示中。 + ::: + + OpenCode 可以掃描您提供的任何影像並將其新增到提示中。您可以透過將影像拖放到終端機中來完成此操作。 + +3. **建置功能** + + 一旦您對計畫感到滿意,請切換回*建置模式*,再次按 **Tab** 鍵。 + + ```bash frame="none" + + ``` + + 並要求它做出改變。 + + ```bash frame="none" + Sounds good! Go ahead and make the changes. + ``` + +--- + +### 做出改變 + +對於更直接的變更,您可以要求 OpenCode 直接建置它,無需先審閱計畫。 + +```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 +handled in the /notes route in @packages/functions/src/notes.ts and implement +the same logic in @packages/functions/src/settings.ts +``` + +您需要確保提供大量詳細資訊,以便 OpenCode 做出正確的變更。 + +--- + +### 撤銷變更 + +假設您要求 OpenCode 進行一些變更。 + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +但你意識到這不是你想要的。您**可以撤銷**變更,使用 `/undo` 指令。 + +```bash frame="none" +/undo +``` + +OpenCode 現在將復原您所做的變更並再次顯示您的原始訊息。 + +```txt frame="none" "@packages/functions/src/api/index.ts" +Can you refactor the function in @packages/functions/src/api/index.ts? +``` + +從這裡您可以調整提示並要求 OpenCode 重試。 + +:::tip +您可以多次執行 `/undo` 以撤銷多項變更。 +::: + +或者您**可以使用 `/redo` 指令重做**變更。 + +```bash frame="none" +/redo +``` + +--- + +## 分享 + +您與 OpenCode 的對話可以[與您的團隊分享](/docs/share)。 + +```bash frame="none" +/share +``` + +這將建立目前對話的連結並將其複製到剪貼簿。 + +:::note +預設情況下不分享對話。 +::: + +這是帶有 OpenCode 的[範例對話](https://opencode.ai/s/4XP1fce5)。 + +--- + +## 自訂 + +就是這樣!您現在已經是使用 OpenCode 的專家了。 + +要使其成為您自己的,我們建議 [選擇一個主題](/docs/themes)、[自訂按鍵綁定](/docs/keybinds)、[設定程式碼格式化程式](/docs/formatters)、[建立自定義指令](/docs/commands) 或使用 [OpenCode 設定](/docs/config)。 diff --git a/packages/web/src/content/docs/zh-tw/keybinds.mdx b/packages/web/src/content/docs/zh-tw/keybinds.mdx new file mode 100644 index 00000000000..de3d6882f27 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/keybinds.mdx @@ -0,0 +1,192 @@ +--- +title: 按鍵綁定 +description: 自定義您的按鍵綁定。 +--- + +opencode 有一個按鍵綁定列表,您可以透過 opencode 設定進行自定義。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "leader": "ctrl+x", + "app_exit": "ctrl+c,ctrl+d,q", + "editor_open": "e", + "theme_list": "t", + "sidebar_toggle": "b", + "scrollbar_toggle": "none", + "username_toggle": "none", + "status_view": "s", + "tool_details": "none", + "session_export": "x", + "session_new": "n", + "session_list": "l", + "session_timeline": "g", + "session_fork": "none", + "session_rename": "none", + "session_share": "none", + "session_unshare": "none", + "session_interrupt": "escape", + "session_compact": "c", + "session_child_cycle": "right", + "session_child_cycle_reverse": "left", + "session_parent": "up", + "messages_page_up": "pageup,ctrl+alt+b", + "messages_page_down": "pagedown,ctrl+alt+f", + "messages_line_up": "ctrl+alt+y", + "messages_line_down": "ctrl+alt+e", + "messages_half_page_up": "ctrl+alt+u", + "messages_half_page_down": "ctrl+alt+d", + "messages_first": "ctrl+g,home", + "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", + "messages_copy": "y", + "messages_undo": "u", + "messages_redo": "r", + "messages_last_user": "none", + "messages_toggle_conceal": "h", + "model_list": "m", + "model_cycle_recent": "f2", + "model_cycle_recent_reverse": "shift+f2", + "model_cycle_favorite": "none", + "model_cycle_favorite_reverse": "none", + "variant_cycle": "ctrl+t", + "command_list": "ctrl+p", + "agent_list": "a", + "agent_cycle": "tab", + "agent_cycle_reverse": "shift+tab", + "input_clear": "ctrl+c", + "input_paste": "ctrl+v", + "input_submit": "return", + "input_newline": "shift+return,ctrl+return,alt+return,ctrl+j", + "input_move_left": "left,ctrl+b", + "input_move_right": "right,ctrl+f", + "input_move_up": "up", + "input_move_down": "down", + "input_select_left": "shift+left", + "input_select_right": "shift+right", + "input_select_up": "shift+up", + "input_select_down": "shift+down", + "input_line_home": "ctrl+a", + "input_line_end": "ctrl+e", + "input_select_line_home": "ctrl+shift+a", + "input_select_line_end": "ctrl+shift+e", + "input_visual_line_home": "alt+a", + "input_visual_line_end": "alt+e", + "input_select_visual_line_home": "alt+shift+a", + "input_select_visual_line_end": "alt+shift+e", + "input_buffer_home": "home", + "input_buffer_end": "end", + "input_select_buffer_home": "shift+home", + "input_select_buffer_end": "shift+end", + "input_delete_line": "ctrl+shift+d", + "input_delete_to_line_end": "ctrl+k", + "input_delete_to_line_start": "ctrl+u", + "input_backspace": "backspace,shift+backspace", + "input_delete": "ctrl+d,delete,shift+delete", + "input_undo": "ctrl+-,super+z", + "input_redo": "ctrl+.,super+shift+z", + "input_word_forward": "alt+f,alt+right,ctrl+right", + "input_word_backward": "alt+b,alt+left,ctrl+left", + "input_select_word_forward": "alt+shift+f,alt+shift+right", + "input_select_word_backward": "alt+shift+b,alt+shift+left", + "input_delete_word_forward": "alt+d,alt+delete,ctrl+delete", + "input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace", + "history_previous": "up", + "history_next": "down", + "terminal_suspend": "ctrl+z", + "terminal_title_toggle": "none", + "tips_toggle": "h", + "display_thinking": "none" + } +} +``` + +--- + +## Leader 鍵 + +opencode 對大多數按鍵綁定使用 `leader` 鍵。這可以避免終端機中的衝突。 + +預設情況下,`ctrl+x` 是 Leader 鍵,大多數操作要求您先按 Leader 鍵,然後再按快速鍵。例如,要開始新工作階段,請先按 `ctrl+x`,然後按 `n`。 + +您不需要為鍵綁定使用 Leader 鍵,但我們建議您這樣做。 + +--- + +## 禁用按鍵綁定 + +您可以透過將鍵添加到您的設定中並使用值「none」來禁用鍵綁定。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "session_compact": "none" + } +} +``` + +--- + +## 桌面提示快速鍵 + +opencode 桌面應用程式提示輸入支援常見的 Readline/Emacs 風格的文字編輯快速鍵。這些是內建的,目前無法透過 `opencode.json` 進行設定。 + +| 快速鍵 | 動作 | +| -------- | ------------------------- | +| `ctrl+a` | 移至當前行開頭 | +| `ctrl+e` | 移至當前行尾 | +| `ctrl+b` | 將游標向後移動一個字元 | +| `ctrl+f` | 將游標向前移動一個字元 | +| `alt+b` | 將游標向後移動一個字 | +| `alt+f` | 將游標向前移動一個字 | +| `ctrl+d` | 刪除游標下的字元 | +| `ctrl+k` | 刪除至行尾 | +| `ctrl+u` | 刪除至行首 | +| `ctrl+w` | 刪除前一個單字 | +| `alt+d` | 刪除下一個單字 | +| `ctrl+t` | 調換字元 | +| `ctrl+g` | 取消彈出視窗/中止執行回應 | + +--- + +## Shift+Enter + +預設情況下,某些終端機不發送帶有 Enter 的輔助鍵。您可能需要將終端機設定為發送 `Shift+Enter` 作為跳脫序列。 + +### Windows Terminal + +打開您的 `settings.json`: + +``` +%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json +``` + +將其添加到根級 `actions` 陣列: + +```json +"actions": [ + { + "command": { + "action": "sendInput", + "input": "\u001b[13;2u" + }, + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +將其添加到根級 `keybindings` 陣列: + +```json +"keybindings": [ + { + "keys": "shift+enter", + "id": "User.sendInput.ShiftEnterCustom" + } +] +``` + +儲存檔案並重新啟動 Windows Terminal 或打開新分頁。 diff --git a/packages/web/src/content/docs/zh-tw/lsp.mdx b/packages/web/src/content/docs/zh-tw/lsp.mdx new file mode 100644 index 00000000000..54bc37c2635 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/lsp.mdx @@ -0,0 +1,188 @@ +--- +title: LSP 伺服器 +description: opencode 與您的 LSP 伺服器整合。 +--- + +opencode 與您的語言伺服器協定 (LSP) 整合,以幫助 LLM 與您的程式碼庫互動。它使用診斷向 LLM 提供回饋。 + +--- + +## 內建 + +opencode 附帶了多種適用於流行語言的內建 LSP 伺服器: + +| 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+)` 已安裝 | +| kotlin-ls | .kt、.kts | Kotlin 專案的自動安裝 | +| lua-ls | .lua | 自動安裝 Lua 專案 | +| nil | .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-analyzer | .rs | `rust-analyzer` 指令可用 | +| sourcekit-lsp | .swift、.objc、.objcpp | `swift` 已安裝(`xcode` 在 macOS 上) | +| svelte | .svelte | Svelte 專案的自動安裝 | +| terraform-ls | .tf、.tfvars | 從 GitHub Releases 自動安裝 | +| tinymist | .typ、.typc | 從 GitHub Releases 自動安裝 | +| typescript | .ts、.tsx、.js、.jsx、.mjs、.cjs、.mts、.cts | `typescript` 專案中的相依套件 | +| vue | .vue | Vue 專案自動安裝 | +| yaml-ls | .yaml、.yml | 自動安裝 Red Hat yaml-language-server | +| zls | .zig、.zon | `zig` 指令可用 | + +當檢測到上述檔案副檔名之一且滿足要求時,LSP 伺服器將自動啟用。 + +:::note +您可以透過將 `OPENCODE_DISABLE_LSP_DOWNLOAD` 環境變數設定為 `true` 來禁用自動 LSP 伺服器下載。 +::: + +--- + +## 它是如何運作的 + +當 opencode 打開一個檔案時,它: + +1. 根據所有啟用的 LSP 伺服器檢查檔案副檔名。 +2. 如果尚未執行,則啟動相應的 LSP 伺服器。 + +--- + +## 設定 + +您可以透過 opencode 設定中的 `lsp` 部分自定義 LSP 伺服器。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +``` + +每個 LSP 伺服器支援以下功能: + +| 屬性 | 類型 | 描述 | +| ---------------- | ------ | ----------------------------------- | +| `disabled` | 布林值 | 將其設定為 `true` 以禁用 LSP 伺服器 | +| `command` | 字串[] | 啟動 LSP 伺服器的指令 | +| `extensions` | 字串[] | 此 LSP 伺服器應處理的檔案副檔名 | +| `env` | 物件 | 啟動伺服器時設定的環境變數 | +| `initialization` | 物件 | 發送到 LSP 伺服器的初始化選項 | + +讓我們看一些例子。 + +--- + +### 環境變數 + +啟動 LSP 伺服器時使用 `env` 屬性設定環境變數: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### 初始化選項 + +使用 `initialization` 屬性將初始化選項傳遞給 LSP 伺服器。這些是在 LSP `initialize` 請求期間發送的伺服器特定設定: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +初始化選項因 LSP 伺服器而異。檢查 LSP 伺服器的文件以獲取可用選項。 +::: + +--- + +### 禁用 LSP 伺服器 + +要全域禁用**所有** LSP 伺服器,請將 `lsp` 設定為 `false`: + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": false +} +``` + +要禁用**特定** LSP 伺服器,請將 `disabled` 設定為 `true`: + +```json title="opencode.json" {5} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +--- + +### 自定義 LSP 伺服器 + +您可以透過指定指令和檔案副檔名來添加自定義 LSP 伺服器: + +```json title="opencode.json" {4-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +--- + +## 附加資訊 + +### PHP Intelephense + +PHP Intelephense 透過授權金鑰提供高級功能。您可以透過將(僅)金鑰放入位於以下位置的文字檔案中來提供授權金鑰: + +- 在 macOS/Linux 上:`$HOME/intelephense/license.txt` +- 在 Windows 上:`%USERPROFILE%/intelephense/license.txt` + +該檔案應僅包含授權金鑰,不包含其他內容。 diff --git a/packages/web/src/content/docs/zh-tw/mcp-servers.mdx b/packages/web/src/content/docs/zh-tw/mcp-servers.mdx new file mode 100644 index 00000000000..829e696e924 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/mcp-servers.mdx @@ -0,0 +1,511 @@ +--- +title: MCP 伺服器 +description: 添加本地和遠端 MCP 工具。 +--- + +您可以使用「模型上下文協定」或 MCP 將外部工具添加到 opencode。 opencode 支援本地和遠端伺服器。 + +添加後,MCP 工具將自動與內建工具一起供 LLM 使用。 + +--- + +#### 注意事項 + +當您使用 MCP 伺服器時,它會添加到上下文中。如果您有很多工具,這會很快增加。因此,我們建議您謹慎選擇使用哪些 MCP 伺服器。 + +:::tip +MCP 伺服器會添加到您的上下文中,因此您需要小心啟用哪些伺服器。 +::: + +某些 MCP 伺服器(例如 GitHub MCP 伺服器)往往會添加大量 tokens,並且很容易超出上下文限制。 + +--- + +## 啟用 + +您可以在 `mcp` 下的 [opencode 設定](https://opencode.ai/docs/config/) 中定義 MCP 伺服器。為每個 MCP 添加唯一的名稱。當提示 LLM 時,您可以透過名稱引用該 MCP。 + +```jsonc title="opencode.jsonc" {6} +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "name-of-mcp-server": { + // ... + "enabled": true, + }, + "name-of-other-mcp-server": { + // ... + }, + }, +} +``` + +您還可以透過將 `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 + } + } +} +``` + +您的本地設定值會覆寫遠端預設值。有關更多詳細資訊,請參閱 [設定優先級](/docs/config#precedence-order)。 + +--- + +## 本地 + +使用 `type` 將本地 MCP 伺服器添加到 MCP 物件中的 `"local"`。 + +```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` | 字串 | 是 | MCP 伺服器連接類型,必須是 `"local"`。 | +| `command` | 陣列 | 是 | 執行 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` | 字串 | 是 | MCP 伺服器連接類型,必須是 `"remote"`。 | +| `url` | 字串 | 是 | 遠端 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 ` [手動觸發流程](#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 + +如果要禁用伺服器的自動 OAuth(例如,對於使用 API 金鑰的伺服器),請將 `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 設定物件,或 `false` 以禁用 OAuth 自動檢測。 | +| `clientId` | String | OAuth 客戶端 ID。如果未提供,將嘗試動態客戶端註冊。 | +| `clientSecret` | String | OAuth 客戶端密鑰(如果授權伺服器需要)。 | +| `scope` | String | 授權期間請求的 OAuth 範圍。 | + +#### 偵錯 + +如果遠端 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 設定來管理它們。 + +--- + +### 全域 + +這意味著您可以全域啟用或禁用它們。 + +```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 + } +} +``` + +我們也可以使用 glob 模式來禁用所有匹配的 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 + } +} +``` + +這裡我們使用 glob 模式 `my-mcp*` 來禁用所有 MCP。 + +--- + +### 每個代理 + +如果您有大量 MCP 伺服器,您可能只想為每個代理啟用它們並全域禁用它們。為此: + +1. 全局禁用它作為工具。 +2. 在您的 [代理設定](/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 + } + } + } +} +``` + +--- + +#### Glob 模式 + +glob 模式使用簡單的正規表示式 globbing 模式: + +- `*` 匹配零個或多個任意字元(例如,`"my-mcp*"` 匹配 `my-mcp_search`、`my-mcp_list` 等) +- `?` 恰好匹配一個字元 +- 所有其他字元均按字面意思匹配 + +:::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 伺服器](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` 環境變數。 + +將 `use context7` 添加到提示中以使用 Context7 MCP 伺服器。 + +```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. +``` + +--- + +### Vercel 的 Grep + +添加 [Vercel 的 Grep](https://grep.app) MCP 伺服器以搜尋 GitHub 上的程式碼片段。 + +```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/zh-tw/models.mdx b/packages/web/src/content/docs/zh-tw/models.mdx new file mode 100644 index 00000000000..082f8ba4d29 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/models.mdx @@ -0,0 +1,223 @@ +--- +title: 模型 +description: 配置 LLM 供應商和模型。 +--- + +OpenCode 使用 [AI SDK](https://ai-sdk.dev/) 和 [Models.dev](https://models.dev) 來支援 **75+ LLM 供應商**,並且它支援執行本地模型。 + +--- + +## 供應商 + +預設情況下會預先載入大多數流行的供應商。如果您已透過 `/connect` 指令添加了供應商的憑證,那麼它們將在您啟動 OpenCode 時可用。 + +了解有關 [供應商](/docs/providers) 的更多資訊。 + +--- + +## 選擇模型 + +配置完供應商後,您可以透過輸入以下內容來選擇您想要的模型: + +```bash frame="none" +/models +``` + +--- + +## 推薦模型 + +那裡有很多模型,每週都會有新模型問世。 + +:::tip +考慮使用我們推薦的模型之一。 +::: + +然而,既擅長生成程式碼又擅長工具呼叫的只有少數。 + +以下是與 OpenCode 配合良好的幾個模型,排名不分先後。 (這不是詳盡的列表,也不一定是最新的): + +- GPT 5.2 +- GPT 5.1 Codex +- Claude Opus 4.5 +- Claude Sonnet 4.5 +- Minimax M2.1 +- Gemini 3 Pro + +--- + +## 設定預設值 + +要將其中之一設定為預設模型,您可以在您的 +OpenCode 配置。 + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "model": "lmstudio/google/gemma-3n-e4b" +} +``` + +這裡完整的 ID 是 `provider_id/model_id`。例如,如果您使用 [OpenCode Zen](/docs/zen),則您將使用 `opencode/gpt-5.1-codex` 來表示 GPT 5.1 Codex。 + +如果您配置了 [自定義供應商](/docs/providers#custom),則 `provider_id` 是配置中 `provider` 部分的鍵,`model_id` 是 `provider.models` 中的鍵。 + +--- + +## 配置模型 + +您可以透過 config.json 全局配置模型的選項。 + +```jsonc title="opencode.jsonc" {7-12,19-24} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "options": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + "include": ["reasoning.encrypted_content"], + }, + }, + }, + }, + "anthropic": { + "models": { + "claude-sonnet-4-5-20250929": { + "options": { + "thinking": { + "type": "enabled", + "budgetTokens": 16000, + }, + }, + }, + }, + }, + }, +} +``` + +在這裡,我們為兩個內建模型配置全局設定:`gpt-5`(透過 `openai` 供應商存取時)和 `claude-sonnet-4-20250514`(透過 `anthropic` 供應商存取時)。 +內建供應商和模型名稱可以在 [Models.dev](https://models.dev) 上找到。 + +您還可以為您正在使用的任何代理配置這些選項。代理配置會覆寫此處的所有全局選項。 [了解更多](/docs/agents/#additional)。 + +您還可以定義擴展內建變體的自定義變體。變體允許您為同一模型配置不同的設定,而無需建立重複的項目: + +```jsonc title="opencode.jsonc" {6-21} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "opencode": { + "models": { + "gpt-5": { + "variants": { + "high": { + "reasoningEffort": "high", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + "low": { + "reasoningEffort": "low", + "textVerbosity": "low", + "reasoningSummary": "auto", + }, + }, + }, + }, + }, + }, +} +``` + +--- + +## 變體 + +許多模型支援具有不同配置的多種變體。OpenCode 附帶了流行供應商的內建預設變體。 + +### 內建變體 + +OpenCode 附帶了許多供應商的預設變體: + +**Anthropic**: + +- `high` - 高思考預算(預設) +- `max` - 最大思考預算 + +**OpenAI**: + +因模型而異,但大致如下: + +- `none` - 沒有推理 +- `minimal` - 最少的推理工作 +- `low` - 推理工作量低 +- `medium` - 中等推理工作量 +- `high` - 高推理能力 +- `xhigh` - 極高的推理能力 + +**Google**: + +- `low` - 降低工作量/Tokens 預算 +- `high` - 更高的工作量/Tokens 預算 + +:::tip +該列表並不全面。許多其他供應商也有內建的預設值。 +::: + +### 自定義變體 + +您可以覆寫現有變體或添加您自己的變體: + +```jsonc title="opencode.jsonc" {7-18} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "openai": { + "models": { + "gpt-5": { + "variants": { + "thinking": { + "reasoningEffort": "high", + "textVerbosity": "low", + }, + "fast": { + "disabled": true, + }, + }, + }, + }, + }, + }, +} +``` + +### 循環變體 + +使用鍵綁定 `variant_cycle` 在變體之間快速切換。 [了解更多](/docs/keybinds)。 + +--- + +## 載入模型 + +當 OpenCode 啟動時,它會按以下優先順序檢查模型: + +1. `--model` 或 `-m` 命令列旗標。格式與設定檔中的相同:`provider_id/model_id`。 + +2. OpenCode 配置中的模型列表。 + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "model": "anthropic/claude-sonnet-4-20250514" + } + ``` + + 這裡的格式是 `provider/model`。 + +3. 最後使用的模型。 + +4. 第一個模型使用內部優先順序。 diff --git a/packages/web/src/content/docs/zh-tw/modes.mdx b/packages/web/src/content/docs/zh-tw/modes.mdx new file mode 100644 index 00000000000..0d44dc2dd03 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/modes.mdx @@ -0,0 +1,331 @@ +--- +title: 模式 +description: 不同的模式適用於不同的使用案例。 +--- + +:::caution +現在透過 opencode 設定中的 `agent` 選項配置模式。這 +`mode` 選項現已棄用。 [了解更多](/docs/agents)。 +::: + +opencode 中的模式允許您自定義不同使用案例的行為、工具和提示。 + +它具有兩種內建模式:**建置 (Build)**和**計畫 (Plan)**。您可以自定義 +這些或透過 opencode 設定配置您自己的。 + +您可以在工作階段期間在模式之間切換或在設定檔中配置它們。 + +--- + +## 內建 + +opencode 有兩種內建模式。 + +--- + +### 建置 (Build) + +建置是啟用所有工具的**預設**模式。這是開發工作的標準模式,您需要完全存取檔案操作和系統指令。 + +--- + +### 計畫 (Plan) + +專為規劃和分析而設計的受限模式。在計畫模式下,預設情況下禁用以下工具: + +- `write` - 無法建立新檔案 +- `edit` - 無法修改現有檔案,位於 `.opencode/plans/*.md` 的用於詳細說明計畫本身的檔案除外 +- `patch` - 無法套用 Patch +- `bash` - 無法執行 shell 指令 + +當您希望 AI 分析程式碼、建議變更或建立計畫而不對程式碼庫進行任何實際修改時,此模式非常有用。 + +--- + +## 切換 + +您可以在工作階段期間使用 _Tab_ 鍵在模式之間切換。或者您配置的 `switch_mode` 鍵綁定。 + +另請參閱:[格式化程式](/docs/formatters) 有關程式碼格式配置的資訊。 + +--- + +## 設定 + +您可以自定義內建模式或透過配置建立自己的模式。可以透過兩種方式配置模式: + +### JSON 配置 + +在 `opencode.json` 設定檔中配置模式: + +```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 配置 + +您還可以使用 Markdown 檔案定義模式。將它們放入: + +- 全域:`~/.config/opencode/modes/` +- 專案:`.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. +``` + +Markdown 檔名成為模式名稱(例如,`review.md` 建立 `review` 模式)。 + +讓我們詳細看看這些配置選項。 + +--- + +### 模型 (Model) + +使用 `model` 配置覆寫此模式的預設模型。對於使用針對不同任務最佳化的不同模型很有用。例如,更快的規劃模型、更強大的實作模型。 + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### 溫度 (Temperature) + +使用 `temperature` 配置控制 AI 回應的隨機性和創造性。較低的值使回應更加集中和確定,而較高的值則增加創造力和可變性。 + +```json title="opencode.json" +{ + "mode": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +溫度值的範圍通常為 0.0 到 1.0: + +- **0.0-0.2**:非常集中且確定的回應,非常適合程式碼分析和規劃 +- **0.3-0.5**:具有一定創造力的平衡回應,適合一般開發任務 +- **0.6-1.0**:更有創意和多樣化的反應,有助於腦力激盪和探索 + +```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}" + } + } +} +``` + +如果未指定溫度,opencode 將使用特定於模型的預設值(大多數模型通常為 0,Qwen 模型為 0.55)。 + +--- + +### 提示 (Prompt) + +使用 `prompt` 配置為此模式指定自定義系統提示檔案。提示檔案應包含特定於該模式用途的指令。 + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +該路徑是相對於設定檔所在位置的。所以這適用於 +全域 opencode 配置和專案特定配置。 + +--- + +### 工具 (Tools) + +使用 `tools` 配置控制在此模式下可用的工具。您可以透過將特定工具設定為 `true` 或 `false` 來啟用或禁用特定工具。 + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +如果未指定任何工具,則預設啟用所有工具。 + +--- + +#### 可用工具 + +這裡是所有可以透過模式配置控制的工具。 + +| 工具 | 描述 | +| ----------- | ---------------- | +| `bash` | 執行 shell 指令 | +| `edit` | 修改現有檔案 | +| `write` | 建立新檔案 | +| `read` | 讀取檔案內容 | +| `grep` | 搜尋檔案內容 | +| `glob` | 按模式尋找檔案 | +| `list` | 列出目錄內容 | +| `patch` | 對檔案套用 Patch | +| `todowrite` | 管理待辦事項清單 | +| `todoread` | 閱讀待辦事項清單 | +| `webfetch` | 取得網頁內容 | + +--- + +## 自定義模式 + +您可以透過將自定義模式添加到配置來建立自己的自定義模式。以下是使用這兩種方法的範例: + +### 使用 JSON 配置 + +```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 + } + } + } +} +``` + +### 使用 Markdown 檔案 + +在 `.opencode/modes/` 中為專案特定模式建立模式檔案,在 `~/.config/opencode/modes/` 中為全域模式建立模式檔案: + +```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 +``` + +--- + +### 使用案例 + +以下是不同模式的一些常見使用案例。 + +- **建置模式**:啟用所有工具的完整開發工作 +- **計畫模式**:分析和計畫,無需變更 +- **審閱模式**:使用唯讀存取權限和文件工具進行程式碼審閱 +- **除錯模式**:專注於啟用 bash 和讀取工具的調查 +- **文件模式**:使用檔案操作但不使用系統指令的文件編寫 + +您可能還會發現不同的模型適用於不同的使用案例。 diff --git a/packages/web/src/content/docs/zh-tw/network.mdx b/packages/web/src/content/docs/zh-tw/network.mdx new file mode 100644 index 00000000000..1bd900dbb13 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/network.mdx @@ -0,0 +1,57 @@ +--- +title: 網路 +description: 配置代理伺服器和自定義憑證。 +--- + +opencode 支援企業網路環境的標準代理環境變數和自定義憑證。 + +--- + +## 代理伺服器 + +opencode 遵循標準代理環境變數。 + +```bash +# HTTPS proxy (recommended) +export HTTPS_PROXY=https://proxy.example.com:8080 + +# HTTP proxy (if HTTPS not available) +export HTTP_PROXY=http://proxy.example.com:8080 + +# Bypass proxy for local server (required) +export NO_PROXY=localhost,127.0.0.1 +``` + +:::caution +TUI 與本地 HTTP 伺服器通訊。您必須繞過此連接的代理以防止路由迴圈。 +::: + +您可以使用 [CLI 旗標](/docs/cli#run) 配置伺服器的連接埠和主機名稱。 + +--- + +### 身分驗證 + +如果您的代理需要基本身分驗證,請在 URL 中包含憑證。 + +```bash +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +``` + +:::caution +避免對密碼進行寫死。使用環境變數或安全憑證儲存區。 +::: + +對於需要高級身分驗證(例如 NTLM 或 Kerberos)的代理,請考慮使用支援您的身分驗證方法的 LLM 閘道。 + +--- + +## 自定義憑證 + +如果您的企業使用自定義 CA 進行 HTTPS 連接,請配置 opencode 以信任它們。 + +```bash +export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem +``` + +這適用於代理連接和直接 API 存取。 diff --git a/packages/web/src/content/docs/zh-tw/permissions.mdx b/packages/web/src/content/docs/zh-tw/permissions.mdx new file mode 100644 index 00000000000..7f14b9ebc06 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/permissions.mdx @@ -0,0 +1,237 @@ +--- +title: 權限 +description: 控制哪些操作需要批准才能執行。 +--- + +opencode 使用 `permission` 配置來決定給定的操作是否應自動執行、提示您或被阻止。 + +從 `v1.1.1` 開始,舊版 `tools` 布林配置已被棄用,並已合併到 `permission` 中。仍支援舊的 `tools` 配置以實現向後相容性。 + +--- + +## 操作 + +每個權限規則解析為以下之一: + +- `"allow"` — 未經批准執行 +- `"ask"` — 提示批准 +- `"deny"` — 阻止該操作 + +--- + +## 配置 + +您可以全局設定權限(使用 `*`),並覆寫特定工具。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "*": "ask", + "bash": "allow", + "edit": "deny" + } +} +``` + +您還可以一次設定所有權限: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": "allow" +} +``` + +--- + +## 精細規則(物件語法) + +對於大多數權限,您可以使用物件根據工具輸入應用不同的操作。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "npm *": "allow", + "rm *": "deny", + "grep *": "allow" + }, + "edit": { + "*": "deny", + "packages/web/src/content/docs/*.mdx": "allow" + } + } +} +``` + +規則透過模式匹配進行評估,**最後匹配的規則獲勝**。常見的模式是將通用的 `"*"` 規則放在前面,然後再放置更具體的規則。 + +### 通配符 + +權限模式使用簡單的通配符匹配: + +- `*` 匹配零個或多個任意字元 +- `?` 恰好匹配一個字元 +- 所有其他字元均按字面意思匹配 + +### 主目錄展開 + +您可以在模式開頭使用 `~` 或 `$HOME` 來引用您的主目錄。這對於 [`external_directory`](#external-directories) 規則特別有用。 + +- `~/projects/*` -> `/Users/username/projects/*` +- `$HOME/projects/*` -> `/Users/username/projects/*` +- `~` -> `/Users/username` + +### 外部目錄 + +使用 `external_directory` 允許工具呼叫存取啟動 opencode 的工作目錄之外的路徑。這適用於任何採用路徑作為輸入的工具(例如 `read`、`edit`、`list`、`glob`、`grep` 和許多 `bash` 指令)。 + +主目錄展開(如 `~/...`)僅影響模式的編寫方式。它不會使外部路徑成為當前工作空間的一部分,因此仍必須透過 `external_directory` 允許工作目錄之外的路徑。 + +例如,這允許存取 `~/projects/personal/` 下的所有內容: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + } + } +} +``` + +此處允許的任何目錄都會繼承與當前工作空間相同的預設值。自 [`read` 預設為 `allow`](#defaults) 起,也允許讀取 `external_directory` 下的項目,除非被覆寫。當工具應限制在這些路徑中時添加顯式規則,例如在保留讀取的同時阻止編輯: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "external_directory": { + "~/projects/personal/**": "allow" + }, + "edit": { + "~/projects/personal/**": "deny" + } + } +} +``` + +將列表重點放在受信任的路徑上,並根據其他工具的需要疊加額外的允許或拒絕規則(例如 `bash`)。 + +--- + +## 可用權限 + +opencode 權限由工具名稱和一些安全防護措施決定: + +- `read` — 讀取檔案(與檔案路徑匹配) +- `edit` — 所有檔案修改(涵蓋 `edit`、`write`、`patch`、`multiedit`) +- `glob` — 檔案通配符(匹配通配符模式) +- `grep` — 內容搜尋(匹配正規表示式模式) +- `list` — 列出目錄中的檔案(與目錄路徑匹配) +- `bash` — 執行 shell 指令(匹配 `git status --porcelain` 等解析指令) +- `task` — 啟動子代理(與子代理類型匹配) +- `skill` — 載入技能(與技能名稱匹配) +- `lsp` — 執行 LSP 查詢(當前非精細) +- `todoread`、`todowrite` — 讀取/更新待辦事項清單 +- `webfetch` — 獲取 URL(與 URL 匹配) +- `websearch`、`codesearch` — 網頁/程式碼搜尋(與查詢匹配) +- `external_directory` — 當工具存取專案工作目錄之外的路徑時觸發 +- `doom_loop` — 當相同的工具呼叫使用相同的輸入重複 3 次時觸發 + +--- + +## 預設值 + +如果您不指定任何內容,opencode 將從許可的預設值開始: + +- 大多數權限預設為 `"allow"`。 +- `doom_loop` 和 `external_directory` 預設為 `"ask"`。 +- `read` 是 `"allow"`,但 `.env` 檔案預設被拒絕: + +```json title="opencode.json" +{ + "permission": { + "read": { + "*": "allow", + "*.env": "deny", + "*.env.*": "deny", + "*.env.example": "allow" + } + } +} +``` + +--- + +## 「問」(Ask) 的作用是什麼 + +當 opencode 提示批准時,UI 會提供三種結果: + +- `once` — 僅批准此請求 +- `always` — 批准與建議模式匹配的未來請求(對於當前 opencode 工作階段的其餘部分) +- `reject` — 拒絕請求 + +`always` 將批准的模式集由該工具提供(例如,bash 批准通常將安全指令前綴(如 `git status*`)列入白名單)。 + +--- + +## 代理 + +您可以覆寫每個代理的權限。代理權限與全局配置合併,代理規則優先。 [了解更多](/docs/agents#permissions) 關於代理權限。 + +:::note +有關更詳細的模式匹配範例,請參閱上面的 [精細規則(物件語法)](#granular-rules-object-syntax) 部分。 +::: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "deny", + "git push *": "deny", + "grep *": "allow" + } + }, + "agent": { + "build": { + "permission": { + "bash": { + "*": "ask", + "git *": "allow", + "git commit *": "ask", + "git push *": "deny", + "grep *": "allow" + } + } + } + } +} +``` + +您還可以在 Markdown 中配置代理權限: + +```markdown title="~/.config/opencode/agents/review.md" +--- +description: Code review without edits +mode: subagent +permission: + edit: deny + bash: ask + webfetch: deny +--- + +Only analyze code and suggest changes. +``` + +:::tip +對帶有參數的指令使用模式匹配。 `"grep *"` 允許 `grep pattern file.txt`,而 `"grep"` 單獨會阻止它。像 `git status` 這樣的指令適用於預設行為,但在傳遞參數時需要顯式許可(如 `"git status *"`)。 +::: diff --git a/packages/web/src/content/docs/zh-tw/plugins.mdx b/packages/web/src/content/docs/zh-tw/plugins.mdx new file mode 100644 index 00000000000..1b586c3df6b --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/plugins.mdx @@ -0,0 +1,385 @@ +--- +title: 外掛 +description: 編寫您自己的外掛來擴展 opencode。 +--- + +外掛允許您透過掛鉤各種事件和自定義行為來擴展 opencode。您可以建立外掛來新增新功能、與外部服務整合或修改 opencode 的預設行為。 + +例如,查看社群建立的[外掛](/docs/ecosystem#plugins)。 + +--- + +## 使用外掛 + +有兩種載入外掛的方法。 + +--- + +### 從本地檔案 + +將 JavaScript 或 TypeScript 檔案放置在外掛目錄中。 + +- `.opencode/plugins/` - 專案級外掛 +- `~/.config/opencode/plugins/` - 全域外掛 + +這些目錄中的檔案會在啟動時自動載入。 + +--- + +### 來自 npm + +在設定檔中指定 npm 套件。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] +} +``` + +支援常規和範圍 npm 套件。 + +瀏覽[生態系統](/docs/ecosystem#plugins)中的可用外掛。 + +--- + +### 外掛是如何安裝的 + +**npm 外掛** 在啟動時使用 Bun 自動安裝。套件及其相依套件快取在 `~/.cache/opencode/node_modules/` 中。 + +**本地外掛**直接從外掛目錄載入。要使用外部套件,您必須在設定目錄中建立 `package.json`(請參閱[相依性](#dependencies)),或將外掛發佈到 npm 和[將其添加到您的設定中](/docs/config#plugins)。 + +--- + +### 載入順序 + +外掛從所有來源載入,所有掛鉤按順序執行。載入順序為: + +1. 全域設定 (`~/.config/opencode/opencode.json`) +2. 專案設定(`opencode.json`) +3. 全域外掛目錄 (`~/.config/opencode/plugins/`) +4. 專案外掛目錄(`.opencode/plugins/`) + +具有相同名稱和版本的重複 npm 套件將被載入一次。但是,本地外掛和名稱相似的 npm 外掛都是分開載入的。 + +--- + +## 建立一個外掛 + +外掛是一個 **JavaScript/TypeScript 模組**,它匯出一個或多個外掛 +函式。每個函式接收一個上下文物件並返回一個掛鉤物件。 + +--- + +### 相依性 + +本地外掛和自定義工具可以使用外部 npm 套件。將 `package.json` 添加到您的設定目錄,其中包含您需要的相依套件。 + +```json title=".opencode/package.json" +{ + "dependencies": { + "shescape": "^2.1.0" + } +} +``` + +opencode 在啟動時執行 `bun install` 來安裝這些。然後您的外掛和工具就可以匯入它們。 + +```ts title=".opencode/plugins/my-plugin.ts" +import { escape } from "shescape" + +export const MyPlugin = async (ctx) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "bash") { + output.args.command = escape(output.args.command) + } + }, + } +} +``` + +--- + +### 基本結構 + +```js title=".opencode/plugins/example.js" +export const MyPlugin = async ({ project, client, $, directory, worktree }) => { + console.log("Plugin initialized!") + + return { + // Hook implementations go here + } +} +``` + +外掛函式接收: + +- `project`:當前專案資訊。 +- `directory`:當前工作目錄。 +- `worktree`:git 工作樹路徑。 +- `client`:用於與 AI 互動的 opencode SDK 客戶端。 +- `$`:Bun 的 [shell API](https://bun.com/docs/runtime/shell) 用於執行指令。 + +--- + +### TypeScript 支援 + +對於 TypeScript 外掛,您可以從外掛套件中匯入類型: + +```ts title="my-plugin.ts" {1} +import type { Plugin } from "@opencode-ai/plugin" + +export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { + return { + // Type-safe hook implementations + } +} +``` + +--- + +### 事件 + +外掛可以訂閱事件,如下面的範例部分所示。以下是可用的不同事件的列表。 + +#### 指令事件 + +- `command.executed` + +#### 檔案事件 + +- `file.edited` +- `file.watcher.updated` + +#### 安裝事件 + +- `installation.updated` + +#### LSP 事件 + +- `lsp.client.diagnostics` +- `lsp.updated` + +#### 訊息事件 + +- `message.part.removed` +- `message.part.updated` +- `message.removed` +- `message.updated` + +#### 權限事件 + +- `permission.asked` +- `permission.replied` + +#### 伺服器事件 + +- `server.connected` + +#### 工作階段事件 + +- `session.created` +- `session.compacted` +- `session.deleted` +- `session.diff` +- `session.error` +- `session.idle` +- `session.status` +- `session.updated` + +#### Todo 事件 + +- `todo.updated` + +#### Shell 事件 + +- `shell.env` + +#### 工具事件 + +- `tool.execute.after` +- `tool.execute.before` + +#### TUI 事件 + +- `tui.prompt.append` +- `tui.command.execute` +- `tui.toast.show` + +--- + +## 範例 + +以下是一些可用於擴展 opencode 的外掛範例。 + +--- + +### 發送通知 + +當某些事件發生時發送通知: + +```js title=".opencode/plugins/notification.js" +export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { + return { + event: async ({ event }) => { + // Send notification on session completion + if (event.type === "session.idle") { + await $`osascript -e 'display notification "Session completed!" with title "opencode"'` + } + }, + } +} +``` + +我們使用 `osascript` 在 macOS 上執行 AppleScript。這裡我們用它來發送通知。 + +:::note +如果您使用 opencode 桌面應用程式,它可以在回應準備就緒或工作階段出錯時自動發送系統通知。 +::: + +--- + +### .env 保護 + +阻止 opencode 讀取 `.env` 檔案: + +```javascript title=".opencode/plugins/env-protection.js" +export const EnvProtection = async ({ project, client, $, directory, worktree }) => { + return { + "tool.execute.before": async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } + }, + } +} +``` + +--- + +### 注入環境變數 + +將環境變數注入所有 shell 執行(AI 工具和使用者終端機): + +```javascript title=".opencode/plugins/inject-env.js" +export const InjectEnvPlugin = async () => { + return { + "shell.env": async (input, output) => { + output.env.MY_API_KEY = "secret" + output.env.PROJECT_ROOT = input.cwd + }, + } +} +``` + +--- + +### 自定義工具 + +外掛還可以向 opencode 添加自定義工具: + +```ts title=".opencode/plugins/custom-tools.ts" +import { type Plugin, tool } from "@opencode-ai/plugin" + +export const CustomToolsPlugin: Plugin = async (ctx) => { + return { + tool: { + mytool: tool({ + description: "This is a custom tool", + args: { + foo: tool.schema.string(), + }, + async execute(args, context) { + const { directory, worktree } = context + return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` + }, + }), + }, + } +} +``` + +`tool` 輔助程式建立一個 opencode 可以呼叫的自定義工具。它採用 Zod 模式函式並返回一個工具定義: + +- `description`:該工具的作用 +- `args`:工具參數的 Zod 模式 +- `execute`:呼叫工具時執行的函式 + +您的自定義工具將可與內建工具一起用於 opencode。 + +--- + +### 記錄 + +使用 `client.app.log()` 而不是 `console.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(` +## 自定義上下文 + +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` 陣列將被忽略。 diff --git a/packages/web/src/content/docs/zh-tw/providers.mdx b/packages/web/src/content/docs/zh-tw/providers.mdx new file mode 100644 index 00000000000..44bf90d99be --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/providers.mdx @@ -0,0 +1,1886 @@ +--- +title: 供應商 +description: 使用 OpenCode 中的任何 LLM 供應商。 +--- + +import config from "../../../../config.mjs" +export const console = config.console + +OpenCode 使用 [AI SDK](https://ai-sdk.dev/) 和 [Models.dev](https://models.dev) 來支援 **75+ LLM 供應商**,並且它支援執行本地模型。 + +要添加供應商,您需要: + +1. 使用 `/connect` 指令添加供應商的 API 金鑰。 +2. 在 OpenCode 配置中配置供應商。 + +--- + +### 憑證 + +當您使用 `/connect` 指令添加供應商的 API 金鑰時,它們會被儲存 +在 `~/.local/share/opencode/auth.json`。 + +--- + +### 配置 + +您可以在 OpenCode 配置的 `provider` 部分自定義供應商。 + +--- + +#### 基本網址 (Base URL) + +您可以透過設定 `baseURL` 選項來自定義任何供應商的基本 URL。這在使用代理服務或自定義端點時非常有用。 + +```json title="opencode.json" {6} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": { + "options": { + "baseURL": "https://api.anthropic.com/v1" + } + } + } +} +``` + +--- + +## OpenCode Zen + +OpenCode Zen 是 OpenCode 團隊提供的模型列表,這些模型已被 +經過測試和驗證,可以與 OpenCode 良好配合。 [了解更多](/docs/zen)。 + +:::tip +如果您是新手,我們建議您從 OpenCode Zen 開始。 +::: + +1. 在 TUI 中執行 `/connect` 指令,選擇 opencode,然後前往 [opencode.ai/auth](https://opencode.ai/auth)。 + + ```txt + /connect + ``` + +2. 登入,添加您的帳單詳細資訊,然後複製您的 API 金鑰。 + +3. 貼上您的 API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 在 TUI 中執行 `/models` 以查看我們推薦的模型列表。 + + ```txt + /models + ``` + +它的工作方式與 OpenCode 中的任何其他供應商一樣,並且完全可以選擇使用。 + +--- + +## 目錄 + +讓我們詳細了解一些供應商。如果您想將供應商添加到 +列表,請隨時打開 PR。 + +:::note +在這裡沒有看到供應商?提交 PR。 +::: + +--- + +### 302.AI + +1. 前往 [302.AI 主控台](https://302.ai/),建立一個帳戶並生成一個 API 金鑰。 + +2. 執行 `/connect` 指令並搜尋 **302.AI**。 + + ```txt + /connect + ``` + +3. 輸入您的 302.AI API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令選擇模型。 + + ```txt + /models + ``` + +--- + +### Amazon Bedrock + +要將 Amazon Bedrock 與 OpenCode 結合使用: + +1. 前往 Amazon Bedrock 主控台中的 **Model catalog** 並請求 + 存取您想要的模型。 + + :::tip + 您需要能夠在 Amazon Bedrock 中存取所需的模型。 + ::: + +2. **使用以下方法之一配置身分驗證**: + + #### 環境變數(快速啟動) + + 執行 opencode 時設定以下環境變數之一: + + ```bash + # Option 1: Using AWS access keys + AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode + + # Option 2: Using named AWS profile + AWS_PROFILE=my-profile opencode + + # Option 3: Using Bedrock bearer token + AWS_BEARER_TOKEN_BEDROCK=XXX opencode + ``` + + 或者將它們添加到您的 bash 設定檔中: + + ```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" + } + } + } + } + ``` + + **可用選項:** + - `region` - AWS 區域(例如 `us-east-1`、`eu-west-1`) + - `profile` - 來自 `~/.aws/credentials` 的 AWS 命名設定檔 + - `endpoint` - 用於 VPC 端點的自定義端點 URL(通用 `baseURL` 選項的別名) + + :::tip + 設定檔選項優先於環境變數。 + ::: + + #### 高級: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" + } + } + } + } + ``` + + :::note + `endpoint` 選項是通用 `baseURL` 選項的別名,使用 AWS 特定術語。如果同時指定 `endpoint` 和 `baseURL`,則 `endpoint` 優先。 + ::: + + #### 認證方式 + - **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**:建立 IAM 使用者並在 AWS Console 中生成存取金鑰 + - **`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. **Bearer Token** - `AWS_BEARER_TOKEN_BEDROCK` 環境變數或來自 `/connect` 指令的令牌 + 2. **AWS Credential Chain** - 設定檔、存取金鑰、共享憑證、IAM 角色、Web 身分令牌 (EKS IRSA)、實例元數據 + + :::note + 當設定 Bearer Token 時(透過 `/connect` 或 `AWS_BEARER_TOKEN_BEDROCK`),它優先於所有 AWS 憑證方法(包括配置的設定檔)。 + ::: + +3. 執行 `/models` 指令選擇所需的模型。 + + ```txt + /models + ``` + +:::note +對於自定義推理設定檔,請在鍵中使用模型和供應商名稱,並將 `id` 屬性設定為 arn。這確保了正確的快取: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + // ... + "models": { + "anthropic-claude-sonnet-4.5": { + "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" + } + } + } + } +} +``` + +::: + +--- + +### Anthropic + +1. 註冊後,執行 `/connect` 指令並選擇 Anthropic。 + + ```txt + /connect + ``` + +2. 在這裡您可以選擇 **Claude Pro/Max** 選項,它將打開您的瀏覽器 + 並要求您進行身分驗證。 + + ```txt + ┌ Select auth method + │ + │ Claude Pro/Max + │ Create an API Key + │ Manually enter API Key + └ + ``` + +3. 現在,當您使用 `/models` 指令時,所有 Anthropic 模型都應該可用。 + + ```txt + /models + ``` + +:::info +[Anthropic](https://anthropic.com) 不正式支援在 OpenCode 中使用您的 Claude Pro/Max 訂閱。 +::: + +##### 使用 API 金鑰 + +如果您沒有 Pro/Max 訂閱,您還可以選擇 **Create an API Key**。它還會打開您的瀏覽器並要求您登入 Anthropic 並為您提供一個可以貼上到終端機中的代碼。 + +或者,如果您已有 API 金鑰,則可以選擇 **Manually enter API Key** 並將其貼上到您的終端機中。 + +--- + +### Azure OpenAI + +:::note +如果遇到 "I'm sorry, but I cannot assist with that request" 錯誤,請嘗試將 Azure 資源中的內容篩選器從 **DefaultV2** 更改為 **Default**。 +::: + +1. 轉到 [Azure portal](https://portal.azure.com/) 並建立 **Azure OpenAI** 資源。您需要: + - **Resource name**:這將成為您的 API 端點 (`https://RESOURCE_NAME.openai.azure.com/`) 的一部分 + - **API key**:來自您的資源的 `KEY 1` 或 `KEY 2` + +2. 轉到 [Azure AI Foundry](https://ai.azure.com/) 並部署模型。 + + :::note + 部署名稱必須與模型名稱匹配,OpenCode 才能正常工作。 + ::: + +3. 執行 `/connect` 指令並搜尋 **Azure**。 + + ```txt + /connect + ``` + +4. 輸入您的 API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. 將您的資源名稱設定為環境變數: + + ```bash + AZURE_RESOURCE_NAME=XXX opencode + ``` + + 或者將其添加到您的 bash 設定檔中: + + ```bash title="~/.bash_profile" + export AZURE_RESOURCE_NAME=XXX + ``` + +6. 執行 `/models` 指令以選擇您部署的模型。 + + ```txt + /models + ``` + +--- + +### Azure Cognitive Services + +1. 轉到 [Azure portal](https://portal.azure.com/) 並建立 **Azure OpenAI** 資源。您需要: + - **Resource name**:這將成為您的 API 端點 (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) 的一部分 + - **API key**:來自您的資源的 `KEY 1` 或 `KEY 2` + +2. 轉到 [Azure AI Foundry](https://ai.azure.com/) 並部署模型。 + + :::note + 部署名稱必須與模型名稱匹配,OpenCode 才能正常工作。 + ::: + +3. 執行 `/connect` 指令並搜尋 **Azure Cognitive Services**。 + + ```txt + /connect + ``` + +4. 輸入您的 API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +5. 將您的資源名稱設定為環境變數: + + ```bash + AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode + ``` + + 或者將其添加到您的 bash 設定檔中: + + ```bash title="~/.bash_profile" + export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX + ``` + +6. 執行 `/models` 指令以選擇您部署的模型。 + + ```txt + /models + ``` + +--- + +### Baseten + +1. 前往 [Baseten](https://app.baseten.co/),建立一個帳戶並生成一個 API 金鑰。 + +2. 執行 `/connect` 指令並搜尋 **Baseten**。 + + ```txt + /connect + ``` + +3. 輸入您的 Baseten API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令選擇模型。 + + ```txt + /models + ``` + +--- + +### Cerebras + +1. 前往 [Cerebras console](https://inference.cerebras.ai/),建立一個帳戶並生成一個 API 金鑰。 + +2. 執行 `/connect` 指令並搜尋 **Cerebras**。 + + ```txt + /connect + ``` + +3. 輸入您的 Cerebras API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令選擇模型,如 _Qwen 3 Coder 480B_。 + + ```txt + /models + ``` + +--- + +### Cloudflare AI Gateway + +Cloudflare AI Gateway 讓您可以透過統一端點存取來自 OpenAI、Anthropic、Workers AI 等的模型。使用 [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/),您不需要為每個供應商提供單獨的 API 金鑰。 + +1. 前往 [Cloudflare dashboard](https://dash.cloudflare.com/),導覽至 **AI** > **AI Gateway**,然後建立一個新閘道。 + +2. 將您的 Account ID 和 Gateway ID 設定為環境變數。 + + ```bash title="~/.bash_profile" + export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id + export CLOUDFLARE_GATEWAY_ID=your-gateway-id + ``` + +3. 執行 `/connect` 指令並搜尋 **Cloudflare AI Gateway**。 + + ```txt + /connect + ``` + +4. 輸入您的 Cloudflare API 令牌。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + + 或者將其設定為環境變數。 + + ```bash title="~/.bash_profile" + export CLOUDFLARE_API_TOKEN=your-api-token + ``` + +5. 執行 `/models` 指令選擇模型。 + + ```txt + /models + ``` + + 您還可以透過 OpenCode 配置添加模型。 + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "cloudflare-ai-gateway": { + "models": { + "openai/gpt-4o": {}, + "anthropic/claude-sonnet-4": {} + } + } + } + } + ``` + +--- + +### Cortecs + +1. 前往 [Cortecs console](https://cortecs.ai/),建立一個帳戶並生成一個 API 金鑰。 + +2. 執行 `/connect` 指令並搜尋 **Cortecs**。 + + ```txt + /connect + ``` + +3. 輸入您的 Cortecs API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令選擇一個模型,如 _Kimi K2 Instruct_。 + + ```txt + /models + ``` + +--- + +### DeepSeek + +1. 前往 [DeepSeek console](https://platform.deepseek.com/),建立一個帳戶,然後單擊 **Create new API key**。 + +2. 執行 `/connect` 指令並搜尋 **DeepSeek**。 + + ```txt + /connect + ``` + +3. 輸入您的 DeepSeek API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令以選擇 DeepSeek 模型,例如 _DeepSeek Reasoner_。 + + ```txt + /models + ``` + +--- + +### Deep Infra + +1. 前往 [Deep Infra dashboard](https://deepinfra.com/dash),建立一個帳戶並生成一個 API 金鑰。 + +2. 執行 `/connect` 指令並搜尋 **Deep Infra**。 + + ```txt + /connect + ``` + +3. 輸入您的 Deep Infra API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令選擇模型。 + + ```txt + /models + ``` + +--- + +### Firmware + +1. 前往 [Firmware dashboard](https://app.firmware.ai/signup),建立一個帳戶並生成一個 API 金鑰。 + +2. 執行 `/connect` 指令並搜尋 **Firmware**。 + + ```txt + /connect + ``` + +3. 輸入您的 Firmware API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令選擇模型。 + + ```txt + /models + ``` + +--- + +### Fireworks AI + +1. 前往 [Fireworks AI console](https://app.fireworks.ai/),建立一個帳戶,然後單擊 **Create API Key**。 + +2. 執行 `/connect` 指令並搜尋 **Fireworks AI**。 + + ```txt + /connect + ``` + +3. 輸入您的 Fireworks AI API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令選擇一個模型,如 _Kimi K2 Instruct_。 + + ```txt + /models + ``` + +--- + +### GitLab Duo + +GitLab Duo 透過 GitLab 的 Anthropic 代理提供具有本機工具呼叫功能的 AI 驅動的代理聊天。 + +1. 執行 `/connect` 指令並選擇 GitLab。 + + ```txt + /connect + ``` + +2. 選擇您的身分驗證方法: + + ```txt + ┌ Select auth method + │ + │ OAuth (Recommended) + │ Personal Access Token + │ + └ + ``` + + #### 使用 OAuth(推薦) + + 選擇 **OAuth**,您的瀏覽器將打開以進行授權。 + + #### 使用 Personal Access Token + 1. 前往 [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens) + 2. 單擊 **Add new token** + 3. Name:`OpenCode`,Scopes:`api` + 4. 複製令牌(以 `glpat-` 開頭) + 5. 在終端機中輸入它 + +3. 執行 `/models` 指令以查看可用模型。 + + ```txt + /models + ``` + + 提供三種基於 Claude 的模型: + - **duo-chat-haiku-4-5**(Default)- 快速任務的快速回應 + - **duo-chat-sonnet-4-5** - 大多數工作流程的平衡性能 + - **duo-chat-opus-4-5** - 最有能力進行複雜分析 + +:::note +如果您不想將令牌儲存在 OpenCode auth 儲存中,也可以指定 `GITLAB_TOKEN` 環境變數。 +::: + +##### 自託管 GitLab + +:::note[合規性注意事項] +OpenCode 使用小型模型來執行某些 AI 任務,例如生成工作階段標題。 +預設情況下,它配置為使用 gpt-5-nano,由 Zen 託管。若要鎖定 OpenCode +僅使用您自己的 GitLab 託管實例,請將以下內容添加到您的 +`opencode.json` 檔案。還建議禁用工作階段分享。 + +```json +{ + "$schema": "https://opencode.ai/config.json", + "small_model": "gitlab/duo-chat-haiku-4-5", + "share": "disabled" +} +``` + +::: + +對於自託管的 GitLab 實例: + +```bash +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_TOKEN=glpat-... +``` + +如果您的實例執行自定義 AI 閘道: + +```bash +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +``` + +或者添加到您的 bash 設定檔中: + +```bash title="~/.bash_profile" +export GITLAB_INSTANCE_URL=https://gitlab.company.com +export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +export GITLAB_TOKEN=glpat-... +``` + +:::note +您的 GitLab 管理員必須啟用以下功能: + +1. [Duo Agent Platform](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) 用於使用者、組或實例 +2. Feature flags(透過 Rails console): + - `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(允許對儲存庫進行唯讀存取) + +然後將應用程式 ID 公開為環境變數: + +```bash +export GITLAB_OAUTH_CLIENT_ID=your_application_id_here +``` + +更多文件請參見 [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth) 主頁。 + +##### 配置 + +透過 `opencode.json` 定制: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "gitlab": { + "options": { + "instanceUrl": "https://gitlab.com", + "featureFlags": { + "duo_agent_platform_agentic_chat": true, + "duo_agent_platform": true + } + } + } + } +} +``` + +##### GitLab API Tools(可選,但強烈推薦) + +要存取 GitLab 工具(merge requests、issues、pipelines、CI/CD 等): + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["@gitlab/opencode-gitlab-plugin"] +} +``` + +該外掛提供全面的 GitLab 儲存庫管理功能,包括 MR 審閱、問題追蹤、管線監控等。 + +--- + +### GitHub Copilot + +要將 GitHub Copilot 訂閱與 OpenCode 結合使用: + +:::note +某些模型可能需要 [Pro+ +subscription](https://github.com/features/copilot/plans) 來使用。 +::: + +1. 執行 `/connect` 指令並搜尋 GitHub Copilot。 + + ```txt + /connect + ``` + +2. 導覽至 [github.com/login/device](https://github.com/login/device) 並輸入代碼。 + + ```txt + ┌ Login with GitHub Copilot + │ + │ https://github.com/login/device + │ + │ Enter code: 8F43-6FCF + │ + └ Waiting for authorization... + ``` + +3. 現在執行 `/models` 指令來選擇您想要的模型。 + + ```txt + /models + ``` + +--- + +### Google Vertex AI + +要將 Google Vertex AI 與 OpenCode 結合使用: + +1. 前往 Google Cloud Console 中的 **Model Garden** 並檢查 + 您所在地區提供的模型。 + + :::note + 您需要有一個啟用了 Vertex AI API 的 Google Cloud 專案。 + ::: + +2. 設定所需的環境變數: + - `GOOGLE_CLOUD_PROJECT`:您的 Google Cloud 專案 ID + - `VERTEX_LOCATION`(可選):Vertex AI 的區域(預設為 `global`) + - 身分驗證(選擇一項): + - `GOOGLE_APPLICATION_CREDENTIALS`:Path to your service account JSON key file + - Authenticate using gcloud CLI: `gcloud auth application-default login` + + 在執行 opencode 時設定它們。 + + ```bash + GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode + ``` + + 或者將它們添加到您的 bash 設定檔中。 + + ```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` 區域無需額外成本即可提高可用性並減少錯誤。使用區域端點(例如 `us-central1`)來滿足資料駐留要求。 [了解更多](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) +::: + +3. 執行 `/models` 指令選擇所需的模型。 + + ```txt + /models + ``` + +--- + +### Groq + +1. 前往 [Groq console](https://console.groq.com/),單擊 **Create API Key**,然後複製金鑰。 + +2. 執行 `/connect` 指令並搜尋 Groq。 + + ```txt + /connect + ``` + +3. 輸入供應商的 API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令選擇您想要的。 + + ```txt + /models + ``` + +--- + +### Hugging Face + +[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 Providers 權限的令牌。 + +2. 執行 `/connect` 指令並搜尋 **Hugging Face**。 + + ```txt + /connect + ``` + +3. 輸入您的 Hugging Face 令牌。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令來選擇模型,如 _Kimi-K2-Instruct_ 或 _GLM-4.6_。 + + ```txt + /models + ``` + +--- + +### Helicone + +[Helicone](https://helicone.ai) 是一個 LLM 可觀測性平台,可為您的 AI 應用程式提供記錄、監控和分析。 The Helicone AI Gateway 根據模型自動將您的請求路由到適當的供應商。 + +1. 前往 [Helicone](https://helicone.ai),建立一個帳戶,並從您的儀表板生成 API 金鑰。 + +2. 執行 `/connect` 指令並搜尋 **Helicone**。 + + ```txt + /connect + ``` + +3. 輸入您的 Helicone API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令選擇模型。 + + ```txt + /models + ``` + +有關更多供應商和高級功能(例如快取和速率限制),請查看 [Helicone documentation](https://docs.helicone.ai)。 + +#### 可選配置 + +如果您發現 Helicone 的功能或模型未透過 OpenCode 自動配置,您始終可以自行配置。 + +這是 [Helicone's Model Directory](https://helicone.ai/models),您將需要它來獲取要添加的模型的 ID。 + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + }, + "models": { + "gpt-4o": { + // Model ID (from Helicone's model directory page) + "name": "GPT-4o", // Your own custom name for the model + }, + "claude-sonnet-4-20250514": { + "name": "Claude Sonnet 4", + }, + }, + }, + }, +} +``` + +#### 自定義標頭 + +Helicone 支援快取、使用者追蹤和工作階段管理等功能的自定義標頭。使用 `options.headers` 將它們添加到您的供應商配置中: + +```jsonc title="~/.config/opencode/opencode.jsonc" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "helicone": { + "npm": "@ai-sdk/openai-compatible", + "name": "Helicone", + "options": { + "baseURL": "https://ai-gateway.helicone.ai", + "headers": { + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "opencode", + }, + }, + }, + }, +} +``` + +##### 工作階段追蹤 + +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 +``` + +將其添加到您的配置中。 + +```json title="opencode.json" +{ + "plugin": ["opencode-helicone-session"] +} +``` + +該外掛將 `Helicone-Session-Id` 和 `Helicone-Session-Name` 標頭注入您的請求中。在 Helicone 的 Sessions 頁面中,您將看到每個 OpenCode 對話都列為單獨的工作階段。 + +##### 常見 Helicone 標頭 + +| Header | Description | +| -------------------------- | ------------------------------------------------------ | +| `Helicone-Cache-Enabled` | 啟用回應快取 (`true`/`false`) | +| `Helicone-User-Id` | 按使用者追蹤指標 | +| `Helicone-Property-[Name]` | 添加自定義屬性(例如 `Helicone-Property-Environment`) | +| `Helicone-Prompt-Id` | 將請求與提示版本相關聯 | + +有關所有可用標頭,請參閱 [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory)。 + +--- + +### llama.cpp + +您可以透過 [llama.cpp's](https://github.com/ggml-org/llama.cpp) llama-server 公用程式配置 OpenCode 以使用本地模型 + +```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "llama.cpp": { + "npm": "@ai-sdk/openai-compatible", + "name": "llama-server (local)", + "options": { + "baseURL": "http://127.0.0.1:8080/v1" + }, + "models": { + "qwen3-coder:a3b": { + "name": "Qwen3-Coder: a3b-30b (local)", + "limit": { + "context": 128000, + "output": 65536 + } + } + } + } + } +} +``` + +在這個例子中: + +- `llama.cpp` 是自定義供應商 ID。這可以是您想要的任何字串。 +- `npm` 指定用於此供應商的套件。這裡,`@ai-sdk/openai-compatible` 用於任何 OpenAI 相容的 API。 +- `name` 是 UI 中供應商的顯示名稱。 +- `options.baseURL` 是本地伺服器的端點。 +- `models` 是模型 ID 與其配置的對應。模型名稱將顯示在模型選擇列表中。 + +--- + +### IO.NET + +IO.NET 提供了 17 種針對各種使用案例進行最佳化的模型: + +1. 前往 [IO.NET console](https://ai.io.net/),建立一個帳戶並生成一個 API 金鑰。 + +2. 執行 `/connect` 指令並搜尋 **IO.NET**。 + + ```txt + /connect + ``` + +3. 輸入您的 IO.NET API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令選擇模型。 + + ```txt + /models + ``` + +--- + +### LM Studio + +您可以透過 LM Studio 配置 OpenCode 以使用本地模型。 + +```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { + "baseURL": "http://127.0.0.1:1234/v1" + }, + "models": { + "google/gemma-3n-e4b": { + "name": "Gemma 3n-e4b (local)" + } + } + } + } +} +``` + +在這個例子中: + +- `lmstudio` 是自定義供應商 ID。這可以是您想要的任何字串。 +- `npm` 指定用於此供應商的套件。這裡,`@ai-sdk/openai-compatible` 用於任何 OpenAI 相容的 API。 +- `name` 是 UI 中供應商的顯示名稱。 +- `options.baseURL` 是本地伺服器的端點。 +- `models` 是模型 ID 與其配置的對應。模型名稱將顯示在模型選擇列表中。 + +--- + +### Moonshot AI + +要使用 Moonshot AI 中的 Kimi K2: + +1. 前往 [Moonshot AI console](https://platform.moonshot.ai/console),建立一個帳戶,然後單擊 **Create API key**。 + +2. 執行 `/connect` 指令並搜尋 **Moonshot AI**。 + + ```txt + /connect + ``` + +3. 輸入您的 Moonshot API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令選擇 _Kimi K2_。 + + ```txt + /models + ``` + +--- + +### MiniMax + +1. 前往 [MiniMax API Console](https://platform.minimax.io/login),建立一個帳戶並生成一個 API 金鑰。 + +2. 執行 `/connect` 指令並搜尋 **MiniMax**。 + + ```txt + /connect + ``` + +3. 輸入您的 MiniMax API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令選擇模型,如 _M2.1_。 + + ```txt + /models + ``` + +--- + +### Nebius Token Factory + +1. 前往 [Nebius Token Factory console](https://tokenfactory.nebius.com/),建立一個帳戶,然後單擊 **Add Key**。 + +2. 執行 `/connect` 指令並搜尋 **Nebius Token Factory**。 + + ```txt + /connect + ``` + +3. 輸入您的 Nebius Token Factory API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 執行 `/models` 指令選擇一個模型,如 _Kimi K2 Instruct_。 + + ```txt + /models + ``` + +--- + +### Ollama + +您可以透過 Ollama 配置 OpenCode 以使用本地模型。 + +:::tip +Ollama 可以自動為 OpenCode 配置自身。詳情請參閱 [Ollama integration docs](https://docs.ollama.com/integrations/opencode)。 +::: + +```json title="opencode.json" "ollama" {5, 6, 8, 10-14} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama (local)", + "options": { + "baseURL": "http://localhost:11434/v1" + }, + "models": { + "llama2": { + "name": "Llama 2" + } + } + } + } +} +``` + +在這個例子中: + +- `ollama` 是自定義供應商 ID。這可以是您想要的任何字串。 +- `npm` 指定用於此供應商的套件。這裡,`@ai-sdk/openai-compatible` 用於任何 OpenAI 相容的 API。 +- `name` 是 UI 中供應商的顯示名稱。 +- `options.baseURL` 是本地伺服器的端點。 +- `models` 是模型 ID 與其配置的對應。模型名稱將顯示在模型選擇列表中。 + +:::tip +如果工具呼叫不起作用,請嘗試增加 Ollama 中的 `num_ctx`。從 16k - 32k 左右開始。 +::: + +--- + +### Ollama Cloud + +要將 Ollama Cloud 與 OpenCode 結合使用: + +1. 前往 [https://ollama.com/](https://ollama.com/) 並登入或建立帳戶。 + +2. 導覽到 **Settings** > **Keys**,然後單擊 **Add API Key** 以生成新的 API 金鑰。 + +3. 複製 API 金鑰以在 OpenCode 中使用。 + +4. 執行 `/connect` 指令並搜尋 **Ollama Cloud**。 + + ```txt + /connect + ``` + +5. 輸入您的 Ollama Cloud API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +6. **Important**:在 OpenCode 中使用雲端模型之前,您必須將模型資訊拉取到本地: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. 執行 `/models` 指令以選擇您的 Ollama Cloud 模型。 + + ```txt + /models + ``` + +--- + +### OpenAI + +我們建議註冊 [ChatGPT Plus or Pro](https://chatgpt.com/pricing)。 + +1. 註冊後,執行 `/connect` 指令並選擇 OpenAI。 + + ```txt + /connect + ``` + +2. 在這裡您可以選擇 **ChatGPT Plus/Pro** 選項,它將打開您的瀏覽器 + 並要求您進行身分驗證。 + + ```txt + ┌ Select auth method + │ + │ ChatGPT Plus/Pro + │ Manually enter API Key + └ + ``` + +3. 現在,當您使用 `/models` 指令時,所有 OpenAI 模型都應該可用。 + + ```txt + /models + ``` + +##### 使用 API 金鑰 + +如果您已有 API 金鑰,可以選擇 **Manually enter API Key** 並將其貼上到您的終端機中。 + +--- + +### OpenCode Zen + +OpenCode Zen 是 OpenCode 團隊提供的經過測試和驗證的模型列表。 [了解更多](/docs/zen)。 + +1. 登入 **OpenCode Zen** 並單擊 **Create API Key**。 + +2. 執行 `/connect` 指令並搜尋 **OpenCode Zen**。 + + ```txt + /connect + ``` + +3. 輸入您的 OpenCode API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ 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 透過統一平台提供對 OpenAI、Anthropic、Google、Amazon、Meta、Mistral 和 AI21 的 40 多個模型的存取。 + +1. 轉到您的 [SAP BTP Cockpit](https://account.hana.ondemand.com/),導覽到您的 SAP AI Core 服務實例,然後建立一個服務金鑰。 + + :::tip + 服務金鑰是一個包含 `clientid`、`clientsecret`、`url` 和 `serviceurls.AI_API_URL` 的 JSON 物件。您可以在 BTP Cockpit 的 **Services** > **Instances and Subscriptions** 下找到您的 AI Core 實例。 + ::: + +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 設定檔中: + + ```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' + ``` + +4. (可選)設定部署 ID 和資源組: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + 這些設定是可選的,應根據您的 SAP AI Core 設定進行配置。 + ::: + +5. 執行 `/models` 指令從 40 多個可用模型中進行選擇。 + + ```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. 輸入您的 OVHcloud AI Endpoints API 金鑰。 + + ```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"] + } + } + } + } + } +} +``` + +一些有用的路由選項: + +| Option | Description | +| ------------------- | ---------------------------------------------------- | +| `order` | Provider sequence to try | +| `only` | Restrict to specific providers | +| `zeroDataRetention` | Only use providers with zero data retention policies | + +--- + +### 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": {} + } + } + } + } + ``` + +--- + +## 自定義供應商 + +要添加 `/connect` 指令中未列出的任何 **OpenAI-compatible** 供應商: + +:::tip +您可以將任何與 OpenAI 相容的供應商與 OpenCode 結合使用。大多數現代 AI 供應商都提供與 OpenAI 相容的 API。 +::: + +1. 執行 `/connect` 指令並向下捲動到 **Other**。 + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. 輸入供應商的唯一 ID。 + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::note + 選擇一個容易記住的 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**:API 端點 URL。 + - **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**:模型接受的最大輸入 tokens。 +- **limit.output**:模型可以生成的最大 tokens。 + +`limit` 欄位允許 OpenCode 了解您還剩下多少上下文。標準供應商會自動從 models.dev 中提取這些內容。 + +--- + +## 疑難排解 + +如果您在配置供應商時遇到問題,請檢查以下內容: + +1. **檢查 auth 設定**:執行 `opencode auth list` 以查看憑證是否 + 供應商的配置已添加到您的配置中。 + + 這不適用於 Amazon Bedrock 等依賴環境變數進行身分驗證的供應商。 + +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/zh-tw/rules.mdx b/packages/web/src/content/docs/zh-tw/rules.mdx new file mode 100644 index 00000000000..2ce0c327b69 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/rules.mdx @@ -0,0 +1,180 @@ +--- +title: 規則 +description: 設定 opencode 的自定義指令。 +--- + +您可以透過建立 `AGENTS.md` 檔案來提供 opencode 的自定義指令。這和 Cursor 的規則類似。它包含將包含在 LLM 上下文中的說明,以便為您的特定專案自定義其行為。 + +--- + +## 初始化 + +要建立新的 `AGENTS.md` 檔案,您可以在 opencode 中執行 `/init` 指令。 + +:::tip +您應該將專案的 `AGENTS.md` 檔案提交到 Git。 +::: + +這將掃描您的專案及其所有內容,以了解該專案的內容並生成一個 `AGENTS.md` 檔案。這有助於 opencode 更好地導覽專案。 + +如果您有現有的 `AGENTS.md` 檔案,這將嘗試添加到其中。 + +--- + +## 範例 + +您也可以手動建立此檔案。以下是您可以放入 `AGENTS.md` 檔案中的一些內容的範例。 + +```markdown title="AGENTS.md" +# SST v3 Monorepo Project + +This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. + +## Project Structure + +- `packages/` - Contains all workspace packages (functions, core, web, etc.) +- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) +- `sst.config.ts` - Main SST configuration with dynamic imports + +## Code Standards + +- Use TypeScript with strict mode enabled +- Shared code goes in `packages/core/` with proper exports configuration +- Functions go in `packages/functions/` +- Infrastructure should be split into logical files in `infra/` + +## Monorepo Conventions + +- Import shared modules using workspace names: `@my-app/core/example` +``` + +我們在此處添加特定於專案的說明,這將在您的團隊中共享。 + +--- + +## 類型 + +opencode 還支援從多個位置讀取 `AGENTS.md` 檔案。這有不同的目的。 + +### 專案 + +將 `AGENTS.md` 放置在專案根目錄中以獲取特定於專案的規則。這些僅適用於您在此目錄或其子目錄中工作時。 + +### 全域 + +您還可以在 `~/.config/opencode/AGENTS.md` 檔案中包含全域規則。這適用於所有 opencode 工作階段。 + +由於這未提交給 Git 或與您的團隊共享,因此我們建議使用它來指定 LLM 應遵循的任何個人規則。 + +### Claude Code 相容性 + +對於從 Claude Code 遷移的使用者,opencode 支援 Claude Code 的檔案慣例作為備援: + +- **專案規則**:專案目錄中的 `CLAUDE.md`(如果 `AGENTS.md` 不存在則使用) +- **全域規則**:`~/.claude/CLAUDE.md`(如果不存在 `~/.config/opencode/AGENTS.md` 則使用) +- **技能**:`~/.claude/skills/` — 詳情請參閱 [代理技能](/docs/skills/) + +要禁用 Claude Code 相容性,請設定以下環境變數之一: + +```bash +export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support +export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md +export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills +``` + +--- + +## 優先順序 + +當 opencode 啟動時,它會按以下順序尋找規則檔案: + +1. **本地檔案**,從當前目錄向上遍歷 (`AGENTS.md`,`CLAUDE.md`) +2. **全域檔案** `~/.config/opencode/AGENTS.md` +3. **Claude Code 檔案** 位於 `~/.claude/CLAUDE.md`(除非禁用) + +第一個匹配的檔案在每個類別中獲勝。例如,如果您同時擁有 `AGENTS.md` 和 `CLAUDE.md`,則僅使用 `AGENTS.md`。同樣,`~/.config/opencode/AGENTS.md` 優先於 `~/.claude/CLAUDE.md`。 + +--- + +## 自定義指令 + +您可以在 `opencode.json` 或全域 `~/.config/opencode/opencode.json` 中指定自定義指令檔案。這允許您和您的團隊重複使用現有規則,而不必將它們複製到 AGENTS.md。 + +範例: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] +} +``` + +您還可以使用遠端 URL 從 Web 載入指令。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] +} +``` + +遠端指令的獲取有 5 秒的超時時間。 + +所有指令檔案均與您的 `AGENTS.md` 檔案合併。 + +--- + +## 引用外部檔案 + +雖然 opencode 不會自動解析 `AGENTS.md` 中的檔案引用,但您可以透過兩種方式實現類似的功能: + +### 使用 opencode.json + +推薦的方法是在 `instructions` 中使用 `opencode.json` 欄位: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] +} +``` + +### AGENTS.md 中的手動說明 + +您可以透過在 `AGENTS.md` 中提供明確的指令來教 opencode 讀取外部檔案。這是一個實際的範例: + +```markdown title="AGENTS.md" +# TypeScript Project Rules + +## External File Loading + +CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. + +Instructions: + +- Do NOT preemptively load all references - use lazy loading based on actual need +- When loaded, treat content as mandatory instructions that override defaults +- Follow references recursively when needed + +## Development Guidelines + +For TypeScript code style and best practices: @docs/typescript-guidelines.md +For React component architecture and hooks patterns: @docs/react-patterns.md +For REST API design and error handling: @docs/api-standards.md +For testing strategies and coverage requirements: @test/testing-guidelines.md + +## General Guidelines + +Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. +``` + +這種方法允許您: + +- 建立模組化、可重複使用的規則檔案 +- 透過符號連結或 git 子模組在專案之間共享規則 +- 保持 AGENTS.md 簡潔,同時參考詳細指南 +- 確保 opencode 僅在特定任務需要時載入檔案 + +:::tip +對於 Monorepos 或具有共享標準的專案,使用 `opencode.json` 和 glob 模式(如 `packages/*/AGENTS.md`)比手動指令更易於維護。 +::: diff --git a/packages/web/src/content/docs/zh-tw/sdk.mdx b/packages/web/src/content/docs/zh-tw/sdk.mdx new file mode 100644 index 00000000000..713718c9b3d --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/sdk.mdx @@ -0,0 +1,391 @@ +--- +title: SDK +description: opencode 伺服器的類型安全 JS 客戶端。 +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +opencode JS/TS SDK 提供類型安全的客戶端用於與伺服器互動。 +使用它以程式化方式構建整合和控制 opencode。 + +[了解更多](/docs/server) 關於伺服器如何工作。例如,查看社群構建的[專案](/docs/ecosystem#projects)。 + +--- + +## 安裝 + +從 npm 安裝 SDK: + +```bash +npm install @opencode-ai/sdk +``` + +--- + +## 建立客戶端 + +建立 opencode 的實例: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const { client } = await createOpencode() +``` + +這會同時啟動伺服器和客戶端 + +#### 選項 + +| 選項 | 類型 | 描述 | 預設 | +| ---------- | ------------- | ------------------------------ | ----------- | +| `hostname` | `string` | 伺服器主機名稱 | `127.0.0.1` | +| `port` | `number` | 伺服器連接埠 | `4096` | +| `signal` | `AbortSignal` | 取消的中止訊號 | `undefined` | +| `timeout` | `number` | 伺服器啟動超時(以毫秒為單位) | `5000` | +| `config` | `Config` | 設定物件 | `{}` | + +--- + +## 配置 + +您可以傳遞設定物件來自定義行為。該實例仍然會選擇您的 `opencode.json`,但您可以覆寫或添加內聯設定: + +```javascript +import { createOpencode } from "@opencode-ai/sdk" + +const opencode = await createOpencode({ + hostname: "127.0.0.1", + port: 4096, + config: { + model: "anthropic/claude-3-5-sonnet-20241022", + }, +}) + +console.log(`Server running at ${opencode.server.url}`) + +opencode.server.close() +``` + +## 僅限客戶端 + +如果您已經有一個正在執行的 opencode 實例,您可以建立一個客戶端實例來連接到它: + +```javascript +import { createOpencodeClient } from "@opencode-ai/sdk" + +const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", +}) +``` + +#### 選項 + +| 選項 | 類型 | 描述 | 預設 | +| --------------- | ---------- | ---------------------------- | ----------------------- | +| `baseUrl` | `string` | 伺服器的 URL | `http://localhost:4096` | +| `fetch` | `function` | 自定義 fetch 實作 | `globalThis.fetch` | +| `parseAs` | `string` | 回應解析方法 | `auto` | +| `responseStyle` | `string` | 返回樣式:`data` 或 `fields` | `fields` | +| `throwOnError` | `boolean` | 拋出錯誤而不是返回 | `false` | + +--- + +## 類型 + +SDK 包含所有 API 類型的 TypeScript 定義。直接匯入它們: + +```typescript +import type { Session, Message, Part } from "@opencode-ai/sdk" +``` + +所有類型均根據伺服器的 OpenAPI 規範生成,並可在 types 檔案中找到。 + +--- + +## 錯誤 + +SDK 可能會拋出錯誤,您可以捕捉並處理這些錯誤: + +```typescript +try { + await client.session.get({ path: { id: "invalid-id" } }) +} catch (error) { + console.error("Failed to get session:", (error as Error).message) +} +``` + +--- + +## API + +SDK 透過類型安全的客戶端公開所有伺服器 API。 + +--- + +### 全域 + +| 方法 | 描述 | 回應 | +| ----------------- | ------------------------ | ------------------------------------ | +| `global.health()` | 檢查伺服器健康狀態和版本 | `{ healthy: true, version: string }` | + +--- + +#### 範例 + +```javascript +const health = await client.global.health() +console.log(health.data.version) +``` + +--- + +### 應用程式 + +| 方法 | 描述 | 回應 | +| -------------- | ------------------ | ------------------------------------------- | +| `app.log()` | 寫入日誌項目 | `boolean` | +| `app.agents()` | 列出所有可用的代理 | Agent[] | + +--- + +#### 範例 + +```javascript +// Write a log entry +await client.app.log({ + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, +}) + +// List available agents +const agents = await client.app.agents() +``` + +--- + +### 專案 + +| 方法 | 描述 | 回應 | +| ------------------- | ------------ | --------------------------------------------- | +| `project.list()` | 列出所有專案 | Project[] | +| `project.current()` | 獲取當前專案 | Project | + +--- + +#### 範例 + +```javascript +// List all projects +const projects = await client.project.list() + +// Get current project +const currentProject = await client.project.current() +``` + +--- + +### 路徑 + +| 方法 | 描述 | 回應 | +| ------------ | ------------ | ---------------------------------------- | +| `path.get()` | 獲取當前路徑 | Path | + +--- + +#### 範例 + +```javascript +// Get current path information +const pathInfo = await client.path.get() +``` + +--- + +### 配置 + +| 方法 | 描述 | 回應 | +| -------------------- | -------------------- | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | 獲取設定資訊 | Config | +| `config.providers()` | 列出供應商和預設模型 | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +#### 範例 + +```javascript +const config = await client.config.get() + +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 })` | 發送提示訊息 | `body.noReply: true` 返回 UserMessage(僅上下文)。預設返回帶有 AI 回應的 AssistantMessage | +| `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` | + +--- + +#### 範例 + +```javascript +// Create and manage sessions +const session = await client.session.create({ + body: { title: "My session" }, +}) + +const sessions = await client.session.list() + +// Send a prompt message +const result = await client.session.prompt({ + path: { id: session.id }, + body: { + model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, + parts: [{ type: "text", text: "Hello!" }], + }, +}) + +// Inject context without triggering AI response (useful for plugins) +await client.session.prompt({ + path: { id: session.id }, + body: { + noReply: true, + parts: [{ type: "text", text: "You are a helpful assistant." }], + }, +}) +``` + +--- + +### 檔案 + +| 方法 | 描述 | 回應 | +| ------------------------- | -------------------- | ----------------------------------------------------------------------------------- | +| `find.text({ query })` | 搜尋檔案中的文字 | 具有 `path`, `lines`, `line_number`, `absolute_offset`, `submatches` 的匹配物件陣列 | +| `find.files({ query })` | 按名稱尋找檔案和目錄 | `string[]`(路徑) | +| `find.symbols({ query })` | 尋找工作區符號 | Symbol[] | +| `file.read({ query })` | 讀取檔案 | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | 獲取追蹤檔案的狀態 | File[] | + +`find.files` 支援一些可選的查詢欄位: + +- `type`:`"file"` 或 `"directory"` +- `directory`:覆寫搜尋的專案根目錄 +- `limit`:最大結果 (1–200) + +--- + +#### 範例 + +```javascript +// Search and read files +const textResults = await client.find.text({ + query: { pattern: "function.*opencode" }, +}) + +const files = await client.find.files({ + query: { query: "*.ts", type: "file" }, +}) + +const directories = await client.find.files({ + query: { query: "packages", type: "directory", limit: 20 }, +}) + +const content = await client.file.read({ + query: { path: "src/index.ts" }, +}) +``` + +--- + +### TUI + +| 方法 | 描述 | 回應 | +| ------------------------------ | ------------------ | --------- | +| `tui.appendPrompt({ body })` | 將文字附加到提示 | `boolean` | +| `tui.openHelp()` | 打開說明對話方塊 | `boolean` | +| `tui.openSessions()` | 打開工作階段選擇器 | `boolean` | +| `tui.openThemes()` | 打開主題選擇器 | `boolean` | +| `tui.openModels()` | 打開模型選擇器 | `boolean` | +| `tui.submitPrompt()` | 提交當前提示 | `boolean` | +| `tui.clearPrompt()` | 清除提示 | `boolean` | +| `tui.executeCommand({ body })` | 執行指令 | `boolean` | +| `tui.showToast({ body })` | 顯示 Toast 通知 | `boolean` | + +--- + +#### 範例 + +```javascript +// Control TUI interface +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + +await client.tui.showToast({ + body: { message: "Task completed", variant: "success" }, +}) +``` + +--- + +### 授權 + +| 方法 | 描述 | 回應 | +| ------------------- | ---------------- | --------- | +| `auth.set({ ... })` | 設定身分驗證憑證 | `boolean` | + +--- + +#### 範例 + +```javascript +await client.auth.set({ + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, +}) +``` + +--- + +### 事件 + +| 方法 | 描述 | 回應 | +| ------------------- | -------------------- | -------------------- | +| `event.subscribe()` | 伺服器發送的事件串流 | 伺服器發送的事件串流 | + +--- + +#### 範例 + +```javascript +// Listen to real-time events +const events = await client.event.subscribe() +for await (const event of events.stream) { + console.log("Event:", event.type, event.properties) +} +``` diff --git a/packages/web/src/content/docs/zh-tw/server.mdx b/packages/web/src/content/docs/zh-tw/server.mdx new file mode 100644 index 00000000000..1c038a59dd4 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/server.mdx @@ -0,0 +1,287 @@ +--- +title: 伺服器 +description: 透過 HTTP 與 opencode 伺服器互動。 +--- + +import config from "../../../../config.mjs" +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` + +`opencode serve` 指令執行一個無介面 HTTP 伺服器,該伺服器公開 opencode 客戶端可以使用的 OpenAPI 端點。 + +--- + +### 用法 + +```bash +opencode serve [--port ] [--hostname ] [--cors ] +``` + +#### 選項 + +| 旗標 | 描述 | 預設 | +| --------------- | ------------------------- | ---------------- | +| `--port` | 監聽連接埠 | `4096` | +| `--hostname` | 監聽的主機名稱 | `127.0.0.1` | +| `--mdns` | 啟用 mDNS 探索 | `false` | +| `--mdns-domain` | mDNS 服務的自定義網域名稱 | `opencode.local` | +| `--cors` | 允許的其他瀏覽器來源 | `[]` | + +`--cors` 可以多次傳遞: + +```bash +opencode serve --cors http://localhost:5173 --cors https://app.example.com +``` + +--- + +### 身分驗證 + +設定 `OPENCODE_SERVER_PASSWORD` 以使用 HTTP 基本身分驗證保護伺服器。使用者名稱預設為 `opencode`,或設定 `OPENCODE_SERVER_USERNAME` 來覆蓋它。這適用於 `opencode serve` 和 `opencode web`。 + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve +``` + +--- + +### 它是如何運作的 + +當您執行 `opencode` 時,它會啟動 TUI 和伺服器。 TUI 是 +與伺服器對話的客戶端。伺服器公開 OpenAPI 3.1 規範 +端點。該端點還用於生成 [軟體開發套件](/docs/sdk)。 + +:::tip +使用 opencode 伺服器以程式化方式與 opencode 進行互動。 +::: + +此架構讓 opencode 支援多個客戶端,並允許您以程式化方式與 opencode 進行互動。 + +您可以執行 `opencode serve` 來啟動獨立伺服器。如果您有 +opencode TUI 執行,`opencode serve` 將啟動一個新伺服器。 + +--- + +#### 連接到現有伺服器 + +當您啟動 TUI 時,它會隨機分配連接埠和主機名稱。您可以改為傳入 `--hostname` 和 `--port` [旗標](/docs/cli)。然後使用它連接到其伺服器。 + +[`/tui`](#tui) 端點可用於透過伺服器驅動 TUI。例如,您可以預填充或執行提示。此設定由 opencode [IDE](/docs/ide) 外掛使用。 + +--- + +## 規格 + +伺服器發布了 OpenAPI 3.1 規範,可以在以下位置查看: + +``` +http://:/doc +``` + +例如,`http://localhost:4096/doc`。使用規範生成客戶端或檢查請求和回應類型。或者在 Swagger 瀏覽器中查看它。 + +--- + +## API + +opencode 伺服器公開以下 API。 + +--- + +### 全域 + +| 方法 | 路徑 | 描述 | 回應 | +| ----- | ---------------- | ------------------------ | ------------------------------------ | +| `GET` | `/global/health` | 獲取伺服器健康狀態和版本 | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | 獲取全域事件(SSE 串流) | 事件串流 | + +--- + +### 專案 + +| 方法 | 路徑 | 描述 | 回應 | +| ----- | ------------------ | ------------ | --------------------------------------------- | +| `GET` | `/project` | 列出所有專案 | Project[] | +| `GET` | `/project/current` | 獲取當前專案 | Project | + +--- + +### 路徑和 VCS + +| 方法 | 路徑 | 描述 | 回應 | +| ----- | ------- | ----------------------- | ------------------------------------------- | +| `GET` | `/path` | 獲取當前路徑 | Path | +| `GET` | `/vcs` | 獲取當前專案的 VCS 資訊 | VcsInfo | + +--- + +### 實例 + +| 方法 | 路徑 | 描述 | 回應 | +| ------ | ------------------- | ------------ | --------- | +| `POST` | `/instance/dispose` | 處置當前實例 | `boolean` | + +--- + +### 配置 + +| 方法 | 路徑 | 描述 | 回應 | +| ------- | ------------------- | -------------------- | ---------------------------------------------------------------------------------------- | +| `GET` | `/config` | 獲取設定資訊 | Config | +| `PATCH` | `/config` | 更新設定 | Config | +| `GET` | `/config/providers` | 列出供應商和預設模型 | `{ providers: `Provider[]`, default: { [key: string]: string } }` | + +--- + +### 供應商 + +| 方法 | 路徑 | 描述 | 回應 | +| ------ | -------------------------------- | ----------------------- | ----------------------------------------------------------------------------------- | +| `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` | 處理供應商的 OAuth 回調 | `boolean` | + +--- + +### 工作階段 + +| 方法 | 路徑 | 描述 | 備註 | +| -------- | ---------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------- | +| `GET` | `/session` | 列出所有工作階段 | 返回 Session[] | +| `POST` | `/session` | 建立新工作階段 | 正文:`{ parentID?, title? }`,返回 Session | +| `GET` | `/session/status` | 獲取所有工作階段的狀態 | 返回 `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | 獲取工作階段詳細資訊 | 返回 Session | +| `DELETE` | `/session/:id` | 刪除工作階段及其所有數據 | 返回 `boolean` | +| `PATCH` | `/session/:id` | 更新工作階段屬性 | 正文:`{ title? }`,返回 Session | +| `GET` | `/session/:id/children` | 獲取工作階段的子工作階段 | 返回 Session[] | +| `GET` | `/session/:id/todo` | 獲取工作階段的待辦事項清單 | 返回 Todo[] | +| `POST` | `/session/:id/init` | 分析應用程式並建立 `AGENTS.md` | 主體:`{ messageID, providerID, modelID }`,返回`boolean` | +| `POST` | `/session/:id/fork` | 在訊息中分岔現有工作階段 | 正文:`{ messageID? }`,返回 Session | +| `POST` | `/session/:id/abort` | 中止正在執行的工作階段 | 返回 `boolean` | +| `POST` | `/session/:id/share` | 分享工作階段 | 返回 Session | +| `DELETE` | `/session/:id/share` | 取消分享工作階段 | 返回 Session | +| `GET` | `/session/:id/diff` | 獲取本次工作階段的差異 | 查詢:`messageID?`,返回 FileDiff[] | +| `POST` | `/session/:id/summarize` | 工作階段摘要 | 主體:`{ providerID, modelID }`,返回`boolean` | +| `POST` | `/session/:id/revert` | 還原訊息 | 主體:`{ messageID, partID? }`,返回`boolean` | +| `POST` | `/session/:id/unrevert` | 恢復所有已還原的訊息 | 返回 `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | 回覆權限請求 | 主體:`{ response, remember? }`,返回`boolean` | + +--- + +### 訊息 + +| 方法 | 路徑 | 描述 | 備註 | +| ------ | --------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `GET` | `/session/:id/message` | 列出工作階段中的訊息 | 查詢:`limit?`,返回`{ info: `Message`, parts: `Part[]`}[]` | +| `POST` | `/session/:id/message` | 發送訊息並等待回覆 | 主體:`{ 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` | 執行斜線指令 | 主體:`{ messageID?, agent?, model?, command, arguments }`,返回`{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/shell` | 執行 shell 指令 | 主體:`{ agent, model?, command }`,返回`{ info: `Message`, parts: `Part[]`}` | + +--- + +### 指令 + +| 方法 | 路徑 | 描述 | 回應 | +| ----- | ---------- | ------------ | --------------------------------------------- | +| `GET` | `/command` | 列出所有指令 | Command[] | + +--- + +### 檔案 + +| 方法 | 路徑 | 描述 | 回應 | +| ----- | ------------------------ | -------------------- | ----------------------------------------------------------------------------------- | +| `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` 查詢參數 + +- `query`(必需)- 搜尋字串(模糊匹配) +- `type`(可選)- 將結果限制為 `"file"` 或 `"directory"` +- `directory` (可選) — 覆寫搜尋的專案根目錄 +- `limit`(可選)— 最大結果 (1–200) +- `dirs`(可選)- 舊旗標(`"false"` 僅返回檔案) + +--- + +### 工具(實驗) + +| 方法 | 路徑 | 描述 | 回應 | +| ----- | ------------------------------------------- | ---------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | 列出所有工具 ID | ToolID | +| `GET` | `/experimental/tool?provider=

&model=` | 列出具有模型 JSON 架構的工具 | ToolList | + +--- + +### LSP、格式化程式和 MCP + +| 方法 | 路徑 | 描述 | 回應 | +| ------ | ------------ | ------------------- | -------------------------------------------------------- | +| `GET` | `/lsp` | 獲取 LSP 伺服器狀態 | LSPStatus[] | +| `GET` | `/formatter` | 獲取格式化程式狀態 | FormatterStatus[] | +| `GET` | `/mcp` | 獲取 MCP 伺服器狀態 | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | 動態添加 MCP 伺服器 | body: `{ name, config }`, 返回 MCP 狀態物件 | + +--- + +### 代理 + +| 方法 | 路徑 | 描述 | 回應 | +| ----- | -------- | ------------------ | ------------------------------------------- | +| `GET` | `/agent` | 列出所有可用的代理 | Agent[] | + +--- + +### 記錄 + +| 方法 | 路徑 | 描述 | 回應 | +| ------ | ------ | --------------------------------------------------------- | --------- | +| `POST` | `/log` | 寫入日誌項目。正文:`{ service, level, message, extra? }` | `boolean` | + +--- + +### TUI + +| 方法 | 路徑 | 描述 | 回應 | +| ------ | ----------------------- | ------------------------------------------- | ------------ | +| `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` | 顯示 Toast (`{ title?, message, variant }`) | `boolean` | +| `GET` | `/tui/control/next` | 等待下一個控制請求 | 控制請求物件 | +| `POST` | `/tui/control/response` | 回應控制請求 (`{ body }`) | `boolean` | + +--- + +### 授權 + +| 方法 | 路徑 | 描述 | 回應 | +| ----- | ----------- | ------------------------------------------ | --------- | +| `PUT` | `/auth/:id` | 設定身分驗證憑證。正文必須與供應商架構匹配 | `boolean` | + +--- + +### 事件 + +| 方法 | 路徑 | 描述 | 回應 | +| ----- | -------- | --------------------------------------------------------------------------- | -------------------- | +| `GET` | `/event` | 伺服器發送的事件串流。第一個活動是 `server.connected`,然後是事件匯流排事件 | 伺服器發送的事件串流 | + +--- + +### 文件 + +| 方法 | 路徑 | 描述 | 回應 | +| ----- | ------ | ---------------- | ----------------------------- | +| `GET` | `/doc` | OpenAPI 3.1 規範 | 具有 OpenAPI 規範的 HTML 頁面 | diff --git a/packages/web/src/content/docs/zh-tw/share.mdx b/packages/web/src/content/docs/zh-tw/share.mdx new file mode 100644 index 00000000000..a7733e346a6 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/share.mdx @@ -0,0 +1,128 @@ +--- +title: 分享 +description: 分享您的 opencode 對話。 +--- + +opencode 的共享功能允許您建立 opencode 對話的公共連結,以便您可以與團隊成員協作或從其他人那裡獲得幫助。 + +:::note +任何知道連結的人都可以公開存取共享對話。 +::: + +--- + +## 它是如何運作的 + +當您共享對話時,opencode: + +1. 為您的工作階段建立唯一的公共 URL +2. 將您的對話歷史記錄同步到我們的伺服器 +3. 透過可共享連結進行對話 — `opncd.ai/s/` + +--- + +## 模式 + +opencode 支援三種控制對話共享方式的共享模式: + +--- + +### 手動(預設) + +opencode 預設使用手動共享模式。工作階段不會自動共享,但您可以使用 `/share` 指令手動共享它們: + +``` +/share +``` + +這將生成一個唯一的 URL,並將其複製到您的剪貼簿。 + +要在 [設定檔](/docs/config) 中明確設定手動模式: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "manual" +} +``` + +--- + +### 自動分享 + +您可以在 [設定檔](/docs/config) 中將 `share` 選項設定為 `"auto"` 來為所有新對話啟用自動共享: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "auto" +} +``` + +啟用自動共享後,每個新對話都會自動共享並生成連結。 + +--- + +### 已禁用 + +您可以在 [設定檔](/docs/config) 中將 `share` 選項設定為 `"disabled"` 來完全禁用共享: + +```json title="opencode.json" +{ + "$schema": "https://opncd.ai/config.json", + "share": "disabled" +} +``` + +要在整個團隊中針對給定專案強制執行此操作,請將其添加到專案中的 `opencode.json` 並簽入 Git。 + +--- + +## 取消共享 + +要停止共享對話並將其從公共存取中刪除: + +``` +/unshare +``` + +這將刪除共享連結並刪除與對話相關的數據。 + +--- + +## 隱私 + +分享對話時需要記住一些事項。 + +--- + +### 資料保留 + +共享對話仍然可以存取,直到您明確取消共享。這 +包括: + +- 完整的對話歷史記錄 +- 所有訊息和回覆 +- 工作階段元數據 + +--- + +### 建議 + +- 僅共享不包含敏感資訊的對話。 +- 分享之前查看對話內容。 +- 協作完成後取消共享對話。 +- 避免與專有程式碼或機密數據共享對話。 +- 對於敏感專案,完全禁用共享。 + +--- + +## 對於企業 + +對於企業部署,共享功能可以是: + +- **出於安全合規性完全禁用** +- **僅限**僅透過 SSO 進行身分驗證的使用者 +- **在您自己的基礎架構上自行託管** + +[了解更多](/docs/enterprise) 關於在您的組織中使用 opencode。 diff --git a/packages/web/src/content/docs/zh-tw/skills.mdx b/packages/web/src/content/docs/zh-tw/skills.mdx new file mode 100644 index 00000000000..f9bd62263b7 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/skills.mdx @@ -0,0 +1,222 @@ +--- +title: 代理技能 +description: 透過 SKILL.md 定義定義可重複使用行為 +--- + +代理技能讓 opencode 從您的儲存庫或主目錄中發現可重複使用的指令。 +技能透過原生 `skill` 工具按需載入 - 代理可以查看可用技能並可以在需要時載入完整內容。 + +--- + +## 放置檔案 + +每個技能名稱建立一個資料夾,並在其中放入 `SKILL.md`。 +opencode 搜尋這些位置: + +- 專案設定:`.opencode/skills//SKILL.md` +- 全域設定:`~/.config/opencode/skills//SKILL.md` +- Claude 專案相容:`.claude/skills//SKILL.md` +- 全域 Claude 相容:`~/.claude/skills//SKILL.md` +- 專案代理相容:`.agents/skills//SKILL.md` +- 全域代理相容:`~/.agents/skills//SKILL.md` + +--- + +## 了解發現 + +對於專案本地路徑,opencode 將從當前工作目錄開始,直到到達 git 工作樹。 +它載入 `skills/*/SKILL.md` 中任何匹配的 `.opencode/` 以及一路上任何匹配的 `.claude/skills/*/SKILL.md` 或 `.agents/skills/*/SKILL.md`。 + +全域定義也從 `~/.config/opencode/skills/*/SKILL.md`、`~/.claude/skills/*/SKILL.md` 和 `~/.agents/skills/*/SKILL.md` 載入。 + +--- + +## 撰寫 Frontmatter + +每個 `SKILL.md` 必須以 YAML frontmatter 開頭。 +僅識別這些欄位: + +- `name`(必填) +- `description`(必填) +- `license`(可選) +- `compatibility`(可選) +- `metadata`(可選,字串到字串對應) + +未知的 frontmatter 欄位將被忽略。 + +--- + +## 驗證名稱 + +`name` 必須: + +- 長度為 1–64 個字元 +- 為小寫字母數字並帶有單個連字號分隔符 +- 不以 `-` 開頭或結尾 +- 不包含連續 `--` +- 匹配包含 `SKILL.md` 的目錄名 + +等效的正規表示式: + +```text +^[a-z0-9]+(-[a-z0-9]+)*$ +``` + +--- + +## 遵循長度規則 + +`description` 必須是 1-1024 個字元。 +保持足夠具體,以便代理能夠正確選擇。 + +--- + +## 使用一個範例 + +像這樣建立 `.opencode/skills/git-release/SKILL.md`: + +```markdown +--- +name: git-release +description: Create consistent releases and changelogs +license: MIT +compatibility: opencode +metadata: + audience: maintainers + workflow: github +--- + +## What I do + +- Draft release notes from merged PRs +- Propose a version bump +- Provide a copy-pasteable `gh release create` command + +## When to use me + +Use this when you are preparing a tagged release. +Ask clarifying questions if the target versioning scheme is unclear. +``` + +--- + +## 識別工具說明 + +opencode 在 `skill` 工具描述中列出了可用的技能。 +每個項目都包含技能名稱和描述: + +```xml + + + git-release + Create consistent releases and changelogs + + +``` + +代理透過呼叫工具來載入技能: + +``` +skill({ name: "git-release" }) +``` + +--- + +## 配置權限 + +使用 `opencode.json` 中基於模式的權限控制代理可以存取哪些技能: + +```json +{ + "permission": { + "skill": { + "*": "allow", + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask" + } + } +} +``` + +| 許可 | 行為 | +| ------- | -------------------------- | +| `allow` | 技能立即載入 | +| `deny` | 技能對代理隱藏,存取被拒絕 | +| `ask` | 載入前提示使用者批准 | + +模式支援通配符:`internal-*` 匹配 `internal-docs`、`internal-tools` 等。 + +--- + +## 覆寫每個代理 + +為特定代理授予與全域預設權限不同的權限。 + +**對於自定義代理**(在代理前言中): + +```yaml +--- +permission: + skill: + "documents-*": "allow" +--- +``` + +**對於內建代理**(在 `opencode.json` 中): + +```json +{ + "agent": { + "plan": { + "permission": { + "skill": { + "internal-*": "allow" + } + } + } + } +} +``` + +--- + +## 禁用技能工具 + +完全禁用不應該使用技能的代理: + +**對於自定義代理**: + +```yaml +--- +tools: + skill: false +--- +``` + +**對於內建代理**: + +```json +{ + "agent": { + "plan": { + "tools": { + "skill": false + } + } + } +} +``` + +禁用時,`` 部分將被完全省略。 + +--- + +## 解決載入問題 + +如果某項技能沒有顯示: + +1. 驗證 `SKILL.md` 是否全部大寫拼寫 +2. 檢查 frontmatter 是否包含 `name` 和 `description` +3. 確保技能名稱在所有位置都是唯一的 +4. 檢查權限 - `deny` 的技能對代理隱藏 diff --git a/packages/web/src/content/docs/zh-tw/themes.mdx b/packages/web/src/content/docs/zh-tw/themes.mdx new file mode 100644 index 00000000000..d47e1afe5ea --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/themes.mdx @@ -0,0 +1,369 @@ +--- +title: 主題 +description: 選擇內建主題或定義您自己的主題。 +--- + +使用 opencode,您可以從多個內建主題之一中進行選擇,使用適合您的終端機主題的主題,或者定義您自己的自定義主題。 + +預設情況下,opencode 使用我們自己的 `opencode` 主題。 + +--- + +## 終端機要求 + +為了使主題能夠正確顯示完整的調色盤,您的終端機必須支援**真彩色**(24 位元顏色)。大多數現代終端機預設支援此功能,但您可能需要啟用它: + +- **檢查支援**:執行 `echo $COLORTERM` - 它應該輸出 `truecolor` 或 `24bit` +- **啟用真彩色**:在 shell 設定檔中設定環境變數 `COLORTERM=truecolor` +- **終端機相容性**:確保您的終端機模擬器支援 24 位元顏色(大多數現代終端機,​​如 iTerm2、Alacritty、Kitty、Windows Terminal 和最新版本的 GNOME Terminal 都支援) + +如果沒有真彩色支援,主題的顏色精度可能會降低或回退到最接近的 256 色近似值。 + +--- + +## 內建主題 + +opencode 附帶了幾個內建主題。 + +| 名稱 | 描述 | +| ---------------------- | ------------------------------------------------------------------ | +| `system` | 適應您終端機的背景顏色 | +| `tokyonight` | 基於 [Tokyo Night](https://github.com/folke/tokyonight.nvim) 主題 | +| `everforest` | 基於 [Everforest](https://github.com/sainnhe/everforest) 主題 | +| `ayu` | 基於 [Ayu](https://github.com/ayu-theme) 深色主題 | +| `catppuccin` | 基於 [Catppuccin](https://github.com/catppuccin) 主題 | +| `catppuccin-macchiato` | 基於 [Catppuccin](https://github.com/catppuccin) 主題 | +| `gruvbox` | 基於 [Gruvbox](https://github.com/morhetz/gruvbox) 主題 | +| `kanagawa` | 基於 [Kanagawa](https://github.com/rebelot/kanagawa.nvim) 主題 | +| `nord` | 基於 [Nord](https://github.com/nordtheme/nord) 主題 | +| `matrix` | 駭客風格黑底綠主題 | +| `one-dark` | 基於 [One Dark](https://github.com/Th3Whit3Wolf/one-nvim) 深色主題 | + +此外,我們還在不斷添加新主題。 + +--- + +## 系統主題 + +`system` 主題旨在自動適應您終端機的配色方案。與使用固定顏色的傳統主題不同,_system_ 主題: + +- **生成灰階**:根據終端機的背景顏色建立自定義灰階,確保最佳對比度。 +- **使用 ANSI 顏色**:利用標準 ANSI 顏色 (0-15) 進行語法高亮顯示和 UI 元素,尊重終端機的調色盤。 +- **保留終端機預設設定**:使用 `none` 作為文字和背景顏色,以保持終端機的原生外觀。 + +系統主題適合以下使用者: + +- 希望 opencode 與其終端機的外觀相匹配 +- 使用自定義終端機配色方案 +- 希望所有終端機應用程式具有一致的外觀 + +--- + +## 使用主題 + +您可以透過使用 `/theme` 指令調出主題選擇來選擇主題。或者您可以在 [設定](/docs/config) 中指定它。 + +```json title="opencode.json" {3} +{ + "$schema": "https://opencode.ai/config.json", + "theme": "tokyonight" +} +``` + +--- + +## 自定義主題 + +opencode 支援靈活的基於 JSON 的主題系統,允許使用者輕鬆建立和自定義主題。 + +--- + +### 階層 + +主題按以下順序從多個目錄載入,其中後面的目錄覆寫前面的目錄: + +1. **內建主題** - 這些主題嵌入在二進位檔案中 +2. **使用者設定目錄** - 在 `~/.config/opencode/themes/*.json` 或 `$XDG_CONFIG_HOME/opencode/themes/*.json` 中定義 +3. **專案根目錄** - 定義在 `/.opencode/themes/*.json` +4. **當前工作目錄** - 在 `./.opencode/themes/*.json` 中定義 + +如果多個目錄包含同名主題,則將使用優先順序較高的目錄中的主題。 + +--- + +### 建立主題 + +要建立自定義主題,請在主題目錄之一中建立一個 JSON 檔案。 + +對於使用者範圍的主題: + +```bash no-frame +mkdir -p ~/.config/opencode/themes +vim ~/.config/opencode/themes/my-theme.json +``` + +以及針對特定專案的主題。 + +```bash no-frame +mkdir -p .opencode/themes +vim .opencode/themes/my-theme.json +``` + +--- + +### JSON 格式 + +主題使用靈活的 JSON 格式,支援: + +- **十六進位顏色**:`"#ffffff"` +- **ANSI 顏色**:`3` (0-255) +- **顏色參考**:`"primary"` 或自定義定義 +- **深色/淺色版本**:`{"dark": "#000", "light": "#fff"}` +- **無顏色**:`"none"` - 使用終端機的預設顏色或透明 + +--- + +### 顏色定義 + +`defs` 部分是可選的,它允許您定義可在主題中引用的可重複使用顏色。 + +--- + +### 終端機預設值 + +特殊值 `"none"` 可用於任何顏色以繼承終端機的預設顏色。這對於建立與終端機配色方案無縫融合的主題特別有用: + +- `"text": "none"` - 使用終端機的預設前景色 +- `"background": "none"` - 使用終端機的預設背景顏色 + +--- + +### 範例 + +以下是自定義主題的範例: + +```json title="my-theme.json" +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "nord0": "#2E3440", + "nord1": "#3B4252", + "nord2": "#434C5E", + "nord3": "#4C566A", + "nord4": "#D8DEE9", + "nord5": "#E5E9F0", + "nord6": "#ECEFF4", + "nord7": "#8FBCBB", + "nord8": "#88C0D0", + "nord9": "#81A1C1", + "nord10": "#5E81AC", + "nord11": "#BF616A", + "nord12": "#D08770", + "nord13": "#EBCB8B", + "nord14": "#A3BE8C", + "nord15": "#B48EAD" + }, + "theme": { + "primary": { + "dark": "nord8", + "light": "nord10" + }, + "secondary": { + "dark": "nord9", + "light": "nord9" + }, + "accent": { + "dark": "nord7", + "light": "nord7" + }, + "error": { + "dark": "nord11", + "light": "nord11" + }, + "warning": { + "dark": "nord12", + "light": "nord12" + }, + "success": { + "dark": "nord14", + "light": "nord14" + }, + "info": { + "dark": "nord8", + "light": "nord10" + }, + "text": { + "dark": "nord4", + "light": "nord0" + }, + "textMuted": { + "dark": "nord3", + "light": "nord1" + }, + "background": { + "dark": "nord0", + "light": "nord6" + }, + "backgroundPanel": { + "dark": "nord1", + "light": "nord5" + }, + "backgroundElement": { + "dark": "nord1", + "light": "nord4" + }, + "border": { + "dark": "nord2", + "light": "nord3" + }, + "borderActive": { + "dark": "nord3", + "light": "nord2" + }, + "borderSubtle": { + "dark": "nord2", + "light": "nord3" + }, + "diffAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffContext": { + "dark": "nord3", + "light": "nord3" + }, + "diffHunkHeader": { + "dark": "nord3", + "light": "nord3" + }, + "diffHighlightAdded": { + "dark": "nord14", + "light": "nord14" + }, + "diffHighlightRemoved": { + "dark": "nord11", + "light": "nord11" + }, + "diffAddedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffContextBg": { + "dark": "nord1", + "light": "nord5" + }, + "diffLineNumber": { + "dark": "nord2", + "light": "nord4" + }, + "diffAddedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "diffRemovedLineNumberBg": { + "dark": "#3B4252", + "light": "#E5E9F0" + }, + "markdownText": { + "dark": "nord4", + "light": "nord0" + }, + "markdownHeading": { + "dark": "nord8", + "light": "nord10" + }, + "markdownLink": { + "dark": "nord9", + "light": "nord9" + }, + "markdownLinkText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCode": { + "dark": "nord14", + "light": "nord14" + }, + "markdownBlockQuote": { + "dark": "nord3", + "light": "nord3" + }, + "markdownEmph": { + "dark": "nord12", + "light": "nord12" + }, + "markdownStrong": { + "dark": "nord13", + "light": "nord13" + }, + "markdownHorizontalRule": { + "dark": "nord3", + "light": "nord3" + }, + "markdownListItem": { + "dark": "nord8", + "light": "nord10" + }, + "markdownListEnumeration": { + "dark": "nord7", + "light": "nord7" + }, + "markdownImage": { + "dark": "nord9", + "light": "nord9" + }, + "markdownImageText": { + "dark": "nord7", + "light": "nord7" + }, + "markdownCodeBlock": { + "dark": "nord4", + "light": "nord0" + }, + "syntaxComment": { + "dark": "nord3", + "light": "nord3" + }, + "syntaxKeyword": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxFunction": { + "dark": "nord8", + "light": "nord8" + }, + "syntaxVariable": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxString": { + "dark": "nord14", + "light": "nord14" + }, + "syntaxNumber": { + "dark": "nord15", + "light": "nord15" + }, + "syntaxType": { + "dark": "nord7", + "light": "nord7" + }, + "syntaxOperator": { + "dark": "nord9", + "light": "nord9" + }, + "syntaxPunctuation": { + "dark": "nord4", + "light": "nord0" + } + } +} +``` diff --git a/packages/web/src/content/docs/zh-tw/tools.mdx b/packages/web/src/content/docs/zh-tw/tools.mdx new file mode 100644 index 00000000000..a030a5e8462 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/tools.mdx @@ -0,0 +1,379 @@ +--- +title: 工具 +description: 管理 LLM 可以使用的工具。 +--- + +工具允許 LLM 在您的程式碼庫中執行操作。 opencode 附帶了一組內建工具,但您可以使用 [自定義工具](/docs/custom-tools) 或 [MCP 伺服器](/docs/mcp-servers) 對其進行擴展。 + +預設情況下,所有工具都是**啟用**並且不需要執行權限。您可以透過 [權限](/docs/permissions) 控制工具行為。 + +--- + +## 配置 + +使用 `permission` 欄位控制工具行為。您可以允許、拒絕或要求批准每個工具。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "deny", + "bash": "ask", + "webfetch": "allow" + } +} +``` + +您還可以使用通配符同時控制多個工具。例如,要求 MCP 伺服器批准所有工具: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "mymcp_*": "ask" + } +} +``` + +[了解更多](/docs/permissions) 關於配置權限。 + +--- + +## 內建 + +以下是 opencode 中可用的所有內建工具。 + +--- + +### bash + +在專案環境中執行 shell 指令。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "bash": "allow" + } +} +``` + +該工具允許 LLM 執行 `npm install`、`git status` 等終端機指令或任何其他 shell 指令。 + +--- + +### edit + +使用精確的字串替換修改現有檔案。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +該工具透過替換精確的文字匹配來對檔案執行精確編輯。這是 LLM 修改程式碼的主要方式。 + +--- + +### write + +建立新檔案或覆蓋現有檔案。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +使用它允許 LLM 建立新檔案。如果現有檔案已經存在,它將覆蓋它們。 + +:::note +`write` 工具由 `edit` 權限控制,該權限涵蓋所有檔案修改(`edit`、`write`、`patch`、`multiedit`)。 +::: + +--- + +### read + +從程式碼庫中讀取檔案內容。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": "allow" + } +} +``` + +該工具讀取檔案並返回其內容。它支援讀取大檔案的特定行範圍。 + +--- + +### grep + +使用正規表示式搜尋檔案內容。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "grep": "allow" + } +} +``` + +在您的程式碼庫中快速進行內容搜尋。支援完整的正規表示式語法和檔案模式過濾。 + +--- + +### glob + +透過模式匹配尋找檔案。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "glob": "allow" + } +} +``` + +使用 `**/*.js` 或 `src/**/*.ts` 等全域模式搜尋檔案。返回按修改時間排序的匹配檔案路徑。 + +--- + +### list + +列出給定路徑中的檔案和目錄。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "list": "allow" + } +} +``` + +該工具列出目錄內容。它接受全域模式來過濾結果。 + +--- + +### lsp(實驗性) + +與您配置的 LSP 伺服器互動,以獲得程式碼智慧功能,例如定義、引用、游標懸停資訊和呼叫階層。 + +:::note +該工具僅在 `OPENCODE_EXPERIMENTAL_LSP_TOOL=true`(或 `OPENCODE_EXPERIMENTAL=true`)時可用。 +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "lsp": "allow" + } +} +``` + +支援的操作包括 `goToDefinition`、`findReferences`、`hover`、`documentSymbol`、`workspaceSymbol`、`goToImplementation`、`prepareCallHierarchy`、`incomingCalls` 和 `outgoingCalls`。 + +要配置哪些 LSP 伺服器可用於您的專案,請參閱 [LSP 伺服器](/docs/lsp)。 + +--- + +### patch + +對檔案套用 Patch。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "allow" + } +} +``` + +該工具將 Patch 檔案套用到您的程式碼庫。對於套用來自各種來源的差異和 Patch 很有用。 + +:::note +`patch` 工具由 `edit` 權限控制,該權限涵蓋所有檔案修改(`edit`、`write`、`patch`、`multiedit`)。 +::: + +--- + +### skill + +載入 [技能](/docs/skills)(`SKILL.md` 檔案)並在對話中返回其內容。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "skill": "allow" + } +} +``` + +--- + +### todowrite + +在編碼工作階段期間管理待辦事項清單。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todowrite": "allow" + } +} +``` + +建立和更新任務列表以追蹤複雜操作期間的進度。LLM 使用它來組織多步驟任務。 + +:::note +預設情況下,子代理禁用此工具,但您可以手動啟用它。 [了解更多](/docs/agents/#permissions) +::: + +--- + +### todoread + +閱讀現有的待辦事項清單。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "todoread": "allow" + } +} +``` + +讀取當前待辦事項清單狀態。LLM 用來追蹤哪些任務待處理或已完成。 + +:::note +預設情況下,子代理禁用此工具,但您可以手動啟用它。 [了解更多](/docs/agents/#permissions) +::: + +--- + +### webfetch + +獲取網頁內容。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "webfetch": "allow" + } +} +``` + +允許 LLM 獲取和閱讀網頁。對於尋找文件或研究線上資源很有用。 + +--- + +### websearch + +在網路上搜尋資訊。 + +:::note +僅當使用 opencode 供應商或 `OPENCODE_ENABLE_EXA` 環境變數設定為任何真值(例如 `true` 或 `1`)時,此工具才可用。 + +要在啟動 opencode 時啟用: + +```bash +OPENCODE_ENABLE_EXA=1 opencode +``` + +::: + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "websearch": "allow" + } +} +``` + +使用 Exa AI 執行網路搜尋以線上尋找相關資訊。對於研究主題、尋找時事或收集超出訓練數據截止範圍的資訊很有用。 + +不需要 API 金鑰 - 該工具無需身分驗證即可直接連接到 Exa AI 的託管 MCP 服務。 + +:::tip +當您需要尋找資訊(發現)時,請使用 `websearch`;當您需要從特定 URL 檢索內容(檢索)時,請使用 `webfetch`。 +::: + +--- + +### question + +在執行過程中詢問使用者問題。 + +```json title="opencode.json" {4} +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "question": "allow" + } +} +``` + +該工具允許 LLM 在任務期間詢問使用者問題。它適用於: + +- 收集使用者偏好或要求 +- 澄清不明確的指令 +- 就實作選擇做出決策 +- 提供選擇方向 + +每個問題都包含標題、問題文字和選項列表。使用者可以從提供的選項中進行選擇或輸入自定義答案。當存在多個問題時,使用者可以在提交所有答案之前在這些問題之間導航。 + +--- + +## 自定義工具 + +自定義工具可讓您定義 LLM 可以呼叫的自己的函式。這些是在您的設定檔中定義的並且可以執行任意程式碼。 + +[了解更多](/docs/custom-tools) 關於建立自定義工具。 + +--- + +## MCP 伺服器 + +MCP(模型上下文協定)伺服器允許您整合外部工具和服務。這包括資料庫存取、API 整合和第三方服務。 + +[了解更多](/docs/mcp-servers) 關於配置 MCP 伺服器。 + +--- + +## 內部結構 + +在內部,`grep`、`glob` 和 `list` 等工具在底層使用 [ripgrep](https://github.com/BurntSushi/ripgrep)。預設情況下,ripgrep 遵循 `.gitignore` 模式,這意味著 `.gitignore` 中列出的檔案和目錄將從搜尋和列表中排除。 + +--- + +### 忽略模式 + +要包含通常會被忽略的檔案,請在專案根目錄中建立一個 `.ignore` 檔案。該檔案可以明確允許某些路徑。 + +```text title=".ignore" +!node_modules/ +!dist/ +!build/ +``` + +例如,此 `.ignore` 檔案允許 ripgrep 在 `node_modules/`、`dist/` 和 `build/` 目錄中搜尋,即使它們列在 `.gitignore` 中。 diff --git a/packages/web/src/content/docs/zh-tw/troubleshooting.mdx b/packages/web/src/content/docs/zh-tw/troubleshooting.mdx new file mode 100644 index 00000000000..17c5aa3a6a7 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/troubleshooting.mdx @@ -0,0 +1,300 @@ +--- +title: 疑難排解 +description: 常見問題以及如何解決它們。 +--- + +要除錯 opencode 問題,請首先檢查其儲存在磁碟上的日誌和本地數據。 + +--- + +## 日誌 + +日誌檔案寫入: + +- **macOS/Linux**:`~/.local/share/opencode/log/` +- **Windows**:按 `WIN+R` 並貼上 `%USERPROFILE%\.local\share\opencode\log` + +日誌檔案以時間戳命名(例如 `2025-01-09T123456.log`),並保留最近的 10 個日誌檔案。 + +您可以使用 `--log-level` 命令列選項設定日誌等級以獲取更詳細的除錯資訊。例如,`opencode --log-level DEBUG`。 + +--- + +## 儲存 + +opencode 將工作階段數據和其他應用程式數據儲存在磁碟上: + +- **macOS/Linux**:`~/.local/share/opencode/` +- **Windows**:按 `WIN+R` 並貼上 `%USERPROFILE%\.local\share\opencode` + +該目錄包含: + +- `auth.json` - 身分驗證數據,例如 API 金鑰、OAuth 令牌 +- `log/` - 應用程式日誌 +- `project/` - 專案特定數據,例如工作階段和訊息數據 + - 如果專案位於 Git 儲存庫中,則它儲存在 `.//storage/` 中 + - 如果不是 Git 儲存庫,則儲存在 `./global/storage/` 中 + +--- + +## 桌面應用程式 + +opencode Desktop 在背景執行本地 opencode 伺服器(`opencode-cli` sidecar)。大多數問題是由行為不當的外掛、損壞的快取或錯誤的伺服器設定引起的。 + +### 快速檢查 + +- 完全退出並重新啟動應用程式。 +- 如果應用程式顯示錯誤螢幕,請單擊「**重新啟動**」並複製錯誤詳細資訊。 +- 僅限 macOS:`OpenCode` 選單 -> **重新載入 Webview**(如果 UI 為空白/凍結,則有幫助)。 + +--- + +### 禁用外掛 + +如果桌面應用程式在啟動時崩潰、卡住或行為異常,請首先禁用外掛。 + +#### 檢查全域配置 + +打開全域設定檔並查找 `plugin` 鍵。 + +- **macOS/Linux**:`~/.config/opencode/opencode.jsonc`(或 `~/.config/opencode/opencode.json`) +- **macOS/Linux**(較舊的安裝):`~/.local/share/opencode/opencode.jsonc` +- **Windows**:按 `WIN+R` 並貼上 `%USERPROFILE%\.config\opencode\opencode.jsonc` + +如果您配置了外掛,請透過刪除鍵或將其設定為空陣列來暫時禁用它們: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [], +} +``` + +#### 檢查外掛目錄 + +opencode 還可以從磁碟載入本地外掛。暫時將它們移開(或重命名資料夾)並重新啟動桌面應用程式: + +- **全域外掛** + - **macOS/Linux**:`~/.config/opencode/plugins/` + - **Windows**:按 `WIN+R` 並貼上 `%USERPROFILE%\.config\opencode\plugins` +- **專案外掛**(僅當您使用每個專案配置時) + - `/.opencode/plugins/` + +如果應用程式再次開始工作,請一次重新啟用一個外掛,以找出導致問題的外掛。 + +--- + +### 清除快取 + +如果禁用外掛沒有幫助(或者外掛安裝被卡住),請清除快取,以便 opencode 可以重建它。 + +1. 完全退出 opencode Desktop。 +2. 刪除快取目錄: + +- **macOS**:Finder -> `Cmd+Shift+G` -> 貼上 `~/.cache/opencode` +- **Linux**:刪除 `~/.cache/opencode`(或執行 `rm -rf ~/.cache/opencode`) +- **Windows**:按 `WIN+R` 並貼上 `%USERPROFILE%\.cache\opencode` + +3. 重新啟動 opencode 桌面。 + +--- + +### 修復伺服器連接問題 + +opencode Desktop 可以啟動自己的本地伺服器(預設)或連接到您配置的伺服器 URL。 + +如果您看到 **「連接失敗」** 對話方塊(或者應用程式永遠無法通過啟動螢幕),請檢查自定義伺服器 URL。 + +#### 清除桌面預設伺服器 URL + +在主螢幕中,單擊伺服器名稱(帶有狀態點)以打開伺服器選取器。在「**預設伺服器**」部分中,單擊「**清除**」。 + +#### 從您的配置中刪除 `server.port` / `server.hostname` + +如果您的 `opencode.json(c)` 包含 `server` 部分,請將其暫時刪除並重新啟動桌面應用程式。 + +#### 檢查環境變數 + +如果您在環境中設定了 `OPENCODE_PORT`,桌面應用程式將嘗試將該連接埠用於本地伺服器。 + +- 取消設定 `OPENCODE_PORT`(或選擇一個空閒連接埠)並重新啟動。 + +--- + +### Linux:Wayland / X11 問題 + +在 Linux 上,某些 Wayland 設定可能會導致空白視窗或合成器錯誤。 + +- 如果您在 Wayland 上且應用程式空白/崩潰,請嘗試使用 `OC_ALLOW_WAYLAND=1` 啟動。 +- 如果這讓事情變得更糟,請將其刪除並嘗試在 X11 工作階段下啟動。 + +--- + +### Windows:WebView2 執行時 + +在 Windows 上,opencode Desktop 需要 Microsoft Edge **WebView2 執行時**。如果應用程式打開為空白視窗或無法啟動,請安裝/更新 WebView2,然後重試。 + +--- + +### Windows:一般性能問題 + +如果您在 Windows 上遇到性能緩慢、檔案存取問題或終端機問題,請嘗試使用 [WSL(適用於 Linux 的 Windows 子系統)](/docs/windows-wsl)。 WSL 提供了一個可以與 opencode 功能更加無縫協作的 Linux 環境。 + +--- + +### 通知不顯示 + +opencode Desktop 僅在以下情況下顯示系統通知: + +- 在您的作業系統設定中啟用 opencode 通知,並且 +- 應用程式視窗未聚焦。 + +--- + +### 重置桌面應用程式儲存(最後手段) + +如果應用程式無法啟動並且您無法從 UI 內部清除設定,請重置桌面應用程式的保存狀態。 + +1. 退出 opencode Desktop。 +2. 查找並刪除這些檔案(它們位於 opencode Desktop 應用程式資料目錄中): + +- `opencode.settings.dat`(桌面預設伺服器 URL) +- `opencode.global.dat` 和 `opencode.workspace.*.dat`(UI 狀態,如最近的伺服器/專案) + +快速找到目錄: + +- **macOS**:Finder -> `Cmd+Shift+G` -> `~/Library/Application Support`(然後搜尋上面的檔名) +- **Linux**:在 `~/.local/share` 下搜尋上述檔名 +- **Windows**:按 `WIN+R` -> `%APPDATA%`(然後搜尋上面的檔名) + +--- + +## 尋求幫助 + +如果您遇到 opencode 問題: + +1. **在 GitHub 上報告問題** + + 報告錯誤或請求功能的最佳方式是透過我們的 GitHub 儲存庫: + + [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues) + + 在建立新問題之前,請搜尋現有問題以查看您的問題是否已被報告。 + +2. **加入我們的 Discord** + + 如需即時幫助和社群討論,請加入我們的 Discord 伺服器: + + [**opencode.ai/discord**](https://opencode.ai/discord) + +--- + +## 常見問題 + +以下是一些常見問題以及解決方法。 + +--- + +### opencode 無法啟動 + +1. 檢查日誌中是否有錯誤訊息 +2. 嘗試使用 `--print-logs` 執行以查看終端機中的輸出 +3. 確保您擁有最新版本 `opencode upgrade` + +--- + +### 身分驗證問題 + +1. 嘗試使用 TUI 中的 `/connect` 指令重新進行身分驗證 +2. 檢查您的 API 金鑰是否有效 +3. 確保您的網路允許連接到供應商的 API + +--- + +### 模型不可用 + +1. 檢查您是否已通過供應商的身分驗證 +2. 驗證配置中的模型名稱是否正確 +3. 某些模型可能需要特定的存取權限或訂閱 + +如果您遇到 `ProviderModelNotFoundError`,您很可能是錯誤的 +在某處引用模型。 +模型應該像這樣引用:`/` + +範例: + +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +要了解您可以存取哪些模型,請執行 `opencode models` + +--- + +### 供應商初始化錯誤 + +如果遇到 ProviderInitError,您的配置可能無效或損壞。 + +要解決這個問題: + +1. 首先,按照 [供應商指南](/docs/providers) 驗證您的供應商是否已正確設定 +2. 如果問題仍然存在,請嘗試清除儲存的配置: + + ```bash + rm -rf ~/.local/share/opencode + ``` + + 在 Windows 上,按 `WIN+R` 並刪除:`%USERPROFILE%\.local\share\opencode` + +3. 使用 TUI 中的 `/connect` 指令向您的供應商重新進行身分驗證。 + +--- + +### AI_APICallError 和供應商套件問題 + +如果您遇到 API 呼叫錯誤,這可能是由於過時的供應商套件造成的。 opencode 根據需要動態安裝供應商套件(OpenAI、Anthropic、Google 等)並將其快取在本地。 + +要解決供應商套件問題: + +1. 清除供應商套件快取: + + ```bash + rm -rf ~/.cache/opencode + ``` + + 在 Windows 上,按 `WIN+R` 並刪除:`%USERPROFILE%\.cache\opencode` + +2. 重新啟動 opencode 以重新安裝最新的供應商套件 + +這將強制 opencode 下載最新版本的供應商套件,這通常可以解決模型參數和 API 更改的相容性問題。 + +--- + +### 複製/貼上在 Linux 上不起作用 + +Linux 使用者需要安裝以下剪貼簿公用程式之一才能使用複製/貼上功能: + +**對於 X11 系統:** + +```bash +apt install -y xclip +# or +apt install -y xsel +``` + +**對於 Wayland 系統:** + +```bash +apt install -y wl-clipboard +``` + +**對於無介面環境:** + +```bash +apt install -y xvfb +# and run: +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +export DISPLAY=:99.0 +``` + +opencode 將檢測您是否使用 Wayland 並更喜歡 `wl-clipboard`,否則它將嘗試按 `xclip` 和 `xsel` 的順序尋找剪貼簿工具。 diff --git a/packages/web/src/content/docs/zh-tw/tui.mdx b/packages/web/src/content/docs/zh-tw/tui.mdx new file mode 100644 index 00000000000..f234bad8cc1 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/tui.mdx @@ -0,0 +1,390 @@ +--- +title: TUI +description: 使用 OpenCode 終端機使用者介面。 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components" + +OpenCode 提供了一個互動式終端機介面或 TUI,供您與 LLM 一起處理專案。 + +執行 OpenCode 會啟動當前目錄的 TUI。 + +```bash +opencode +``` + +或者您可以為特定的工作目錄啟動它。 + +```bash +opencode /path/to/project +``` + +進入 TUI 後,您可以透過訊息進行提示。 + +```text +Give me a quick summary of the codebase. +``` + +--- + +## 檔案參考 + +您可以使用 `@` 在訊息中引用檔案。這會在當前工作目錄中進行模糊檔案搜尋。 + +:::tip +您還可以使用 `@` 來引用訊息中的檔案。 +::: + +```text "@packages/functions/src/api/index.ts" +How is auth handled in @packages/functions/src/api/index.ts? +``` + +檔案的內容會自動添加到對話中。 + +--- + +## Bash 指令 + +以 `!` 開始一條訊息以執行 shell 指令。 + +```bash frame="none" +!ls -la +``` + +指令的輸出將作為工具結果添加到對話中。 + +--- + +## 指令 + +使用 OpenCode TUI 時,您可以輸入 `/` 後跟指令名稱來快速執行操作。例如: + +```bash frame="none" +/help +``` + +大多數指令也有使用 `ctrl+x` 作為 Leader 鍵的按鍵綁定,其中 `ctrl+x` 是預設的 Leader 鍵。 [了解更多](/docs/keybinds)。 + +以下是所有可用的斜線指令: + +--- + +### connect + +將供應商添加到 OpenCode。允許您從可用的供應商中進行選擇並添加其 API 金鑰。 + +```bash frame="none" +/connect +``` + +--- + +### compact + +壓縮當前工作階段。 _別名_:`/summarize` + +```bash frame="none" +/compact +``` + +**按鍵綁定:** `ctrl+x c` + +--- + +### details + +切換工具執行詳細資訊。 + +```bash frame="none" +/details +``` + +**按鍵綁定:** `ctrl+x d` + +--- + +### editor + +打開外部編輯器來撰寫訊息。使用 `EDITOR` 環境變數中設定的編輯器。 [了解更多](#editor-setup)。 + +```bash frame="none" +/editor +``` + +**按鍵綁定:** `ctrl+x e` + +--- + +### exit + +退出 OpenCode。 _別名_:`/quit`、`/q` + +```bash frame="none" +/exit +``` + +**按鍵綁定:** `ctrl+x q` + +--- + +### export + +將當前對話導出到 Markdown 並在預設編輯器中打開。使用 `EDITOR` 環境變數中設定的編輯器。 [了解更多](#editor-setup)。 + +```bash frame="none" +/export +``` + +**按鍵綁定:** `ctrl+x x` + +--- + +### help + +顯示說明對話方塊。 + +```bash frame="none" +/help +``` + +**按鍵綁定:** `ctrl+x h` + +--- + +### init + +建立或更新 `AGENTS.md` 檔案。 [了解更多](/docs/rules)。 + +```bash frame="none" +/init +``` + +**按鍵綁定:** `ctrl+x i` + +--- + +### models + +列出可用模型。 + +```bash frame="none" +/models +``` + +**按鍵綁定:** `ctrl+x m` + +--- + +### new + +開始新的工作階段。 _別名_:`/clear` + +```bash frame="none" +/new +``` + +**按鍵綁定:** `ctrl+x n` + +--- + +### redo + +重做之前撤銷的訊息。僅在使用 `/undo` 後可用。 + +:::tip +任何檔案變更也將被恢復。 +::: + +在內部,這使用 Git 來管理檔案變更。所以你的專案**需要 +是一個 Git 儲存庫**。 + +```bash frame="none" +/redo +``` + +**按鍵綁定:** `ctrl+x r` + +--- + +### sessions + +列出工作階段並在工作階段之間切換。 _別名_:`/resume`、`/continue` + +```bash frame="none" +/sessions +``` + +**按鍵綁定:** `ctrl+x l` + +--- + +### share + +分享當前工作階段。 [了解更多](/docs/share)。 + +```bash frame="none" +/share +``` + +**按鍵綁定:** `ctrl+x s` + +--- + +### themes + +列出可用的主題。 + +```bash frame="none" +/theme +``` + +**按鍵綁定:** `ctrl+x t` + +--- + +### thinking + +切換對話中思考/推理區塊的可見性。啟用後,您可以看到支援擴展思考的模型的推理過程。 + +:::note +該指令僅控制是否**顯示** - 它不啟用或禁用模型的推理功能。要切換實際推理功能,請使用 `ctrl+t` 循環切換模型變體。 +::: + +```bash frame="none" +/thinking +``` + +--- + +### undo + +撤銷對話中的最後一條訊息。刪除最近的使用者訊息、所有後續回應以及任何檔案變更。 + +:::tip +所做的任何檔案變更也將被恢復。 +::: + +在內部,這使用 Git 來管理檔案變更。所以你的專案**需要 +是一個 Git 儲存庫**。 + +```bash frame="none" +/undo +``` + +**按鍵綁定:** `ctrl+x u` + +--- + +### unshare + +取消分享當前工作階段。 [了解更多](/docs/share#un-sharing)。 + +```bash frame="none" +/unshare +``` + +--- + +## 編輯器設定 + +`/editor` 和 `/export` 指令都使用 `EDITOR` 環境變數中指定的編輯器。 + + + + ```bash + # Example for nano or vim + export EDITOR=nano + export EDITOR=vim + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + export EDITOR="code --wait" + ``` + + To make it permanent, add this to your shell profile; + `~/.bashrc`, `~/.zshrc`, etc. + + + + + ```bash + set EDITOR=notepad + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + set EDITOR=code --wait + ``` + + To make it permanent, use **System Properties** > **Environment + Variables**. + + + + + ```powershell + $env:EDITOR = "notepad" + + # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc. + # include --wait + $env:EDITOR = "code --wait" + ``` + + To make it permanent, add this to your PowerShell profile. + + + + +流行的編輯器選項包括: + +- `code` - Visual Studio Code +- `cursor` - Cursor +- `windsurf` - Windsurf +- `nvim` - Neovim 編輯器 +- `vim` - Vim 編輯器 +- `nano` - Nano 編輯器 +- `notepad` - Windows 記事本 +- `subl` - Sublime Text + +:::note +某些編輯器(例如 VS Code)需要以 `--wait` 旗標啟動。 +::: + +某些編輯器需要命令列參數才能在阻止模式下執行。 `--wait` 旗標使編輯器處理程序阻塞直到關閉。 + +--- + +## 配置 + +您可以透過 OpenCode 設定檔自定義 TUI 行為。 + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "tui": { + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } + } +} +``` + +### 選項 + +- `scroll_acceleration` - 啟用 macOS 風格的捲動加速,實現平滑、自然的捲動。啟用後,捲動速度會隨著快速捲動手勢而增加,並在較慢的移動時保持精確。 **此設定優先於 `scroll_speed`,並在啟用時覆寫它。** +- `scroll_speed` - 控制使用捲動指令時 TUI 捲動的速度(最小值:`1`)。預設為 `3`。 **注意:如果 `scroll_acceleration.enabled` 設定為 `true`,則忽略此設定。** + +--- + +## 自定義 + +您可以使用指令面板(`ctrl+x h` 或 `/help`)自定義 TUI 視圖的各個方面。這些設定在重新啟動後仍然存在。 + +--- + +#### 使用者名稱顯示 + +切換您的使用者名稱是否出現在聊天訊息中。透過以下方式存取: + +- 指令面板:搜尋「使用者名稱」或「隱藏使用者名稱」 +- 該設定會自動保留並在 TUI 工作階段中被記住 diff --git a/packages/web/src/content/docs/zh-tw/web.mdx b/packages/web/src/content/docs/zh-tw/web.mdx new file mode 100644 index 00000000000..548307ffb21 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/web.mdx @@ -0,0 +1,142 @@ +--- +title: Web +description: 在瀏覽器中使用 opencode。 +--- + +opencode 可以在瀏覽器中作為 Web 應用程式執行,無需終端機即可提供同樣強大的 AI 程式碼體驗。 + +![opencode Web - 新工作階段](../../../assets/web/web-homepage-new-session.png) + +## 入門 + +透過執行以下指令啟動 Web 介面: + +```bash +opencode web +``` + +這將在 `127.0.0.1` 上啟動一個具有隨機可用連接埠的本地伺服器,並自動在預設瀏覽器中打開 opencode。 + +:::caution +如果未設定 `OPENCODE_SERVER_PASSWORD`,伺服器將不安全。這對於本地使用來說很好,但應該針對網路存取進行設定。 +::: + +:::tip[Windows 使用者] +為了獲得最佳體驗,請從 [WSL](/docs/windows-wsl) 而不是 PowerShell 執行 `opencode web`。這確保了正確的檔案系統存取和終端機整合。 +::: + +--- + +## 配置 + +您可以使用命令列旗標或在 [設定檔](/docs/config) 中配置 Web 伺服器。 + +### 連接埠 + +預設情況下,opencode 選擇一個可用連接埠。您可以指定一個連接埠: + +```bash +opencode web --port 4096 +``` + +### 主機名稱 + +預設情況下,伺服器綁定到 `127.0.0.1`(僅限 localhost)。要使 opencode 在您的網路上可存取: + +```bash +opencode web --hostname 0.0.0.0 +``` + +當使用 `0.0.0.0` 時,opencode 將顯示本地位址和網路位址: + +``` + Local access: http://localhost:4096 + Network access: http://192.168.1.100:4096 +``` + +### mDNS 探索 + +啟用 mDNS 以使您的伺服器在本地網路上可探索: + +```bash +opencode web --mdns +``` + +這會自動將主機名稱設定為 `0.0.0.0` 並將伺服器廣播為 `opencode.local`。 + +您可以自定義 mDNS 網域名稱以在同一網路上執行多個實例: + +```bash +opencode web --mdns --mdns-domain myproject.local +``` + +### CORS + +允許 CORS 的其他域(對於自定義前端有用): + +```bash +opencode web --cors https://example.com +``` + +### 身分驗證 + +要保護存取,請使用 `OPENCODE_SERVER_PASSWORD` 環境變數設定密碼: + +```bash +OPENCODE_SERVER_PASSWORD=secret opencode web +``` + +使用者名稱預設為 `opencode`,但可以使用 `OPENCODE_SERVER_USERNAME` 進行更改。 + +--- + +## 使用 Web 介面 + +啟動後,Web 介面將提供對 opencode 工作階段的存取。 + +### 工作階段 + +從主頁查看和管理您的工作階段。您可以查看活動工作階段並開始新工作階段。 + +![opencode Web - 活動工作階段](../../../assets/web/web-homepage-active-session.png) + +### 伺服器狀態 + +單擊「查看伺服器」可查看連接的伺服器及其狀態。 + +![opencode Web - 查看伺服器](../../../assets/web/web-homepage-see-servers.png) + +--- + +## 連接終端機 + +您可以將終端機 TUI 連接到正在執行的 Web 伺服器: + +```bash +# Start the web server +opencode web --port 4096 + +# In another terminal, attach the TUI +opencode attach http://localhost:4096 +``` + +這允許您同時使用 Web 介面和終端機,共享相同的工作階段和狀態。 + +--- + +## 設定檔 + +您還可以在 `opencode.json` 設定檔中配置伺服器設定: + +```json +{ + "server": { + "port": 4096, + "hostname": "0.0.0.0", + "mdns": true, + "cors": ["https://example.com"] + } +} +``` + +命令列旗標優先於設定檔設定。 diff --git a/packages/web/src/content/docs/zh-tw/windows-wsl.mdx b/packages/web/src/content/docs/zh-tw/windows-wsl.mdx new file mode 100644 index 00000000000..db858db02e2 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/windows-wsl.mdx @@ -0,0 +1,113 @@ +--- +title: Windows (WSL) +description: 在 Windows 透過 WSL 使用 opencode。 +--- + +import { Steps } from "@astrojs/starlight/components" + +雖然 opencode 可以直接在 Windows 上執行,但為了獲得最佳體驗,我們建議使用 [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install)。WSL 提供了可與 opencode 功能順暢配合的 Linux 環境。 + +:::tip[為什麼要用 WSL?] +WSL 提供更好的檔案系統效能、完整的terminal支援,以及與 opencode 依賴之開發工具的相容性。 +::: + +--- + +## 設定 + + + +1. **安裝 WSL** + + 如果你尚未安裝,請依照 Microsoft 官方指南[安裝 WSL](https://learn.microsoft.com/en-us/windows/wsl/install)。 + +2. **在 WSL 中安裝 opencode** + + 完成 WSL 設定後,打開 WSL terminal,並使用其中一種[安裝方式](/docs/)安裝 opencode。 + + ```bash + curl -fsSL https://opencode.ai/install | bash + ``` + +3. **從 WSL 使用 opencode** + + 移動到你的專案目錄(可透過 `/mnt/c/`、`/mnt/d/` 等路徑存取 Windows 檔案),然後執行 opencode。 + + ```bash + cd /mnt/c/Users/YourName/project + opencode + ``` + + + +--- + +## 桌面應用程式 + WSL 伺服器 + +如果你偏好使用 opencode 桌面應用程式,但希望在 WSL 內執行伺服器: + +1. **在 WSL 中啟動伺服器**,並使用 `--hostname 0.0.0.0` 允許外部連線: + + ```bash + opencode serve --hostname 0.0.0.0 --port 4096 + ``` + +2. **將桌面應用程式連線到** `http://localhost:4096` + +:::note +若你的環境中 `localhost` 無法使用,請改用 WSL 的 IP 位址連線(在 WSL 執行:`hostname -I`),並使用 `http://:4096`。 +::: + +:::caution +使用 `--hostname 0.0.0.0` 時,請設定 `OPENCODE_SERVER_PASSWORD` 來保護伺服器。 + +```bash +OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0 +``` + +::: + +--- + +## Web 用戶端 + WSL + +在 Windows 上取得最佳 Web 體驗: + +1. **請在 WSL terminal執行 `opencode web`**,而不是在 PowerShell 執行: + + ```bash + opencode web --hostname 0.0.0.0 + ``` + +2. **在 Windows 瀏覽器中開啟** `http://localhost:`(opencode 會輸出該 URL) + +從 WSL 執行 `opencode web` 可確保正確的檔案系統存取與terminal整合,同時仍可由 Windows 瀏覽器使用。 + +--- + +## 存取 Windows 檔案 + +WSL 可透過 `/mnt/` 目錄存取你所有的 Windows 檔案: + +- `C:` drive → `/mnt/c/` +- `D:` drive → `/mnt/d/` +- 其他磁碟機也相同 + +範例: + +```bash +cd /mnt/c/Users/YourName/Documents/project +opencode +``` + +:::tip +為了更流暢的使用體驗,建議將你的儲存庫 clone 或複製到 WSL 檔案系統(例如 `~/code/`)中,再從那裡執行 opencode。 +::: + +--- + +## 提示 + +- 即使專案存放在 Windows 磁碟機上,也建議在 WSL 中執行 opencode,檔案存取會更順暢 +- 可將 opencode 與 VS Code 的 [WSL 擴充套件](https://code.visualstudio.com/docs/remote/wsl)搭配使用,建立整合式開發流程 +- opencode 的設定與工作階段會儲存在 WSL 環境中的 `~/.local/share/opencode/` diff --git a/packages/web/src/content/docs/zh-tw/zen.mdx b/packages/web/src/content/docs/zh-tw/zen.mdx new file mode 100644 index 00000000000..142597fadcc --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/zen.mdx @@ -0,0 +1,254 @@ +--- +title: Zen +description: opencode 提供的精選模型列表。 +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Zen 是 opencode 團隊提供的經過測試和驗證的模型列表。 + +:::note +OpenCode Zen 目前處於測試階段。 +::: + +Zen 的工作方式與 opencode 中的任何其他供應商一樣。您登入 OpenCode Zen 並獲取 +您的 API 金鑰。它是**完全可選的**,您不需要使用它即可使用 +opencode。 + +--- + +## 背景 + +市面上有很多模型,但其中只有少數幾個 +這些模型可以很好地用作程式碼代理。此外,大多數供應商都 +配置非常不同;所以你會得到截然不同的性能和質量。 + +:::tip +我們測試了一組精選的與 opencode 配合良好的模型和供應商。 +::: + +因此,如果您透過 OpenRouter 之類的東西使用模型,那麼您永遠無法 +確定您是否獲得了您想要的模型的最佳版本。 + +為了解決這個問題,我們做了幾件事: + +1. 我們測試了一組選定的模型,並與他們的團隊討論瞭如何 + 最好執行它們。 +2. 然後我們與一些供應商合作以確保這些服務得到服務 + 正確。 +3. 最後,我們對模型/供應商的組合進行了基準測試並提出了 + 並附上一份我們覺得不錯的推薦清單。 + +OpenCode Zen 是一個 AI 閘道,可讓您存取這些模型。 + +--- + +## 它是如何運作的 + +OpenCode Zen 的工作方式與 opencode 中的任何其他供應商一樣。 + +1. 您登入 **OpenCode Zen**,添加您的帳單 + 詳細資訊,然後複製您的 API 金鑰。 +2. 您在 TUI 中執行 `/connect` 指令,選擇 OpenCode Zen,然後貼上您的 API 金鑰。 +3. 在 TUI 中執行 `/models` 以查看我們推薦的模型列表。 + +您需要按請求付費,並且可以將點數添加到您的帳戶中。 + +--- + +## 端點 + +您還可以透過以下 API 端點存取我們的模型。 + +| 模型 | 模型 ID | 端點 | AI SDK 套件 | +| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| 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 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 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-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 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.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 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 配置中的 [模型編號](/docs/config/#models) +使用格式 `opencode/`。例如,對於 GPT 5.2 Codex,您將 +在您的配置中使用 `opencode/gpt-5.2-codex`。 + +--- + +### 模型 + +您可以從以下位置獲取可用模型及其元數據的完整列表: + +``` +https://opencode.ai/zen/v1/models +``` + +--- + +## 定價 + +我們支援按用量付費模式。以下是**每 100 萬 Tokens 的價格**。 + +| 模型 | 輸入 | 輸出 | 快取讀取 | 快取寫入 | +| --------------------------------- | ------ | ------ | -------- | -------- | +| Big Pickle | Free | Free | Free | - | +| MiniMax M2.1 Free | Free | Free | Free | - | +| MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | +| GLM 4.7 Free | Free | Free | Free | - | +| 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 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 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.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 | Free | Free | Free | - | + +您可能會在使用歷史記錄中注意到 _Claude Haiku 3.5_。這是一個 [低成本模型](/docs/config/#models),用於生成工作階段標題。 + +:::note +信用卡費用按成本轉嫁(4.4% + 每筆交易 0.30 美元);除此之外我們不收取任何費用。 +::: + +免費模型: + +- GLM 4.7 免費版在 opencode 上限時提供。團隊正在利用這段時間收集回饋並改進模型。 +- Kimi K2.5 Free 在 opencode 上限時提供。團隊正在利用這段時間收集回饋並改進模型。 +- MiniMax M2.1 免費版在 opencode 上限時提供。團隊正在利用這段時間收集回饋並改進模型。 +- Big Pickle 是一個秘密模型,在 opencode 上限時免費。團隊正在利用這段時間收集回饋並改進模型。 + +如果您有任何疑問,請聯絡我們。 + +--- + +### 自動重新載入 + +如果您的餘額低於 5 美元,Zen 將自動加值 20 美元。 + +您可以更改自動加值金額。您還可以完全禁用自動重新載入。 + +--- + +### 每月限額 + +您還可以為整個工作區和每個工作區設定每月使用限制 +你的團隊的成員。 + +例如,假設您將每月使用限額設定為 20 美元,Zen 將不會使用 +一個月超過 20 美元。但如果你啟用了自動重新載入,Zen 可能會結束 +如果您的餘額低於 5 美元,則向您收取超過 20 美元的費用。 + +--- + +## 隱私 + +我們所有的模型都在美國託管。我們的供應商遵循零保留政策,不會將您的數據用於模型訓練,但以下情況除外: + +- Big Pickle:在免費期間,收集的數據可用於改進模型。 +- GLM 4.7 免費:在免費期間,收集的數據可用於改進模型。 +- Kimi K2.5 免費:在免費期間,收集的數據可用於改進模型。 +- MiniMax M2.1 免費:在免費期間,收集的數據可用於改進模型。 +- 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 對團隊也很有效。您可以邀請隊友、分配角色、精選 +您的團隊使用的模型等等。 + +:::note +作為測試版的一部分,工作區目前對團隊免費。 +::: + +作為測試版的一部分,管理工作區目前對團隊免費。我們將會 +很快就會分享更多有關定價的細節。 + +--- + +### 角色 + +您可以邀請團隊成員到您的工作區並分配角色: + +- **管理員**:管理模型、成員、API 金鑰和計費 +- **成員**:僅管理自己的 API 金鑰 + +管理員還可以為每個成員設定每月支出限額,以控制成本。 + +--- + +### 模型存取 + +管理員可以啟用或禁用工作區的特定模型。對禁用模型發出的請求將返回錯誤。 + +這對於您想要禁用以下模型的情況很有用: +收集數據。 + +--- + +### 帶上你自己的金鑰 + +您可以使用自己的 OpenAI 或 Anthropic API 金鑰,同時仍然存取 Zen 中的其他模型。 + +當您使用自己的金鑰時,Tokens 將由供應商直接計費,而不是由 Zen。 + +例如,您的組織可能已經擁有 OpenAI 或 Anthropic 的金鑰 +你想使用它而不是 Zen 提供的。 + +--- + +## 目標 + +我們建立 OpenCode Zen 的目的是: + +1. **設定基準**編碼代理的最佳模型/供應商。 +2. 可以使用**最高品質**選項,而不是降低性能或轉向更便宜的供應商。 +3. 透過按成本價銷售來傳遞任何**價格下跌**;所以唯一的加價就是支付我們的處理費。 +4. 透過允許您將其與任何其他編碼代理一起使用,**無鎖定**。並且始終允許您將任何其他供應商與 opencode 一起使用。 diff --git a/packages/web/src/content/i18n/ar.json b/packages/web/src/content/i18n/ar.json new file mode 100644 index 00000000000..d8029441fe7 --- /dev/null +++ b/packages/web/src/content/i18n/ar.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "وكيل برمجة بالذكاء الاصطناعي مصمم لـ terminal", + "app.header.home": "الرئيسية", + "app.header.docs": "التوثيق", + "app.footer.issueLink": "وجدت خطأ؟ افتح بلاغا", + "app.footer.discordLink": "انضم إلى مجتمع Discord الخاص بنا", + "app.lander.hero.title": "وكيل البرمجة بالذكاء الاصطناعي المصمم لـ terminal.", + "app.lander.cta.getStarted": "ابدأ الآن", + "app.lander.features.native_tui.title": "TUI أصلي", + "app.lander.features.native_tui.description": "واجهة terminal أصلية، سريعة الاستجابة، وقابلة للتخصيص.", + "app.lander.features.lsp_enabled.title": "يدعم LSP", + "app.lander.features.lsp_enabled.description": "يحمّل تلقائيا خوادم LSP المناسبة لـ LLM.", + "app.lander.features.multi_session.title": "جلسات متعددة", + "app.lander.features.multi_session.description": "شغّل عدة وكلاء بالتوازي على نفس المشروع.", + "app.lander.features.shareable_links.title": "روابط قابلة للمشاركة", + "app.lander.features.shareable_links.description": "شارك رابطا لأي جلسة للرجوع إليها أو لتصحيح الأخطاء.", + "app.lander.features.github_copilot.description": "سجّل الدخول عبر GitHub لاستخدام حساب Copilot الخاص بك.", + "app.lander.features.chatgpt_plus_pro.description": "سجّل الدخول عبر OpenAI لاستخدام حساب ChatGPT Plus أو Pro.", + "app.lander.features.use_any_model.title": "استخدم أي نموذج", + "app.lander.features.use_any_model.prefix": "يدعم أكثر من 75 مزودا لـ LLM عبر", + "app.lander.features.use_any_model.suffix": "بما في ذلك النماذج المحلية.", + "app.lander.images.tui.caption": "opencode TUI مع سمة tokyonight", + "app.lander.images.tui.alt": "opencode TUI مع سمة tokyonight", + "app.lander.images.vscode.caption": "opencode في VS Code", + "app.lander.images.vscode.alt": "opencode في VS Code", + "app.lander.images.github.caption": "opencode في GitHub", + "app.lander.images.github.alt": "opencode في GitHub", + "share.meta_description": "opencode - وكيل البرمجة بالذكاء الاصطناعي المصمم لـ terminal.", + "share.not_found": "غير موجود", + "share.link_to_message": "رابط إلى هذه الرسالة", + "share.copied": "تم النسخ!", + "share.copy": "نسخ", + "share.show_more": "عرض المزيد", + "share.show_less": "عرض أقل", + "share.show_results": "عرض النتائج", + "share.hide_results": "إخفاء النتائج", + "share.show_details": "عرض التفاصيل", + "share.hide_details": "إخفاء التفاصيل", + "share.show_preview": "عرض المعاينة", + "share.hide_preview": "إخفاء المعاينة", + "share.show_contents": "عرض المحتويات", + "share.hide_contents": "إخفاء المحتويات", + "share.show_output": "عرض المخرجات", + "share.hide_output": "إخفاء المخرجات", + "share.error": "خطأ", + "share.waiting_for_messages": "بانتظار الرسائل...", + "share.status_connected_waiting": "متصل، بانتظار الرسائل...", + "share.status_connecting": "جارٍ الاتصال...", + "share.status_disconnected": "غير متصل", + "share.status_reconnecting": "جارٍ إعادة الاتصال...", + "share.status_error": "خطأ", + "share.status_unknown": "غير معروف", + "share.error_id_not_found": "لم يتم العثور على id", + "share.error_api_url_not_found": "لم يتم العثور على API URL", + "share.error_connection_failed": "فشل الاتصال", + "share.opencode_version": "إصدار opencode", + "share.opencode_name": "opencode", + "share.models": "النماذج", + "share.cost": "التكلفة", + "share.input_tokens": "رموز الإدخال", + "share.output_tokens": "رموز الإخراج", + "share.reasoning_tokens": "رموز التفكير", + "share.scroll_to_bottom": "التمرير إلى الأسفل", + "share.attachment": "مرفق", + "share.thinking": "تفكير", + "share.thinking_pending": "جارٍ التفكير...", + "share.creating_plan": "جارٍ إنشاء الخطة", + "share.completing_plan": "جارٍ إكمال الخطة", + "share.updating_plan": "جارٍ تحديث الخطة", + "share.match_one": "مطابقة", + "share.match_other": "مطابقات", + "share.result_one": "نتيجة", + "share.result_other": "نتائج", + "share.debug_key": "المفتاح" +} diff --git a/packages/web/src/content/i18n/bs.json b/packages/web/src/content/i18n/bs.json new file mode 100644 index 00000000000..6dc96ce7f39 --- /dev/null +++ b/packages/web/src/content/i18n/bs.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "AI agent za kodiranje, napravljen za terminal", + "app.header.home": "Početna", + "app.header.docs": "Dokumentacija", + "app.footer.issueLink": "Pronašli ste grešku? Prijavite problem", + "app.footer.discordLink": "Pridružite se našoj Discord zajednici", + "app.lander.hero.title": "AI agent za kodiranje, napravljen za terminal.", + "app.lander.cta.getStarted": "Započnite", + "app.lander.features.native_tui.title": "Izvorni TUI", + "app.lander.features.native_tui.description": "Prilagodljiv, izvorni, tematski interfejs terminala.", + "app.lander.features.lsp_enabled.title": "LSP omogućen", + "app.lander.features.lsp_enabled.description": "Automatski učitava ispravne LSP-ove za LLM.", + "app.lander.features.multi_session.title": "Više sesija", + "app.lander.features.multi_session.description": "Pokrenite više agenata paralelno na istom projektu.", + "app.lander.features.shareable_links.title": "Linkovi za dijeljenje", + "app.lander.features.shareable_links.description": "Podijelite link do bilo koje sesije za referencu ili otklanjanje grešaka.", + "app.lander.features.github_copilot.description": "Prijavite se na GitHub da koristite svoj Copilot nalog.", + "app.lander.features.chatgpt_plus_pro.description": "Prijavite se na OpenAI da koristite svoj ChatGPT Plus ili Pro nalog.", + "app.lander.features.use_any_model.title": "Koristite bilo koji model", + "app.lander.features.use_any_model.prefix": "Podržava 75+ LLM provajdera kroz", + "app.lander.features.use_any_model.suffix": "uključujući lokalne modele.", + "app.lander.images.tui.caption": "OpenCode TUI u tokyonight temi", + "app.lander.images.tui.alt": "OpenCode TUI u tokyonight temi", + "app.lander.images.vscode.caption": "OpenCode u VS Code", + "app.lander.images.vscode.alt": "OpenCode u VS Code", + "app.lander.images.github.caption": "OpenCode u GitHub", + "app.lander.images.github.alt": "OpenCode u GitHub", + "share.meta_description": "OpenCode - AI agent za kodiranje napravljen za terminal.", + "share.not_found": "Nije pronađeno", + "share.link_to_message": "Link do ove poruke", + "share.copied": "Kopirano!", + "share.copy": "Kopiraj", + "share.show_more": "Prikaži više", + "share.show_less": "Prikaži manje", + "share.show_results": "Prikaži rezultate", + "share.hide_results": "Sakrij rezultate", + "share.show_details": "Prikaži detalje", + "share.hide_details": "Sakrij detalje", + "share.show_preview": "Prikaži pregled", + "share.hide_preview": "Sakrij pregled", + "share.show_contents": "Prikaži sadržaj", + "share.hide_contents": "Sakrij sadržaj", + "share.show_output": "Prikaži izlaz", + "share.hide_output": "Sakrij izlaz", + "share.error": "Greška", + "share.waiting_for_messages": "Čekanje poruka...", + "share.status_connected_waiting": "Povezano, čekanje poruka...", + "share.status_connecting": "Povezivanje...", + "share.status_disconnected": "Prekinuto", + "share.status_reconnecting": "Ponovno povezivanje...", + "share.status_error": "Greška", + "share.status_unknown": "Nepoznato", + "share.error_id_not_found": "ID nije pronađen", + "share.error_api_url_not_found": "API URL nije pronađen", + "share.error_connection_failed": "Povezivanje nije uspjelo", + "share.opencode_version": "OpenCode verzija", + "share.opencode_name": "OpenCode", + "share.models": "Modeli", + "share.cost": "Cijena", + "share.input_tokens": "Ulazni tokeni", + "share.output_tokens": "Izlazni tokeni", + "share.reasoning_tokens": "Tokeni rezonovanja", + "share.scroll_to_bottom": "Pomjerite na dno", + "share.attachment": "Prilog", + "share.thinking": "Razmišljanje", + "share.thinking_pending": "razmišlja...", + "share.creating_plan": "Kreiranje plana", + "share.completing_plan": "Završavanje plana", + "share.updating_plan": "Ažuriranje plana", + "share.match_one": "podudaranje", + "share.match_other": "podudaranja", + "share.result_one": "rezultat", + "share.result_other": "rezultati", + "share.debug_key": "Ključ" +} diff --git a/packages/web/src/content/i18n/da.json b/packages/web/src/content/i18n/da.json new file mode 100644 index 00000000000..a375c6713e8 --- /dev/null +++ b/packages/web/src/content/i18n/da.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "AI-kodningsagent bygget til terminalen", + "app.header.home": "Hjem", + "app.header.docs": "Dokumentation", + "app.footer.issueLink": "Har du fundet en fejl? Opret en issue", + "app.footer.discordLink": "Bliv en del af vores Discord-fællesskab", + "app.lander.hero.title": "AI-kodningsagenten bygget til terminalen.", + "app.lander.cta.getStarted": "Kom i gang", + "app.lander.features.native_tui.title": "Indbygget TUI", + "app.lander.features.native_tui.description": "En responsiv, indbygget, temavenlig terminal-brugergrænseflade.", + "app.lander.features.lsp_enabled.title": "LSP aktiveret", + "app.lander.features.lsp_enabled.description": "Indlæser automatisk de rigtige LSPs for LLM.", + "app.lander.features.multi_session.title": "Flere sessioner", + "app.lander.features.multi_session.description": "Start flere agenter parallelt på det samme projekt.", + "app.lander.features.shareable_links.title": "Delbare links", + "app.lander.features.shareable_links.description": "Del et link til enhver session til reference eller til fejlretning.", + "app.lander.features.github_copilot.description": "Log ind med GitHub for at bruge din Copilot konto.", + "app.lander.features.chatgpt_plus_pro.description": "Log ind med OpenAI for at bruge din ChatGPT Plus eller Pro-konto.", + "app.lander.features.use_any_model.title": "Brug enhver model", + "app.lander.features.use_any_model.prefix": "Understøtter 75+ LLM udbydere igennem", + "app.lander.features.use_any_model.suffix": "herunder lokale modeller.", + "app.lander.images.tui.caption": "opencode TUI med tokyonight-temaet", + "app.lander.images.tui.alt": "opencode TUI med tokyonight-temaet", + "app.lander.images.vscode.caption": "opencode i VS Code", + "app.lander.images.vscode.alt": "opencode i VS Code", + "app.lander.images.github.caption": "opencode i GitHub", + "app.lander.images.github.alt": "opencode i GitHub", + "share.meta_description": "opencode - AI-kodningsagenten bygget til terminalen.", + "share.not_found": "Ikke fundet", + "share.link_to_message": "Link til denne besked", + "share.copied": "Kopieret!", + "share.copy": "Kopiér", + "share.show_more": "Vis mere", + "share.show_less": "Vis mindre", + "share.show_results": "Vis resultater", + "share.hide_results": "Skjul resultater", + "share.show_details": "Vis detaljer", + "share.hide_details": "Skjul detaljer", + "share.show_preview": "Vis forhåndsvisning", + "share.hide_preview": "Skjul forhåndsvisning", + "share.show_contents": "Vis indhold", + "share.hide_contents": "Skjul indhold", + "share.show_output": "Vis output", + "share.hide_output": "Skjul output", + "share.error": "Fejl", + "share.waiting_for_messages": "Venter på beskeder...", + "share.status_connected_waiting": "Forbundet, venter på beskeder...", + "share.status_connecting": "Opretter forbindelse...", + "share.status_disconnected": "Afbrudt", + "share.status_reconnecting": "Genopretter forbindelse...", + "share.status_error": "Fejl", + "share.status_unknown": "Ukendt", + "share.error_id_not_found": "id ikke fundet", + "share.error_api_url_not_found": "API URL ikke fundet", + "share.error_connection_failed": "Forbindelsen mislykkedes", + "share.opencode_version": "opencode-version", + "share.opencode_name": "opencode", + "share.models": "Modeller", + "share.cost": "Omkostning", + "share.input_tokens": "Input-tokens", + "share.output_tokens": "Output-tokens", + "share.reasoning_tokens": "Ræsonneringstokens", + "share.scroll_to_bottom": "Rul til bunden", + "share.attachment": "Vedhæftet fil", + "share.thinking": "Tænker", + "share.thinking_pending": "Tænker...", + "share.creating_plan": "Oprettelse af plan", + "share.completing_plan": "Færdiggør plan", + "share.updating_plan": "Opdatering af plan", + "share.match_one": "træf", + "share.match_other": "træf", + "share.result_one": "resultat", + "share.result_other": "resultater", + "share.debug_key": "Nøgle" +} diff --git a/packages/web/src/content/i18n/de.json b/packages/web/src/content/i18n/de.json new file mode 100644 index 00000000000..9d631436891 --- /dev/null +++ b/packages/web/src/content/i18n/de.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "AI-Coding-Agent für das Terminal", + "app.header.home": "Startseite", + "app.header.docs": "Dokumentation", + "app.footer.issueLink": "Einen Fehler gefunden? Eröffne ein Issue", + "app.footer.discordLink": "Tritt unserer Discord-Community bei", + "app.lander.hero.title": "Der AI-Coding-Agent für das Terminal.", + "app.lander.cta.getStarted": "Loslegen", + "app.lander.features.native_tui.title": "Natives TUI", + "app.lander.features.native_tui.description": "Eine reaktionsschnelle, native, anpassbare Terminal-UI.", + "app.lander.features.lsp_enabled.title": "LSP aktiviert", + "app.lander.features.lsp_enabled.description": "Lädt automatisch die passenden LSPs für das LLM.", + "app.lander.features.multi_session.title": "Mehrere Sitzungen", + "app.lander.features.multi_session.description": "Starten Sie mehrere Agenten parallel für dasselbe Projekt.", + "app.lander.features.shareable_links.title": "Gemeinsam nutzbare Links", + "app.lander.features.shareable_links.description": "Teilen Sie einen Link zu beliebigen Sitzungen als Referenz oder zum Debuggen.", + "app.lander.features.github_copilot.description": "Melden Sie sich bei GitHub an, um Ihr Copilot-Konto zu verwenden.", + "app.lander.features.chatgpt_plus_pro.description": "Melden Sie sich mit OpenAI an, um Ihr ChatGPT Plus- oder Pro-Konto zu verwenden.", + "app.lander.features.use_any_model.title": "Beliebiges Modell nutzen", + "app.lander.features.use_any_model.prefix": "Unterstützt 75+ LLM-Provider über", + "app.lander.features.use_any_model.suffix": "einschließlich lokaler Modelle.", + "app.lander.images.tui.caption": "opencode TUI mit dem tokyonight Theme", + "app.lander.images.tui.alt": "opencode TUI mit dem tokyonight Theme", + "app.lander.images.vscode.caption": "opencode im VS-Code-Editor", + "app.lander.images.vscode.alt": "opencode im VS-Code-Editor", + "app.lander.images.github.caption": "opencode auf GitHub", + "app.lander.images.github.alt": "opencode auf GitHub", + "share.meta_description": "opencode - Der AI-Coding-Agent für das Terminal.", + "share.not_found": "Nicht gefunden", + "share.link_to_message": "Link zu dieser Nachricht", + "share.copied": "Kopiert!", + "share.copy": "Kopieren", + "share.show_more": "Mehr anzeigen", + "share.show_less": "Weniger anzeigen", + "share.show_results": "Ergebnisse anzeigen", + "share.hide_results": "Ergebnisse ausblenden", + "share.show_details": "Details anzeigen", + "share.hide_details": "Details ausblenden", + "share.show_preview": "Vorschau anzeigen", + "share.hide_preview": "Vorschau ausblenden", + "share.show_contents": "Inhalte anzeigen", + "share.hide_contents": "Inhalte ausblenden", + "share.show_output": "Ausgabe anzeigen", + "share.hide_output": "Ausgabe ausblenden", + "share.error": "Fehler", + "share.waiting_for_messages": "Warten auf Nachrichten...", + "share.status_connected_waiting": "Verbunden, warte auf Nachrichten...", + "share.status_connecting": "Verbinden...", + "share.status_disconnected": "Getrennt", + "share.status_reconnecting": "Verbindet erneut...", + "share.status_error": "Fehler", + "share.status_unknown": "Unbekannt", + "share.error_id_not_found": "ID nicht gefunden", + "share.error_api_url_not_found": "API URL nicht gefunden", + "share.error_connection_failed": "Verbindung fehlgeschlagen", + "share.opencode_version": "opencode Version", + "share.opencode_name": "opencode", + "share.models": "Modelle", + "share.cost": "Kosten", + "share.input_tokens": "Eingabe-Token", + "share.output_tokens": "Ausgabe-Token", + "share.reasoning_tokens": "Reasoning-Token", + "share.scroll_to_bottom": "Nach unten scrollen", + "share.attachment": "Anhang", + "share.thinking": "Denken", + "share.thinking_pending": "Denken...", + "share.creating_plan": "Plan wird erstellt", + "share.completing_plan": "Plan wird abgeschlossen", + "share.updating_plan": "Plan wird aktualisiert", + "share.match_one": "Treffer", + "share.match_other": "Treffer", + "share.result_one": "Ergebnis", + "share.result_other": "Ergebnisse", + "share.debug_key": "Schlüssel" +} diff --git a/packages/web/src/content/i18n/en.json b/packages/web/src/content/i18n/en.json new file mode 100644 index 00000000000..fedb70a6cba --- /dev/null +++ b/packages/web/src/content/i18n/en.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "AI coding agent built for the terminal", + "app.header.home": "Home", + "app.header.docs": "Docs", + "app.footer.issueLink": "Found a bug? Open an issue", + "app.footer.discordLink": "Join our Discord community", + "app.lander.hero.title": "The AI coding agent built for the terminal.", + "app.lander.cta.getStarted": "Get Started", + "app.lander.features.native_tui.title": "Native TUI", + "app.lander.features.native_tui.description": "A responsive, native, themeable terminal UI.", + "app.lander.features.lsp_enabled.title": "LSP enabled", + "app.lander.features.lsp_enabled.description": "Automatically loads the right LSPs for the LLM.", + "app.lander.features.multi_session.title": "Multi-session", + "app.lander.features.multi_session.description": "Start multiple agents in parallel on the same project.", + "app.lander.features.shareable_links.title": "Shareable links", + "app.lander.features.shareable_links.description": "Share a link to any sessions for reference or to debug.", + "app.lander.features.github_copilot.description": "Log in with GitHub to use your Copilot account.", + "app.lander.features.chatgpt_plus_pro.description": "Log in with OpenAI to use your ChatGPT Plus or Pro account.", + "app.lander.features.use_any_model.title": "Use any model", + "app.lander.features.use_any_model.prefix": "Supports 75+ LLM providers through", + "app.lander.features.use_any_model.suffix": "including local models.", + "app.lander.images.tui.caption": "opencode TUI with the tokyonight theme", + "app.lander.images.tui.alt": "opencode TUI with the tokyonight theme", + "app.lander.images.vscode.caption": "opencode in VS Code", + "app.lander.images.vscode.alt": "opencode in VS Code", + "app.lander.images.github.caption": "opencode in GitHub", + "app.lander.images.github.alt": "opencode in GitHub", + "share.meta_description": "opencode - The AI coding agent built for the terminal.", + "share.not_found": "Not found", + "share.link_to_message": "Link to this message", + "share.copied": "Copied!", + "share.copy": "Copy", + "share.show_more": "Show more", + "share.show_less": "Show less", + "share.show_results": "Show results", + "share.hide_results": "Hide results", + "share.show_details": "Show details", + "share.hide_details": "Hide details", + "share.show_preview": "Show preview", + "share.hide_preview": "Hide preview", + "share.show_contents": "Show contents", + "share.hide_contents": "Hide contents", + "share.show_output": "Show output", + "share.hide_output": "Hide output", + "share.error": "Error", + "share.waiting_for_messages": "Waiting for messages...", + "share.status_connected_waiting": "Connected, waiting for messages...", + "share.status_connecting": "Connecting...", + "share.status_disconnected": "Disconnected", + "share.status_reconnecting": "Reconnecting...", + "share.status_error": "Error", + "share.status_unknown": "Unknown", + "share.error_id_not_found": "id not found", + "share.error_api_url_not_found": "API URL not found", + "share.error_connection_failed": "Connection failed", + "share.opencode_version": "opencode version", + "share.opencode_name": "opencode", + "share.models": "Models", + "share.cost": "Cost", + "share.input_tokens": "Input Tokens", + "share.output_tokens": "Output Tokens", + "share.reasoning_tokens": "Reasoning Tokens", + "share.scroll_to_bottom": "Scroll to bottom", + "share.attachment": "Attachment", + "share.thinking": "Thinking", + "share.thinking_pending": "Thinking...", + "share.creating_plan": "Creating plan", + "share.completing_plan": "Completing plan", + "share.updating_plan": "Updating plan", + "share.match_one": "match", + "share.match_other": "matches", + "share.result_one": "result", + "share.result_other": "results", + "share.debug_key": "Key" +} diff --git a/packages/web/src/content/i18n/es.json b/packages/web/src/content/i18n/es.json new file mode 100644 index 00000000000..a30a7f06492 --- /dev/null +++ b/packages/web/src/content/i18n/es.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "Agente de codificación con IA para terminal", + "app.header.home": "Inicio", + "app.header.docs": "Documentación", + "app.footer.issueLink": "¿Encontraste un error? Abre una incidencia", + "app.footer.discordLink": "Únete a nuestra comunidad de Discord", + "app.lander.hero.title": "El agente de codificación con IA hecho para terminal.", + "app.lander.cta.getStarted": "Comenzar", + "app.lander.features.native_tui.title": "Nativo TUI", + "app.lander.features.native_tui.description": "Una UI de terminal responsiva, nativa y personalizable.", + "app.lander.features.lsp_enabled.title": "LSP habilitado", + "app.lander.features.lsp_enabled.description": "Carga automáticamente los LSP correctos para LLM.", + "app.lander.features.multi_session.title": "Multisesión", + "app.lander.features.multi_session.description": "Inicia varios agentes en paralelo en el mismo proyecto.", + "app.lander.features.shareable_links.title": "Enlaces para compartir", + "app.lander.features.shareable_links.description": "Comparte un enlace a cualquier sesion para referencia o depuracion.", + "app.lander.features.github_copilot.description": "Inicia sesion con GitHub para usar tu cuenta Copilot.", + "app.lander.features.chatgpt_plus_pro.description": "Inicia sesion con OpenAI para usar tu cuenta ChatGPT Plus or Pro.", + "app.lander.features.use_any_model.title": "Usa cualquier modelo", + "app.lander.features.use_any_model.prefix": "Admite más de 75 proveedores LLM a través de", + "app.lander.features.use_any_model.suffix": "incluyendo modelos locales.", + "app.lander.images.tui.caption": "opencode TUI con el tema tokyonight", + "app.lander.images.tui.alt": "opencode TUI con el tema tokyonight", + "app.lander.images.vscode.caption": "opencode en VS Code", + "app.lander.images.vscode.alt": "opencode en VS Code", + "app.lander.images.github.caption": "opencode en GitHub", + "app.lander.images.github.alt": "opencode en GitHub", + "share.meta_description": "opencode - Agente de codificacion con IA para terminal.", + "share.not_found": "No encontrado", + "share.link_to_message": "Enlace a este mensaje", + "share.copied": "¡Copiado!", + "share.copy": "Copiar", + "share.show_more": "Mostrar más", + "share.show_less": "Mostrar menos", + "share.show_results": "Mostrar resultados", + "share.hide_results": "Ocultar resultados", + "share.show_details": "Mostrar detalles", + "share.hide_details": "Ocultar detalles", + "share.show_preview": "Mostrar vista previa", + "share.hide_preview": "Ocultar vista previa", + "share.show_contents": "Mostrar contenidos", + "share.hide_contents": "Ocultar contenidos", + "share.show_output": "Mostrar salida", + "share.hide_output": "Ocultar salida", + "share.error": "Error", + "share.waiting_for_messages": "Esperando mensajes...", + "share.status_connected_waiting": "Conectado, esperando mensajes...", + "share.status_connecting": "Conectando...", + "share.status_disconnected": "Desconectado", + "share.status_reconnecting": "Reconectando...", + "share.status_error": "Error", + "share.status_unknown": "Desconocido", + "share.error_id_not_found": "no encontrado", + "share.error_api_url_not_found": "URL de la API no encontrada", + "share.error_connection_failed": "Error de conexión", + "share.opencode_version": "Versión opencode", + "share.opencode_name": "opencode", + "share.models": "Modelos", + "share.cost": "Costo", + "share.input_tokens": "Tokens de entrada", + "share.output_tokens": "Tokens de salida", + "share.reasoning_tokens": "Tokens de razonamiento", + "share.scroll_to_bottom": "Desplazarse hacia abajo", + "share.attachment": "Adjunto", + "share.thinking": "Pensamiento", + "share.thinking_pending": "Pensando...", + "share.creating_plan": "Creando plan", + "share.completing_plan": "Completando el plan", + "share.updating_plan": "Actualizando el plan", + "share.match_one": "coincidencia", + "share.match_other": "coincidencias", + "share.result_one": "resultado", + "share.result_other": "resultados", + "share.debug_key": "Clave" +} diff --git a/packages/web/src/content/i18n/fr.json b/packages/web/src/content/i18n/fr.json new file mode 100644 index 00000000000..294badf4957 --- /dev/null +++ b/packages/web/src/content/i18n/fr.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "Agent IA de code conçu pour le terminal", + "app.header.home": "Accueil", + "app.header.docs": "Documentation", + "app.footer.issueLink": "Vous avez trouvé un bug ? Ouvrez une issue", + "app.footer.discordLink": "Rejoignez notre communauté Discord", + "app.lander.hero.title": "L'agent de codage AI conçu pour le terminal.", + "app.lander.cta.getStarted": "Commencer", + "app.lander.features.native_tui.title": "TUI natif", + "app.lander.features.native_tui.description": "Une interface terminal native, réactive et personnalisable.", + "app.lander.features.lsp_enabled.title": "LSP activé", + "app.lander.features.lsp_enabled.description": "Charge automatiquement les bons LSP pour le LLM.", + "app.lander.features.multi_session.title": "Sessions multiples", + "app.lander.features.multi_session.description": "Démarrez plusieurs agents en parallèle sur le même projet.", + "app.lander.features.shareable_links.title": "Liens partageables", + "app.lander.features.shareable_links.description": "Partagez un lien vers n’importe quelle session pour référence ou pour déboguer.", + "app.lander.features.github_copilot.description": "Connectez-vous avec GitHub pour utiliser votre compte Copilot.", + "app.lander.features.chatgpt_plus_pro.description": "Connectez-vous avec OpenAI pour utiliser votre compte ChatGPT Plus ou Pro.", + "app.lander.features.use_any_model.title": "Utiliser n'importe quel modèle", + "app.lander.features.use_any_model.prefix": "Prend en charge plus de 75 fournisseurs LLM via", + "app.lander.features.use_any_model.suffix": "y compris des modèles locaux.", + "app.lander.images.tui.caption": "opencode TUI avec le thème tokyonight", + "app.lander.images.tui.alt": "opencode TUI avec le thème tokyonight", + "app.lander.images.vscode.caption": "opencode dans VS Code", + "app.lander.images.vscode.alt": "opencode dans VS Code", + "app.lander.images.github.caption": "opencode dans GitHub", + "app.lander.images.github.alt": "opencode dans GitHub", + "share.meta_description": "opencode - Agent IA de code conçu pour le terminal.", + "share.not_found": "Pas trouvé", + "share.link_to_message": "Lien vers ce message", + "share.copied": "Copié!", + "share.copy": "Copier", + "share.show_more": "Afficher plus", + "share.show_less": "Afficher moins", + "share.show_results": "Afficher les résultats", + "share.hide_results": "Masquer les résultats", + "share.show_details": "Afficher les détails", + "share.hide_details": "Masquer les détails", + "share.show_preview": "Afficher l'aperçu", + "share.hide_preview": "Masquer l'aperçu", + "share.show_contents": "Afficher le contenu", + "share.hide_contents": "Masquer le contenu", + "share.show_output": "Afficher la sortie", + "share.hide_output": "Masquer la sortie", + "share.error": "Erreur", + "share.waiting_for_messages": "En attente de messages...", + "share.status_connected_waiting": "Connecté, en attente de messages...", + "share.status_connecting": "Connexion...", + "share.status_disconnected": "Déconnecté", + "share.status_reconnecting": "Reconnexion...", + "share.status_error": "Erreur", + "share.status_unknown": "Inconnu", + "share.error_id_not_found": "id introuvable", + "share.error_api_url_not_found": "API URL introuvable", + "share.error_connection_failed": "La connexion a échoué", + "share.opencode_version": "version d'opencode", + "share.opencode_name": "opencode", + "share.models": "Modèles", + "share.cost": "Coût", + "share.input_tokens": "Tokens d'entrée", + "share.output_tokens": "Tokens de sortie", + "share.reasoning_tokens": "Tokens de raisonnement", + "share.scroll_to_bottom": "Faire défiler vers le bas", + "share.attachment": "Pièce jointe", + "share.thinking": "Réflexion", + "share.thinking_pending": "Réflexion...", + "share.creating_plan": "Création du plan", + "share.completing_plan": "Finalisation du plan", + "share.updating_plan": "Mise à jour du plan", + "share.match_one": "correspondance", + "share.match_other": "correspondances", + "share.result_one": "résultat", + "share.result_other": "résultats", + "share.debug_key": "Clé" +} diff --git a/packages/web/src/content/i18n/it.json b/packages/web/src/content/i18n/it.json new file mode 100644 index 00000000000..a9ed2b1f86c --- /dev/null +++ b/packages/web/src/content/i18n/it.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "Agente AI di coding creato per il terminale", + "app.header.home": "Inizio", + "app.header.docs": "Documentazione", + "app.footer.issueLink": "Hai trovato un bug? Apri una issue", + "app.footer.discordLink": "Unisciti alla nostra community Discord", + "app.lander.hero.title": "L'agente AI di coding creato per il terminale.", + "app.lander.cta.getStarted": "Inizia", + "app.lander.features.native_tui.title": "TUI nativa", + "app.lander.features.native_tui.description": "Un'interfaccia per terminale reattiva, nativa e personalizzabile.", + "app.lander.features.lsp_enabled.title": "LSP abilitato", + "app.lander.features.lsp_enabled.description": "Carica automaticamente gli LSP corretti per l'LLM.", + "app.lander.features.multi_session.title": "Multi-sessione", + "app.lander.features.multi_session.description": "Avvia più agenti in parallelo sullo stesso progetto.", + "app.lander.features.shareable_links.title": "Link condivisibili", + "app.lander.features.shareable_links.description": "Condividi un link a qualsiasi sessione per riferimento o debug.", + "app.lander.features.github_copilot.description": "Accedi con GitHub per usare il tuo account Copilot.", + "app.lander.features.chatgpt_plus_pro.description": "Accedi con OpenAI per usare il tuo account ChatGPT Plus o Pro.", + "app.lander.features.use_any_model.title": "Usa qualsiasi modello", + "app.lander.features.use_any_model.prefix": "Supporta oltre 75 provider LLM tramite", + "app.lander.features.use_any_model.suffix": "inclusi i modelli locali.", + "app.lander.images.tui.caption": "TUI di opencode con il tema tokyonight", + "app.lander.images.tui.alt": "TUI di opencode con il tema tokyonight", + "app.lander.images.vscode.caption": "opencode su VS Code", + "app.lander.images.vscode.alt": "opencode su VS Code", + "app.lander.images.github.caption": "opencode su GitHub", + "app.lander.images.github.alt": "opencode su GitHub", + "share.meta_description": "opencode - L'agente AI di coding creato per il terminale.", + "share.not_found": "Non trovato", + "share.link_to_message": "Link a questo messaggio", + "share.copied": "Copiato!", + "share.copy": "Copia", + "share.show_more": "Mostra altro", + "share.show_less": "Mostra meno", + "share.show_results": "Mostra risultati", + "share.hide_results": "Nascondi risultati", + "share.show_details": "Mostra dettagli", + "share.hide_details": "Nascondi dettagli", + "share.show_preview": "Mostra anteprima", + "share.hide_preview": "Nascondi anteprima", + "share.show_contents": "Mostra contenuto", + "share.hide_contents": "Nascondi contenuto", + "share.show_output": "Mostra output", + "share.hide_output": "Nascondi output", + "share.error": "Errore", + "share.waiting_for_messages": "In attesa di messaggi...", + "share.status_connected_waiting": "Connesso, in attesa di messaggi...", + "share.status_connecting": "Connessione in corso...", + "share.status_disconnected": "Disconnesso", + "share.status_reconnecting": "Riconnessione in corso...", + "share.status_error": "Errore", + "share.status_unknown": "Sconosciuto", + "share.error_id_not_found": "ID non trovato", + "share.error_api_url_not_found": "URL API non trovato", + "share.error_connection_failed": "Connessione non riuscita", + "share.opencode_version": "Versione OpenCode", + "share.opencode_name": "opencode", + "share.models": "Modelli", + "share.cost": "Costo", + "share.input_tokens": "Token di input", + "share.output_tokens": "Token di output", + "share.reasoning_tokens": "Token di ragionamento", + "share.scroll_to_bottom": "Scorri in basso", + "share.attachment": "Allegato", + "share.thinking": "Elaborazione", + "share.thinking_pending": "Elaborazione...", + "share.creating_plan": "Creazione piano", + "share.completing_plan": "Completamento piano", + "share.updating_plan": "Aggiornamento piano", + "share.match_one": "corrispondenza", + "share.match_other": "corrispondenze", + "share.result_one": "risultato", + "share.result_other": "risultati", + "share.debug_key": "Chiave" +} diff --git a/packages/web/src/content/i18n/ja.json b/packages/web/src/content/i18n/ja.json new file mode 100644 index 00000000000..9ef6851e528 --- /dev/null +++ b/packages/web/src/content/i18n/ja.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "ターミナル向けのAIコーディングエージェント", + "app.header.home": "ホーム", + "app.header.docs": "ドキュメント", + "app.footer.issueLink": "バグを見つけたらIssueを作成", + "app.footer.discordLink": "Discordコミュニティに参加", + "app.lander.hero.title": "ターミナル向けのAIコーディングエージェント", + "app.lander.cta.getStarted": "始める", + "app.lander.features.native_tui.title": "ネイティブ TUI", + "app.lander.features.native_tui.description": "レスポンシブでネイティブ、テーマ対応のターミナル UI。", + "app.lander.features.lsp_enabled.title": "LSP対応", + "app.lander.features.lsp_enabled.description": "LLMに最適なLSPを自動で読み込みます。", + "app.lander.features.multi_session.title": "マルチセッション", + "app.lander.features.multi_session.description": "同じプロジェクトで複数のエージェントを並列で起動します。", + "app.lander.features.shareable_links.title": "共有リンク", + "app.lander.features.shareable_links.description": "参照やデバッグのためにセッションリンクを共有します。", + "app.lander.features.github_copilot.description": "Copilotアカウントを使うにはGitHubでログインします。", + "app.lander.features.chatgpt_plus_pro.description": "ChatGPT PlusまたはProアカウントを使うにはOpenAIでログインします。", + "app.lander.features.use_any_model.title": "任意のモデルを使う", + "app.lander.features.use_any_model.prefix": "75以上のLLMプロバイダーをサポート", + "app.lander.features.use_any_model.suffix": "ローカルモデルを含みます。", + "app.lander.images.tui.caption": "tokyonightテーマのopencode TUI", + "app.lander.images.tui.alt": "tokyonightテーマのopencode TUI", + "app.lander.images.vscode.caption": "VS Codeでのopencode", + "app.lander.images.vscode.alt": "VS Codeでのopencode", + "app.lander.images.github.caption": "GitHubでのopencode", + "app.lander.images.github.alt": "GitHubでのopencode", + "share.meta_description": "opencode - ターミナル向けのAIコーディングエージェント。", + "share.not_found": "見つかりません", + "share.link_to_message": "このメッセージへのリンク", + "share.copied": "コピーしました!", + "share.copy": "コピー", + "share.show_more": "もっと見る", + "share.show_less": "表示を減らす", + "share.show_results": "結果を表示", + "share.hide_results": "結果を非表示", + "share.show_details": "詳細を表示", + "share.hide_details": "詳細を非表示", + "share.show_preview": "プレビューを表示", + "share.hide_preview": "プレビューを非表示", + "share.show_contents": "内容を表示", + "share.hide_contents": "内容を非表示", + "share.show_output": "出力を表示", + "share.hide_output": "出力を非表示", + "share.error": "エラー", + "share.waiting_for_messages": "メッセージを待機中...", + "share.status_connected_waiting": "接続済み、メッセージを待機中...", + "share.status_connecting": "接続中...", + "share.status_disconnected": "切断されました", + "share.status_reconnecting": "再接続中...", + "share.status_error": "エラー", + "share.status_unknown": "不明", + "share.error_id_not_found": "idが見つかりません", + "share.error_api_url_not_found": "API URLが見つかりません", + "share.error_connection_failed": "接続に失敗しました", + "share.opencode_version": "opencode バージョン", + "share.opencode_name": "opencode", + "share.models": "モデル", + "share.cost": "コスト", + "share.input_tokens": "入力トークン", + "share.output_tokens": "出力トークン", + "share.reasoning_tokens": "推論トークン", + "share.scroll_to_bottom": "一番下までスクロール", + "share.attachment": "添付ファイル", + "share.thinking": "思考", + "share.thinking_pending": "思考中...", + "share.creating_plan": "計画を作成", + "share.completing_plan": "計画を完了", + "share.updating_plan": "計画を更新", + "share.match_one": "一致", + "share.match_other": "一致", + "share.result_one": "結果", + "share.result_other": "結果", + "share.debug_key": "キー" +} diff --git a/packages/web/src/content/i18n/ko.json b/packages/web/src/content/i18n/ko.json new file mode 100644 index 00000000000..6336655170c --- /dev/null +++ b/packages/web/src/content/i18n/ko.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "터미널에 최적화된 AI coding agent", + "app.header.home": "홈", + "app.header.docs": "문서", + "app.footer.issueLink": "버그를 찾으셨나요? 이슈를 열어 주세요", + "app.footer.discordLink": "Discord 커뮤니티에 참여하세요", + "app.lander.hero.title": "터미널을 위해 만든 AI coding agent.", + "app.lander.cta.getStarted": "시작하기", + "app.lander.features.native_tui.title": "네이티브 TUI", + "app.lander.features.native_tui.description": "반응형의 네이티브 테마형 터미널 UI입니다.", + "app.lander.features.lsp_enabled.title": "LSP 지원", + "app.lander.features.lsp_enabled.description": "LLM에 맞는 LSP를 자동으로 불러옵니다.", + "app.lander.features.multi_session.title": "멀티 세션", + "app.lander.features.multi_session.description": "같은 프로젝트에서 여러 에이전트를 병렬로 실행합니다.", + "app.lander.features.shareable_links.title": "공유 링크", + "app.lander.features.shareable_links.description": "참고나 디버깅을 위해 세션 링크를 공유합니다.", + "app.lander.features.github_copilot.description": "GitHub 로그인으로 Copilot 계정을 사용할 수 있습니다.", + "app.lander.features.chatgpt_plus_pro.description": "OpenAI 로그인으로 ChatGPT Plus 또는 Pro를 사용할 수 있습니다.", + "app.lander.features.use_any_model.title": "모든 모델 사용", + "app.lander.features.use_any_model.prefix": "75개 이상의 LLM provider를 지원하며", + "app.lander.features.use_any_model.suffix": "로컬 모델도 포함됩니다.", + "app.lander.images.tui.caption": "tokyonight theme의 opencode TUI", + "app.lander.images.tui.alt": "tokyonight theme의 opencode TUI", + "app.lander.images.vscode.caption": "VS Code에서 실행 중인 opencode", + "app.lander.images.vscode.alt": "VS Code에서 실행 중인 opencode", + "app.lander.images.github.caption": "GitHub에서 실행 중인 opencode", + "app.lander.images.github.alt": "GitHub에서 실행 중인 opencode", + "share.meta_description": "opencode - terminal을 위한 AI coding agent.", + "share.not_found": "찾을 수 없음", + "share.link_to_message": "이 메시지 링크", + "share.copied": "복사됨", + "share.copy": "복사", + "share.show_more": "더 보기", + "share.show_less": "접기", + "share.show_results": "결과 보기", + "share.hide_results": "결과 숨기기", + "share.show_details": "세부 정보 보기", + "share.hide_details": "세부 정보 숨기기", + "share.show_preview": "미리보기 보기", + "share.hide_preview": "미리보기 숨기기", + "share.show_contents": "내용 보기", + "share.hide_contents": "내용 숨기기", + "share.show_output": "출력 보기", + "share.hide_output": "출력 숨기기", + "share.error": "오류", + "share.waiting_for_messages": "메시지를 기다리는 중...", + "share.status_connected_waiting": "연결됨, 메시지를 기다리는 중...", + "share.status_connecting": "연결 중...", + "share.status_disconnected": "연결 끊김", + "share.status_reconnecting": "재연결 중...", + "share.status_error": "오류", + "share.status_unknown": "알 수 없음", + "share.error_id_not_found": "id를 찾을 수 없음", + "share.error_api_url_not_found": "API URL을 찾을 수 없음", + "share.error_connection_failed": "연결 실패", + "share.opencode_version": "opencode 버전", + "share.opencode_name": "opencode", + "share.models": "모델", + "share.cost": "비용", + "share.input_tokens": "입력 토큰", + "share.output_tokens": "출력 토큰", + "share.reasoning_tokens": "추론 토큰", + "share.scroll_to_bottom": "맨 아래로 이동", + "share.attachment": "첨부 파일", + "share.thinking": "생각 중", + "share.thinking_pending": "생각 중...", + "share.creating_plan": "계획 생성 중", + "share.completing_plan": "계획 완료 중", + "share.updating_plan": "계획 업데이트 중", + "share.match_one": "일치", + "share.match_other": "일치", + "share.result_one": "결과", + "share.result_other": "결과", + "share.debug_key": "키" +} diff --git a/packages/web/src/content/i18n/nb.json b/packages/web/src/content/i18n/nb.json new file mode 100644 index 00000000000..c91ba2e2291 --- /dev/null +++ b/packages/web/src/content/i18n/nb.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "AI-kodeagent bygget for terminalen", + "app.header.home": "Hjem", + "app.header.docs": "Dokumenter", + "app.footer.issueLink": "Fant du en feil? Åpne en issue", + "app.footer.discordLink": "Bli med i Discord-fellesskapet vårt", + "app.lander.hero.title": "AI-kodeagenten bygget for terminalen.", + "app.lander.cta.getStarted": "Kom i gang", + "app.lander.features.native_tui.title": "Innebygd TUI", + "app.lander.features.native_tui.description": "En responsiv, native og tilpassbar TUI.", + "app.lander.features.lsp_enabled.title": "LSP aktivert", + "app.lander.features.lsp_enabled.description": "Laster automatisk de riktige LSP-ene for LLM.", + "app.lander.features.multi_session.title": "Multi-sesjon", + "app.lander.features.multi_session.description": "Start flere agenter parallelt på samme prosjekt.", + "app.lander.features.shareable_links.title": "Delbare lenker", + "app.lander.features.shareable_links.description": "Del en lenke til en valgfri økt for referanse eller feilsøking.", + "app.lander.features.github_copilot.description": "Logg på med GitHub for å bruke Copilot-kontoen din.", + "app.lander.features.chatgpt_plus_pro.description": "Logg på med OpenAI for å bruke ChatGPT Plus- eller Pro-kontoen din.", + "app.lander.features.use_any_model.title": "Bruk hvilken som helst modell", + "app.lander.features.use_any_model.prefix": "Støtter 75+ LLM-leverandører gjennom", + "app.lander.features.use_any_model.suffix": "inkludert lokale modeller.", + "app.lander.images.tui.caption": "opencode TUI med tokyonight-temaet", + "app.lander.images.tui.alt": "opencode TUI med tokyonight-temaet", + "app.lander.images.vscode.caption": "opencode i VS Code", + "app.lander.images.vscode.alt": "opencode i VS Code", + "app.lander.images.github.caption": "opencode i GitHub", + "app.lander.images.github.alt": "opencode i GitHub", + "share.meta_description": "opencode - AI-kodeagenten bygget for terminalen.", + "share.not_found": "Ikke funnet", + "share.link_to_message": "Link til denne meldingen", + "share.copied": "Kopiert!", + "share.copy": "Kopier", + "share.show_more": "Vis mer", + "share.show_less": "Vis mindre", + "share.show_results": "Vis resultater", + "share.hide_results": "Skjul resultater", + "share.show_details": "Vis detaljer", + "share.hide_details": "Skjul detaljer", + "share.show_preview": "Vis forhåndsvisning", + "share.hide_preview": "Skjul forhåndsvisning", + "share.show_contents": "Vis innhold", + "share.hide_contents": "Skjul innholdet", + "share.show_output": "Vis utdata", + "share.hide_output": "Skjul utdata", + "share.error": "Feil", + "share.waiting_for_messages": "Venter på meldinger...", + "share.status_connected_waiting": "Tilkoblet, venter på meldinger...", + "share.status_connecting": "Kobler til...", + "share.status_disconnected": "Koblet fra", + "share.status_reconnecting": "Kobler til på nytt...", + "share.status_error": "Feil", + "share.status_unknown": "Ukjent", + "share.error_id_not_found": "id ikke funnet", + "share.error_api_url_not_found": "API URL ikke funnet", + "share.error_connection_failed": "Tilkobling mislyktes", + "share.opencode_version": "opencode versjon", + "share.opencode_name": "opencode", + "share.models": "Modeller", + "share.cost": "Kostnad", + "share.input_tokens": "Inndata-tokens", + "share.output_tokens": "Utdata-tokens", + "share.reasoning_tokens": "Resonneringstokens", + "share.scroll_to_bottom": "Rull til bunnen", + "share.attachment": "Vedlegg", + "share.thinking": "Tenker", + "share.thinking_pending": "Tenker...", + "share.creating_plan": "Oppretter plan", + "share.completing_plan": "Fullfører plan", + "share.updating_plan": "Oppdaterer plan", + "share.match_one": "treff", + "share.match_other": "treff", + "share.result_one": "resultat", + "share.result_other": "resultater", + "share.debug_key": "Nøkkel" +} diff --git a/packages/web/src/content/i18n/pl.json b/packages/web/src/content/i18n/pl.json new file mode 100644 index 00000000000..8cc874f82c6 --- /dev/null +++ b/packages/web/src/content/i18n/pl.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "Agent kodujący AI zbudowany dla terminala", + "app.header.home": "Strona główna", + "app.header.docs": "Dokumentacja", + "app.footer.issueLink": "Znalazłeś błąd? Otwórz issue", + "app.footer.discordLink": "Dołącz do naszej społeczności Discord", + "app.lander.hero.title": "Agent kodujący AI zbudowany dla terminala.", + "app.lander.cta.getStarted": "Rozpocznij", + "app.lander.features.native_tui.title": "Natywny TUI", + "app.lander.features.native_tui.description": "Responsywny, natywny, tematyczny interfejs terminala.", + "app.lander.features.lsp_enabled.title": "Włączone LSP", + "app.lander.features.lsp_enabled.description": "Automatycznie ładuje odpowiednie LSP dla LLM.", + "app.lander.features.multi_session.title": "Wiele sesji", + "app.lander.features.multi_session.description": "Uruchom wielu agentów równolegle w jednym projekcie.", + "app.lander.features.shareable_links.title": "Udostępniane linki", + "app.lander.features.shareable_links.description": "Udostępnij link do dowolnych sesji w celach informacyjnych lub do debugowania.", + "app.lander.features.github_copilot.description": "Zaloguj się w GitHub, aby korzystać ze swojego konta Copilot.", + "app.lander.features.chatgpt_plus_pro.description": "Zaloguj się za pomocą OpenAI, aby korzystać ze swojego konta ChatGPT Plus lub Pro.", + "app.lander.features.use_any_model.title": "Użyj dowolnego modelu", + "app.lander.features.use_any_model.prefix": "Obsługuje ponad 75 dostawców LLM przez", + "app.lander.features.use_any_model.suffix": "w tym modele lokalne.", + "app.lander.images.tui.caption": "opencode TUI z motywem tokyonight", + "app.lander.images.tui.alt": "opencode TUI z motywem tokyonight", + "app.lander.images.vscode.caption": "opencode w VS Code", + "app.lander.images.vscode.alt": "opencode w VS Code", + "app.lander.images.github.caption": "opencode w GitHub", + "app.lander.images.github.alt": "opencode w GitHub", + "share.meta_description": "opencode - agent kodujący AI dla terminala.", + "share.not_found": "Nie znaleziono", + "share.link_to_message": "Link do tej wiadomości", + "share.copied": "Skopiowano!", + "share.copy": "Kopiuj", + "share.show_more": "Pokaż więcej", + "share.show_less": "Pokaż mniej", + "share.show_results": "Pokaż wyniki", + "share.hide_results": "Ukryj wyniki", + "share.show_details": "Pokaż szczegóły", + "share.hide_details": "Ukryj szczegóły", + "share.show_preview": "Pokaż podgląd", + "share.hide_preview": "Ukryj podgląd", + "share.show_contents": "Pokaż zawartość", + "share.hide_contents": "Ukryj zawartość", + "share.show_output": "Pokaż dane wyjściowe", + "share.hide_output": "Ukryj dane wyjściowe", + "share.error": "Błąd", + "share.waiting_for_messages": "Oczekiwanie na wiadomości...", + "share.status_connected_waiting": "Połączono, czekam na wiadomości...", + "share.status_connecting": "Łączenie...", + "share.status_disconnected": "Rozłączono", + "share.status_reconnecting": "Ponowne łączenie...", + "share.status_error": "Błąd", + "share.status_unknown": "Nieznany", + "share.error_id_not_found": "Nie znaleziono identyfikatora", + "share.error_api_url_not_found": "Nie znaleziono API URL", + "share.error_connection_failed": "Połączenie nie powiodło się", + "share.opencode_version": "Wersja opencode", + "share.opencode_name": "opencode", + "share.models": "Modele", + "share.cost": "Koszt", + "share.input_tokens": "Tokeny wejściowe", + "share.output_tokens": "Tokeny wyjściowe", + "share.reasoning_tokens": "Tokeny wnioskowania", + "share.scroll_to_bottom": "Przewiń w dół", + "share.attachment": "Załącznik", + "share.thinking": "Myślenie", + "share.thinking_pending": "Myślenie...", + "share.creating_plan": "Tworzenie planu", + "share.completing_plan": "Uzupełnianie planu", + "share.updating_plan": "Aktualizacja planu", + "share.match_one": "dopasowanie", + "share.match_other": "dopasowania", + "share.result_one": "wynik", + "share.result_other": "wyniki", + "share.debug_key": "Klawisz" +} diff --git a/packages/web/src/content/i18n/pt-BR.json b/packages/web/src/content/i18n/pt-BR.json new file mode 100644 index 00000000000..c7a378131f0 --- /dev/null +++ b/packages/web/src/content/i18n/pt-BR.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "Agente de codificação de IA construído para o terminal", + "app.header.home": "Início", + "app.header.docs": "Documentação", + "app.footer.issueLink": "Encontrou um bug? Abra uma issue", + "app.footer.discordLink": "Participe da nossa comunidade no Discord", + "app.lander.hero.title": "O agente de codificação de IA construído para o terminal.", + "app.lander.cta.getStarted": "Começar", + "app.lander.features.native_tui.title": "TUI nativo", + "app.lander.features.native_tui.description": "Uma interface de terminal nativa, responsiva e com tema personalizável.", + "app.lander.features.lsp_enabled.title": "LSP habilitado", + "app.lander.features.lsp_enabled.description": "Carrega automaticamente os LSPs corretos para o LLM.", + "app.lander.features.multi_session.title": "Multi-sessão", + "app.lander.features.multi_session.description": "Inicie vários agentes em paralelo no mesmo projeto.", + "app.lander.features.shareable_links.title": "Links compartilháveis", + "app.lander.features.shareable_links.description": "Compartilhe um link para qualquer sessão para referência ou para depuração.", + "app.lander.features.github_copilot.description": "Faça login com o GitHub para usar sua conta do Copilot.", + "app.lander.features.chatgpt_plus_pro.description": "Faça login com a OpenAI para usar sua conta do ChatGPT Plus ou Pro.", + "app.lander.features.use_any_model.title": "Use qualquer modelo", + "app.lander.features.use_any_model.prefix": "Suporta mais de 75 provedores de LLM através de", + "app.lander.features.use_any_model.suffix": "incluindo modelos locais.", + "app.lander.images.tui.caption": "opencode TUI com o tema tokyonight", + "app.lander.images.tui.alt": "opencode TUI com o tema tokyonight", + "app.lander.images.vscode.caption": "opencode no VS Code", + "app.lander.images.vscode.alt": "opencode no VS Code", + "app.lander.images.github.caption": "opencode no GitHub", + "app.lander.images.github.alt": "opencode no GitHub", + "share.meta_description": "opencode - O agente de codificação de IA construído para o terminal.", + "share.not_found": "Não encontrado", + "share.link_to_message": "Link para esta mensagem", + "share.copied": "Copiado!", + "share.copy": "Copiar", + "share.show_more": "Mostrar mais", + "share.show_less": "Mostrar menos", + "share.show_results": "Mostrar resultados", + "share.hide_results": "Ocultar resultados", + "share.show_details": "Mostrar detalhes", + "share.hide_details": "Ocultar detalhes", + "share.show_preview": "Mostrar pré-visualização", + "share.hide_preview": "Ocultar pré-visualização", + "share.show_contents": "Mostrar conteúdos", + "share.hide_contents": "Ocultar conteúdos", + "share.show_output": "Mostrar saída", + "share.hide_output": "Ocultar saída", + "share.error": "Erro", + "share.waiting_for_messages": "Aguardando mensagens...", + "share.status_connected_waiting": "Conectado, aguardando mensagens...", + "share.status_connecting": "Conectando...", + "share.status_disconnected": "Desconectado", + "share.status_reconnecting": "Reconectando...", + "share.status_error": "Erro", + "share.status_unknown": "Desconhecido", + "share.error_id_not_found": "id não encontrado", + "share.error_api_url_not_found": "API URL não encontrada", + "share.error_connection_failed": "Falha na conexão", + "share.opencode_version": "versão do opencode", + "share.opencode_name": "opencode", + "share.models": "Modelos", + "share.cost": "Custo", + "share.input_tokens": "Tokens de Entrada", + "share.output_tokens": "Tokens de Saída", + "share.reasoning_tokens": "Tokens de Raciocínio", + "share.scroll_to_bottom": "Rolar para baixo", + "share.attachment": "Anexo", + "share.thinking": "Pensando", + "share.thinking_pending": "Pensando...", + "share.creating_plan": "Criando plano", + "share.completing_plan": "Concluindo plano", + "share.updating_plan": "Atualizando plano", + "share.match_one": "correspondência", + "share.match_other": "correspondências", + "share.result_one": "resultado", + "share.result_other": "resultados", + "share.debug_key": "Chave" +} diff --git a/packages/web/src/content/i18n/ru.json b/packages/web/src/content/i18n/ru.json new file mode 100644 index 00000000000..945bc7b0bd0 --- /dev/null +++ b/packages/web/src/content/i18n/ru.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "AI-агент для программирования, созданный для терминала", + "app.header.home": "Главная", + "app.header.docs": "Документация", + "app.footer.issueLink": "Нашли ошибку? Откройте issue", + "app.footer.discordLink": "Присоединяйтесь к нашему сообществу в Discord", + "app.lander.hero.title": "AI-агент для программирования, созданный для терминала.", + "app.lander.cta.getStarted": "Начать", + "app.lander.features.native_tui.title": "Нативный TUI", + "app.lander.features.native_tui.description": "Отзывчивый нативный интерфейс терминала с поддержкой тем.", + "app.lander.features.lsp_enabled.title": "Поддержка LSP", + "app.lander.features.lsp_enabled.description": "Автоматически загружает подходящие LSP для LLM.", + "app.lander.features.multi_session.title": "Несколько сессий", + "app.lander.features.multi_session.description": "Запускайте несколько агентов параллельно в одном проекте.", + "app.lander.features.shareable_links.title": "Ссылки для общего доступа", + "app.lander.features.shareable_links.description": "Поделитесь ссылкой на любую сессию для справки или отладки.", + "app.lander.features.github_copilot.description": "Войдите через GitHub, чтобы использовать аккаунт Copilot.", + "app.lander.features.chatgpt_plus_pro.description": "Войдите через OpenAI, чтобы использовать аккаунт ChatGPT Plus или Pro.", + "app.lander.features.use_any_model.title": "Используйте любую модель", + "app.lander.features.use_any_model.prefix": "Поддерживает 75+ провайдеров LLM через", + "app.lander.features.use_any_model.suffix": "включая локальные модели.", + "app.lander.images.tui.caption": "opencode TUI с темой tokyonight", + "app.lander.images.tui.alt": "opencode TUI с темой tokyonight", + "app.lander.images.vscode.caption": "opencode в VS Code", + "app.lander.images.vscode.alt": "opencode в VS Code", + "app.lander.images.github.caption": "opencode в GitHub", + "app.lander.images.github.alt": "opencode в GitHub", + "share.meta_description": "opencode - AI-агент для программирования, созданный для терминала.", + "share.not_found": "Не найдено", + "share.link_to_message": "Ссылка на это сообщение", + "share.copied": "Скопировано!", + "share.copy": "Копировать", + "share.show_more": "Показать больше", + "share.show_less": "Показать меньше", + "share.show_results": "Показать результаты", + "share.hide_results": "Скрыть результаты", + "share.show_details": "Показать детали", + "share.hide_details": "Скрыть детали", + "share.show_preview": "Показать предпросмотр", + "share.hide_preview": "Скрыть предпросмотр", + "share.show_contents": "Показать содержимое", + "share.hide_contents": "Скрыть содержимое", + "share.show_output": "Показать вывод", + "share.hide_output": "Скрыть вывод", + "share.error": "Ошибка", + "share.waiting_for_messages": "Ожидание сообщений...", + "share.status_connected_waiting": "Подключено, ожидание сообщений...", + "share.status_connecting": "Подключение...", + "share.status_disconnected": "Отключено", + "share.status_reconnecting": "Повторное подключение...", + "share.status_error": "Ошибка", + "share.status_unknown": "Неизвестно", + "share.error_id_not_found": "id не найден", + "share.error_api_url_not_found": "API URL не найден", + "share.error_connection_failed": "Не удалось подключиться", + "share.opencode_version": "версия opencode", + "share.opencode_name": "opencode", + "share.models": "Модели", + "share.cost": "Стоимость", + "share.input_tokens": "Входные токены", + "share.output_tokens": "Выходные токены", + "share.reasoning_tokens": "Токены рассуждения", + "share.scroll_to_bottom": "Прокрутить вниз", + "share.attachment": "Вложение", + "share.thinking": "Размышление", + "share.thinking_pending": "Размышление...", + "share.creating_plan": "Создание плана", + "share.completing_plan": "Завершение плана", + "share.updating_plan": "Обновление плана", + "share.match_one": "совпадение", + "share.match_other": "совпадений", + "share.result_one": "результат", + "share.result_other": "результатов", + "share.debug_key": "Ключ" +} diff --git a/packages/web/src/content/i18n/th.json b/packages/web/src/content/i18n/th.json new file mode 100644 index 00000000000..11eb7145cfb --- /dev/null +++ b/packages/web/src/content/i18n/th.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "เอเจนต์เขียนโค้ด AI ที่สร้างมาเพื่อ terminal", + "app.header.home": "หน้าหลัก", + "app.header.docs": "เอกสาร", + "app.footer.issueLink": "พบข้อผิดพลาดหรือไม่? เปิด issue", + "app.footer.discordLink": "เข้าร่วมชุมชน Discord ของเรา", + "app.lander.hero.title": "เอเจนต์เขียนโค้ด AI ที่สร้างมาเพื่อ terminal", + "app.lander.cta.getStarted": "เริ่มต้นใช้งาน", + "app.lander.features.native_tui.title": "TUI แบบเนทีฟ", + "app.lander.features.native_tui.description": "อินเทอร์เฟซ terminal แบบเนทีฟที่ตอบสนองไวและปรับธีมได้", + "app.lander.features.lsp_enabled.title": "รองรับ LSP", + "app.lander.features.lsp_enabled.description": "โหลด LSP ที่เหมาะสมสำหรับ LLM โดยอัตโนมัติ", + "app.lander.features.multi_session.title": "หลายเซสชัน", + "app.lander.features.multi_session.description": "เริ่มเอเจนต์หลายตัวพร้อมกันบนโปรเจ็กต์เดียวกัน", + "app.lander.features.shareable_links.title": "ลิงก์ที่แชร์ได้", + "app.lander.features.shareable_links.description": "แชร์ลิงก์ไปยังเซสชันใดก็ได้เพื่ออ้างอิงหรือดีบัก", + "app.lander.features.github_copilot.description": "เข้าสู่ระบบด้วย GitHub เพื่อใช้บัญชี Copilot ของคุณ", + "app.lander.features.chatgpt_plus_pro.description": "เข้าสู่ระบบด้วย OpenAI เพื่อใช้บัญชี ChatGPT Plus หรือ Pro ของคุณ", + "app.lander.features.use_any_model.title": "ใช้ได้ทุกโมเดล", + "app.lander.features.use_any_model.prefix": "รองรับผู้ให้บริการ LLM มากกว่า 75 รายผ่าน", + "app.lander.features.use_any_model.suffix": "รวมถึงโมเดลภายในเครื่อง", + "app.lander.images.tui.caption": "opencode TUI พร้อมธีม tokyonight", + "app.lander.images.tui.alt": "opencode TUI พร้อมธีม tokyonight", + "app.lander.images.vscode.caption": "opencode ใน VS Code", + "app.lander.images.vscode.alt": "opencode ใน VS Code", + "app.lander.images.github.caption": "opencode ใน GitHub", + "app.lander.images.github.alt": "opencode ใน GitHub", + "share.meta_description": "opencode - เอเจนต์เขียนโค้ด AI ที่สร้างมาเพื่อ terminal", + "share.not_found": "ไม่พบ", + "share.link_to_message": "ลิงก์ไปยังข้อความนี้", + "share.copied": "คัดลอกแล้ว!", + "share.copy": "คัดลอก", + "share.show_more": "แสดงเพิ่มเติม", + "share.show_less": "แสดงน้อยลง", + "share.show_results": "แสดงผลลัพธ์", + "share.hide_results": "ซ่อนผลลัพธ์", + "share.show_details": "แสดงรายละเอียด", + "share.hide_details": "ซ่อนรายละเอียด", + "share.show_preview": "แสดงตัวอย่าง", + "share.hide_preview": "ซ่อนตัวอย่าง", + "share.show_contents": "แสดงเนื้อหา", + "share.hide_contents": "ซ่อนเนื้อหา", + "share.show_output": "แสดงเอาต์พุต", + "share.hide_output": "ซ่อนเอาต์พุต", + "share.error": "ข้อผิดพลาด", + "share.waiting_for_messages": "กำลังรอข้อความ...", + "share.status_connected_waiting": "เชื่อมต่อแล้ว กำลังรอข้อความ...", + "share.status_connecting": "กำลังเชื่อมต่อ...", + "share.status_disconnected": "ตัดการเชื่อมต่อแล้ว", + "share.status_reconnecting": "กำลังเชื่อมต่อใหม่...", + "share.status_error": "ข้อผิดพลาด", + "share.status_unknown": "ไม่ทราบสถานะ", + "share.error_id_not_found": "ไม่พบ id", + "share.error_api_url_not_found": "ไม่พบ API URL", + "share.error_connection_failed": "การเชื่อมต่อล้มเหลว", + "share.opencode_version": "เวอร์ชัน opencode", + "share.opencode_name": "opencode", + "share.models": "โมเดล", + "share.cost": "ค่าใช้จ่าย", + "share.input_tokens": "โทเค็นอินพุต", + "share.output_tokens": "โทเค็นเอาต์พุต", + "share.reasoning_tokens": "โทเค็นการให้เหตุผล", + "share.scroll_to_bottom": "เลื่อนไปด้านล่าง", + "share.attachment": "ไฟล์แนบ", + "share.thinking": "กำลังคิด", + "share.thinking_pending": "กำลังคิด...", + "share.creating_plan": "กำลังสร้างแผน", + "share.completing_plan": "กำลังทำแผนให้เสร็จ", + "share.updating_plan": "กำลังอัปเดตแผน", + "share.match_one": "รายการที่ตรงกัน", + "share.match_other": "รายการที่ตรงกัน", + "share.result_one": "ผลลัพธ์", + "share.result_other": "ผลลัพธ์", + "share.debug_key": "คีย์" +} diff --git a/packages/web/src/content/i18n/tr.json b/packages/web/src/content/i18n/tr.json new file mode 100644 index 00000000000..9f3e95aa79c --- /dev/null +++ b/packages/web/src/content/i18n/tr.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "Terminal için AI kodlama asistanı", + "app.header.home": "Ana sayfa", + "app.header.docs": "Dokümanlar", + "app.footer.issueLink": "Bir hata mı buldunuz? Issue açın", + "app.footer.discordLink": "Discord topluluğumuza katılın", + "app.lander.hero.title": "Terminal için üretilmiş AI kodlama ajanı.", + "app.lander.cta.getStarted": "Başlayın", + "app.lander.features.native_tui.title": "Yerel TUI", + "app.lander.features.native_tui.description": "Hızlı, yerel ve tema uyumlu terminal arayüzü.", + "app.lander.features.lsp_enabled.title": "LSP etkin", + "app.lander.features.lsp_enabled.description": "LLM için doğru LSP'leri otomatik yükler.", + "app.lander.features.multi_session.title": "Çoklu oturum", + "app.lander.features.multi_session.description": "Aynı projede birden fazla agent'ı paralel başlatın.", + "app.lander.features.shareable_links.title": "Paylaşılabilir bağlantılar", + "app.lander.features.shareable_links.description": "Referans veya hata ayıklama için oturum bağlantısı paylaşın.", + "app.lander.features.github_copilot.description": "Copilot hesabınızı kullanmak için GitHub ile giriş yapın.", + "app.lander.features.chatgpt_plus_pro.description": "ChatGPT Plus veya Pro hesabınızı kullanmak için OpenAI ile giriş yapın.", + "app.lander.features.use_any_model.title": "Herhangi bir modeli kullanın", + "app.lander.features.use_any_model.prefix": "75+ LLM sağlayıcısını destekler", + "app.lander.features.use_any_model.suffix": "yerel modeller dahil.", + "app.lander.images.tui.caption": "tokyonight temasıyla opencode TUI", + "app.lander.images.tui.alt": "tokyonight temasıyla opencode TUI", + "app.lander.images.vscode.caption": "VS Code içinde opencode", + "app.lander.images.vscode.alt": "VS Code içinde opencode", + "app.lander.images.github.caption": "GitHub'da opencode", + "app.lander.images.github.alt": "GitHub'da opencode", + "share.meta_description": "opencode - Terminal için üretilmiş AI kodlama aracı.", + "share.not_found": "Bulunamadı", + "share.link_to_message": "Bu mesaja bağlantı", + "share.copied": "Kopyalandı!", + "share.copy": "Kopyala", + "share.show_more": "Daha fazla göster", + "share.show_less": "Daha az göster", + "share.show_results": "Sonuçları göster", + "share.hide_results": "Sonuçları gizle", + "share.show_details": "Ayrıntıları göster", + "share.hide_details": "Ayrıntıları gizle", + "share.show_preview": "Önizlemeyi göster", + "share.hide_preview": "Önizlemeyi gizle", + "share.show_contents": "İçeriği göster", + "share.hide_contents": "İçeriği gizle", + "share.show_output": "Çıktıyı göster", + "share.hide_output": "Çıktıyı gizle", + "share.error": "Hata", + "share.waiting_for_messages": "Mesajlar bekleniyor...", + "share.status_connected_waiting": "Bağlandı, mesajlar bekleniyor...", + "share.status_connecting": "Bağlanıyor...", + "share.status_disconnected": "Bağlantı kesildi", + "share.status_reconnecting": "Yeniden bağlanıyor...", + "share.status_error": "Hata", + "share.status_unknown": "Bilinmiyor", + "share.error_id_not_found": "id bulunamadı", + "share.error_api_url_not_found": "API URL bulunamadı", + "share.error_connection_failed": "Bağlantı başarısız", + "share.opencode_version": "opencode sürümü", + "share.opencode_name": "opencode", + "share.models": "Modeller", + "share.cost": "Maliyet", + "share.input_tokens": "Girdi Token'ları", + "share.output_tokens": "Çıktı Token'ları", + "share.reasoning_tokens": "Akıl Yürütme Token'ları", + "share.scroll_to_bottom": "En alta kaydır", + "share.attachment": "Ek", + "share.thinking": "Düşünüyor", + "share.thinking_pending": "Düşünüyor...", + "share.creating_plan": "Plan oluşturuluyor", + "share.completing_plan": "Plan tamamlanıyor", + "share.updating_plan": "Plan güncelleniyor", + "share.match_one": "eşleşme", + "share.match_other": "eşleşme", + "share.result_one": "sonuç", + "share.result_other": "sonuç", + "share.debug_key": "Anahtar" +} diff --git a/packages/web/src/content/i18n/zh-CN.json b/packages/web/src/content/i18n/zh-CN.json new file mode 100644 index 00000000000..e1c9f0c9eab --- /dev/null +++ b/packages/web/src/content/i18n/zh-CN.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "为终端打造的 AI 编码代理", + "app.header.home": "首页", + "app.header.docs": "文档", + "app.footer.issueLink": "发现问题?提交 issue", + "app.footer.discordLink": "加入我们的 Discord 社区", + "app.lander.hero.title": "为终端打造的 AI 编码代理。", + "app.lander.cta.getStarted": "开始使用", + "app.lander.features.native_tui.title": "原生 TUI", + "app.lander.features.native_tui.description": "响应迅速、原生且可主题化的 terminal UI。", + "app.lander.features.lsp_enabled.title": "LSP 已启用", + "app.lander.features.lsp_enabled.description": "自动为 LLM 加载合适的 LSP。", + "app.lander.features.multi_session.title": "多会话", + "app.lander.features.multi_session.description": "在同一项目中并行启动多个代理。", + "app.lander.features.shareable_links.title": "可分享链接", + "app.lander.features.shareable_links.description": "分享任意会话链接用于参考或调试。", + "app.lander.features.github_copilot.description": "使用 GitHub 登录并使用你的 Copilot 账号。", + "app.lander.features.chatgpt_plus_pro.description": "使用 OpenAI 登录并使用你的 ChatGPT Plus 或 Pro 账号。", + "app.lander.features.use_any_model.title": "使用任意模型", + "app.lander.features.use_any_model.prefix": "通过以下方式支持 75+ LLM 提供商", + "app.lander.features.use_any_model.suffix": "包括本地模型。", + "app.lander.images.tui.caption": "opencode TUI(tokyonight 主题)", + "app.lander.images.tui.alt": "opencode TUI(tokyonight 主题)", + "app.lander.images.vscode.caption": "VS Code 中的 opencode", + "app.lander.images.vscode.alt": "VS Code 中的 opencode", + "app.lander.images.github.caption": "GitHub 中的 opencode", + "app.lander.images.github.alt": "GitHub 中的 opencode", + "share.meta_description": "opencode - 为终端打造的 AI 编码代理。", + "share.not_found": "未找到", + "share.link_to_message": "链接到此消息", + "share.copied": "已复制!", + "share.copy": "复制", + "share.show_more": "显示更多", + "share.show_less": "显示更少", + "share.show_results": "显示结果", + "share.hide_results": "隐藏结果", + "share.show_details": "显示详情", + "share.hide_details": "隐藏详情", + "share.show_preview": "显示预览", + "share.hide_preview": "隐藏预览", + "share.show_contents": "显示内容", + "share.hide_contents": "隐藏内容", + "share.show_output": "显示输出", + "share.hide_output": "隐藏输出", + "share.error": "错误", + "share.waiting_for_messages": "正在等待消息...", + "share.status_connected_waiting": "已连接,正在等待消息...", + "share.status_connecting": "正在连接...", + "share.status_disconnected": "已断开连接", + "share.status_reconnecting": "正在重新连接...", + "share.status_error": "错误", + "share.status_unknown": "未知", + "share.error_id_not_found": "未找到 id", + "share.error_api_url_not_found": "未找到 API URL", + "share.error_connection_failed": "连接失败", + "share.opencode_version": "opencode 版本", + "share.opencode_name": "opencode", + "share.models": "模型", + "share.cost": "成本", + "share.input_tokens": "输入 Tokens", + "share.output_tokens": "输出 Tokens", + "share.reasoning_tokens": "推理 Tokens", + "share.scroll_to_bottom": "滚动到底部", + "share.attachment": "附件", + "share.thinking": "思考", + "share.thinking_pending": "思考中...", + "share.creating_plan": "正在创建计划", + "share.completing_plan": "正在完成计划", + "share.updating_plan": "正在更新计划", + "share.match_one": "匹配", + "share.match_other": "匹配项", + "share.result_one": "结果", + "share.result_other": "结果", + "share.debug_key": "键" +} diff --git a/packages/web/src/content/i18n/zh-TW.json b/packages/web/src/content/i18n/zh-TW.json new file mode 100644 index 00000000000..82cc25771ed --- /dev/null +++ b/packages/web/src/content/i18n/zh-TW.json @@ -0,0 +1,75 @@ +{ + "app.head.titleSuffix": "為終端機打造的 AI 程式碼代理", + "app.header.home": "首頁", + "app.header.docs": "文件", + "app.footer.issueLink": "發現問題?提交 Issue", + "app.footer.discordLink": "加入我們的 Discord 社群", + "app.lander.hero.title": "為終端機打造的 AI 程式碼代理。", + "app.lander.cta.getStarted": "開始使用", + "app.lander.features.native_tui.title": "原生 TUI", + "app.lander.features.native_tui.description": "反應靈敏、原生、可自訂主題的終端機 UI。", + "app.lander.features.lsp_enabled.title": "LSP 已啟用", + "app.lander.features.lsp_enabled.description": "自動為 LLM 載入正確的 LSP。", + "app.lander.features.multi_session.title": "多重工作階段", + "app.lander.features.multi_session.description": "在同一專案上並行啟動多個代理。", + "app.lander.features.shareable_links.title": "可分享的連結", + "app.lander.features.shareable_links.description": "分享任何工作階段的連結以供參考或除錯。", + "app.lander.features.github_copilot.description": "使用 GitHub 登入以使用您的 Copilot 帳戶。", + "app.lander.features.chatgpt_plus_pro.description": "使用 OpenAI 登入以使用您的 ChatGPT Plus 或 Pro 帳戶。", + "app.lander.features.use_any_model.title": "使用任何模型", + "app.lander.features.use_any_model.prefix": "透過以下方式支援 75+ LLM 供應商", + "app.lander.features.use_any_model.suffix": "包括本地模型。", + "app.lander.images.tui.caption": "OpenCode TUI (Tokyo Night 主題)", + "app.lander.images.tui.alt": "OpenCode TUI (Tokyo Night 主題)", + "app.lander.images.vscode.caption": "OpenCode 在 VS Code 中", + "app.lander.images.vscode.alt": "OpenCode 在 VS Code 中", + "app.lander.images.github.caption": "OpenCode 在 GitHub 中", + "app.lander.images.github.alt": "OpenCode 在 GitHub 中", + "share.meta_description": "OpenCode - 為終端機打造的 AI 程式碼代理。", + "share.not_found": "找不到", + "share.link_to_message": "連結到此訊息", + "share.copied": "已複製!", + "share.copy": "複製", + "share.show_more": "顯示更多", + "share.show_less": "顯示較少", + "share.show_results": "顯示結果", + "share.hide_results": "隱藏結果", + "share.show_details": "顯示詳情", + "share.hide_details": "隱藏詳細資訊", + "share.show_preview": "顯示預覽", + "share.hide_preview": "隱藏預覽", + "share.show_contents": "顯示內容", + "share.hide_contents": "隱藏內容", + "share.show_output": "顯示輸出", + "share.hide_output": "隱藏輸出", + "share.error": "錯誤", + "share.waiting_for_messages": "等待訊息...", + "share.status_connected_waiting": "已連線,等待訊息...", + "share.status_connecting": "正在連線...", + "share.status_disconnected": "已斷開連線", + "share.status_reconnecting": "正在重新連線...", + "share.status_error": "錯誤", + "share.status_unknown": "未知", + "share.error_id_not_found": "找不到 ID", + "share.error_api_url_not_found": "找不到 API URL", + "share.error_connection_failed": "連線失敗", + "share.opencode_version": "OpenCode 版本", + "share.opencode_name": "opencode", + "share.models": "模型", + "share.cost": "成本", + "share.input_tokens": "輸入 Tokens", + "share.output_tokens": "輸出 Tokens", + "share.reasoning_tokens": "推理 Tokens", + "share.scroll_to_bottom": "捲動到底部", + "share.attachment": "附件", + "share.thinking": "思考中", + "share.thinking_pending": "思考中...", + "share.creating_plan": "建立計畫", + "share.completing_plan": "完成計畫", + "share.updating_plan": "更新計畫", + "share.match_one": "符合項目", + "share.match_other": "符合項目", + "share.result_one": "結果", + "share.result_other": "結果", + "share.debug_key": "金鑰" +} diff --git a/packages/web/src/i18n/locales.ts b/packages/web/src/i18n/locales.ts new file mode 100644 index 00000000000..67e36dfe148 --- /dev/null +++ b/packages/web/src/i18n/locales.ts @@ -0,0 +1,114 @@ +export const docsLocale = [ + "ar", + "bs", + "da", + "de", + "es", + "fr", + "it", + "ja", + "ko", + "nb", + "pl", + "pt-br", + "ru", + "th", + "tr", + "zh-cn", + "zh-tw", +] as const + +export type DocsLocale = (typeof docsLocale)[number] + +export const locale = ["root", ...docsLocale] as const + +export type Locale = (typeof locale)[number] + +export const localeAlias = { + ar: "ar", + br: "pt-br", + bs: "bs", + da: "da", + de: "de", + en: "root", + es: "es", + fr: "fr", + it: "it", + ja: "ja", + ko: "ko", + nb: "nb", + nn: "nb", + no: "nb", + pl: "pl", + pt: "pt-br", + "pt-br": "pt-br", + root: "root", + ru: "ru", + th: "th", + tr: "tr", + zh: "zh-cn", + "zh-cn": "zh-cn", + zht: "zh-tw", + "zh-tw": "zh-tw", +} as const satisfies Record + +const starts = [ + ["ko", "ko"], + ["bs", "bs"], + ["de", "de"], + ["es", "es"], + ["fr", "fr"], + ["it", "it"], + ["da", "da"], + ["ja", "ja"], + ["pl", "pl"], + ["ru", "ru"], + ["ar", "ar"], + ["th", "th"], + ["tr", "tr"], + ["en", "root"], +] as const + +function parse(input: string) { + let decoded = "" + try { + decoded = decodeURIComponent(input) + } catch { + return null + } + + const value = decoded.trim().toLowerCase() + if (!value) return null + return value +} + +export function exactLocale(input: string) { + const value = parse(input) + if (!value) return null + if (value in localeAlias) { + return localeAlias[value as keyof typeof localeAlias] + } + + return null +} + +export function matchLocale(input: string) { + const value = parse(input) + if (!value) return null + + if (value.startsWith("zh")) { + if (value.includes("hant") || value.includes("-tw") || value.includes("-hk") || value.includes("-mo")) { + return "zh-tw" + } + return "zh-cn" + } + + if (value in localeAlias) { + return localeAlias[value as keyof typeof localeAlias] + } + + if (value.startsWith("pt")) return "pt-br" + if (value.startsWith("no") || value.startsWith("nb") || value.startsWith("nn")) return "nb" + + return starts.find((item) => value.startsWith(item[0]))?.[1] ?? null +} diff --git a/packages/web/src/middleware.ts b/packages/web/src/middleware.ts new file mode 100644 index 00000000000..97d085dfbf9 --- /dev/null +++ b/packages/web/src/middleware.ts @@ -0,0 +1,77 @@ +import { defineMiddleware } from "astro:middleware" +import { exactLocale, matchLocale } from "./i18n/locales" + +function docsAlias(pathname: string) { + const hit = /^\/docs\/([^/]+)(\/.*)?$/.exec(pathname) + if (!hit) return null + + const value = hit[1] ?? "" + const tail = hit[2] ?? "" + const locale = exactLocale(value) + if (!locale) return null + + const next = locale === "root" ? `/docs${tail}` : `/docs/${locale}${tail}` + if (next === pathname) return null + return next +} + +function localeFromCookie(header: string | null) { + if (!header) return null + const raw = header + .split(";") + .map((x) => x.trim()) + .find((x) => x.startsWith("oc_locale=")) + ?.slice("oc_locale=".length) + if (!raw) return null + return matchLocale(raw) +} + +function localeFromAcceptLanguage(header: string | null) { + if (!header) return "root" + + const items = header + .split(",") + .map((raw) => raw.trim()) + .filter(Boolean) + .map((raw) => { + const parts = raw.split(";").map((x) => x.trim()) + const lang = parts[0] ?? "" + const q = parts + .slice(1) + .find((x) => x.startsWith("q=")) + ?.slice(2) + return { + lang, + q: q ? Number.parseFloat(q) : 1, + } + }) + .sort((a, b) => b.q - a.q) + + const locale = items + .map((item) => item.lang) + .filter((lang) => lang && lang !== "*") + .map((lang) => matchLocale(lang)) + .find((lang) => lang) + + return locale ?? "root" +} + +export const onRequest = defineMiddleware((ctx, next) => { + const alias = docsAlias(ctx.url.pathname) + if (alias) { + const url = new URL(ctx.request.url) + url.pathname = alias + return ctx.redirect(url.toString(), 302) + } + + if (ctx.url.pathname !== "/docs" && ctx.url.pathname !== "/docs/") return next() + + const locale = + localeFromCookie(ctx.request.headers.get("cookie")) ?? + localeFromAcceptLanguage(ctx.request.headers.get("accept-language")) + if (!locale || locale === "root") return next() + + const url = new URL(ctx.request.url) + url.pathname = `/docs/${locale}/` + return ctx.redirect(url.toString(), 302) +}) diff --git a/packages/web/src/types/starlight-virtual.d.ts b/packages/web/src/types/starlight-virtual.d.ts new file mode 100644 index 00000000000..ba6bfb299db --- /dev/null +++ b/packages/web/src/types/starlight-virtual.d.ts @@ -0,0 +1,14 @@ +declare module "virtual:starlight/user-images" { + export const logos: { + dark?: { + src: string + width: number + height: number + } + light?: { + src: string + width: number + height: number + } + } +} diff --git a/patches/@standard-community%2Fstandard-openapi@0.2.9.patch b/patches/@standard-community%2Fstandard-openapi@0.2.9.patch new file mode 100644 index 00000000000..2ac5af09ab7 --- /dev/null +++ b/patches/@standard-community%2Fstandard-openapi@0.2.9.patch @@ -0,0 +1,16 @@ +diff --git a/dist/vendors/convert.js b/dist/vendors/convert.js +index 0d615eebfd7cd646937ec1b29f8332db73586ec1..7b146f903c07a9377d676753691cba67781879be 100644 +--- a/dist/vendors/convert.js ++++ b/dist/vendors/convert.js +@@ -74,7 +74,10 @@ function convertToOpenAPISchema(jsonSchema, context) { + $ref: `#/components/schemas/${id}` + }; + } else if (_jsonSchema.$ref) { +- const { $ref, $defs } = _jsonSchema; ++ const { $ref, $defs, ...rest } = _jsonSchema; ++ if ($ref.includes("://")) { ++ return Object.keys(rest).length > 0 ? rest : { type: "string" }; ++ } + const ref = $ref.split("/").pop(); + context.components.schemas = { + ...context.components.schemas, diff --git a/square-logos.patch b/square-logos.patch new file mode 100644 index 00000000000..3ff84535d36 --- /dev/null +++ b/square-logos.patch @@ -0,0 +1,234 @@ +From 90904222b6f8c86a6d0a8ebed9661950f632a4e8 Mon Sep 17 00:00:00 2001 +From: OpenCode Bot +Date: Wed, 11 Feb 2026 18:44:27 +0000 +Subject: [PATCH] add square logo variants to brand page + +--- + .../asset/brand/opencode-logo-dark-square.png | Bin 0 -> 697 bytes + .../asset/brand/opencode-logo-dark-square.svg | 18 ++++++ + .../brand/opencode-logo-light-square.png | Bin 0 -> 697 bytes + .../brand/opencode-logo-light-square.svg | 18 ++++++ + .../preview-opencode-logo-dark-square.png | Bin 0 -> 1477 bytes + .../preview-opencode-logo-light-square.png | Bin 0 -> 1467 bytes + .../console/app/src/routes/brand/index.tsx | 60 ++++++++++++++++++ + 7 files changed, 96 insertions(+) + create mode 100644 packages/console/app/src/asset/brand/opencode-logo-dark-square.png + create mode 100644 packages/console/app/src/asset/brand/opencode-logo-dark-square.svg + create mode 100644 packages/console/app/src/asset/brand/opencode-logo-light-square.png + create mode 100644 packages/console/app/src/asset/brand/opencode-logo-light-square.svg + create mode 100644 packages/console/app/src/asset/brand/preview-opencode-logo-dark-square.png + create mode 100644 packages/console/app/src/asset/brand/preview-opencode-logo-light-square.png + +diff --git a/packages/console/app/src/asset/brand/opencode-logo-dark-square.png b/packages/console/app/src/asset/brand/opencode-logo-dark-square.png +new file mode 100644 +index 0000000000000000000000000000000000000000..673c7e3a20f917fae56719ed1c35b4614ecd5f53 +GIT binary patch +literal 697 +zcmeAS@N?(olHy`uVBq!ia0y~yV2S`?CT5_>VU7ZSAjOjI=FjGH{Nb; +zK*kCWpQS*Gu_VYZn8D%MjWiG^$=lt9p@UV{1IXbl@Q5sCU=ULUVMfm&l@CBc_7YED +zSN2y-+(O#2cjOjy1NC%xx;TbZ+cptHiBA{`nI*paup{S3j3^ +HP6 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/packages/console/app/src/asset/brand/opencode-logo-light-square.png b/packages/console/app/src/asset/brand/opencode-logo-light-square.png +new file mode 100644 +index 0000000000000000000000000000000000000000..5c710474abc4668504cb9678da1de6ad33458af9 +GIT binary patch +literal 697 +zcmeAS@N?(olHy`uVBq!ia0y~yV2S`?CT5_>VU7ZSAjOjI=?NMQ +zuI#UvxP`Q3@5n9a2I}eXba4!+xb^m&Auof10LupBPR|gd%^Pa$ST1R0Y?7Y-#K)To +z;B|Kx*A}XPw8m+J2ZSxX>Q05w@qT^w8q-9EeYYip%rt<}q*~${QIe8al4_M)lnSI6 +zj0}v-bPbGj4GlvKEv!rot&EJc4GgRd4DxoxEJD$co1c=IR*74K{PQPrKn)C@u6{1- +HoD!M<*)j+` + +literal 0 +HcmV?d00001 + +diff --git a/packages/console/app/src/asset/brand/opencode-logo-light-square.svg b/packages/console/app/src/asset/brand/opencode-logo-light-square.svg +new file mode 100644 +index 0000000..a738ad8 +--- /dev/null ++++ b/packages/console/app/src/asset/brand/opencode-logo-light-square.svg +@@ -0,0 +1,18 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/packages/console/app/src/asset/brand/preview-opencode-logo-dark-square.png b/packages/console/app/src/asset/brand/preview-opencode-logo-dark-square.png +new file mode 100644 +index 0000000000000000000000000000000000000000..604ad7aa7a87c71d4a3972f18da4044e53f745fe +GIT binary patch +literal 1477 +zcmeAS@N?(olHy`uVBq!ia0y~yV4MKL9LzwG?TN?!0V$SrM_)$E)e-c@Ne1&9> +zAYTTCDm4a%h86~fUqGRT7Yq!g1`G_Z5*Qe)W-u^_7tGleXakf83GfMV1=1hiyun28 +zU%gs1cdnz2jklZIqq}#b!@|5=U4d+%%7=IEM1_VzxRD_to-Qsx1sTc7KrJ6$zXlo@ +zFuxY$Hi42LzhDLii5Gug>4^i8#NSshUI=lk@B-x+lf2zs7&=&GJ%Aj}0*}aI1_m)z +z5N7lYQuzQBWH0gbb!C6W#4V()m9m%>=ouDUPZ!6Kid%0la{4g^2(UVS^9^9Ux#z#* +zUM9{NA)j{pe@M$Rs$BIl=U=S8$$a1WzrRdo{gl+0z}h6r5vC9^6c`^Bx}VO;+bO}5 +zvNP)ZgKMjwCMdj@`|<2Y_0Pt}1ZL)gY-~-uJS@@@9A*XrISC3k4mfNWo)RazbGPm0 +z-*LChSmMOL4?kJISKi=fE3%ne|KQy6WQCxi5SK$J*`YY~T7$y$*OKq5Bzd2d?Vs~N +z@B8fph5p+U-+hzde)4_q^MCH|=dNhx2_G663hFce=0A)TEv>6k&v^?1%NErV*NBpo +z#FA92 +RH-Q=$JYD@<);T3K0RY|)#{mEU + +literal 0 +HcmV?d00001 + +diff --git a/packages/console/app/src/asset/brand/preview-opencode-logo-light-square.png b/packages/console/app/src/asset/brand/preview-opencode-logo-light-square.png +new file mode 100644 +index 0000000000000000000000000000000000000000..3964d8528440323730053e56f9d957539937b99d +GIT binary patch +literal 1467 +zcmeAS@N?(olHy`uVBq!ia0y~yV4MKL9LzwG?TN?!0V$SrM_)$E)e-c@Ne1&9> +zAYTTCDm4a%h86~fUqGRT7Yq!g1`G_Z5*Qe)W-u^_7tGleXakh+3-AeX1=5Oga+pX- +zUcR`n@W%CP=g*zh*VWm(dpD2)RHh&+YpAEUZ|@!;cmKY<7tWv4*U?$OZY@wf(5P=q +zw@e07{3Stt!3+!%FaEyL69*!Rzpq|wUamVGD8-oM?e4vL>4nJh^c}w +zqi2xH2cRH(iKnkC`zt1HA#JUc#jHSIuvmGzIEGZ*dV8@wmnlGi)v?HEMncg4sk@lD +zIaT_d_YAOLQ7v(eC`m~yNwrEY +zN(E93Mg~S^x&}tNhK3=A7FH(4Rz{ZE1_o9J1{oeVQc*PI=BH$)RpQnlDVlH-sDZ)L +L)z4*}Q$iB}B`L3| + +literal 0 +HcmV?d00001 + +diff --git a/packages/console/app/src/routes/brand/index.tsx b/packages/console/app/src/routes/brand/index.tsx +index eda3c84..9140462 100644 +--- a/packages/console/app/src/routes/brand/index.tsx ++++ b/packages/console/app/src/routes/brand/index.tsx +@@ -7,18 +7,24 @@ import { useI18n } from "~/context/i18n" + import { LocaleLinks } from "~/component/locale-links" + import previewLogoLight from "../../asset/brand/preview-opencode-logo-light.png" + import previewLogoDark from "../../asset/brand/preview-opencode-logo-dark.png" ++import previewLogoLightSquare from "../../asset/brand/preview-opencode-logo-light-square.png" ++import previewLogoDarkSquare from "../../asset/brand/preview-opencode-logo-dark-square.png" + import previewWordmarkLight from "../../asset/brand/preview-opencode-wordmark-light.png" + import previewWordmarkDark from "../../asset/brand/preview-opencode-wordmark-dark.png" + import previewWordmarkSimpleLight from "../../asset/brand/preview-opencode-wordmark-simple-light.png" + import previewWordmarkSimpleDark from "../../asset/brand/preview-opencode-wordmark-simple-dark.png" + import logoLightPng from "../../asset/brand/opencode-logo-light.png" + import logoDarkPng from "../../asset/brand/opencode-logo-dark.png" ++import logoLightSquarePng from "../../asset/brand/opencode-logo-light-square.png" ++import logoDarkSquarePng from "../../asset/brand/opencode-logo-dark-square.png" + import wordmarkLightPng from "../../asset/brand/opencode-wordmark-light.png" + import wordmarkDarkPng from "../../asset/brand/opencode-wordmark-dark.png" + import wordmarkSimpleLightPng from "../../asset/brand/opencode-wordmark-simple-light.png" + import wordmarkSimpleDarkPng from "../../asset/brand/opencode-wordmark-simple-dark.png" + import logoLightSvg from "../../asset/brand/opencode-logo-light.svg" + import logoDarkSvg from "../../asset/brand/opencode-logo-dark.svg" ++import logoLightSquareSvg from "../../asset/brand/opencode-logo-light-square.svg" ++import logoDarkSquareSvg from "../../asset/brand/opencode-logo-dark-square.svg" + import wordmarkLightSvg from "../../asset/brand/opencode-wordmark-light.svg" + import wordmarkDarkSvg from "../../asset/brand/opencode-wordmark-dark.svg" + import wordmarkSimpleLightSvg from "../../asset/brand/opencode-wordmark-simple-light.svg" +@@ -135,6 +141,60 @@ export default function Brand() { + +

+ ++
++ OpenCode brand guidelines ++
++ ++ ++
++
++
++ OpenCode brand guidelines ++
++ ++ ++
++
+
+ OpenCode brand guidelines +
+-- +2.39.5 +