Compare commits

..

1 Commits

Author SHA1 Message Date
Aiden Cline
5ecebc1013 fix: ensure anthropic models on OR also have variant support 2026-02-13 10:28:23 -06:00
93 changed files with 922 additions and 1409 deletions

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS و Linux (موصى به، دائما محدث)
brew install opencode # macOS و Linux (صيغة brew الرسمية، تحديث اقل)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # اي نظام
nix run nixpkgs#opencode # او github:anomalyco/opencode لاحدث فرع dev
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS e Linux (recomendado, sempre atualizado)
brew install opencode # macOS e Linux (fórmula oficial do brew, atualiza menos)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # qualquer sistema
nix run nixpkgs#opencode # ou github:anomalyco/opencode para a branch dev mais recente
```

View File

@@ -51,8 +51,7 @@ 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)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
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
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS og Linux (anbefalet, altid up to date)
brew install opencode # macOS og Linux (officiel brew formula, opdateres sjældnere)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # alle OS
nix run nixpkgs#opencode # eller github:anomalyco/opencode for nyeste dev-branch
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS und Linux (empfohlen, immer aktuell)
brew install opencode # macOS und Linux (offizielle Brew-Formula, seltener aktualisiert)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # jedes Betriebssystem
nix run nixpkgs#opencode # oder github:anomalyco/opencode für den neuesten dev-Branch
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS y Linux (recomendado, siempre al día)
brew install opencode # macOS y Linux (fórmula oficial de brew, se actualiza menos)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # cualquier sistema
nix run nixpkgs#opencode # o github:anomalyco/opencode para la rama dev más reciente
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS et Linux (recommandé, toujours à jour)
brew install opencode # macOS et Linux (formule officielle brew, mise à jour moins fréquente)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # n'importe quel OS
nix run nixpkgs#opencode # ou github:anomalyco/opencode pour la branche dev la plus récente
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS e Linux (consigliato, sempre aggiornato)
brew install opencode # macOS e Linux (formula brew ufficiale, aggiornata meno spesso)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # Qualsiasi OS
nix run nixpkgs#opencode # oppure github:anomalyco/opencode per lultima branch di sviluppo
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS と Linux推奨。常に最新
brew install opencode # macOS と Linux公式 brew formula。更新頻度は低め
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # どのOSでも
nix run nixpkgs#opencode # または github:anomalyco/opencode で最新 dev ブランチ
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS 및 Linux (권장, 항상 최신)
brew install opencode # macOS 및 Linux (공식 brew formula, 업데이트 빈도 낮음)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # 어떤 OS든
nix run nixpkgs#opencode # 또는 github:anomalyco/opencode 로 최신 dev 브랜치
```

View File

@@ -51,8 +51,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS and Linux (recommended, always up to date)
brew install opencode # macOS and Linux (official brew formula, updated less)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # Any OS
nix run nixpkgs#opencode # or github:anomalyco/opencode for latest dev branch
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS og Linux (anbefalt, alltid oppdatert)
brew install opencode # macOS og Linux (offisiell brew-formel, oppdateres sjeldnere)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # alle OS
nix run nixpkgs#opencode # eller github:anomalyco/opencode for nyeste dev-branch
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS i Linux (polecane, zawsze aktualne)
brew install opencode # macOS i Linux (oficjalna formuła brew, rzadziej aktualizowana)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # dowolny system
nix run nixpkgs#opencode # lub github:anomalyco/opencode dla najnowszej gałęzi dev
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS и Linux (рекомендуем, всегда актуально)
brew install opencode # macOS и Linux (официальная формула brew, обновляется реже)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # любая ОС
nix run nixpkgs#opencode # или github:anomalyco/opencode для самой свежей ветки dev
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS และ Linux (แนะนำ อัปเดตเสมอ)
brew install opencode # macOS และ Linux (brew formula อย่างเป็นทางการ อัปเดตน้อยกว่า)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # ระบบปฏิบัติการใดก็ได้
nix run nixpkgs#opencode # หรือ github:anomalyco/opencode สำหรับสาขาพัฒนาล่าสุด
```

View File

@@ -50,8 +50,7 @@ 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)
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
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
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS 和 Linux推荐始终保持最新
brew install opencode # macOS 和 Linux官方 brew formula更新频率较低
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # 任意系统
nix run nixpkgs#opencode # 或用 github:anomalyco/opencode 获取最新 dev 分支
```

View File

@@ -50,8 +50,7 @@ scoop install opencode # Windows
choco install opencode # Windows
brew install anomalyco/tap/opencode # macOS 與 Linux推薦始終保持最新
brew install opencode # macOS 與 Linux官方 brew formula更新頻率較低
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin # Arch Linux
mise use -g opencode # 任何作業系統
nix run nixpkgs#opencode # 或使用 github:anomalyco/opencode 以取得最新開發分支
```

View File

@@ -1,8 +1,8 @@
{
"nodeModules": {
"x86_64-linux": "sha256-FsFTitxnN2brebZDBRGJB0NWTOVYDa/QcNRH0ip/Gk4=",
"aarch64-linux": "sha256-knSEqEPyonBUfmGZKTq5Om4HikItWbfPdfT7p6iljzs=",
"aarch64-darwin": "sha256-uRgWfuOlLECRCOszm8XhySiWxu9IdDhpSbosPZPAZVI=",
"x86_64-darwin": "sha256-gHuA+Ud9L+XLvKm5Vp5jCXfZWOtunnmX/lB8vczHsG0="
"x86_64-linux": "sha256-XIf7b6yALzH1/MkGGrsmq2DeXIC9vgD9a7D/dxhi6iU=",
"aarch64-linux": "sha256-mKDCs6QhIelWc3E17zOufaSDTovtjO/Xyh3JtlWl01s=",
"aarch64-darwin": "sha256-wC7bbbIyZ62uMxTr9FElTbEBMrfz0S/ndqwZZ3V9EOA=",
"x86_64-darwin": "sha256-/7Nn65m5Zhvzz0TKsG9nWd2v5WDHQNi3UzCfuAR8SLo="
}
}

View File

@@ -1,43 +0,0 @@
import { test, expect } from "../fixtures"
import { promptSelector } from "../selectors"
import { sessionIDFromUrl } from "../actions"
// Regression test for Issue #12453: the synchronous POST /message endpoint holds
// the connection open while the agent works, causing "Failed to fetch" over
// VPN/Tailscale. The fix switches to POST /prompt_async which returns immediately.
test("prompt succeeds when sync message endpoint is unreachable", async ({ page, sdk, gotoSession }) => {
test.setTimeout(120_000)
// Simulate Tailscale/VPN killing the long-lived sync connection
await page.route("**/session/*/message", (route) => route.abort("connectionfailed"))
await gotoSession()
const token = `E2E_ASYNC_${Date.now()}`
await page.locator(promptSelector).click()
await page.keyboard.type(`Reply with exactly: ${token}`)
await page.keyboard.press("Enter")
await expect(page).toHaveURL(/\/session\/[^/?#]+/, { timeout: 30_000 })
const sessionID = sessionIDFromUrl(page.url())!
try {
// Agent response arrives via SSE despite sync endpoint being dead
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)
} finally {
await sdk.session.delete({ sessionID }).catch(() => undefined)
}
})

View File

@@ -1,5 +1,5 @@
import "@/index.css"
import { ErrorBoundary, Show, Suspense, lazy, type JSX, type ParentProps } from "solid-js"
import { ErrorBoundary, Suspense, lazy, type JSX, type ParentProps } from "solid-js"
import { Router, Route, Navigate } from "@solidjs/router"
import { MetaProvider } from "@solidjs/meta"
import { Font } from "@opencode-ai/ui/font"
@@ -156,11 +156,8 @@ export function AppBaseProviders(props: ParentProps) {
function ServerKey(props: ParentProps) {
const server = useServer()
return (
<Show when={server.url} keyed>
{props.children}
</Show>
)
if (!server.url) return null
return props.children
}
export function AppInterface(props: { defaultUrl?: string; children?: JSX.Element; isSidecar?: boolean }) {

View File

@@ -385,7 +385,7 @@ export function createPromptSubmit(input: PromptSubmitInput) {
const send = async () => {
const ok = await waitForWorktree()
if (!ok) return
await client.session.promptAsync({
await client.session.prompt({
sessionID: session.id,
agent,
model,

View File

@@ -552,7 +552,7 @@ export function SessionHeader() {
</Show>
</div>
</Show>
<div class="flex items-center gap-3 ml-2 shrink-0">
<div class="hidden lg:flex items-center gap-3 ml-2 shrink-0">
<TooltipKeybind
title={language.t("command.terminal.toggle")}
keybind={command.keybind("terminal.toggle")}

View File

@@ -156,10 +156,6 @@ export const Terminal = (props: TerminalProps) => {
let serializeAddon: SerializeAddon
let fitAddon: FitAddon
let handleResize: () => void
let fitFrame: number | undefined
let sizeTimer: ReturnType<typeof setTimeout> | undefined
let pendingSize: { cols: number; rows: number } | undefined
let lastSize: { cols: number; rows: number } | undefined
let disposed = false
const cleanups: VoidFunction[] = []
const start =
@@ -213,43 +209,6 @@ export const Terminal = (props: TerminalProps) => {
const [terminalColors, setTerminalColors] = createSignal<TerminalColors>(getTerminalColors())
const scheduleFit = () => {
if (disposed) return
if (!fitAddon) return
if (fitFrame !== undefined) return
fitFrame = requestAnimationFrame(() => {
fitFrame = undefined
if (disposed) return
fitAddon.fit()
})
}
const scheduleSize = (cols: number, rows: number) => {
if (disposed) return
if (lastSize?.cols === cols && lastSize?.rows === rows) return
pendingSize = { cols, rows }
if (!lastSize) {
lastSize = pendingSize
void pushSize(cols, rows)
return
}
if (sizeTimer !== undefined) return
sizeTimer = setTimeout(() => {
sizeTimer = undefined
const next = pendingSize
if (!next) return
pendingSize = undefined
if (disposed) return
if (lastSize?.cols === next.cols && lastSize?.rows === next.rows) return
lastSize = next
void pushSize(next.cols, next.rows)
}, 100)
}
createEffect(() => {
const colors = getTerminalColors()
setTerminalColors(colors)
@@ -261,16 +220,6 @@ export const Terminal = (props: TerminalProps) => {
const font = monoFontFamily(settings.appearance.font())
if (!term) return
setOptionIfSupported(term, "fontFamily", font)
scheduleFit()
})
let zoom = platform.webviewZoom?.()
createEffect(() => {
const next = platform.webviewZoom?.()
if (next === undefined) return
if (next === zoom) return
zoom = next
scheduleFit()
})
const focusTerminal = () => {
@@ -314,6 +263,25 @@ export const Terminal = (props: TerminalProps) => {
const once = { value: false }
const url = new URL(sdk.url + `/pty/${local.pty.id}/connect`)
url.searchParams.set("directory", sdk.directory)
url.searchParams.set("cursor", String(start !== undefined ? start : local.pty.buffer ? -1 : 0))
url.protocol = url.protocol === "https:" ? "wss:" : "ws:"
if (window.__OPENCODE__?.serverPassword) {
url.username = "opencode"
url.password = window.__OPENCODE__?.serverPassword
}
const socket = new WebSocket(url)
socket.binaryType = "arraybuffer"
cleanups.push(() => {
if (socket.readyState !== WebSocket.CLOSED && socket.readyState !== WebSocket.CLOSING) socket.close()
})
if (disposed) {
cleanup()
return
}
ws = socket
const restore = typeof local.pty.buffer === "string" ? local.pty.buffer : ""
const restoreSize =
restore &&
@@ -376,28 +344,9 @@ export const Terminal = (props: TerminalProps) => {
focusTerminal()
if (typeof document !== "undefined" && document.fonts) {
document.fonts.ready.then(scheduleFit)
}
const onResize = t.onResize((size) => {
scheduleSize(size.cols, size.rows)
})
cleanups.push(() => disposeIfDisposable(onResize))
const onData = t.onData((data) => {
if (ws?.readyState === WebSocket.OPEN) ws.send(data)
})
cleanups.push(() => disposeIfDisposable(onData))
const onKey = t.onKey((key) => {
if (key.key == "Enter") {
props.onSubmit?.()
}
})
cleanups.push(() => disposeIfDisposable(onKey))
const startResize = () => {
fit.observeResize()
handleResize = scheduleFit
handleResize = () => fit.fit()
window.addEventListener("resize", handleResize)
cleanups.push(() => window.removeEventListener("resize", handleResize))
}
@@ -405,13 +354,11 @@ export const Terminal = (props: TerminalProps) => {
if (restore && restoreSize) {
t.write(restore, () => {
fit.fit()
scheduleSize(t.cols, t.rows)
if (typeof local.pty.scrollY === "number") t.scrollToLine(local.pty.scrollY)
startResize()
})
} else {
fit.fit()
scheduleSize(t.cols, t.rows)
if (restore) {
t.write(restore, () => {
if (typeof local.pty.scrollY === "number") t.scrollToLine(local.pty.scrollY)
@@ -420,38 +367,35 @@ export const Terminal = (props: TerminalProps) => {
startResize()
}
const onResize = t.onResize(async (size) => {
if (socket.readyState === WebSocket.OPEN) {
await pushSize(size.cols, size.rows)
}
})
cleanups.push(() => disposeIfDisposable(onResize))
const onData = t.onData((data) => {
if (socket.readyState === WebSocket.OPEN) {
socket.send(data)
}
})
cleanups.push(() => disposeIfDisposable(onData))
const onKey = t.onKey((key) => {
if (key.key == "Enter") {
props.onSubmit?.()
}
})
cleanups.push(() => disposeIfDisposable(onKey))
// t.onScroll((ydisp) => {
// console.log("Scroll position:", ydisp)
// })
const url = new URL(sdk.url + `/pty/${local.pty.id}/connect`)
url.searchParams.set("directory", sdk.directory)
url.searchParams.set("cursor", String(start !== undefined ? start : local.pty.buffer ? -1 : 0))
url.protocol = url.protocol === "https:" ? "wss:" : "ws:"
if (window.__OPENCODE__?.serverPassword) {
url.username = "opencode"
url.password = window.__OPENCODE__?.serverPassword
}
const socket = new WebSocket(url)
socket.binaryType = "arraybuffer"
ws = socket
cleanups.push(() => {
if (socket.readyState !== WebSocket.CLOSED && socket.readyState !== WebSocket.CLOSING) socket.close()
})
if (disposed) {
cleanup()
return
}
const handleOpen = () => {
local.onConnect?.()
scheduleSize(t.cols, t.rows)
void pushSize(t.cols, t.rows)
}
socket.addEventListener("open", handleOpen)
cleanups.push(() => socket.removeEventListener("open", handleOpen))
if (socket.readyState === WebSocket.OPEN) handleOpen()
const decoder = new TextDecoder()
const handleMessage = (event: MessageEvent) => {
@@ -518,8 +462,6 @@ export const Terminal = (props: TerminalProps) => {
onCleanup(() => {
disposed = true
if (fitFrame !== undefined) cancelAnimationFrame(fitFrame)
if (sizeTimer !== undefined) clearTimeout(sizeTimer)
output?.flush()
persistTerminal({ term, addon: serializeAddon, cursor, pty: local.pty, onCleanup: props.onCleanup })
cleanup()
@@ -535,7 +477,7 @@ export const Terminal = (props: TerminalProps) => {
classList={{
...(local.classList ?? {}),
"select-text": true,
"size-full px-6 py-3 font-mono relative overflow-hidden": true,
"size-full px-6 py-3 font-mono": true,
[local.class ?? ""]: !!local.class,
}}
{...others}

View File

@@ -57,10 +57,6 @@ export type Locale =
type RawDictionary = typeof en & typeof uiEn
type Dictionary = i18n.Flatten<RawDictionary>
function cookie(locale: Locale) {
return `oc_locale=${encodeURIComponent(locale)}; Path=/; Max-Age=31536000; SameSite=Lax`
}
const LOCALES: readonly Locale[] = [
"en",
"zh",
@@ -203,7 +199,6 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont
createEffect(() => {
if (typeof document !== "object") return
document.documentElement.lang = locale()
document.cookie = cookie(locale())
})
return {

View File

@@ -1758,7 +1758,7 @@ export default function Page() {
</div>
<TerminalPanel
open={view().terminal.opened()}
open={isDesktop() && view().terminal.opened()}
height={layout.terminal.height()}
resize={layout.terminal.resize}
close={view().terminal.close}

View File

@@ -1,7 +1,7 @@
import { type ValidComponent, createEffect, createMemo, For, Match, on, onCleanup, Show, Switch } from "solid-js"
import { createStore, produce } from "solid-js/store"
import { Dynamic } from "solid-js/web"
import { sampledChecksum } from "@opencode-ai/util/encode"
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"
@@ -49,7 +49,7 @@ export function FileTabContent(props: {
return props.file.get(p)
})
const contents = createMemo(() => state()?.content?.content ?? "")
const cacheKey = createMemo(() => sampledChecksum(contents()))
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"
@@ -163,20 +163,11 @@ export function FileTabContent(props: {
return
}
const estimateTop = (range: SelectedLineRange) => {
const line = Math.max(range.start, range.end)
const height = 24
const offset = 2
return Math.max(0, (line - 1) * height + offset)
}
const large = contents().length > 500_000
const next: Record<string, number> = {}
for (const comment of fileComments()) {
const marker = findMarker(root, comment.selection)
if (marker) next[comment.id] = markerTop(el, marker)
else if (large) next[comment.id] = estimateTop(comment.selection)
if (!marker) continue
next[comment.id] = markerTop(el, marker)
}
const removed = Object.keys(note.positions).filter((id) => next[id] === undefined)
@@ -203,12 +194,12 @@ export function FileTabContent(props: {
}
const marker = findMarker(root, range)
if (marker) {
setNote("draftTop", markerTop(el, marker))
if (!marker) {
setNote("draftTop", undefined)
return
}
setNote("draftTop", large ? estimateTop(range) : undefined)
setNote("draftTop", markerTop(el, marker))
}
const scheduleComments = () => {

View File

@@ -2,6 +2,4 @@ preload = ["@opentui/solid/preload"]
[test]
preload = ["./test/preload.ts"]
# timeout is not actually parsed from bunfig.toml (see src/bunfig.zig in oven-sh/bun)
# using --timeout in package.json scripts instead
# https://github.com/oven-sh/bun/issues/7789
timeout = 30000 # 30 seconds - allow time for package installation

View File

@@ -7,7 +7,7 @@
"private": true,
"scripts": {
"typecheck": "tsgo --noEmit",
"test": "bun test --timeout 30000",
"test": "bun test",
"build": "bun run script/build.ts",
"dev": "bun run --conditions=browser ./src/index.ts",
"random": "echo 'Random script updated at $(date)' && echo 'Change queued successfully' && echo 'Another change made' && echo 'Yet another change' && echo 'One more change' && echo 'Final change' && echo 'Another final change' && echo 'Yet another final change'",

View File

@@ -360,7 +360,7 @@ export namespace ProviderTransform {
switch (model.api.npm) {
case "@openrouter/ai-sdk-provider":
if (!model.id.includes("gpt") && !model.id.includes("gemini-3")) return {}
if (!model.id.includes("gpt") && !model.id.includes("gemini-3") && !model.id.includes("claude")) return {}
return Object.fromEntries(OPENAI_EFFORTS.map((effort) => [effort, { reasoning: { effort } }]))
// TODO: YOU CANNOT SET max_tokens if this is set!!!
@@ -720,6 +720,10 @@ export namespace ProviderTransform {
result["promptCacheKey"] = input.sessionID
}
if (input.model.providerID === "openrouter") {
result["prompt_cache_key"] = input.sessionID
}
return result
}

View File

@@ -1,27 +1,10 @@
import {
DEFAULT_VIRTUAL_FILE_METRICS,
type FileContents,
File,
FileOptions,
LineAnnotation,
type SelectedLineRange,
type VirtualFileMetrics,
VirtualizedFile,
Virtualizer,
} from "@pierre/diffs"
import { type FileContents, File, FileOptions, LineAnnotation, type SelectedLineRange } from "@pierre/diffs"
import { ComponentProps, createEffect, createMemo, createSignal, onCleanup, onMount, Show, splitProps } from "solid-js"
import { Portal } from "solid-js/web"
import { createDefaultOptions, styleVariables } from "../pierre"
import { getWorkerPool } from "../pierre/worker"
import { Icon } from "./icon"
const VIRTUALIZE_BYTES = 500_000
const codeMetrics = {
...DEFAULT_VIRTUAL_FILE_METRICS,
lineHeight: 24,
fileGap: 0,
} satisfies Partial<VirtualFileMetrics>
type SelectionSide = "additions" | "deletions"
export type CodeProps<T = {}> = FileOptions<T> & {
@@ -177,28 +160,16 @@ export function Code<T>(props: CodeProps<T>) {
const [findPos, setFindPos] = createSignal<{ top: number; right: number }>({ top: 8, right: 8 })
let instance: File<T> | VirtualizedFile<T> | undefined
let virtualizer: Virtualizer | undefined
let virtualRoot: Document | HTMLElement | undefined
const bytes = createMemo(() => {
const value = local.file.contents as unknown
if (typeof value === "string") return value.length
if (Array.isArray(value)) {
return value.reduce(
(acc, part) => acc + (typeof part === "string" ? part.length + 1 : String(part).length + 1),
0,
)
}
if (value == null) return 0
return String(value).length
})
const virtual = createMemo(() => bytes() > VIRTUALIZE_BYTES)
const options = createMemo(() => ({
...createDefaultOptions<T>("unified"),
...others,
}))
const file = createMemo(
() =>
new File<T>(
{
...createDefaultOptions<T>("unified"),
...others,
},
getWorkerPool("unified"),
),
)
const getRoot = () => {
const host = container.querySelector("diffs-container")
@@ -606,14 +577,6 @@ export function Code<T>(props: CodeProps<T>) {
}
const applySelection = (range: SelectedLineRange | null) => {
const current = instance
if (!current) return false
if (virtual()) {
current.setSelectedLines(range)
return true
}
const root = getRoot()
if (!root) return false
@@ -621,7 +584,7 @@ export function Code<T>(props: CodeProps<T>) {
if (root.querySelectorAll("[data-line]").length < lines) return false
if (!range) {
current.setSelectedLines(null)
file().setSelectedLines(null)
return true
}
@@ -629,12 +592,12 @@ export function Code<T>(props: CodeProps<T>) {
const end = Math.max(range.start, range.end)
if (start < 1 || end > lines) {
current.setSelectedLines(null)
file().setSelectedLines(null)
return true
}
if (!root.querySelector(`[data-line="${start}"]`) || !root.querySelector(`[data-line="${end}"]`)) {
current.setSelectedLines(null)
file().setSelectedLines(null)
return true
}
@@ -645,7 +608,7 @@ export function Code<T>(props: CodeProps<T>) {
return { start: range.start, end: range.end }
})()
current.setSelectedLines(normalized)
file().setSelectedLines(normalized)
return true
}
@@ -656,12 +619,9 @@ export function Code<T>(props: CodeProps<T>) {
const token = renderToken
const lines = virtual() ? undefined : lineCount()
const lines = lineCount()
const isReady = (root: ShadowRoot) =>
virtual()
? root.querySelector("[data-line]") != null
: root.querySelectorAll("[data-line]").length >= (lines ?? 0)
const isReady = (root: ShadowRoot) => root.querySelectorAll("[data-line]").length >= lines
const notify = () => {
if (token !== renderToken) return
@@ -884,41 +844,20 @@ export function Code<T>(props: CodeProps<T>) {
}
createEffect(() => {
const opts = options()
const workerPool = getWorkerPool("unified")
const isVirtual = virtual()
const current = file()
onCleanup(() => {
current.cleanUp()
})
})
createEffect(() => {
observer?.disconnect()
observer = undefined
instance?.cleanUp()
instance = undefined
if (!isVirtual && virtualizer) {
virtualizer.cleanUp()
virtualizer = undefined
virtualRoot = undefined
}
const v = (() => {
if (!isVirtual) return
if (typeof document === "undefined") return
const root = getScrollParent(wrapper) ?? document
if (virtualizer && virtualRoot === root) return virtualizer
virtualizer?.cleanUp()
virtualizer = new Virtualizer()
virtualRoot = root
virtualizer.setup(root, root instanceof Document ? undefined : wrapper)
return virtualizer
})()
instance = isVirtual && v ? new VirtualizedFile<T>(opts, v, codeMetrics, workerPool) : new File<T>(opts, workerPool)
container.innerHTML = ""
const value = text()
instance.render({
file().render({
file: typeof local.file.contents === "string" ? local.file : { ...local.file, contents: value },
lineAnnotations: local.annotations,
containerWrapper: container,
@@ -971,13 +910,6 @@ export function Code<T>(props: CodeProps<T>) {
onCleanup(() => {
observer?.disconnect()
instance?.cleanUp()
instance = undefined
virtualizer?.cleanUp()
virtualizer = undefined
virtualRoot = undefined
clearOverlayScroll()
clearOverlay()
if (findCurrent === host) {

View File

@@ -1,5 +1,5 @@
import { sampledChecksum } from "@opencode-ai/util/encode"
import { FileDiff, type FileDiffOptions, type SelectedLineRange, VirtualizedFileDiff } from "@pierre/diffs"
import { checksum } from "@opencode-ai/util/encode"
import { FileDiff, type SelectedLineRange, VirtualizedFileDiff } from "@pierre/diffs"
import { createMediaQuery } from "@solid-primitives/media"
import { createEffect, createMemo, createSignal, onCleanup, splitProps } from "solid-js"
import { createDefaultOptions, type DiffProps, styleVariables } from "../pierre"
@@ -78,29 +78,14 @@ export function Diff<T>(props: DiffProps<T>) {
const mobile = createMediaQuery("(max-width: 640px)")
const large = createMemo(() => {
const before = typeof local.before?.contents === "string" ? local.before.contents : ""
const after = typeof local.after?.contents === "string" ? local.after.contents : ""
return Math.max(before.length, after.length) > 500_000
})
const largeOptions = {
lineDiffType: "none",
maxLineDiffLength: 0,
tokenizeMaxLineLength: 1,
} satisfies Pick<FileDiffOptions<T>, "lineDiffType" | "maxLineDiffLength" | "tokenizeMaxLineLength">
const options = createMemo<FileDiffOptions<T>>(() => {
const base = {
const options = createMemo(() => {
const opts = {
...createDefaultOptions(props.diffStyle),
...others,
}
const perf = large() ? { ...base, ...largeOptions } : base
if (!mobile()) return perf
if (!mobile()) return opts
return {
...perf,
...opts,
disableLineNumbers: true,
}
})
@@ -543,17 +528,12 @@ export function Diff<T>(props: DiffProps<T>) {
createEffect(() => {
const opts = options()
const workerPool = large() ? getWorkerPool("unified") : getWorkerPool(props.diffStyle)
const workerPool = getWorkerPool(props.diffStyle)
const virtualizer = getVirtualizer()
const annotations = local.annotations
const beforeContents = typeof local.before?.contents === "string" ? local.before.contents : ""
const afterContents = typeof local.after?.contents === "string" ? local.after.contents : ""
const cacheKey = (contents: string) => {
if (!large()) return sampledChecksum(contents, contents.length)
return sampledChecksum(contents)
}
instance?.cleanUp()
instance = virtualizer
? new VirtualizedFileDiff<T>(opts, virtualizer, virtualMetrics, workerPool)
@@ -565,12 +545,12 @@ export function Diff<T>(props: DiffProps<T>) {
oldFile: {
...local.before,
contents: beforeContents,
cacheKey: cacheKey(beforeContents),
cacheKey: checksum(beforeContents),
},
newFile: {
...local.after,
contents: afterContents,
cacheKey: cacheKey(afterContents),
cacheKey: checksum(afterContents),
},
lineAnnotations: annotations,
containerWrapper: container,

View File

@@ -209,8 +209,3 @@
display: block;
}
}
[data-component="markdown"] a.external-link:hover > code {
text-decoration: underline;
text-underline-offset: 2px;
}

View File

@@ -49,19 +49,6 @@ type CopyLabels = {
copied: string
}
const urlPattern = /^https?:\/\/[^\s<>()`"']+$/
function codeUrl(text: string) {
const href = text.trim().replace(/[),.;!?]+$/, "")
if (!urlPattern.test(href)) return
try {
const url = new URL(href)
return url.toString()
} catch {
return
}
}
function createIcon(path: string, slot: string) {
const icon = document.createElement("div")
icon.setAttribute("data-component", "icon")
@@ -123,39 +110,9 @@ function setupCodeCopy(root: HTMLDivElement, labels: CopyLabels) {
wrapper.appendChild(createCopyButton(labels))
}
const markCodeLinks = () => {
const codeNodes = Array.from(root.querySelectorAll(":not(pre) > code"))
for (const code of codeNodes) {
const href = codeUrl(code.textContent ?? "")
const parentLink =
code.parentElement instanceof HTMLAnchorElement && code.parentElement.classList.contains("external-link")
? code.parentElement
: null
if (!href) {
if (parentLink) parentLink.replaceWith(code)
continue
}
if (parentLink) {
parentLink.href = href
continue
}
const link = document.createElement("a")
link.href = href
link.className = "external-link"
link.target = "_blank"
link.rel = "noopener noreferrer"
code.parentNode?.replaceChild(link, code)
link.appendChild(code)
}
}
const handleClick = async (event: MouseEvent) => {
const target = event.target
if (!(target instanceof Element)) return
const button = target.closest('[data-slot="markdown-copy-button"]')
if (!(button instanceof HTMLButtonElement)) return
const code = button.closest('[data-component="markdown-code"]')?.querySelector("code")
@@ -175,7 +132,6 @@ function setupCodeCopy(root: HTMLDivElement, labels: CopyLabels) {
for (const block of blocks) {
ensureWrapper(block)
}
markCodeLinks()
const buttons = Array.from(root.querySelectorAll('[data-slot="markdown-copy-button"]'))
for (const button of buttons) {

View File

@@ -222,30 +222,4 @@
--line-comment-popover-z: 30;
--line-comment-open-z: 6;
}
[data-slot="session-review-large-diff"] {
padding: 12px;
background: var(--background-stronger);
}
[data-slot="session-review-large-diff-title"] {
font-family: var(--font-family-sans);
font-size: var(--font-size-small);
font-weight: var(--font-weight-medium);
color: var(--text-strong);
margin-bottom: 4px;
}
[data-slot="session-review-large-diff-meta"] {
font-family: var(--font-family-sans);
font-size: var(--font-size-small);
color: var(--text-weak);
word-break: break-word;
}
[data-slot="session-review-large-diff-actions"] {
display: flex;
gap: 8px;
margin-top: 10px;
}
}

View File

@@ -17,26 +17,6 @@ import { PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
import { type SelectedLineRange } from "@pierre/diffs"
import { Dynamic } from "solid-js/web"
const MAX_DIFF_LINES = 20_000
const MAX_DIFF_BYTES = 2_000_000
function linesOver(text: string, max: number) {
let lines = 1
for (let i = 0; i < text.length; i++) {
if (text.charCodeAt(i) !== 10) continue
lines++
if (lines > max) return true
}
return lines > max
}
function formatBytes(bytes: number) {
if (!Number.isFinite(bytes) || bytes <= 0) return "0 B"
if (bytes < 1024) return `${bytes} B`
if (bytes < 1024 * 1024) return `${Math.round((bytes / 1024) * 10) / 10} KB`
return `${Math.round((bytes / (1024 * 1024)) * 10) / 10} MB`
}
export type SessionReviewDiffStyle = "unified" | "split"
export type SessionReviewComment = {
@@ -346,28 +326,12 @@ export const SessionReview = (props: SessionReviewProps) => {
{(diff) => {
let wrapper: HTMLDivElement | undefined
const expanded = createMemo(() => open().includes(diff.file))
const [force, setForce] = createSignal(false)
const comments = createMemo(() => (props.comments ?? []).filter((c) => c.file === diff.file))
const commentedLines = createMemo(() => comments().map((c) => c.selection))
const beforeText = () => (typeof diff.before === "string" ? diff.before : "")
const afterText = () => (typeof diff.after === "string" ? diff.after : "")
const tooLarge = createMemo(() => {
if (!expanded()) return false
if (force()) return false
if (isImageFile(diff.file)) return false
const before = beforeText()
const after = afterText()
if (before.length > MAX_DIFF_BYTES || after.length > MAX_DIFF_BYTES) return true
if (linesOver(before, MAX_DIFF_LINES) || linesOver(after, MAX_DIFF_LINES)) return true
return false
})
const isAdded = () => diff.status === "added" || (beforeText().length === 0 && afterText().length > 0)
const isDeleted = () =>
diff.status === "deleted" || (afterText().length === 0 && beforeText().length > 0)
@@ -607,114 +571,94 @@ export const SessionReview = (props: SessionReviewProps) => {
scheduleAnchors()
}}
>
<Show when={expanded()}>
<Switch>
<Match when={isImage() && imageSrc()}>
<div data-slot="session-review-image-container">
<img data-slot="session-review-image" src={imageSrc()} alt={diff.file} />
</div>
</Match>
<Match when={isImage() && isDeleted()}>
<div data-slot="session-review-image-container" data-removed>
<span data-slot="session-review-image-placeholder">
{i18n.t("ui.sessionReview.change.removed")}
</span>
</div>
</Match>
<Match when={isImage() && !imageSrc()}>
<div data-slot="session-review-image-container">
<span data-slot="session-review-image-placeholder">
{imageStatus() === "loading"
? i18n.t("ui.sessionReview.image.loading")
: i18n.t("ui.sessionReview.image.placeholder")}
</span>
</div>
</Match>
<Match when={!isImage() && tooLarge()}>
<div data-slot="session-review-large-diff">
<div data-slot="session-review-large-diff-title">
{i18n.t("ui.sessionReview.largeDiff.title")}
</div>
<div data-slot="session-review-large-diff-meta">
Limit: {MAX_DIFF_LINES.toLocaleString()} lines / {formatBytes(MAX_DIFF_BYTES)}.
Current: {formatBytes(Math.max(beforeText().length, afterText().length))}.
</div>
<div data-slot="session-review-large-diff-actions">
<Button size="normal" variant="secondary" onClick={() => setForce(true)}>
{i18n.t("ui.sessionReview.largeDiff.renderAnyway")}
</Button>
</div>
</div>
</Match>
<Match when={!isImage()}>
<Dynamic
component={diffComponent}
preloadedDiff={diff.preloaded}
diffStyle={diffStyle()}
onRendered={() => {
props.onDiffRendered?.()
scheduleAnchors()
}}
enableLineSelection={props.onLineComment != null}
onLineSelected={handleLineSelected}
onLineSelectionEnd={handleLineSelectionEnd}
selectedLines={selectedLines()}
commentedLines={commentedLines()}
before={{
name: diff.file!,
contents: typeof diff.before === "string" ? diff.before : "",
}}
after={{
name: diff.file!,
contents: typeof diff.after === "string" ? diff.after : "",
<Switch>
<Match when={isImage() && imageSrc()}>
<div data-slot="session-review-image-container">
<img data-slot="session-review-image" src={imageSrc()} alt={diff.file} />
</div>
</Match>
<Match when={isImage() && isDeleted()}>
<div data-slot="session-review-image-container" data-removed>
<span data-slot="session-review-image-placeholder">
{i18n.t("ui.sessionReview.change.removed")}
</span>
</div>
</Match>
<Match when={isImage() && !imageSrc()}>
<div data-slot="session-review-image-container">
<span data-slot="session-review-image-placeholder">
{imageStatus() === "loading" ? "Loading..." : "Image"}
</span>
</div>
</Match>
<Match when={!isImage()}>
<Dynamic
component={diffComponent}
preloadedDiff={diff.preloaded}
diffStyle={diffStyle()}
onRendered={() => {
props.onDiffRendered?.()
scheduleAnchors()
}}
enableLineSelection={props.onLineComment != null}
onLineSelected={handleLineSelected}
onLineSelectionEnd={handleLineSelectionEnd}
selectedLines={selectedLines()}
commentedLines={commentedLines()}
before={{
name: diff.file!,
contents: typeof diff.before === "string" ? diff.before : "",
}}
after={{
name: diff.file!,
contents: typeof diff.after === "string" ? diff.after : "",
}}
/>
</Match>
</Switch>
<For each={comments()}>
{(comment) => (
<LineComment
id={comment.id}
top={positions()[comment.id]}
onMouseEnter={() => setSelection({ file: comment.file, range: comment.selection })}
onClick={() => {
if (isCommentOpen(comment)) {
setOpened(null)
return
}
openComment(comment)
}}
open={isCommentOpen(comment)}
comment={comment.comment}
selection={selectionLabel(comment.selection)}
/>
)}
</For>
<Show when={draftRange()}>
{(range) => (
<Show when={draftTop() !== undefined}>
<LineCommentEditor
top={draftTop()}
value={draft()}
selection={selectionLabel(range())}
onInput={setDraft}
onCancel={() => setCommenting(null)}
onSubmit={(comment) => {
props.onLineComment?.({
file: diff.file,
selection: range(),
comment,
preview: selectionPreview(diff, range()),
})
setCommenting(null)
}}
/>
</Match>
</Switch>
<For each={comments()}>
{(comment) => (
<LineComment
id={comment.id}
top={positions()[comment.id]}
onMouseEnter={() => setSelection({ file: comment.file, range: comment.selection })}
onClick={() => {
if (isCommentOpen(comment)) {
setOpened(null)
return
}
openComment(comment)
}}
open={isCommentOpen(comment)}
comment={comment.comment}
selection={selectionLabel(comment.selection)}
/>
)}
</For>
<Show when={draftRange()}>
{(range) => (
<Show when={draftTop() !== undefined}>
<LineCommentEditor
top={draftTop()}
value={draft()}
selection={selectionLabel(range())}
onInput={setDraft}
onCancel={() => setCommenting(null)}
onSubmit={(comment) => {
props.onLineComment?.({
file: diff.file,
selection: range(),
comment,
preview: selectionPreview(diff, range()),
})
setCommenting(null)
}}
/>
</Show>
)}
</Show>
</Show>
)}
</Show>
</div>
</Accordion.Content>

View File

@@ -8,11 +8,6 @@ export const dict = {
"ui.sessionReview.change.added": "مضاف",
"ui.sessionReview.change.removed": "محذوف",
"ui.sessionReview.change.modified": "معدل",
"ui.sessionReview.image.loading": "جار التحميل...",
"ui.sessionReview.image.placeholder": "صورة",
"ui.sessionReview.largeDiff.title": "Diff كبير جدا لعرضه",
"ui.sessionReview.largeDiff.meta": "الحد: {{lines}} سطر / {{limit}}. الحالي: {{current}}.",
"ui.sessionReview.largeDiff.renderAnyway": "اعرض على أي حال",
"ui.lineComment.label.prefix": "تعليق على ",
"ui.lineComment.label.suffix": "",

View File

@@ -8,11 +8,6 @@ export const dict = {
"ui.sessionReview.change.added": "Adicionado",
"ui.sessionReview.change.removed": "Removido",
"ui.sessionReview.change.modified": "Modificado",
"ui.sessionReview.image.loading": "Carregando...",
"ui.sessionReview.image.placeholder": "Imagem",
"ui.sessionReview.largeDiff.title": "Diff grande demais para renderizar",
"ui.sessionReview.largeDiff.meta": "Limite: {{lines}} linhas / {{limit}}. Atual: {{current}}.",
"ui.sessionReview.largeDiff.renderAnyway": "Renderizar mesmo assim",
"ui.lineComment.label.prefix": "Comentar em ",
"ui.lineComment.label.suffix": "",

View File

@@ -12,11 +12,6 @@ export const dict = {
"ui.sessionReview.change.added": "Dodano",
"ui.sessionReview.change.removed": "Uklonjeno",
"ui.sessionReview.change.modified": "Izmijenjeno",
"ui.sessionReview.image.loading": "Učitavanje...",
"ui.sessionReview.image.placeholder": "Slika",
"ui.sessionReview.largeDiff.title": "Diff je prevelik za prikaz",
"ui.sessionReview.largeDiff.meta": "Limit: {{lines}} linija / {{limit}}. Trenutno: {{current}}.",
"ui.sessionReview.largeDiff.renderAnyway": "Prikaži svejedno",
"ui.lineComment.label.prefix": "Komentar na ",
"ui.lineComment.label.suffix": "",

View File

@@ -9,11 +9,6 @@ export const dict = {
"ui.sessionReview.change.added": "Tilføjet",
"ui.sessionReview.change.removed": "Fjernet",
"ui.sessionReview.change.modified": "Ændret",
"ui.sessionReview.image.loading": "Indlæser...",
"ui.sessionReview.image.placeholder": "Billede",
"ui.sessionReview.largeDiff.title": "Diff er for stor til at blive vist",
"ui.sessionReview.largeDiff.meta": "Grænse: {{lines}} linjer / {{limit}}. Nuværende: {{current}}.",
"ui.sessionReview.largeDiff.renderAnyway": "Vis alligevel",
"ui.lineComment.label.prefix": "Kommenter på ",
"ui.lineComment.label.suffix": "",
"ui.lineComment.editorLabel.prefix": "Kommenterer på ",

View File

@@ -13,11 +13,6 @@ export const dict = {
"ui.sessionReview.change.added": "Hinzugefügt",
"ui.sessionReview.change.removed": "Entfernt",
"ui.sessionReview.change.modified": "Geändert",
"ui.sessionReview.image.loading": "Wird geladen...",
"ui.sessionReview.image.placeholder": "Bild",
"ui.sessionReview.largeDiff.title": "Diff zu groß zum Rendern",
"ui.sessionReview.largeDiff.meta": "Limit: {{lines}} Zeilen / {{limit}}. Aktuell: {{current}}.",
"ui.sessionReview.largeDiff.renderAnyway": "Trotzdem rendern",
"ui.lineComment.label.prefix": "Kommentar zu ",
"ui.lineComment.label.suffix": "",
"ui.lineComment.editorLabel.prefix": "Kommentiere ",

View File

@@ -8,11 +8,6 @@ export const dict = {
"ui.sessionReview.change.added": "Added",
"ui.sessionReview.change.removed": "Removed",
"ui.sessionReview.change.modified": "Modified",
"ui.sessionReview.image.loading": "Loading...",
"ui.sessionReview.image.placeholder": "Image",
"ui.sessionReview.largeDiff.title": "Diff too large to render",
"ui.sessionReview.largeDiff.meta": "Limit: {{lines}} lines / {{limit}}. Current: {{current}}.",
"ui.sessionReview.largeDiff.renderAnyway": "Render anyway",
"ui.lineComment.label.prefix": "Comment on ",
"ui.lineComment.label.suffix": "",

View File

@@ -8,11 +8,6 @@ export const dict = {
"ui.sessionReview.change.added": "Añadido",
"ui.sessionReview.change.removed": "Eliminado",
"ui.sessionReview.change.modified": "Modificado",
"ui.sessionReview.image.loading": "Cargando...",
"ui.sessionReview.image.placeholder": "Imagen",
"ui.sessionReview.largeDiff.title": "Diff demasiado grande para renderizar",
"ui.sessionReview.largeDiff.meta": "Límite: {{lines}} líneas / {{limit}}. Actual: {{current}}.",
"ui.sessionReview.largeDiff.renderAnyway": "Renderizar de todos modos",
"ui.lineComment.label.prefix": "Comentar en ",
"ui.lineComment.label.suffix": "",

View File

@@ -8,11 +8,6 @@ export const dict = {
"ui.sessionReview.change.added": "Ajouté",
"ui.sessionReview.change.removed": "Supprimé",
"ui.sessionReview.change.modified": "Modifié",
"ui.sessionReview.image.loading": "Chargement...",
"ui.sessionReview.image.placeholder": "Image",
"ui.sessionReview.largeDiff.title": "Diff trop volumineux pour être affiché",
"ui.sessionReview.largeDiff.meta": "Limite : {{lines}} lignes / {{limit}}. Actuel : {{current}}.",
"ui.sessionReview.largeDiff.renderAnyway": "Afficher quand même",
"ui.lineComment.label.prefix": "Commenter sur ",
"ui.lineComment.label.suffix": "",

View File

@@ -9,11 +9,6 @@ export const dict = {
"ui.sessionReview.change.added": "追加",
"ui.sessionReview.change.removed": "削除",
"ui.sessionReview.change.modified": "変更",
"ui.sessionReview.image.loading": "読み込み中...",
"ui.sessionReview.image.placeholder": "画像",
"ui.sessionReview.largeDiff.title": "差分が大きすぎて表示できません",
"ui.sessionReview.largeDiff.meta": "上限: {{lines}} 行 / {{limit}}。現在: {{current}}。",
"ui.sessionReview.largeDiff.renderAnyway": "それでも表示する",
"ui.lineComment.label.prefix": "",
"ui.lineComment.label.suffix": "へのコメント",
"ui.lineComment.editorLabel.prefix": "",

View File

@@ -8,11 +8,6 @@ export const dict = {
"ui.sessionReview.change.added": "추가됨",
"ui.sessionReview.change.removed": "삭제됨",
"ui.sessionReview.change.modified": "수정됨",
"ui.sessionReview.image.loading": "로딩 중...",
"ui.sessionReview.image.placeholder": "이미지",
"ui.sessionReview.largeDiff.title": "차이가 너무 커서 렌더링할 수 없습니다",
"ui.sessionReview.largeDiff.meta": "제한: {{lines}}줄 / {{limit}}. 현재: {{current}}.",
"ui.sessionReview.largeDiff.renderAnyway": "그래도 렌더링",
"ui.lineComment.label.prefix": "",
"ui.lineComment.label.suffix": "에 댓글 달기",

View File

@@ -11,11 +11,6 @@ export const dict: Record<Keys, string> = {
"ui.sessionReview.change.added": "Lagt til",
"ui.sessionReview.change.removed": "Fjernet",
"ui.sessionReview.change.modified": "Endret",
"ui.sessionReview.image.loading": "Laster...",
"ui.sessionReview.image.placeholder": "Bilde",
"ui.sessionReview.largeDiff.title": "Diff er for stor til å gjengi",
"ui.sessionReview.largeDiff.meta": "Grense: {{lines}} linjer / {{limit}}. Nåværende: {{current}}.",
"ui.sessionReview.largeDiff.renderAnyway": "Gjengi likevel",
"ui.lineComment.label.prefix": "Kommenter på ",
"ui.lineComment.label.suffix": "",

View File

@@ -9,11 +9,6 @@ export const dict = {
"ui.sessionReview.change.added": "Dodano",
"ui.sessionReview.change.removed": "Usunięto",
"ui.sessionReview.change.modified": "Zmodyfikowano",
"ui.sessionReview.image.loading": "Ładowanie...",
"ui.sessionReview.image.placeholder": "Obraz",
"ui.sessionReview.largeDiff.title": "Diff jest zbyt duży, aby go wyrenderować",
"ui.sessionReview.largeDiff.meta": "Limit: {{lines}} linii / {{limit}}. Obecnie: {{current}}.",
"ui.sessionReview.largeDiff.renderAnyway": "Renderuj mimo to",
"ui.lineComment.label.prefix": "Komentarz do ",
"ui.lineComment.label.suffix": "",
"ui.lineComment.editorLabel.prefix": "Komentowanie: ",

View File

@@ -9,11 +9,6 @@ export const dict = {
"ui.sessionReview.change.added": "Добавлено",
"ui.sessionReview.change.removed": "Удалено",
"ui.sessionReview.change.modified": "Изменено",
"ui.sessionReview.image.loading": "Загрузка...",
"ui.sessionReview.image.placeholder": "Изображение",
"ui.sessionReview.largeDiff.title": "Diff слишком большой для отображения",
"ui.sessionReview.largeDiff.meta": "Лимит: {{lines}} строк / {{limit}}. Текущий: {{current}}.",
"ui.sessionReview.largeDiff.renderAnyway": "Отобразить всё равно",
"ui.lineComment.label.prefix": "Комментарий к ",
"ui.lineComment.label.suffix": "",
"ui.lineComment.editorLabel.prefix": "Комментирование: ",

View File

@@ -8,11 +8,6 @@ export const dict = {
"ui.sessionReview.change.added": "เพิ่ม",
"ui.sessionReview.change.removed": "ลบ",
"ui.sessionReview.change.modified": "แก้ไข",
"ui.sessionReview.image.loading": "กำลังโหลด...",
"ui.sessionReview.image.placeholder": "รูปภาพ",
"ui.sessionReview.largeDiff.title": "Diff มีขนาดใหญ่เกินไปจนไม่สามารถแสดงผลได้",
"ui.sessionReview.largeDiff.meta": "ขีดจำกัด: {{lines}} บรรทัด / {{limit}}. ปัจจุบัน: {{current}}.",
"ui.sessionReview.largeDiff.renderAnyway": "แสดงผลต่อไป",
"ui.lineComment.label.prefix": "แสดงความคิดเห็นบน ",
"ui.lineComment.label.suffix": "",

View File

@@ -12,11 +12,6 @@ export const dict = {
"ui.sessionReview.change.added": "已添加",
"ui.sessionReview.change.removed": "已移除",
"ui.sessionReview.change.modified": "已修改",
"ui.sessionReview.image.loading": "加载中...",
"ui.sessionReview.image.placeholder": "图片",
"ui.sessionReview.largeDiff.title": "差异过大,无法渲染",
"ui.sessionReview.largeDiff.meta": "限制:{{lines}} 行 / {{limit}}。当前:{{current}}。",
"ui.sessionReview.largeDiff.renderAnyway": "仍然渲染",
"ui.lineComment.label.prefix": "评论 ",
"ui.lineComment.label.suffix": "",

View File

@@ -12,11 +12,6 @@ export const dict = {
"ui.sessionReview.change.added": "已新增",
"ui.sessionReview.change.removed": "已移除",
"ui.sessionReview.change.modified": "已修改",
"ui.sessionReview.image.loading": "載入中...",
"ui.sessionReview.image.placeholder": "圖片",
"ui.sessionReview.largeDiff.title": "差異過大,無法渲染",
"ui.sessionReview.largeDiff.meta": "限制:{{lines}} 行 / {{limit}}。目前:{{current}}。",
"ui.sessionReview.largeDiff.renderAnyway": "仍然渲染",
"ui.lineComment.label.prefix": "評論 ",
"ui.lineComment.label.suffix": "",

View File

@@ -28,24 +28,3 @@ export function checksum(content: string): string | undefined {
}
return (hash >>> 0).toString(36)
}
export function sampledChecksum(content: string, limit = 500_000): string | undefined {
if (!content) return undefined
if (content.length <= limit) return checksum(content)
const size = 4096
const points = [
0,
Math.floor(content.length * 0.25),
Math.floor(content.length * 0.5),
Math.floor(content.length * 0.75),
content.length - size,
]
const hashes = points
.map((point) => {
const start = Math.max(0, Math.min(content.length - size, point - Math.floor(size / 2)))
return checksum(content.slice(start, start + size)) ?? ""
})
.join(":")
return `${content.length}:${hashes}`
}

View File

@@ -84,8 +84,7 @@ curl -fsSL https://opencode.ai/install | bash
- **باستخدام Paru على Arch Linux**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -84,8 +84,7 @@ Du kan også installere det med følgende kommandoer:
- **Brug af Paru på Arch Linux**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -84,8 +84,7 @@ Sie können es auch mit den folgenden Befehlen installieren:
- **Verwendung von Paru unter Arch Linux**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -84,8 +84,7 @@ También puedes instalarlo con los siguientes comandos:
- **Usando Paru en Arch Linux**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -84,8 +84,7 @@ Vous pouvez également l'installer avec les commandes suivantes :
- **Via Paru sur Arch Linux**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -81,11 +81,10 @@ You can also install it with the following commands:
> We recommend using the OpenCode tap for the most up to date releases. The official `brew install opencode` formula is maintained by the Homebrew team and is updated less frequently.
- **Installing on Arch Linux**
- **Using Paru on Arch Linux**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -84,8 +84,7 @@ Puoi anche installarlo con i seguenti comandi:
- **Con Paru su Arch Linux**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -84,8 +84,7 @@ curl -fsSL https://opencode.ai/install | bash
- **Arch Linux での Paru の使用**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -1,12 +1,12 @@
---
title: ACP Support
description: Use OpenCode in any ACP-compatible editor.
title: ACP 지원
description: ACP 호환 편집기에서 opencode를 사용하세요.
---
OpenCode는 [Agent Client Protocol](https://agentclientprotocol.com)(ACP)을 지원하므로, ACP 호환 편집기 IDE에서 OpenCode를 직접 사용할 수 있습니다.
opencode는 [Agent Client Protocol](https://agentclientprotocol.com) 또는 (ACP)을 지원하며, 호환 편집기 IDE에서 직접 사용할 수 있습니다.
:::tip
ACP를 지원하는 편집기와 tool 목록은 [ACP progress report](https://zed.dev/blog/acp-progress-report#available-now)에서 확인하세요.
ACP를 지원하는 편집기 및 도구 목록의 경우 [ACP 진행 보고서](https://zed.dev/blog/acp-progress-report#available-now) 확인하십시오.
:::
ACP는 코드 편집기와 AI 코딩 에이전트 간의 통신을 표준화하는 개방형 프로토콜입니다.
@@ -15,17 +15,17 @@ ACP는 코드 편집기와 AI 코딩 에이전트 간의 통신을 표준화하
## 구성
ACP로 OpenCode를 사용하려면, 편집기에서 `opencode acp` 명령을 실행하도록 config를 설정하세요.
ACP를 통해 opencode를 사용하려면 `opencode acp` 명령을 실행하려면 편집기를 구성하십시오.
명령은 OpenCode를 ACP 호환 subprocess로 시작하며, stdio 기반 JSON-RPC를 통해 편집기와 통신합니다.
명령은 opencode를 실행하여 JSON-RPC를 통해 편집기와 통신하는 ACP 호환 하위 프로세스로 시작합니다.
아래는 ACP를 지원하는 주요 편집기 예입니다.
아래는 ACP를 지원하는 인기있는 편집기 예입니다.
---
### Zed
##### Zed
[Zed](https://zed.dev) config(`~/.config/zed/settings.json`)에 다음을 추가하세요.
[Zed](https://zed.dev) 구성 (`~/.config/zed/settings.json`)에 추가 :
```json title="~/.config/zed/settings.json"
{
@@ -38,9 +38,9 @@ ACP로 OpenCode를 사용하려면, 편집기에서 `opencode acp` 명령을 실
}
```
열려면 **Command Palette**에서 `agent: new thread` action을 사용하세요.
그것을 열려면 **Command Palette **에서 `agent: new thread` 동작을 사용하십시오.
`keymap.json`을 수정해 키보드 단축키를 바인딩할 수 있습니다.
`keymap.json`를 편집하여 키보드 단축키도 결합할 수 있습니다.
```json title="keymap.json"
[
@@ -67,9 +67,9 @@ ACP로 OpenCode를 사용하려면, 편집기에서 `opencode acp` 명령을 실
---
### JetBrains IDEs
#### JetBrains IDEs
[JetBrains IDE](https://www.jetbrains.com/)에서는 [documentation](https://www.jetbrains.com/help/ai-assistant/acp.html)에 따라 `acp.json`에 다음을 추가하세요.
[JetBrains IDE]에 추가하십시오 (https://www.jetbrains.com/) [documentation]에 따라 acp.json (https://www.jetbrains.com/help/ai-assistant/acp.html):
```json title="acp.json"
{
@@ -82,13 +82,13 @@ ACP로 OpenCode를 사용하려면, 편집기에서 `opencode acp` 명령을 실
}
```
열려면 AI Chat agent selector에서 새 `OpenCode` agent를 선택하세요.
그것을 열려면 AI Chat Agent selector의 새로운 'opencode' 에이전트를 사용하십시오.
---
### Avante.nvim
#### Avante.nvim
[Avante.nvim](https://github.com/yetone/avante.nvim) config에 다음을 추가하세요.
[Avante.nvim](https://github.com/yetone/avante.nvim) 구성에 추가하십시오:
```lua
{
@@ -101,7 +101,7 @@ ACP로 OpenCode를 사용하려면, 편집기에서 `opencode acp` 명령을 실
}
```
환경 변수를 전달해야 한다면 다음과 같이 설정하세요.
환경 변수를 전달해야 하는 경우:
```lua {6-8}
{
@@ -119,9 +119,9 @@ ACP로 OpenCode를 사용하려면, 편집기에서 `opencode acp` 명령을 실
---
### CodeCompanion.nvim
#### CodeCompanion.nvim
[CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim)에서 OpenCode를 ACP agent로 사용하려면 Neovim config에 다음을 추가하세요.
opencode를 [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim)에서 ACP 에이전트로 사용하려면 Neovim config에 다음을 추가하십시오.
```lua
require("codecompanion").setup({
@@ -136,21 +136,21 @@ require("codecompanion").setup({
})
```
config는 chat에서 OpenCode를 ACP agent로 사용하도록 CodeCompanion을 설정합니다.
구성은 CodeCompanion을 설정하여 채팅을 위한 ACP 에이전트로 opencode를 사용합니다.
환경 변수(`OPENCODE_API_KEY`)를 전달해야 한다면 CodeCompanion.nvim documentation의 [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key)를 참고하세요.
환경 변수 (`OPENCODE_API_KEY`와 같은)를 전달해야하는 경우, CodeCompanion.nvim 문서에서 [Configuring Adapters: Environment variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key)를 참조하십시오.
## 지원
## 지원 기능
OpenCode는 ACP를 통해서도 터미널과 동일하게 동작합니다. 다음 기능을 모두 지원니다.
opencode는 터미널과 동일하게 ACP를 통해 작동합니다. 모든 기능 지원니다:
:::note
`/undo` 및 `/redo`와 같은 일부 내장 슬래시 명령은 현재 지원되지 않습니다.
:::
- 내장 tool(파일 작업, terminal 명령 등)
- 사용자 정의 tool과 slash command
- OpenCode config에 설정 MCP 서버
- `AGENTS.md`의 프로젝트별 규칙
- 사용자 정의 formatter와 linter
- agent 및 권한 시스템
- 내장 도구 (파일 작업, terminal 명령 등)
- 사용자 정의 도구 및 슬래시 명령
- opencode config에 설정 MCP 서버
- `AGENTS.md`의 프로젝트 별 규칙
- 사용자 정의 포맷 및 라이터
- 에이전트 및 권한 시스템

View File

@@ -1,141 +1,141 @@
---
title: Agents
description: Configure and use specialized agents.
title: 에이전트
description: 전문 에이전트를 구성하고 사용하세요.
---
agent는 특정 작업과 워크플로에 맞게 설정할 수 있는 전문 AI assistant입니다. custom prompt, model, tool 접근 권한을 조합해 목적에 맞는 agent를 만들 수 있습니다.
에이전트는 특정 작업과 워크플로우를 전문으로 하는 구성 가능한 AI 보조자입니다. 사용자 정의 프롬프트, 모델, 도구 액세스로 집중된 도구를 만들 수 있습니다.
:::tip
코드를 수정하지 않고 분석과 제안 검토만 하고 싶다면 plan agent를 사용하세요.
코드 변경 없이 제안 검토할 때는 Plan 에이전트를 사용하세요.
:::
세션 중에 agent를 전환하거나 `@` mention으로 호출할 수 있습니다.
세션 중에 에이전트를 전환하거나 `@` 멘션으로 호출할 수 있습니다.
---
## 유형
OpenCode의 agent는 primary agent와 subagent, 두 가지 유형으로 나뉩니다.
OpenCode에는 두 가지 유형의 에이전트가 있습니다: 기본 에이전트(Primary Agent)서브 에이전트(Subagent).
---
### Primary agents
### 기본 에이전트
primary agent는 사용자가 직접 상호작용하는 메인 assistant입니다. **Tab** 키 또는 설정 `switch_agent` keybind로 순환 전환할 수 있습니다. primary agent는 메인 대화를 처리하며, tool 접근은 permission으로 제어합니다. 예를 들어 Build는 모든 tool이 활성화되어 있고 Plan은 제한되어 있습니다.
기본 에이전트는 사용자가 직접 상호 작용하는 주요 보조자입니다. **Tab** 키 또는 설정 `switch_agent` 키바인드를 사용하여 순환할 수 있습니다. 이 에이전트는 주요 대화를 처리합니다. 도구 액세스는 권한을 통해 구성됩니다 — 예를 들어, Build는 모든 도구를 사용할 수 있지만 Plan은 제한니다.
:::tip
세션 중 **Tab** 키로 primary agent를 빠르게 전환할 수 있습니다.
세션 중 **Tab** 키를 사용하여 기본 에이전트를 전환할 수 있습니다.
:::
OpenCode기본 제공 primary agent인 **Build** **Plan**이 포함되어 있습니다. 아래에서 각각 살펴보겠습니다.
OpenCode는 두 가지 내장 기본 에이전트, **Build** **Plan**을 제공합니다. 아래에서 자세히 살펴봅니다.
---
### Subagents
### 서브 에이전트
subagent는 primary agent가 특정 작업을 위해 호출하는 전문 assistant입니다. 메시지에서 **@ mention**으로 직접 호출할 수도 있습니다.
서브 에이전트는 기본 에이전트가 특정 작업을 위해 호출할 수 있는 전문 보조자입니다. 또한 메시지에서 **@멘션**을 통해 수동으로 호출할 수도 있습니다.
OpenCode기본 제공 subagent인 **General** **Explore**가 포함되어 있습니다. 아래에서 살펴보겠습니다.
OpenCode는 두 가지 내장 서브 에이전트, **General** **Explore**를 제공합니다. 아래에서 자세히 살펴봅니다.
---
## 기본 제공
OpenCode는 기본적으로 primary agent 2개와 subagent 2개를 제공합니다.
OpenCode는 기본 에이전트와 두 개의 내장 서브 에이전트를 제공합니다.
---
### Use build
### Build
_Mode_: `primary`
_모드_: `primary`
Build는 모든 tool이 활성화된 **default** primary agent입니다. 파일 작업과 시스템 명령에 대한 전체 접근이 필요한 일반적인 개발 작업에 사용하는 표준 agent입니다.
Build는 모든 도구가 활성화된 **기본** 에이전트입니다. 파일 조작 및 시스템 명령에 대한 전체 액세스가 필요한 개발 작업을 위한 표준 에이전트입니다.
---
### Use plan
### Plan
_Mode_: `primary`
_모드_: `primary`
Plan은 계획과 분석에 특화된 제한형 agent입니다. 더 은 제어력과 의도 않은 변경 방지 위해 permission 시스템을 사용합니다.
기본으로 아래 항목은 모두 `ask`로 설정됩니다.
계획 및 분석을 위해 설계된 제한된 에이전트입니다. 더 은 제어권을 부여하고 의도하지 않은 변경 방지하기 위해 권한 시스템을 사용합니다.
기본으로 다음은 모두 `ask`로 설정됩니다:
- `file edits`: 모든 write, patch, edit
- `file edits`: 모든 쓰기, 패치 및 편집
- `bash`: 모든 bash 명령
코드베이스를 실제로 수정하지 않고 LLM 분석, 변경 제안, 계획 수립만 진행하고 싶을 때 유용합니다.
이 에이전트는 코드를 분석하거나 변경 제안받고 싶지만, 코드베이스에 실제 수정 없이 계획만 만들고 싶을 때 유용합니다.
---
### Use general
### General
_Mode_: `subagent`
_모드_: `subagent`
복잡한 질문을 조사하고 다단계 작업을 행하기 위한 범용 agent입니다. todo 제외한 모든 tool 접근이 가능하므로 필요하면 파일 수정도 할 수 있습니다. 여러 작업 단위를 병렬로 처리할 때 사용하세요.
복잡한 질문을 연구하고 다단계 작업을 행하기 위한 범용 에이전트입니다. 전체 도구 액세스(todo 제외)를 가지므로 필요할 때 파일 변경을 수행할 수 있습니다. 여러 단위의 작업을 병렬로 실행할 때 사용하세요.
---
### Use explore
### Explore
_Mode_: `subagent`
_모드_: `subagent`
코드베이스 탐색에 최적화된 빠른 읽기 전용 agent입니다. 파일을 수정할 수 없습니다. 패턴 기반 파일 탐색, 키워드 검색, 코드베이스 관련 질의 응답을 빠르게 처리할 때 사용하세요.
코드베이스 탐색하는 빠르고 읽기 전용인 에이전트입니다. 파일을 수정할 수 없습니다. 패턴, 키워드로 코드를 검색하거나 코드베이스에 대한 질문에 답하기 위해 파일을 빠르게 찾아야 할 때 사용하세요.
---
### Use compaction
### Compaction
_Mode_: `primary`
_모드_: `primary`
context를 더 짧은 요약으로 압축하는 숨겨진 시스템 agent입니다. 필요할 때 자동으로 실행되며 UI에서 직접 선택할 수 없습니다.
컨텍스트를 작은 요약으로 압축하는 숨겨진 시스템 에이전트입니다. 필요한 경우 자동으로 실행되며 UI에서 선택할 수 없습니다.
---
### Use title
### Title
_Mode_: `primary`
_모드_: `primary`
짧은 세션 제목을 생성하는 숨겨진 시스템 agent입니다. 자동으로 실행되며 UI에서 직접 선택할 수 없습니다.
짧은 세션 제목을 생성하는 숨겨진 시스템 에이전트입니다. 자동으로 실행되며 UI에서 선택할 수 없습니다.
---
### Use summary
### Summary
_Mode_: `primary`
_모드_: `primary`
세션 요약을 생성하는 숨겨진 시스템 agent입니다. 자동으로 실행되며 UI에서 직접 선택할 수 없습니다.
세션 요약을 만드는 숨겨진 시스템 에이전트입니다. 자동으로 실행되며 UI에서 선택할 수 없습니다.
---
## 사용법
1. primary agent는 세션 중 **Tab** 키로 순환 전환할 수 있습니다. 설정한 `switch_agent` keybind를 사용할 수 있습니다.
1. 기본 에이전트의 경우, 세션 중 **Tab** 키를 사용하여 순환합니다. 구성된 `switch_agent` 키바인드도 사용할 수 있습니다.
2. subagent 호출 방법:
- **Automatically**: primary agent가 설명(description)을 바탕으로 특화 작업에 자동 호출합니다.
- 수동 호출: 메시지에서 subagent를 **@ mention**하여 호출합니다. 예:
2. 서브 에이전트는 다음과 같이 호출할 수 있습니다:
- 설명에 근거하여 전문적인 작업을 위해 기본 에이전트에 의해 **자동으로** 호출됨.
- 메시지에서 서브 에이전트를 **@멘션**. 예를 들어:
```txt frame="none"
@general help me search for this function
```
3. **세션 간 이동**: subagent가 child session을 만들면 아래 키로 parent session과 child session 사이를 이동할 수 있습니다.
- **\<Leader>+Right** (또는 설정 `session_child_cycle` keybind): parent → child1 → child2 → ... → parent 순방향 순환
- **\<Leader>+Left** (또는 설정한 `session_child_cycle_reverse` keybind): parent ← child1 ← child2 ← ... ← parent 역방향 순환
3. **세션 간 이동**: 서브 에이전트가 자체 자식 세션을 만들 때, 부모 세션과 자식 세션 간을 탐색할 수 있습니다.
- **\<Leader>+Right** (또는 부모 → 자식1 → 자식2 순으로 이동하기 위해 설정 `session_child_cycle` 키바인드)
- **\<Leader>+Left** (또는 `session_child_cycle_reverse` 키바인드) 부모 방향으로 되돌아가기: 자식2 → 자식1 → 부모
이를 통해 메인 대화와 특화 subagent 작업 사이를 자연스럽게 오갈 수 있습니다.
이를 통해 주요 대화와 전문적인 서브 에이전트 작업 간을 원활하게 전환할 수 있습니다.
---
## 구성
기본 제공 agent를 커스터마이즈하거나 config를 통해 직접 agent를 만들 수 있습니다. agent는 두 가지 방으로 설정합니다.
내장 에이전트를 사용자 정의하거나 구성을 통해 자신만의 에이전트를 만들 수 있습니다. 에이전트는 두 가지 방으로 구성될 수 있습니다:
---
### JSON
`opencode.json` config 파일에서 agent를 설정합니다.
`opencode.json` config 파일에 에이전트 구성:
```json title="opencode.json"
{
@@ -178,10 +178,10 @@ _Mode_: `primary`
### Markdown
Markdown 파일로도 agent를 정의할 수 있습니다. 다음 위치에 두세요.
Markdown 파일을 사용하여 에이전트를 정의 할 수 있습니다. 그들에 게:
- Global: `~/.config/opencode/agents/`
- Per-project: `.opencode/agents/`
- 글로벌: `~/.config/opencode/agents/`
- 프로젝트: `.opencode/agents/`
```markdown title="~/.config/opencode/agents/review.md"
---
@@ -205,19 +205,19 @@ You are in code review mode. Focus on:
Provide constructive feedback without making direct changes.
```
Markdown 파일명은 agent 이름이 됩니다. 예를 들어 `review.md`는 `review` agent를 만듭니다.
markdown 파일 이름은 에이전트 이름입니다. 예를 들어, `review.md`는 `review` 에이전트을 만듭니다.
---
## 옵션
각 config 옵션을 자세히 살펴보겠습니다.
이 구성 옵션을 자세히 살펴봅시다.
---
### Description
### 설명
`description` 옵션으로 agent의 역할과 사용 시점을 간단 설명하세요.
`description` 옵션을 사용하여 에이전트가 무엇을 하고 언제 사용해야 하는지에 대한 간단 설명을 제공합니다.
```json title="opencode.json"
{
@@ -229,15 +229,15 @@ Markdown 파일명은 agent 이름이 됩니다. 예를 들어 `review.md`는 `r
}
```
이 옵션은 **필수** config 항목입니다.
\*\* 필수 구성 옵션입니다.
---
### Temperature
### 온도
`temperature` config로 LLM 응답의 무작위성과 창의성을 제어합니다.
`temperature` 구성으로 LLM 응답의 무작위성과 창의성을 제어합니다.
값이 낮을수록 응답이 더 집중되고 결정적며, 값이 높을수록 창의성과 다양성이 커집니다.
값이 낮을수록 더 집중되고 결정적인 응답을 생성하며, 값이 높을수록 창의성과 가변성이 증가합니다.
```json title="opencode.json"
{
@@ -252,11 +252,11 @@ Markdown 파일명은 agent 이름이 됩니다. 예를 들어 `review.md`는 `r
}
```
Temperature 값은 일반적으로 0.0~1.0 범위를 사용합니다.
온도 값은 일반적으로 0.0에서 1.0 사이입니다:
- **0.0-0.2**: 매우 집중되고 결정적인 응답, 코드 분석/계획에 적
- **0.3-0.5**: 적당한 창의성이 섞인 균형형 응답, 일반 개발 작업에 적합
- **0.6-1.0**: 더 창의적이고 다양한 응답, 브레인스토밍/탐색에 유용
- **0.0-0.2**: 매우 집중되고 신중한 응답, 코드 분석계획에 이상
- **0.3-0.5**: 창의성과 정확성의 균형, 일반 개발 작업에 좋음
- **0.6-1.0**: 더 창의적이고 다양한 응답, 브레인스토밍탐색에 유용
```json title="opencode.json"
{
@@ -276,15 +276,15 @@ Temperature 값은 일반적으로 0.0~1.0 범위를 사용합니다.
}
```
temperature를 지정지 않으면 OpenCode는 model별 기본값을 사용합니다. 일반적으로 대부분의 model은 0, Qwen model은 0.55를 사용합니다.
온도가 지정지 않은 경우, OpenCode는 모델별 기본값을 사용합니다. 일반적으로 대부분의 모델은 0, Qwen 모델의 경우 0.55입니다.
---
### Max steps
## 최대 단계
agent가 텍스트 응답만 하도록 강제되기 전까지 수행할 수 있는 agentic iteration의 최대 횟수를 제어합니다. 비용을 관리하려는 사용자에게 agentic action 제한을 제공하기 위한 옵션입니다.
에이전트가 중지하고 사용자와 다시 상호 작용하기 전에 실행할 수 있는 최대 단계 수를 제어합니다. 이를 통해 에이전트의 행동과 비용을 제어할 수 있습니다.
이 값을 설정지 않으면 model이 중단을 선택하거나 사용자가 세션을 중단할 때까지 agent는 계속 반복합니다.
설정지 않은 경우, 에이전트는 모델이 중지하거나 사용자가 세션을 중단할 때까지 계속됩니다.
```json title="opencode.json"
{
@@ -298,17 +298,17 @@ agent가 텍스트 응답만 하도록 강제되기 전까지 수행할 수 있
}
```
제한에 도달하면 agent는 작업 요약과 남은 권장 작업을 응답하도록 지시하는 특수 시스템 prompt를 받습니다.
제한에 도달하면, 에이전트는 작업 요약과 권장되는 남은 작업을 신속하게 응답하도록 지시받습니다.
:::caution
레거시 `maxSteps` 필드는 deprecated입니다. 대신 `steps`를 사용하세요.
레거시 `maxSteps` 필드는 더 이상 사용되지 않습니다. 대신 `steps`를 사용하십시오.
:::
---
### Disable
#### 비활성화
`true`로 설정하면 agent를 비활성화합니다.
`true`로 설정하여 에이전트를 비활성화합니다.
```json title="opencode.json"
{
@@ -322,9 +322,9 @@ agent가 텍스트 응답만 하도록 강제되기 전까지 수행할 수 있
---
### Prompt
#### 프롬프트
`prompt` config로 해당 agent의 custom 시스템 prompt 파일을 지정합니다. prompt 파일에는 agent 목적에 맞는 지시사항을 작성하세요.
`prompt` 구성으로 이 에이전트를 위한 사용자 정의 시스템 프롬프트 파일을 지정하십시오. 프롬프트 파일은 에이전트의 목적에 따른 지시를 포함해야 합니다.
```json title="opencode.json"
{
@@ -336,16 +336,16 @@ agent가 텍스트 응답만 하도록 강제되기 전까지 수행할 수 있
}
```
이 경로는 config 파일 위치 기준의 상대 경로입니다. 따라서 전역 OpenCode config와 프로젝트별 config 모두에서 동일하게 동작합니다.
이 경로는 구성 파일이 있는 위치 기준으로 합니다. 따라서 글로벌 OpenCode 구성과 프로젝트별 구성 모두에서 작동합니다.
---
### Model
### 모델
`model` config로 해당 agent의 model을 override할 수 있습니다. 작업 특성에 맞춰 model을 달리 쓸 때 유용합니다. 예를 들어 계획에는 더 빠른 model, 구현에는 더 강력한 model을 사용할 수 있습니다.
`model` 구성을 사용하여 이 에이전트에 대한 모델을 재정의합니다. 다른 작업에 최적화된 다른 모델을 사용하는 데 유용합니다. 예를 들어, 계획을 위한 빠른 모델, 구현을 위한 더 강력한 모델 등입니다.
:::tip
model을 지정하지 않으면 primary agent는 [전역으로 설정한 model](/docs/config#models)을 사용하, subagent는 해당 subagent를 호출한 primary agent의 model을 사용합니다.
모델을 지정하지 않는 경우, 기본 에이전트는 [전역 구성 모델](/docs/config#models)을 사용하, 서브 에이전트는 자신을 호출한 기본 에이전트의 모델을 사용합니다.
:::
```json title="opencode.json"
@@ -358,13 +358,13 @@ model을 지정하지 않으면 primary agent는 [전역으로 설정한 model](
}
```
OpenCode config의 model ID는 `provider/model-id` 형식을 사용합니다. 예를 들어 [OpenCode Zen](/docs/zen)을 사용한다면 GPT 5.1 Codex에 `opencode/gpt-5.1-codex`를 사용니다.
OpenCode 구성의 모델 ID는 `provider/model-id` 형식을 사용합니다. 예를 들어, [OpenCode Zen](/docs/zen)을 사용한다면, GPT 5.1 Codex에 `opencode/gpt-5.1-codex`를 사용할 수 있습니다.
---
### Tools
## 도구
`tools` config로 agent에서 사용할 tool을 제어합니다. 각 tool을 `true` 또는 `false`로 설정해 활성화/비활성화할 수 있습니다.
`tools` 구성으로 이 에이전트가 사용할 수 있는 도구를 제어합니다. `true` 또는 `false`로 설정하여 특정 도구를 활성화하거나 비활성화할 수 있습니다.
```json title="opencode.json" {3-6,9-12}
{
@@ -385,10 +385,10 @@ OpenCode config의 model ID는 `provider/model-id` 형식을 사용합니다.
```
:::note
agent별 config는 전역 config를 override합니다.
에이전트별 구성은 글로벌 구성을 덮어씁니다.
:::
와일드카드를 사용하면 여러 tool을 한 번에 제어할 수 있습니다. 예를 들어 MCP 서버 모든 tool을 비활성화하려면 다음과 같이 설정합니다.
한 번에 여러 도구를 제어하기 위해 와일드카드를 사용할 수 있습니다. 예를 들어, MCP 서버에서 모든 도구를 비활성화하려면:
```json title="opencode.json"
{
@@ -405,17 +405,17 @@ agent별 config는 전역 config를 override합니다.
}
```
[tool에 대해 더 알아보기](/docs/tools).
[도구에 대해 더 알아보기](/docs/tools).
---
### Permissions
## 권한
permission을 설정해 agent가 수행할 수 있는 action을 제어할 수 있습니다. 현재 `edit`, `bash`, `webfetch` tool의 permission은 다음 값으로 설정할 수 있습니다.
에이전트가 수행할 수 있는 작업을 관리할 수 있는 권한을 구성할 수 있습니다. 현재 `edit`, `bash` `webfetch` 도구에 대한 권한은 다음과 같습니다.
- `"ask"` — tool 실행 전에 승인 요청
- `"allow"` 승인 없이 모든 작업 허용
- `"deny"` — tool 비활성화
- `"ask"` - 도구를 실행하기 전에 승인 요청
- `"allow"` - 승인 없이 모든 작업 허용
- `"deny"` - 도구 비활성화
```json title="opencode.json"
{
@@ -426,7 +426,7 @@ permission을 설정해 agent가 수행할 수 있는 action을 제어할 수
}
```
이 permission은 agent별로 override할 수 있습니다.
에이전트별로 이 권한을 재정의(override)할 수 있습니다.
```json title="opencode.json" {3-5,8-10}
{
@@ -444,7 +444,7 @@ permission을 설정해 agent가 수행할 수 있는 action을 제어할 수
}
```
Markdown agent에서도 permission을 설정할 수 있습니다.
Markdown 에이전트에서도 권한을 설정할 수 있습니다.
```markdown title="~/.config/opencode/agents/review.md"
---
@@ -463,7 +463,7 @@ permission:
Only analyze code and suggest changes.
```
특정 bash 명령에 대해서도 permission을 설정할 수 있습니다.
특정 bash 명령에 대한 권한을 설정할 수 있습니다.
```json title="opencode.json" {7}
{
@@ -481,7 +481,7 @@ Only analyze code and suggest changes.
}
```
여기에는 glob 패턴을 사용할 수 있습니다.
이것은 glob 패턴을 사용할 수 있습니다.
```json title="opencode.json" {7}
{
@@ -498,8 +498,8 @@ Only analyze code and suggest changes.
}
```
또한 `*` 와일드카드로 모든 명령의 permission을 제어할 수 있습니다.
마지막으로 일치 규칙이 우선하므로 `*` 와일드카드를 먼저 두고, 구체적인 규칙을 에 두세요.
또한 `*` 와일드카드를 사용하여 모든 명령에 대한 권한을 관리할 수 있습니다.
마지막 일치 규칙이 우선하므로, `*` 와일드카드를 먼저 두고 특정 규칙을 나중에 두십시오.
```json title="opencode.json" {8}
{
@@ -517,13 +517,13 @@ Only analyze code and suggest changes.
}
```
[permission에 대해 더 알아보기](/docs/permissions).
[권한에 대해 더 알아보기](/docs/permissions).
---
### Mode
### 모드
`mode` config로 agent 모드를 제어합니다. `mode` 옵션은 agent를 어떤 방식으로 사용할지 결정합니다.
`mode` 구성으로 에이전트 모드를 제어합니다. `mode` 옵션은 에이전트가 어떻게 사용될 수 있는지 결정하는 데 사용됩니다.
```json title="opencode.json"
{
@@ -535,13 +535,13 @@ Only analyze code and suggest changes.
}
```
`mode` `primary`, `subagent`, `all` 중 하나로 설정할 수 있습니다. 설정하지 않으면 기본값은 `all`입니다.
`mode` 옵션은 `primary`, `subagent`, 또는 `all`로 설정할 수 있습니다. `mode`가 지정되지 않은 경우 `all`이 기본값입니다.
---
### Hidden
## 숨김
`hidden: true`를 설정하면 `@` 자동완성 메뉴에서 subagent를 숨길 수 있습니다. 다른 agent가 Task tool을 통해 programmatic으로 호출야 하는 내부 subagent에 유용합니다.
`hidden: true`를 사용하여 `@` 자동 완성 메뉴에서 에이전트를 숨깁니다. 작업 도구를 통해 다른 에이전트에 의해 프로그래밍 방식으로 호출되어야 하는 내부 에이전트에 유용합니다.
```json title="opencode.json"
{
@@ -554,17 +554,17 @@ Only analyze code and suggest changes.
}
```
이 설정은 자동완성 메뉴에서의 사용자 가시성에만 영향을 니다. permission이 허용되면 hidden agent도 모델이 Task tool을 통해 호출 수 있습니다.
자동 완성 메뉴의 사용자 가시성에만 영향을 미칩니다. 숨겨진 에이전트는 권한이 허용된다면 여전히 작업 도구를 통해 모델에 의해 호출 수 있습니다.
:::note
`mode: subagent` agent에만 적용됩니다.
`mode: subagent` 에이전트에만 적용됩니다.
:::
---
### Task permissions
## 작업 권한
`permission.task`로 Task tool을 통해 해당 agent가 호출할 수 있는 subagent 범위를 제어합니다. 유연한 매칭을 glob 패턴을 사용합니다.
`permission.task`와 작업 도구를 통해 에이전트가 호출할 수 있는 서브 에이전트를 제어합니다. 유연한 일치를 glob 패턴을 사용합니다.
```json title="opencode.json"
{
@@ -583,23 +583,23 @@ Only analyze code and suggest changes.
}
```
`deny`로 설정되면 해당 subagent는 Task tool 설명에서 완전히 제거되므로 모델이 호출을 시도하지 않습니다.
`deny`로 설정할 때, 서브 에이전트는 작업 도구 설명에서 완전히 제거됩니다. 따라서 모델은 그것을 호출하려고 시도하지 않습니다.
:::tip
규칙은 선언 순서대로 평가되며, **마지막으로 일치 규칙이 승리합니다**. 위 예에서 `orchestrator-planner`는 `*`(deny)와 `orchestrator-*`(allow) 모두 일치하지만, `orchestrator-*`가 뒤에 있으므로 결과는 `allow`입니다.
규칙은 순서대로 평가되며, **마지막 일치 규칙**이 우선합니다. 위 예에서 `orchestrator-planner`는 `*` (deny)와 `orchestrator-*` (allow) 모두 일치하지만 `orchestrator-*`가 `*` 뒤에 므로 결과는 `allow`입니다.
:::
:::tip
사용자는 agent의 task permission이 deny여도 `@` 자동완성 메뉴를 통해 어떤 subagent든 직접 호출할 수 있습니다.
사용자는 에이전트의 작업 권한이 거부되더라도 `@` 자동 완성 메뉴를 통해 직접 어떤 서브 에이전트든 호출할 수 있습니다.
:::
---
### Color
### 색상
`color` 옵션으로 UI에서 agent의 시각 스타일을 지정할 수 있습니다. 인터페이스에서 agent가 표시되는 방식에 영향을 줍니다.
`color` 옵션으로 UI에서 에이전트의 시각적 모양을 사용자 정의합니다.
유효한 hex 색상(예: `#FF5733`) 또는 theme 색상(`primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`)을 사용하세요.
유효한 hex 색상(예: `#FF5733`) 또는 테마 색상을 사용하십시오: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`.
```json title="opencode.json"
{
@@ -618,7 +618,7 @@ Only analyze code and suggest changes.
### Top P
`top_p` 옵션으로 응답 다양성을 제어합니다. 무작위성 제어하는 Temperature의 대안입니다.
`top_p` 옵션으로 응답 다양성을 제어합니다. 무작위성 제어를 위한 온도의 대안입니다.
```json title="opencode.json"
{
@@ -630,15 +630,15 @@ Only analyze code and suggest changes.
}
```
범위는 0.0~1.0입니다. 값이 낮을수록 집중되고, 높을수록 다양해집니다.
은 0.0에서 1.0 사이입니다. 낮은 값은 더 집중되고, 높은 값은 더 다양니다.
---
### Additional
### 추가 옵션
agent config에 지정한 나머지 옵션은 모델 옵션으로 provider에 **그대로 전달(pass through)** 됩니다. 이를 통해 provider별 기능과 파라미터용할 수 있습니다.
에이전트 구성에 지정하는 다른 옵션은 모델 옵션으로 공급자에게 **직접 전달**됩니다. 이를 통해 공급자별 기능 및 매개변수용할 수 있습니다.
예를 들어 OpenAI reasoning model에서는 reasoning effort를 제어할 수 있습니다.
예를 들어, OpenAI의 추론 모델과 함께, 추론 노력을 제어할 수 있습니다:
```json title="opencode.json" {6,7}
{
@@ -653,55 +653,55 @@ agent config에 지정한 나머지 옵션은 모델 옵션으로 provider에 **
}
```
이 추가 옵션은 model 및 provider마다 다릅니다. 사용 가능한 파라미터는 provider 문서를 확인하세요.
이 추가 옵션은 모델과 공급자별로 다릅니다. 사용 가능한 매개변수는 공급자의 문서를 확인하십시오.
:::tip
사용 가능한 model 목록은 `opencode models` 명령으로 확인할 수 있습니다.
`opencode models`를 실행하여 사용 가능한 모델 목록을 볼 수 있습니다.
:::
---
## 에이전트 생성
## 에이전트 만들기
아래 명령으로 새 agent를 만들 수 있습니다.
다음 명령을 사용하여 새로운 에이전트를 만들 수 있습니다:
```bash
opencode agent create
```
인터랙티브 명령은 다음을 수행합니다.
대화형 명령은:
1. agent 저장 위치를 묻습니다(전역/프로젝트).
2. agent가 수행할 작업의 설명을 습니다.
3. 적절한 시스템 prompt와 식별자를 생성합니다.
4. agent가 접근할 tool을 선택하게 합니다.
5. 마지막으로 agent config가 담긴 Markdown 파일을 생성합니다.
1. 에이전트를 저장 위치를 묻습니다 (전역 또는 프로젝트).
2. 에이전트가 해야 할 일에 대한 설명을 습니다.
3. 적절한 시스템 프롬프트 및 식별자를 생성합니다.
4. 에이전트가 접근할 수 있는 도구를 선택하게 합니다.
5. 마지막으로, 에이전트 구성을 가진 markdown 파일을 생성합니다.
---
## 사용 사례
서로 다른 agent의 대표적인 사용 사례는 다음과 같습니다.
다른 에이전트를 위한 몇 가지 일반적인 사용 사례는 다음과 같습니다.
- **Build agent**: 모든 tool을 활성화한 전체 개발 작업
- **Plan agent**: 코드 변경 없이 분석 계획 수행
- **Review agent**: 읽기 전용 접근 + 문서화 tool 기반 코드 리뷰
- **Debug agent**: bash/read tool 중심의 조사 작업
- **Docs agent**: 파일 작업은 가능하지만 시스템 명령는 문서 작성 작업
- **Build Agent**: 모든 도구와 함께 전체 개발 작업
- **Plan Agent**: 변경 없이 분석 계획
- **Review Agent**: 읽기 전용 액세스 및 문서 도구와 함께 코드 리뷰
- **Debug Agent**: bash 및 읽기 도구와 함께 조사에 집중
- **Docs Agent**: 파일 작업과 문서 작성을 하지만 시스템 명령 없
---
## 예
## 예
실제로 유용하게 쓸 있는 예시 agent를 소개합니다.
여기에 유용 할 수있는 몇 가지 예 에이전트가 있습니다.
:::tip
공유하고 싶은 agent가 있나요? [PR 제출하기](https://github.com/anomalyco/opencode).
공유하고 싶은 에이전트가 있습니까? [PR](https://github.com/anomalyco/opencode).
:::
---
### Documentation agent
### 문서 에이전트
```markdown title="~/.config/opencode/agents/docs-writer.md"
---
@@ -723,7 +723,7 @@ Focus on:
---
### Security auditor
## 보안 감사
```markdown title="~/.config/opencode/agents/security-auditor.md"
---

View File

@@ -1,15 +1,15 @@
---
title: Config
description: Using the OpenCode JSON config.
title: 구성
description: OpenCode JSON 구성을 사용합니다.
---
JSON config 파일로 OpenCode를 설정할 수 있습니다.
JSON 구성 파일을 사용하여 OpenCode를 구성할 수 있습니다.
---
## 형식
OpenCode는 **JSON** **JSONC**(주석이 포함된 JSON) 형식을 모두 지원합니다.
OpenCode는 **JSON** **JSONC** (주석이 있는 JSON) 형식을 지원합니다.
```jsonc title="opencode.jsonc"
{
@@ -25,44 +25,44 @@ OpenCode는 **JSON**과 **JSONC**(주석이 포함된 JSON) 형식을 모두 지
## 위치
config 파일은 여러 위치에 수 있으며, 각 위치에는 우선순위가 있습니다.
구성을 여러 위치에 배치할 수 있으며, 이들은 서로 다른 우선 순위(precedence)를 가집니다.
:::note
config 파일은 **교체되지 않고 병합**됩니다.
구성 파일은 **병합**되며, 대체되지 않습니다.
:::
config 파일은 서로 대체되는 방식이 아니라 병합됩니다. 아래 config 위치의 설정이 결합되며, 충돌하는 key에 대해서만 나중에 로드된 config가 앞선 값을 override합니다. 충돌하지 않는 설정은 모두 유지됩니다.
구성 파일은 함께 병합되며 대체되지 않습니다. 다음 구성 위치의 설정이 결합됩니다. 나중의 구성은 충돌하는 에 대해 이전 구성을 덮어씁니다. 모든 구성의 설정이 보존됩니다.
예를 들어, 전역 config에 `theme: "opencode"` `autoupdate: true`가 있고 프로젝트 config에 `model: "anthropic/claude-sonnet-4-5"`가 있으면 최종 config에는 이 세 설정이 모두 포함됩니다.
예를 들어, 전역 구성이 `theme: "opencode"` `autoupdate: true`를 설정하고 프로젝트 구성이 `model: "anthropic/claude-sonnet-4-5"`를 설정하면 최종 구성에는 세 가지 설정이 모두 포함됩니다.
---
### 우선순위
### 우선 순위
config source는 다음 순서로 로드됩니다(나중 source가 앞선 source를 override).
구성 소스는 다음 순서로 로드됩니다 (나중 소스가 이전 소스를 덮어씀):
1. **Remote config**(`.well-known/opencode`) - 조직 기본값
2. **Global config**(`~/.config/opencode/opencode.json`) - 사용자 기본 설정
3. **Custom config**(`OPENCODE_CONFIG` env var) - custom override
4. **Project config**(프로젝트의 `opencode.json`) - 프로젝트별 설정
5. **`.opencode` directories** - agents, commands, plugins
6. **Inline config**(`OPENCODE_CONFIG_CONTENT` env var) - 런타임 override
1. **원격 구성** (`.well-known/opencode`에서) - 조직 기본값
2. **전역 구성** (`~/.config/opencode/opencode.json`) - 사용자 환경설정
3. **사용자 정의 구성** (`OPENCODE_CONFIG` 환경 변수) - 사용자 정의 재정의
4. **프로젝트별 구성** (`opencode.json`) - 프로젝트별 설정
5. **`.opencode` 디렉토리** - 에이전트, 명령, 플러그인
6. **인라인 구성** (`OPENCODE_CONFIG_CONTENT` 환경 변수) - 런타임 재정의
즉, 프로젝트 config는 전역 기본값을 override할 수 있고, 전역 config는 조직의 Remote 기본값을 override할 수 있습니다.
이것은 프로젝트 구성이 전역 기본값을 덮어쓸 수 있고, 전역 구성이 원격 조직 기본값을 덮어쓸 수 있음을 의미합니다.
:::note
`.opencode` `~/.config/opencode` 디렉토리는 하위 디렉토리에 **복수형 이름**을 사용합니다: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/`, `themes/`. 단수형 이름(예: `agent/`)도 하위 호환성을 위해 지원니다.
`.opencode` `~/.config/opencode` 디렉토리는 하위 디렉토리에 대해 **복수형 이름**을 사용합니다: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/`, 그리고 `themes/`. 단수형 이름(예: `agent/`)도 하위 호환성을 위해 지원니다.
:::
---
### Remote
### 원격
조직은 `.well-known/opencode` endpoint로 기본 config를 제공할 수 있습니다. 이를 지원하는 provider로 인증하면 자동으로 가져옵니다.
조직은 `.well-known/opencode` 엔드포인트를 통해 기본 구성을 제공할 수 있습니다. 이를 지원하는 공급자로 인증할 때 자동으로 가져옵니다.
Remote config는 가장 먼저 로드되어 기본 레이어 역할을 합니다. 이후의 모든 config source(전역, 프로젝트)는 이 기본값을 override할 수 있습니다.
원격 구성은 기본 레이어로 가장 먼저 로드됩니다. 다른 구성 소스(전역, 프로젝트)는 이러한 기본값을 무시(override)할 수 있습니다.
예를 들어, 조직에서 기본 비활성화된 MCP 서버를 제공하는 경우:
예를 들어, 조직 기본적으로 비활성화된 MCP 서버를 제공하는 경우:
```json title="Remote config from .well-known/opencode"
{
@@ -76,7 +76,7 @@ Remote config는 가장 먼저 로드되어 기본 레이어 역할을 합니다
}
```
로컬 config에서 특정 서버를 활성화할 수 있습니다.
로컬 설정에서 특정 서버를 활성화할 수 있습니다:
```json title="opencode.json"
{
@@ -92,65 +92,65 @@ Remote config는 가장 먼저 로드되어 기본 레이어 역할을 합니다
---
### Global
## 전역
전역 OpenCode config는 `~/.config/opencode/opencode.json`에 두세요. theme, provider, keybind 같은 사용자 전체 기본 설정 전역 config로 관리하세요.
`~/.config/opencode/opencode.json`에 전역 OpenCode 구성을 배치합니다. 테마, 공급자, 키바인드와 같은 사용자 전체 기본 설정 전역 구성을 사용하십시오.
전역 config는 조직의 Remote 기본값을 override합니다.
전역 구성은 원격 조직 기본값을 덮어씁니다.
---
### Per project
## 프로젝트별
프로젝트 루트에 `opencode.json`을 추가하세요. 프로젝트 config는 표준 config 파일 중 우선순위장 높아 전역 및 Remote config를 모두 override합니다.
프로젝트 루트에 `opencode.json`을 추가합니다. 프로젝트 구성은 표준 구성 파일 중 가장 높은 우선순위집니다. 이는 전역 및 원격 구성을 모두 덮어씁니다.
:::tip
프로젝트별 config는 프로젝트 루트에 두세요.
프로젝트의 루트에 특정 설정을 둡니다.
:::
OpenCode 시작 현재 디렉토리에서 config 파일을 찾고, 없으면 가장 가까운 Git 디렉토리까지 상위로 탐색합니다.
OpenCode 시작될 때, 현재 디렉토리의 설정 파일이나 가장 가까운 Git 디렉토리를 찾습니다.
파일은 Git에 커밋해도 안전하며 전역 config와 동일한 schema를 사용합니다.
은 Git으로 관리되며 전역 구성과 동일한 스키마를 사용합니다.
---
### Custom path
### 사용자 정의 경로
`OPENCODE_CONFIG` 환경 변수로 custom config 파일 경로를 지정하세요.
`OPENCODE_CONFIG` 환경 변수를 사용하여 사용자 정의 구성 파일 경로를 지정합니다.
```bash
export OPENCODE_CONFIG=/path/to/my/custom-config.json
opencode run "Hello world"
```
Custom config는 우선순위 전역 config와 프로젝트 config 사이에 로드됩니다.
사용자 정의 구성은 우선 순위에서 전역 구성과 프로젝트 구성 사이에 로드됩니다.
---
### Custom directory
## 사용자 정의 디렉토리
`OPENCODE_CONFIG_DIR` 환경 변수로 custom config 디렉토리를 지정할 수 있습니다. 이 디렉토리는 표준 `.opencode` 디렉토리와 동일하게 agents, commands, modes, plugins를 검색하며, 동일한 구조를 따라야 합니다.
`OPENCODE_CONFIG_DIR` 환경 변수를 사용하여 사용자 정의 구성 디렉토리를 지정할 수 있습니다. 이 디렉토리는 표준 `.opencode` 디렉토리와 마찬가지로 에이전트, 명령, 모드 및 플러그인을 검색하며 동일한 구조를 따라야 합니다.
```bash
export OPENCODE_CONFIG_DIR=/path/to/my/config-directory
opencode run "Hello world"
```
custom 디렉토리는 전역 config와 `.opencode` 디렉토리 에 로드되므로 해당 설정을 **override할 수 있습니다**.
사용자 정의 디렉토리는 전역 구성 이후 및 `.opencode` 디렉토리 이전에 로드됩니다.
---
## Schema
## 스키마
config 파일의 schema는 [**`opencode.ai/config.json`**](https://opencode.ai/config.json)에 정의되어 있습니다.
구성 파일에는 [**`opencode.ai/config.json`**](https://opencode.ai/config.json)에 정의된 스키마가 있습니다.
편집기에서 이 schema를 기반으로 validation과 autocomplete를 사용할 수 있습니다.
편집기는 스키마에 따라 유효성 검사 및 자동 완성을 제공해야 합니다.
---
### TUI
#### TUI
`tui` 옵션으로 TUI 관련 설정을 구성할 수 있습니다.
`tui` 옵션을 통해 TUI 관련 설정을 구성할 수 있습니다.
```json title="opencode.json"
{
@@ -165,19 +165,19 @@ config 파일의 schema는 [**`opencode.ai/config.json`**](https://opencode.ai/c
}
```
사용 가능한 옵션:
유효한 옵션:
- `scroll_acceleration.enabled` - macOS 스타일 스크롤 가속을 활성화합니다. **`scroll_speed`보다 우선합니다.**
- `scroll_speed` - 사용자 정의 스크롤 속도 배수(기본: `3`, 최소: `1`). `scroll_acceleration.enabled`가 `true`이면 무시됩니다.
- `diff_style` - diff 렌더링 방식을 제어합니다. `"auto"`는 터미널 너비에 맞춰 조정되고, `"stacked"`는 항상 단일 컬럼으로 표시합니다.
- `scroll_speed` - 사용자 정의 스크롤 속도 배수 (기본: `3`, 최소: `1`). `scroll_acceleration.enabled`가 `true`이면 무시됩니다.
- `diff_style` - diff 렌더링을 제어합니다. `"auto"`는 터미널 너비에 맞고, `"stacked"`는 항상 단일 열을 보여줍니다.
[TUI에 대해 더 알아보기](/docs/tui).
[TUI 사용법에 대해 더 알아보기](/docs/tui).
---
### Server
## 서버
`server` 옵션으로 `opencode serve` `opencode web` 명령의 server 설정을 구성할 수 있습니다.
`opencode serve` `opencode web` 명령에 대한 서버 설정을 구성할 수 있습니다.
```json title="opencode.json"
{
@@ -192,21 +192,21 @@ config 파일의 schema는 [**`opencode.ai/config.json`**](https://opencode.ai/c
}
```
사용 가능한 옵션:
유효한 옵션:
- `port` - 수신할 포트입니다.
- `hostname` - 수신할 호스트명입니다. `mdns`가 활성화되어 있고 hostname이 없으면 기본값은 `0.0.0.0`니다.
- `mdns` - mDNS service discovery를 활성화합니다. 네트워크 다른 기기에서 OpenCode server를 찾을 수 있습니다.
- `mdnsDomain` - mDNS service의 custom 도메인 이름입니다. 기본값은 `opencode.local`입니다. 같은 네트워크에서 여러 인스턴스를 실행할 때 유용합니다.
- `cors` - 브라우저 기반 client에서 HTTP server를 사용할 때 허용할 추가 CORS origin입니다. 값은 전체 origin(scheme + host + optional port) 형식이어야 하며, 예: `https://app.example.com`.
- `port` - 리스닝 포트.
- `hostname` - 리스닝 호스트 이름. `mdns`가 활성화되고 hostname이 설정되지 않으면 `0.0.0.0`이 기본값이 됩니다.
- `mdns` - mDNS 서비스 발견 활성화. 로컬 네트워크 다른 장치가 OpenCode 서버를 찾을 수 있습니다.
- `mdnsDomain` - mDNS 서비스를 위한 사용자 정의 도메인 이름. 기본값은 `opencode.local`입니다. 동일한 네트워크에서 여러 인스턴스를 실행할 때 유용합니다.
- `cors` - 브라우저 기반 클라이언트에서 HTTP 서버를 사용할 때 CORS를 허용할 추가 출처(Origin). 값은 전체 출처(스킴 + 호스트 + 선택적 포트)여야 합니다. 예: `https://app.example.com`.
[server에 대해 더 알아보기](/docs/server).
[서버에 대해 더 알아보기](/docs/server).
---
### Tools
## 도구
`tools` 옵션으로 LLM이 사용할 수 있는 tool을 관리할 수 있습니다.
`tools` 옵션을 통해 LLM이 사용할 수 있는 도구를 구성할 수 있습니다.
```json title="opencode.json"
{
@@ -218,13 +218,13 @@ config 파일의 schema는 [**`opencode.ai/config.json`**](https://opencode.ai/c
}
```
[tool에 대해 더 알아보기](/docs/tools).
[도구에 대해 더 알아보기](/docs/tools).
---
### Models
## 모델
OpenCode config의 `provider`, `model`, `small_model` 옵션으로 사용할 provider와 model을 설정할 수 있습니다.
`provider`, `model`, `small_model` 옵션을 통해 OpenCode 구성에서 사용할 공급자와 모델을 구성할 수 있습니다.
```json title="opencode.json"
{
@@ -235,9 +235,9 @@ OpenCode config의 `provider`, `model`, `small_model` 옵션으로 사용할 pro
}
```
`small_model`은 제목 생성 같은 경량 작업에 사용할 별도 model을 설정합니다. 기본적으로 OpenCode는 provider에서 더 저렴한 model을 사용할 수우선 사용하고, 없으면 메인 model로 fallback합니다.
`small_model` 옵션은 제목 생성 같은 가벼운 작업을 위한 별도의 모델을 구성합니다. 기본적으로, OpenCode는 공급자에게서 사용 가능한 더 저렴한 모델이그것을 사용하고, 그렇지 않으면 주 모델로 돌아갑니다.
provider 옵션에는 `timeout`, `setCacheKey`를 포함할 수 있습니다.
공급자 옵션 `timeout` `setCacheKey`를 포함할 수 있습니다:
```json title="opencode.json"
{
@@ -253,20 +253,20 @@ provider 옵션에는 `timeout`, `setCacheKey`를 포함할 수 있습니다.
}
```
- `timeout` - 요청 timeout(밀리초, 기본값: 300000). `false`로 비활성화할 수 있습니다.
- `setCacheKey` - 지정된 provider에 대해 cache key가 항상 설정되도록 보장합니다.
- `timeout` - 요청 타임아웃(밀리초) (기본값: 300000). `false`로 설정하여 비활성화할 수 있습니다.
- `setCacheKey` - 지정된 공급자에 대해 캐시 키가 항상 설정되도록 강제합니다.
[local model](/docs/models#local)도 설정할 수 있습니다. [더 알아보기](/docs/models).
[로컬 모델](/docs/models#local)을 구성할 수 있습니다. [더 알아보기](/docs/models).
---
#### Provider-Specific Options
### 공급자별 옵션
부 provider는 공통 옵션인 `timeout`, `apiKey` 외에 추가 config 옵션을 지원합니다.
반적인 `timeout` `apiKey` 외에도 일부 공급자는 추가 구성 옵션을 지원합니다.
##### Amazon Bedrock
Amazon Bedrock AWS 전용 config를 지원합니다.
Amazon Bedrock AWS 관련 구성을 지원합니다:
```json title="opencode.json"
{
@@ -283,21 +283,21 @@ Amazon Bedrock은 AWS 전용 config를 지원합니다.
}
```
- `region` - Bedrock AWS 리전(`AWS_REGION` env var 또는 기본값 `us-east-1`)
- `profile` - `~/.aws/credentials`의 AWS named profile(기본값: `AWS_PROFILE` env var)
- `endpoint` - VPC endpoint용 custom endpoint URL입니다. AWS 용어를 사용한 일반 `baseURL` 옵션의 별칭(alias)입니다. 둘 다 지정하면 `endpoint`가 우선합니다.
- `region` - Bedrock를 위한 AWS 리전 (`AWS_REGION` 환경 변수 또는 `us-east-1`이 기본값)
- `profile` - `~/.aws/credentials`의 AWS 프로필 이름 (`AWS_PROFILE` 환경 변수가 기본값)
- `endpoint` - VPC 엔드포인트 등을 위한 사용자 정의 엔드포인트 URL. 이는 AWS 관련 용어를 사용한 일반적인 `baseURL` 옵션의 별칭입니다. 둘 다 지정된 경우 `endpoint`가 우선합니다.
:::note
Bearer token(`AWS_BEARER_TOKEN_BEDROCK` 또는 `/connect`)은 profile 기반 인증보다 우선합니다. 자세한 내용은 [authentication precedence](/docs/providers#authentication-precedence)를 참고하세요.
Bearer 토큰(`AWS_BEARER_TOKEN_BEDROCK` 또는 `/connect`)은 프로필 기반 인증보다 우선합니다. 자세한 내용은 [인증 우선 순위](/docs/providers#authentication-precedence)를 참조하십시오.
:::
[Amazon Bedrock config 더 알아보기](/docs/providers#amazon-bedrock).
[Amazon Bedrock에 대해 더 알아보기](/docs/providers#amazon-bedrock).
---
### Themes
## 테마
`theme` 옵션으로 OpenCode config에서 사용할 theme를 설정할 수 있습니다.
`theme` 옵션을 통해 OpenCode 구성에서 사용할 테마를 설정할 수 있습니다.
```json title="opencode.json"
{
@@ -310,9 +310,9 @@ Bearer token(`AWS_BEARER_TOKEN_BEDROCK` 또는 `/connect`)은 profile 기반 인
---
### Agents
## 에이전트
`agent` 옵션으로 특정 작업 전문 agent를 구성할 수 있습니다.
`agent` 옵션을 통해 특정 작업 전문으로 하는 에이전트를 구성할 수 있습니다.
```jsonc title="opencode.jsonc"
{
@@ -332,13 +332,13 @@ Bearer token(`AWS_BEARER_TOKEN_BEDROCK` 또는 `/connect`)은 profile 기반 인
}
```
`~/.config/opencode/agents/` 또는 `.opencode/agents/` Markdown 파일로 agent를 정의할 수도 있습니다. [더 알아보기](/docs/agents).
`~/.config/opencode/agents/` 또는 `.opencode/agents/`에서 Markdown 파일을 사용하여 에이전트를 정의할 수도 있습니다. [더 알아보기](/docs/agents).
---
### Default agent
### 기본 에이전트
`default_agent` 옵션으로 기본 agent를 설정할 수 있습니다. 별도 지정이 없을 때 어떤 agent를 사용지 결정합니다.
`default_agent` 옵션을 사용하여 기본 에이전트를 설정할 수 있습니다. 명시적으로 지정되지 않았을 때 어떤 에이전트가 사용지 결정합니다.
```json title="opencode.json"
{
@@ -347,15 +347,15 @@ Bearer token(`AWS_BEARER_TOKEN_BEDROCK` 또는 `/connect`)은 profile 기반 인
}
```
기본 agent는 primary agent여야 합니다(subagent 불가). `"build"`, `"plan"` 같은 내장 agent나 직접 정의 [custom agent](/docs/agents)를 지정할 수 있습니다. 지정한 agent가 없거나 subagent이면 OpenCode는 경고와 함께 `"build"`로 fallback합니다.
기본 에이전트는 기본(primary) 에이전트여야 합니다(서브 에이전트 불가). `"build"` 또는 `"plan"` 같은 내장 에이전트이거나 정의 [사용자 정의 에이전트](./agents) 수 있습니다. 지정된 에이전트가 존재하지 않는 경우, OpenCode는 경고와 함께 `"build"`로 돌아갑니다.
이 설정은 TUI, CLI(`opencode run`), 데스크톱 앱, GitHub Action 등 모든 인터페이스에 적용됩니다.
이 설정은 모든 인터페이스에 적용됩니다: TUI, CLI (`opencode run`), 데스크톱 앱 GitHub Action.
---
### Sharing
## 공유
`share` 옵션으로 [share](/docs/share) 기능을 설정할 수 있습니다.
`share` 옵션을 통해 [공유](/docs/share) 기능을 구성할 수 있습니다.
```json title="opencode.json"
{
@@ -364,19 +364,19 @@ Bearer token(`AWS_BEARER_TOKEN_BEDROCK` 또는 `/connect`)은 profile 기반 인
}
```
허용 값:
은 다음과 같습니다:
- `"manual"` - 명령으로 수동 공유 허용(기본값)
- `"auto"` - 새 대화를 자동 공유
- `"disabled"` - 공유 기능 완전 비활성화
- `"manual"` - 명령을 통한 수동 공유 허용 (기본값)
- `"auto"` - 새로운 대화를 자동으로 공유
- `"disabled"` - 공유 기능 완전 비활성화
기본값은 manual 모드이며, `/share` 명령으로 명시적으로 공유해야 니다.
기본적으로 `/share` 명령을 사용하여 대화를 명시적으로 공유해야 하는 수동 모드로 설정됩니다.
---
### Commands
## 명령
`command` 옵션으로 반복 작업용 custom command를 구성할 수 있습니다.
`command` 옵션을 통해 반복 작업을 위한 사용자 정의 명령을 구성할 수 있습니다.
```jsonc title="opencode.jsonc"
{
@@ -387,6 +387,8 @@ Bearer token(`AWS_BEARER_TOKEN_BEDROCK` 또는 `/connect`)은 profile 기반 인
"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.",
@@ -396,13 +398,13 @@ Bearer token(`AWS_BEARER_TOKEN_BEDROCK` 또는 `/connect`)은 profile 기반 인
}
```
`~/.config/opencode/commands/` 또는 `.opencode/commands/` Markdown 파일로 command를 정의할 수도 있습니다. [더 알아보기](/docs/commands).
`~/.config/opencode/commands/` 또는 `.opencode/commands/`에서 Markdown 파일을 사용하여 명령을 정의할 수도 있습니다. [더 알아보기](/docs/commands).
---
### Keybinds
## 키바인드
`keybinds` 옵션으로 keybind를 커스터마이즈할 수 있습니다.
`keybinds` 옵션을 통해 키바인드를 사용자 정의할 수 있습니다.
```json title="opencode.json"
{
@@ -415,9 +417,9 @@ Bearer token(`AWS_BEARER_TOKEN_BEDROCK` 또는 `/connect`)은 profile 기반 인
---
### Autoupdate
## 자동 업데이트
OpenCode는 시작 시 새 업데이트를 자동으로 다운로드합니다. `autoupdate` 옵션으로 비활성화할 수 있습니다.
OpenCode는 시작될 때 자동으로 새로운 업데이트를 다운로드합니다. `autoupdate` 옵션으로 이를 비활성화할 수 있습니다.
```json title="opencode.json"
{
@@ -426,14 +428,14 @@ OpenCode는 시작 시 새 업데이트를 자동으로 다운로드합니다. `
}
```
업데이트를 자동 적용하지 않 새 버전 알림받고 싶다면 `autoupdate`를 `"notify"`로 설정하세요.
이 옵션은 Homebrew 같은 패키지 매니저로 설치지 않은 경우에만 작합니다.
업데이트를 하지 않지만 새 버전 알림받고 싶다면 `autoupdate`를 `"notify"`로 설정하십시오.
Homebrew 같은 패키지 관리자를 사용하여 설치지 않은 경우에만 작합니다.
---
### Formatters
## 포매터
`formatter` 옵션으로 코드 formatter를 설정할 수 있습니다.
`formatter` 옵션을 통해 코드 포매터를 구성할 수 있습니다.
```json title="opencode.json"
{
@@ -453,15 +455,15 @@ OpenCode는 시작 시 새 업데이트를 자동으로 다운로드합니다. `
}
```
[formatter에 대해 더 알아보기](/docs/formatters).
[포매터에 대해 더 알아보기](/docs/formatters).
---
### Permissions
## 권한
기본적으로 OpenCode는 **명시적 승인 없이 모든 작업을 허용**합니다. `permission` 옵션으로 이 동작을 바꿀 수 있습니다.
기본적으로, OpenCode는 **명시적 승인 없이 모든 작업을 허용**합니다. `permission` 옵션을 사용하여 이를 변경할 수 있습니다.
예를 들어 `edit`, `bash` tool이 사용자 승인을 요구하하려면:
예를 들어, `edit` `bash` 도구가 사용자 승인을 요구하도록 설정하려면:
```json title="opencode.json"
{
@@ -473,34 +475,32 @@ OpenCode는 시작 시 새 업데이트를 자동으로 다운로드합니다. `
}
```
[permission에 대해 더 알아보기](/docs/permissions).
[권한에 대해 더 알아보기](/docs/permissions).
---
### Compaction
### 압축
`compaction` 옵션으로 context compaction 동작을 제어할 수 있습니다.
`compaction` 옵션을 통해 컨텍스트 압축 동작을 제어할 수 있습니다.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"compaction": {
"auto": true,
"prune": true,
"reserved": 10000
"prune": true
}
}
```
- `auto` - context가 가득 찼을 때 세션을 자동 compact합니다(기본값: `true`).
- `prune` - token 절약 위해 오래된 tool 출력을 제거합니다(기본값: `true`).
- `reserved` - compaction용 token buffer입니다. compaction 중 overflow가 나지 않도록 충분한 window를 남깁니다.
- `auto` - 컨텍스트가 꽉 차면 자동으로 세션을 압축합니다 (기본값: `true`).
- `prune` - 토큰을 절약하기 위해 오래된 도구 출력을 제거합니다 (기본값: `true`).
---
### Watcher
### 파일 감시자
`watcher` 옵션으로 파일 watcher ignore 패턴을 설정할 수 있습니다.
`watcher` 옵션을 통해 파일 감시자가 무시할 패턴을 설정할 수 있습니다.
```json title="opencode.json"
{
@@ -511,13 +511,13 @@ OpenCode는 시작 시 새 업데이트를 자동으로 다운로드합니다. `
}
```
패턴은 glob 문을 따릅니다. 파일 감시에서 노이즈가 많은 디렉토리를 제외할 때 유용합니다.
패턴은 glob 문을 따릅니다. 잡음이 많은 디렉토리를 제외하는 데 사용하십시오.
---
### MCP servers
### MCP 서버
`mcp` 옵션으로 사용할 MCP server를 설정할 수 있습니다.
`mcp` 옵션을 통해 사용하려는 MCP 서버를 구성할 수 있습니다.
```json title="opencode.json"
{
@@ -530,11 +530,11 @@ OpenCode는 시작 시 새 업데이트를 자동으로 다운로드합니다. `
---
### Plugins
### 플러그인
[Plugins](/docs/plugins)는 custom tool, hook, integration으로 OpenCode를 확장합니다.
[플러그인](/docs/plugins)은 사용자 정의 도구, 훅(hook), 통합으로 OpenCode를 확장합니다.
plugin 파일은 `.opencode/plugins/` 또는 `~/.config/opencode/plugins/`에 두세요. `plugin` 옵션으로 npm plugin을 로드할 수 있습니다.
`.opencode/plugins/` 또는 `~/.config/opencode/plugins/`에 플러그인 파일을 배치하십시오. `plugin` 옵션을 통해 npm에서 플러그인을 로드할 수 있습니다.
```json title="opencode.json"
{
@@ -547,9 +547,9 @@ plugin 파일은 `.opencode/plugins/` 또는 `~/.config/opencode/plugins/`에
---
### Instructions
### 지침
`instructions` 옵션으로 사용 중인 model에 제공할 지침 파일을 설정할 수 있습니다.
`instructions` 옵션을 통해 모델에 대한 지침(Rules)을 구성할 수 있습니다.
```json title="opencode.json"
{
@@ -558,13 +558,13 @@ plugin 파일은 `.opencode/plugins/` 또는 `~/.config/opencode/plugins/`에
}
```
이 옵션은 지침 파일 경로 glob 패턴 배열을 받습니다. [rules에 대해 더 알아보기](/docs/rules).
지침 파일에 대한 경로 glob 패턴 배열을 사용합니다. [규칙에 대해 더 알아보기](/docs/rules).
---
### Disabled providers
## 비활성화된 공급자
`disabled_providers` 옵션으로 자동 로드되는 provider를 비활성화할 수 있습니다. credential이 있어도 특정 provider를 로드하지 않게 하고 싶을 때 유용합니다.
`disabled_providers` 옵션을 통해 자동으로 로드되는 공급자를 비활성화할 수 있습니다. 자격 증명이 유효하더라도 특정 공급자가 로드되는 것을 방지할 때 유용합니다.
```json title="opencode.json"
{
@@ -577,17 +577,17 @@ plugin 파일은 `.opencode/plugins/` 또는 `~/.config/opencode/plugins/`에
`disabled_providers`는 `enabled_providers`보다 우선합니다.
:::
`disabled_providers`는 provider ID 배열을 받습니다. provider가 비활성화되면:
`disabled_providers` 옵션은 공급자 ID 배열을 허용합니다. 공급자가 비활성화되면:
- 환경 변수가 설정되어 있어도 로드되지 않습니다.
- `/connect` 명령으로 API key를 설정해도 로드되지 않습니다.
- 해당 provider의 model은 model 선택 목록에 표시되지 않습니다.
- 환경 변수가 설정된 경우에도 로드되지 않습니다.
- API 키가 `/connect` 명령을 통해 구성되는 경우에도 로드되지 않습니다.
- 공급자의 모델은 모델 선택 목록에 표시되지 않습니다.
---
### Enabled providers
### 활성화된 공급자
`enabled_providers` 옵션으로 provider allowlist를 지정할 수 있습니다. 이 값을 설정하면 지정한 provider만 활성화되고 나머지는 무시됩니다.
`enabled_providers` 옵션을 통해 허용할 공급자를 지정할 수 있습니다. 설정하면 지정된 공급자만 활성화되고 다른 모든 공급자는 무시됩니다.
```json title="opencode.json"
{
@@ -596,19 +596,19 @@ plugin 파일은 `.opencode/plugins/` 또는 `~/.config/opencode/plugins/`에
}
```
provider를 하나씩 비활성화하는 대신, OpenCode가 특정 provider만 사용하도록 제한하고 싶을 때 유용합니다.
OpenCode를 제한하여 특정 공급자만 사용하도록 때 유용합니다.
:::note
`disabled_providers`는 `enabled_providers`보다 우선합니다.
:::
동일 provider가 `enabled_providers`와 `disabled_providers`에 모두 있으면 하위 호환성을 위해 `disabled_providers`가 우선합니다.
공급자가 `enabled_providers`와 `disabled_providers` 둘 다에 나타나면, 하위 호환성을 위해 `disabled_providers`가 우선합니다.
---
### Experimental
### 실험적 기능
`experimental` key에는 현재 활발히 개발 중인 옵션 포함니다.
`experimental` 키는 활발히 개발 중인 옵션 포함니다.
```json title="opencode.json"
{
@@ -618,20 +618,20 @@ provider를 하나씩 비활성화하는 대신, OpenCode가 특정 provider만
```
:::caution
experimental 옵션은 안정적이지 않습니다. 예고 없이 변경되거나 제거될 수 있습니다.
실험적 옵션은 안정적이지 않습니다. 예고 없이 변경되거나 제거될 수 있습니다.
:::
---
## Variables
## 변수
config 파일에서 환경 변수와 파일 내용을 참조할 수 있도록 변수 치환을 사용할 수 있습니다.
구성 파일에서 환경 변수를 참조하고 파일 내용에 대한 변수 대체를 사용할 수 있습니다.
---
### Env vars
##### 환경 변수
`{env:VARIABLE_NAME}` 형식으로 환경 변수를 치환할 수 있습니다.
`{env:VARIABLE_NAME}`을 사용하여 환경 변수를 대체합니다.
```json title="opencode.json"
{
@@ -648,13 +648,13 @@ config 파일에서 환경 변수와 파일 내용을 참조할 수 있도록
}
```
환경 변수가 설정되지 않으면 빈 문자열로 치환됩니다.
환경 변수가 설정되지 않으면 빈 문자열로 대체됩니다.
---
### Files
## 파일
`{file:path/to/file}` 형식으로 파일 내용을 치환할 수 있습니다.
`{file:path/to/file}`를 사용하여 파일 내용을 대체합니다.
```json title="opencode.json"
{
@@ -670,13 +670,13 @@ config 파일에서 환경 변수와 파일 내용을 참조할 수 있도록
}
```
파일 경로는 다음을 지원합니다.
파일 경로는:
- config 파일 디렉토리 기준 상대 경로
- `/` 또는 `~`로 시작하는 절대 경로
- 구성 파일 디렉토리에 상대적이거나
- `/` 또는 `~`로 시작하는 절대 경로여야 합니다.
기능은 다음 상황에 유용합니다.
은 다음에 유용합니다:
- API key 같은 민감 정보를 별도 파일로 분리
- 큰 지침 파일을 config를 복잡하게 만들지 않고 포함
- 여러 config 파일에서 공통 설정 스니펫 재사용
- API 키와 같은 민감한 데이터를 별도 파일에 유지할 때.
- 구성을 어지럽히지 않고 큰 지침 파일을 포함할 때.
- 여러 구성 파일에서 공통 구성 스니펫을 공유할 때.

View File

@@ -1,30 +1,30 @@
---
title: Custom Tools
description: Create tools the LLM can call in OpenCode.
title: 사용자 정의 도구
description: OpenCode에서 LLM이 호출할 수 있는 도구를 만듭니다.
---
custom tool은 대화 중 LLM이 호출할 수 있도록 사용자가 직접 만든 함수입니다. `read`, `write`, `bash` 같은 OpenCode의 [built-in tools](/docs/tools)와 함께 작합니다.
사용자 정의 도구는 LLM이 대화 중에 호출 할 수있는 기능을 만듭니다. 그들은 `read`, `write` `bash` 같은 opencode의 [붙박이 도구](./tools)와 함께 작합니다.
---
## 도구 만들기
tool은 **TypeScript** 또는 **JavaScript** 파일로 정의니다. 다만 tool 정의에서 호출하는 스크립트는 **어떤 언어든** 사용할 수 있습니다. 즉, TypeScript/JavaScript는 tool 정의 자체에만 필요합니다.
도구는 **TypeScript** 또는 **JavaScript** 파일로 정의니다. 그러나 도구 정의는 ** 어떤 언어로 작성된 스크립트를 호출 할 수 있습니다 ** - TypeScript 또는 JavaScript는 도구 정의 자체에사용됩니다.
---
### 위치
## 위치
tool은 다음 위치에 둘 수 있습니다.
그들은 정의 할 수 있습니다:
- 프로젝트의 `.opencode/tools/` 디렉토리(로컬)
- `~/.config/opencode/tools/` 디렉토리(전역)
- 프로젝트의 `.opencode/tools/` 디렉토리에 배치하여 로컬.
- 또는 전 세계적으로 `~/.config/opencode/tools/`에 배치하여.
---
### 구조
## 구조
tool을 가장 쉽게 만드는 방법은 타입 안정성과 validation을 제공하는 `tool()` helper를 사용하는 것입니다.
도구를 만드는 가장 쉬운 방법은 `tool()` helper를 사용하여 유형 안전 및 검증을 제공합니다.
```ts title=".opencode/tools/database.ts" {1}
import { tool } from "@opencode-ai/plugin"
@@ -41,13 +41,13 @@ export default tool({
})
```
**파일 이름** **tool 이름** 됩니다. 위 예시는 `database` tool을 생성합니다.
**파일 이름** **tool name** 됩니다. 위는 `database` 공구를 만듭니다.
---
#### 파일 하나에 여러 tool 정의
### 파일당 여러 도구
하나의 파일에서 여러 tool을 export할 수 있습니다. 각 export는 **별도의 tool**이 되며 이름 **`<filename>_<exportname>`** 형식을 사용합니다.
단일 파일에서 여러 도구를 수출할 수 있습니다. 각 수출은 ** 별도의 도구 ** 이름 ** `<filename>_<exportname>`**:
```ts title=".opencode/tools/math.ts"
import { tool } from "@opencode-ai/plugin"
@@ -75,13 +75,13 @@ export const multiply = tool({
})
```
경우 `math_add`, `math_multiply` 두 tool이 생성됩니다.
것은 2개의 공구를 만듭니다: `math_add` `math_multiply`.
---
### 인자
#### 스키마
인자 타입은 `tool.schema`로 정의할 수 있습니다. `tool.schema`는 [Zod](https://zod.dev) 기반입니다.
`tool.schema`를 사용할 수 있습니다, 그냥 [Zod](https://zod.dev), 인수 유형을 정의합니다.
```ts "tool.schema"
args: {
@@ -89,7 +89,7 @@ args: {
}
```
[Zod](https://zod.dev)를 직접 import해서 일반 객체를 반환하는 방식도 사용할 수 있습니다.
[Zod](https://zod.dev)를 직접 가져오고 일반 객체를 반환할 수 있습니다.
```ts {6}
import { z } from "zod"
@@ -108,9 +108,9 @@ export default {
---
### Context
### 컨텍스트
tool은 현재 세션의 context 정보를 전달받습니다.
도구는 현재 세션에 대한 컨텍스트를받습니다.
```ts title=".opencode/tools/project.ts" {8}
import { tool } from "@opencode-ai/plugin"
@@ -126,18 +126,18 @@ export default tool({
})
```
세션 작업 디렉토리 `context.directory`를 사용하세요.
git worktree 루트 `context.worktree`를 사용하세요.
세션 작업 디렉토리 `context.directory`를 사용합니다.
git worktree 루트 `context.worktree`를 사용합니다.
---
## 예
## 예
### Python으로 tool 작성
### Python 도구 작성
tool은 원하는 언어로 작성할 수 있습니다. 아래는 Python으로 두 숫자를 하는 예입니다.
원하는 모든 언어로 도구를 쓸 수 있습니다. 여기에 Python을 사용하여 두 개의 숫자를 추가하는 예입니다.
먼저 Python 스크립트로 tool을 만듭니다.
먼저 Python 스크립트로 도구를 만듭니다.
```python title=".opencode/tools/add.py"
import sys
@@ -147,7 +147,7 @@ b = int(sys.argv[2])
print(a + b)
```
그다음 이 스크립트를 호출하는 tool 정의를 만듭니다.
다음 도구 정의를 만듭니다.
```ts title=".opencode/tools/python-add.ts" {10}
import { tool } from "@opencode-ai/plugin"
@@ -167,4 +167,4 @@ export default tool({
})
```
여기서는 Python 스크립트를 실행하기 위해 [`Bun.$`](https://bun.com/docs/runtime/shell) 유틸리티를 사용합니다.
여기에 우리는 [`Bun.$`](https://bun.com/docs/runtime/shell) 유틸리티를 사용하여 Python 스크립트를 실행합니다.

View File

@@ -84,8 +84,7 @@ curl -fsSL https://opencode.ai/install | bash
- **Arch Linux에서 Paru 사용**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -84,8 +84,7 @@ Du kan også installere den med følgende kommandoer:
- **Bruke Paru på Arch Linux**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -84,8 +84,7 @@ Możesz też użyć poniższych metod instalacji:
- **Korzystanie z Paru na Arch Linux**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -84,8 +84,7 @@ Você também pode instalá-lo com os seguintes comandos:
- **Usando Paru no Arch Linux**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -84,8 +84,7 @@ curl -fsSL https://opencode.ai/install | bash
- **Использование Paru в Arch Linux**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -84,8 +84,7 @@ curl -fsSL https://opencode.ai/install | bash
- **ใช้ Paru บน Arch Linux**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -84,8 +84,7 @@ Ayrıca aşağıdaki komutlarla da yükleyebilirsiniz:
- **Paru'yu Arch Linux'ta kullanma**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -84,8 +84,7 @@ curl -fsSL https://opencode.ai/install | bash
- **在 Arch Linux 上使用 Paru**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -169,7 +169,7 @@ opencode自动处理远程MCP服务器的OAuth身份验证。当服务器需要
1. 检测 401 响应并启动 OAuth 流程
2. 如果服务器支持,请使用**动态客户端注册 (RFC 7591)**
3. 安全地存Tokens以供将的请求
3. 安全地存Tokens以供将的请求
---
@@ -189,7 +189,7 @@ opencode自动处理远程MCP服务器的OAuth身份验证。当服务器需要
}
```
如果服器需要身份验证opencode 将在您第一次尝试使用它提示您进行身份验证。如果有,您可以使用 `timeout`[手动触发流量](#authenticating)。
如果服器需要身份验证opencode 将在您第一次嘗試使用它提示您进行身份验证。如果有,您可以使用 `timeout`[手动觸發流量](#authenticating)。
---
@@ -218,7 +218,7 @@ opencode自动处理远程MCP服务器的OAuth身份验证。当服务器需要
### 身份验证
您可以手动触发身份验证或管理凭据
您可以手动觸發身份验证或管理憑據
使用特定MCP服务器进行身份验证
@@ -232,7 +232,7 @@ opencode mcp auth my-oauth-server
opencode mcp list
```
删除存储的凭据
删除存儲的憑據
```bash
opencode mcp logout my-oauth-server
@@ -297,7 +297,7 @@ opencode mcp debug my-oauth-server
### 全局
这意味著您可以全局启用或禁用它
这意味著您可以全局启用或禁用它
```json title="opencode.json" {14}
{

View File

@@ -17,7 +17,7 @@ opencode 使用 [AI SDK](https://ai-sdk.dev/) 和 [Models.dev](https://models.de
## 选择模型
配置完提供商,您可以通过入以下内容来选择您想要的模型:
配置完提供商,您可以通过入以下內容來选择您想要的模型:
```bash frame="none"
/models
@@ -27,29 +27,29 @@ opencode 使用 [AI SDK](https://ai-sdk.dev/) 和 [Models.dev](https://models.de
## 推荐模型
有很多模型,每都会有新模型世。
有很多模型,每都会有新模型世。
:::tip
使用我们推的模型之一。
使用我们推的模型之一。
:::
然而,既擅生成代又擅工具调用的只有少
然而,既擅生成代又擅工具调用的只有少
以下是与 opencode 配合良好的几个模型,排名不分前面。(这不是好看的列表,也不一定是最新的):
- GPT 5.2
- GPT 5.1 Codex
- Claude Opus 4.5
- Claude Sonnet 4.5
- Minimax M2.1
- Gemini 3 Pro
- GPT 5.1 法典
- 近距離工作4.5
- 克勞德十四行詩 4.5
- 极小极M2.1
- 雙子座 3 专業版
---
## 设置默认值
要将其中之一设置为默模型,您可以在您的
开代码配置。
要将其中之一设置为默模型,您可以在您的
開代碼配置。
```json title="opencode.json" {3}
{
@@ -143,14 +143,14 @@ opencode 使用 [AI SDK](https://ai-sdk.dev/) 和 [Models.dev](https://models.de
opencode 附带了许多重大的默认变体:
**Anthropic**
**人擇**
- `high` - 高思维预算(默认)
- `max` - 最大预算规划
**OpenAI**
因模型而,但大致如下:
因模型而,但大致如下:
- `none` - 没有推理
- `minimal` - 最少的推理工作
@@ -159,18 +159,18 @@ opencode 附带了许多重大的默认变体:
- `high` - 高推理能力
- `xhigh` - 极高的推理能力
**Google**
**谷歌**
- `low` - 降低工作量/Tokens
- `high` - 更高的努力/Tokens
- `low` - 降低工作量/Tokens
- `high` - 更高的努力/Tokens
:::tip
该列表并不全面。多其他提供商也有内置的默值。
该列表并不全面。多其他提供商也有内置的默值。
:::
### 自定义变体
您可以覆盖现有变体或添加您自己的变体
您可以覆盖現有變體或添加您自己的變體
```jsonc title="opencode.jsonc" {7-18}
{
@@ -195,7 +195,7 @@ opencode 附带了许多重大的默认变体:
}
```
### 切换变体
### 循环变体
使用按键绑定`variant_cycle`在变体之间快速切换。 [了解更多](/docs/keybinds)。
@@ -220,4 +220,4 @@ opencode 附带了许多重大的默认变体:
3. 最后使用的模型。
4. 第一个模型使用内部优先
4. 第一个模型使用内部优先

View File

@@ -1,6 +1,6 @@
---
title: 模式
description: 不同的模式用于不同的用例。
description: 不同的模式用于不同的用例。
---
:::caution
@@ -13,7 +13,7 @@ opencode 中的模式允许自定义不同的示例行为、工具和提示。
它具有两种内置模式:**构建**和**计划**。您可以定制
这些或通过 opencode 配置配置您自己的。
您可以在会话期在模式之间切换或在配置文件中配置它
您可以在会话期在模式之間切換或在配置文件中配置它
---
@@ -25,13 +25,13 @@ opencode 有两种内置模式。
### 构建
建是启用所有工具的**默**模式。这是开发工作的标准模式,您需要完全访问文件操作和系命令。
建是启用所有工具的**默**模式。这是開發工作的標準模式,您需要完全访问文件操作和系命令。
---
### 计划
专为规划和分析而设计的受限模式。在计划模式下,默情况下禁用以下工具:
专为規劃和分析而設計的受限模式。在計劃模式下,默情况下禁用以下工具:
- `write` - 无法创建新文件
- `edit` - 无法修改现有文件,位于 `.opencode/plans/*.md` 的用于详细说明计划本身的文件另外
@@ -52,7 +52,7 @@ opencode 有两种内置模式。
## 配置
您可以自定内置模式或通过配置创建自己的模式。可以通过两种方式配置模式:
您可以自定内置模式或通过配置创建自己的模式。可以通过两种方式配置模式:
### JSON 配置
@@ -112,7 +112,7 @@ Provide constructive feedback without making direct changes.
Markdown 文件名成为模式名称(例如,`review.md` 创建`review` 模式)。
我们详细看看这些配置选项
我们詳細看看这些配置選項
---
@@ -191,7 +191,7 @@ Markdown 文件名成为模式名称(例如,`review.md` 创建`review` 模
}
```
该路是相对于配置文件所在位置的。所以这用于
该路是相对于配置文件所在位置的。所以这用于
全局opencode配置和项目特定配置。
---
@@ -217,13 +217,13 @@ Markdown 文件名成为模式名称(例如,`review.md` 创建`review` 模
}
```
如果未指定任何工具,则默启用所有工具。
如果未指定任何工具,则默启用所有工具。
---
#### 可用工具
是所有可以通过模式配置控制的工具。
是所有可以通过模式配置控制的工具。
| 工具 | 描述 |
| ----------- | ---------------- |
@@ -243,7 +243,7 @@ Markdown 文件名成为模式名称(例如,`review.md` 创建`review` 模
## 自定义模式
您可以通过将自定模式添加到配置创建自己的自定模式。以下是使用这两种方法的示例:
您可以通过将自定模式添加到配置创建自己的自定模式。以下是使用这两种方法的示例:
### 使用 JSON 配置
@@ -320,12 +320,12 @@ Priorities:
### 使用案例
以下是不同模式的一些常用例。
以下是不同模式的一些常用例。
- **构建模式**:启用所有工具的完整开发工作
- **计划模式**:分析和计划,无需更改
- **审阅模式**:使用只访问权限和文档工具行代审阅
- **构建模式**:启用所有工具的完整開發工作
- **计划模式**:分析和計劃,無需更改
- **审阅模式**:使用只访问权限和文档工具行代审阅
- **调试模式**专注于启用bash和读取工具的调查
- **文档模式**:使用文件操作但不使用系命令的文档编写
- **文档模式**:使用文件操作但不使用系命令的文档編寫
您可能还会发现不同的模型用于不同的用例。
您可能还会發現不同的模型用于不同的用例。

View File

@@ -1,6 +1,6 @@
---
title: 网络
description: 配置代理和自定义证书
description: 配置代理和自定義證書
---
opencode支持企业网络环境的标准代理环境变量和自定义证书。
@@ -9,7 +9,7 @@ opencode支持企业网络环境的标准代理环境变量和自定义证书。
## 代理
opencode 遵循标准代理环境变量。
opencode 尊重标准代理环境变量。
```bash
# HTTPS proxy (recommended)
@@ -39,7 +39,7 @@ export HTTPS_PROXY=http://username:password@proxy.example.com:8080
```
:::caution
避免对密码进行硬编码。使用环境变量或安全凭证存储
避免对密碼進行硬編碼。使用環境變量或安全憑證存儲
:::
对于需要高级身份验证(例如 NTLM 或 Kerberos的代理请考虑使用支持您的身份验证方法的 LLM 网关。

View File

@@ -1,6 +1,6 @@
---
title: 权限
description: 控制哪些操作需要批准才能行。
description: 控制哪些操作需要批准才能行。
---
opencode 使用`permission` 配置来决定给定的操作是否应自动运行、提示您或被阻止。
@@ -47,7 +47,7 @@ opencode 使用`permission` 配置来决定给定的操作是否应自动运行
## 粒度规则(对象语法)
对于大多权限,您可以使用对象根据工具入应用不同的操作。
对于大多权限,您可以使用对像根據工具入应用不同的操作。
```json title="opencode.json"
{
@@ -68,11 +68,11 @@ opencode 使用`permission` 配置来决定给定的操作是否应自动运行
}
```
规则通过模式匹配进行评估,**最后匹配的规则获胜**。常的模式是将包万象的 `"*"` 规则放在前面,然再放置更具的规则。
规则通过模式匹配進行評估,**最后匹配的规则獲勝**。常的模式是将包万象的 `"*"` 规则放在前面,然再放置更具的规则。
### 通配符
权限模式使用简单的通配符匹配:
权限模式使用簡單的通配符匹配:
- `*` 匹配零个或多个任意字符
- `?` 恰好匹配一个字符
@@ -80,7 +80,7 @@ opencode 使用`permission` 配置来决定给定的操作是否应自动运行
### 主目录扩展
您可以在模式目录中使用 `~` 或 `$HOME` 来引用您的主目录。这对于 [`外部目录`](#external_directory) 规则特别有用。
您可以在模式目录中使用 `~` 或 `$HOME` 来引用您的主目录。这对于 [`external_directory`](#external-directories) 规则特别有用。
- `~/projects/*` -> `/Users/username/projects/*`
- `$HOME/projects/*` -> `/Users/username/projects/*`
@@ -133,14 +133,14 @@ opencode权限由工具名称和一些安全防护措施决定
- `edit` — 所有文件修改(头部`edit`、`write`、`patch`、`multiedit`
- `glob` — 文件通配符(匹配通配符模式)
- `grep` — 内容搜索(匹配正则表达式模式)
- `list` — 列出目录中的文件(与目录路径匹配)
- `list` — 上市目录中的文件(与目录路径匹配)
- `bash` — 运行 shell 命令(匹配 `git status --porcelain` 等解析命令)
- `task` — 启动子代理(与子代理类型匹配)
- `skill` — 加载技能(与技能名称匹配)
- `lsp` — 运行 LSP 查询(当前非粒度)
- `todoread`、`todowrite` — 取/更新待办事项列表
- `todoread`、`todowrite` — 取/更新待辦事項列表
- `webfetch` — 获取 URL与 URL 匹配)
- `websearch`、`codesearch` — 网页/代搜索(与查询匹配)
- `websearch`、`codesearch` — 網頁/代搜索(与查询匹配)
- `external_directory` — 当工具访问项目工作目录外部的路径时触发
- `doom_loop` — 当相同的工具调用相同的输入重复 3 次时触发
@@ -148,7 +148,7 @@ opencode权限由工具名称和一些安全防护措施决定
## 默认值
如果您未指定任何内容opencode将从宽松的默认值开始:
如果您未指定任何内容opencode分散许可的默认值开始:
- 大部分权限默认为`"allow"`。
- `doom_loop`和`external_directory`默认为`"ask"`。
@@ -171,7 +171,7 @@ opencode权限由工具名称和一些安全防护措施决定
## “询问”的作用是什么
当 opencode 提示批准时UI 会提供三种结果:
当 opencode 提示批准时UI 会提供清晰的结果:
- `once` — 仅批准此请求
- `always` — 批准与建议模式匹配的未来请求(对于当前 opencode 会话的其余部分)

View File

@@ -11,7 +11,7 @@ description: 编写您自己的插件来扩展 opencode。
## 使用插件
有两种加插件的方法。
有两种加插件的方法。
---
@@ -22,7 +22,7 @@ description: 编写您自己的插件来扩展 opencode。
- `.opencode/plugins/` - 项目级插件
- `~/.config/opencode/plugins/` - 全局插件
这些目录中的文件会在启动自动加
这些目录中的文件会在启动自动加
---
@@ -53,7 +53,7 @@ description: 编写您自己的插件来扩展 opencode。
### 加载顺序
插件所有源加,所有挂钩按顺序行。加顺序为:
插件所有源加,所有掛鉤按顺序行。加顺序为:
1. 全局配置 (`~/.config/opencode/opencode.json`)
2. 项目配置(`opencode.json`
@@ -67,7 +67,7 @@ description: 编写您自己的插件来扩展 opencode。
## 创建一个插件
插件是一个 **JavaScript/TypeScript 模块多个**,它导出一个或插件
功能。每个函接收一个上下文对象并返回一个子对象。
功能。每个函接收一个上下文对象并返回一个子对象。
---
@@ -113,7 +113,7 @@ export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
}
```
插件函接收:
插件函接收:
- `project`:当前项目信息。
- `directory`:当前工作目录。
@@ -141,7 +141,7 @@ export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree
### 事件
插件可以订阅事件,如下面的示例部分所示。以下是可用的不同事件的列表。
插件可以訂閱事件,如下面的示例部分所示。以下是可用的不同事件的列表。
#### 命令事件
@@ -217,7 +217,7 @@ export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree
### 发送通知
当某些事件发生时发送通知:
当某些事件發生時發送通知:
```js title=".opencode/plugins/notification.js"
export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => {
@@ -306,7 +306,7 @@ export const CustomToolsPlugin: Plugin = async (ctx) => {
- `args`Zod 模式的工具参数
- `execute`:调用工具时运行的函数
您的自定工具将可与内置工具一起用于opencode。
您的自定工具将可与内置工具一起用于opencode。
---
@@ -333,7 +333,7 @@ export const MyPlugin = async ({ client }) => {
### 压缩钩子
自定义压缩会话包含的上下文:
自定義壓縮会话包含的上下文:
```ts title=".opencode/plugins/compaction.ts"
import type { Plugin } from "@opencode-ai/plugin"

View File

@@ -85,7 +85,7 @@ OpenCode Zen 是opencode团队提供的模型列表这些模型已被
## 目录
我们详细了解一些提供商。如果您想将提供商添加到
我们詳細瞭解一些提供商。如果您想将提供商添加到
列表请随时开启PR。
:::note
@@ -156,7 +156,7 @@ OpenCode Zen 是opencode团队提供的模型列表这些模型已被
export AWS_REGION=us-east-1
```
#### 配置文件(推
#### 配置文件(推
For project-specific or persistent configuration, use `opencode.json`:
@@ -174,13 +174,13 @@ OpenCode Zen 是opencode团队提供的模型列表这些模型已被
}
```
**可用选项**
**可用選項**
- `region` - AWS 区域(例如 `us-east-1`、`eu-west-1`
- `profile` - 来自 `~/.aws/credentials` 的 AWS 命名配置档案
- `endpoint` - VPC 节点节点的自定义节点 URL通用 `baseURL` 选项的别名)
:::提示
配置文件选项优先于环境变量。
配置文件選項优先于环境变量。
:::
#### 高阶VPC 端点
@@ -206,13 +206,13 @@ OpenCode Zen 是opencode团队提供的模型列表这些模型已被
`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
@@ -663,7 +663,7 @@ GitLab Duo 通过 GitLab 的人工代理提供具有本机工具呼叫功能的
2. 单击**添加新Tokens**
3. Name: `OpenCode`, Scopes: `api`
4. 复制Tokens以 `glpat-` 发起人)
5. 在终端中
5. 在终端中
3. 执行 `/models` 命令查看可用模型。
@@ -834,7 +834,7 @@ Google Vertex AI 与 opencode 结合使用:
2. 设置所需的环境变量:
- `GOOGLE_CLOUD_PROJECT`您的Google云专案ID
- `VERTEX_LOCATION`可选Vertex AI的区域默认为`global`
- 身份验证(选择一
- 身份验证(选择一
- `GOOGLE_APPLICATION_CREDENTIALS`:服务帐户 JSON 密钥文件的路径
- 使用 gcloud CLI 进行身份验证:`gcloud auth application-default login`
@@ -903,7 +903,7 @@ The `global` region improves availability and reduces errors at no extra cost. U
/connect
```
3. 入您的 Hugging Face API 密钥
3. 入您的擁抱臉標記
```txt
┌ API key
@@ -949,7 +949,7 @@ The `global` region improves availability and reduces errors at no extra cost. U
For more providers and advanced features like caching and rate limiting, check the [Helicone documentation](https://docs.helicone.ai).
#### 可配置
#### 可配置
如果您发现Helicone的某些功能或模型未通过opencode自动配置您始终可以自行配置。
@@ -979,7 +979,7 @@ Here's [Helicone's Model Directory](https://helicone.ai/models), you'll need thi
}
```
#### 自定义标头
#### 自定義標頭
Helicone 支持快速获取、用户跟踪和会话管理等功能的自定义标头。使用 `options.headers` 将它们添加到您提供的方案配置中:
@@ -1002,7 +1002,7 @@ Helicone 支持快速获取、用户跟踪和会话管理等功能的自定义
}
```
##### 会话跟
##### 会话跟
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.
@@ -1022,7 +1022,7 @@ npm install -g opencode-helicone-session
##### 常见螺旋接头
| 标题 | 描述 |
| 標題 | 描述 |
| -------------------------- | ----------------------------------------------------- |
| `Helicone-Cache-Enabled` | Enable response caching (`true`/`false`) |
| `Helicone-User-Id` | 点击用户跟踪指标 |
@@ -1635,9 +1635,9 @@ Vercel AI Gateway 可以让您跨统一端点访问来自 OpenAI、Anthropic、G
}
```
一些有用的路由选项
一些有用的路由選項
| 选项 | 描述 |
| 選項 | 描述 |
| ------------------- | ---------------------- |
| `order` | 提供商尝试顺序 |
| `only` | 限制特定提供商 |
@@ -1816,7 +1816,7 @@ Vercel AI Gateway 可以让您跨统一端点访问来自 OpenAI、Anthropic、G
}
```
以下是配置选项
以下是配置選項
- **npm**要使用AI的SDK包`@ai-sdk/openai-compatible`用于OpenAI兼容的事业
- **名称**UI中的显示名称。
- **模型**:可用模型。
@@ -1824,7 +1824,7 @@ Vercel AI Gateway 可以让您跨统一端点访问来自 OpenAI、Anthropic、G
- **options.apiKey**如果不使用身份验证可以选择设置API 密钥。
- **options.headers**:可选择设置自定义标头。
关高阶选项的更多资讯,请参见下面的示例。
關高階選項的更多資訊,请參見下面的示例。
5. 执行 `/models` 命令,您提供的自定义程序和模型将出现在选择列表中。
@@ -1875,7 +1875,7 @@ Vercel AI Gateway 可以让您跨统一端点访问来自 OpenAI、Anthropic、G
## 故障排除
如果您在配置提供商遇到问题,请检查以下容:
如果您在配置提供商遇到問題,请检查以下容:
1. **Check the auth setup**: Run `opencode auth list` to see if the credentials
提供商的配置已添加到您的配置中。

View File

@@ -1,6 +1,6 @@
---
title: 规则
description: 设置opencode的自定指令。
description: 设置opencode的自定指令。
---
您可以通过 `AGENTS.md` 文件创建 opencode 的自定义指令。这和 Cursor 的规则类似。它包含将包含在 LLM 上下文中的说明,方便您的特定项目自定义其行为。
@@ -48,7 +48,7 @@ This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for
- Import shared modules using workspace names: `@my-app/core/example`
```
我们在此添加特定于目的明,这将在您的团队中共享。
我们在此添加特定于目的明,这将在您的團隊中共享。
---
@@ -66,7 +66,7 @@ opencode 还支持从多个位置读取 `AGENTS.md` 文件。这有不同的目
由于此未提交给 Git 或与您的团队共享,因此我们建议使用它来指定 LLM 应遵循的任何个人规则。
### 克德代兼容性
### 克德代兼容性
Error 500 (Server Error)!!1500.Thats an error.There was an error. Please try again later.Thats all we know.
@@ -118,7 +118,7 @@ export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills
}
```
程指令的获取有 5 秒的超时时间
程指令的获取有 5 秒的超時時間
所有说明文件均与您的`AGENTS.md`文件合并。
@@ -168,9 +168,9 @@ For testing strategies and coverage requirements: @test/testing-guidelines.md
Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md.
```
方法允许您:
方法允许您:
- 创建模化、可重用的规则文件
- 创建模化、可重用的规则文件
- 通过符号链接或git子模块在项目之间共享规则
- 保持 AGENTS.md 简洁,同时参考详细指南
- 确保opencode仅在特定任务需要时加载文件

View File

@@ -33,7 +33,7 @@ import { createOpencode } from "@opencode-ai/sdk"
const { client } = await createOpencode()
```
这会同启动服务器和客
这会同启动服务器和客
#### 选项
@@ -99,7 +99,7 @@ SDK 包括所有 API 型以外的 TypeScript 定义。直接汇入其中:
import type { Session, Message, Part } from "@opencode-ai/sdk"
```
所有型均根服务器的 OpenAPI 规范生成,并可在 <a href={typesUrl}> 型文件 </a> 中找到。
所有型均根服务器的 OpenAPI 規範生成,并可在 <a href={typesUrl}> 型文件 </a> 中找到。
---
@@ -192,7 +192,7 @@ const currentProject = await client.project.current()
| 方法 | 描述 | 回应 |
| ------------ | ------------ | ---------------------------------------- |
| `path.get()` | 获取当前路 | <a href={typesUrl}><code>路</code></a> |
| `path.get()` | 获取当前路 | <a href={typesUrl}><code>路</code></a> |
---
@@ -209,7 +209,7 @@ const pathInfo = await client.path.get()
| 方法 | 描述 | 回应 |
| -------------------- | -------------------- | --------------------------------------------------------------------------------------------------- |
| `config.get()` | 获取配置资讯 | <a href={typesUrl}><code>配置</code></a> |
| `config.get()` | 获取配置資訊 | <a href={typesUrl}><code>配置</code></a> |
| `config.providers()` | 列出提供商和默认模型 | `{ providers: `<a href={typesUrl}><code>提供商[]</code></a>`, default: { [key: string]: string } }` |
---
@@ -226,14 +226,14 @@ const { providers, default: defaults } = await client.config.providers()
### 会话
| 方法 | 描述 | 备注 |
| 方法 | 描述 | 筆記 |
| ---------------------------------------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `session.list()` | 列出会话 | 返回 <a href={typesUrl}><code>Session[]</code></a> |
| `session.get({ path })` | 获取会话 | 返回 <a href={typesUrl}><code>会话</code></a> |
| `session.children({ path })` | 列出子会话 | 返回 <a href={typesUrl}><code>Session[]</code></a> |
| `session.create({ body })` | 建立会话 | 返回 <a href={typesUrl}><code>会话</code></a> |
| `session.delete({ path })` | 离开会话 | 返回`boolean` |
| `session.update({ path, body })` | 更新会话性 | 返回 <a href={typesUrl}><code>会话</code></a> |
| `session.update({ path, body })` | 更新会话性 | 返回 <a href={typesUrl}><code>会话</code></a> |
| `session.init({ path, body })` | Analyze app and create `AGENTS.md` | Returns `boolean` |
| `session.abort({ path })` | 中止正在执行的会话 | 返回`boolean` |
| `session.share({ path })` | 分享会 | 返回 <a href={typesUrl}><code>会话</code></a> |
@@ -241,7 +241,7 @@ const { providers, default: defaults } = await client.config.providers()
| `session.summarize({ path, body })` | 会议总结 | 返回`boolean` |
| `session.messages({ path })` | 列出会话中的消息 | 返回 `{ info: `<a href={typesUrl}><code>消息</code></a>`, parts: `<a href={typesUrl}><code>部分[]</code></a>`}[]` |
| `session.message({ path })` | 获取消息详情 | 返回 `{ info: `<a href={typesUrl}><code>消息</code></a>`, parts: `<a href={typesUrl}><code>部分[]</code></a>`}` |
| `session.prompt({ path, body })` | 发送提示资讯 | `body.noReply: true` 返回 UserMessage仅限上下文。默认返回 <a href={typesUrl}><code>AssistantMessage</code></a> 以及 AI 应 |
| `session.prompt({ path, body })` | 发送提示資訊 | `body.noReply: true` 返回 UserMessage仅限上下文。默认返回 <a href={typesUrl}><code>AssistantMessage</code></a> 以及 AI 应 |
| `session.command({ path, body })` | 向会话发送命令 | 返回 `{ info: `<a href={typesUrl}><code>AssistantMessage</code></a>`, parts: `<a href={typesUrl}><code>部分[]</code></a>`}` |
| `session.shell({ path, body })` | 执行 shell 命令 | 返回 <a href={typesUrl}><code>AssistantMessage</code></a> |
| `session.revert({ path, body })` | 回复消息 | 返回 <a href={typesUrl}><code>会话</code></a> |
@@ -287,9 +287,9 @@ await client.session.prompt({
| ------------------------- | -------------------- | ----------------------------------------------------------------------------------- |
| `find.text({ query })` | 搜索档案中文字 | 具有 `path`、`lines`、`line_number`、`absolute_offset`、`submatches` 的匹配对象数组 |
| `find.files({ query })` | 按名称查询档案和目录 | `string[]`(路径) |
| `find.symbols({ query })` | 查询工作区符 | <a href={typesUrl}><code>符[]</code></a> |
| `find.symbols({ query })` | 查询工作区符 | <a href={typesUrl}><code>符[]</code></a> |
| `file.read({ query })` | 读取档案 | `{ type: "raw" \| "patch", content: string }` |
| `file.status({ query? })` | 获取跟文件的状态 | <a href={typesUrl}><code>文件[]</code></a> |
| `file.status({ query? })` | 获取跟文件的狀態 | <a href={typesUrl}><code>文件[]</code></a> |
`find.files` 支持一些可选的查询栏位:

View File

@@ -44,7 +44,7 @@ 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 规范
@@ -61,7 +61,7 @@ opencode TUI running, `opencode serve` will start a new server.
---
#### 连接到有服务器
#### 连接到有服务器
当您启动 TUI 时,它会随机分配端口和主机名。您可以重新设置 `--hostname` 和 `--port` [flags](/docs/cli)。使用它连线到其服务器然后器。
@@ -69,7 +69,7 @@ opencode TUI running, `opencode serve` will start a new server.
---
##
##
服务器发布了OpenAPI 3.1规范,可以在以下位置查看:
@@ -89,7 +89,7 @@ opencode服务器公开以下API。
### 全局
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ----- | ---------------- | ------------------------ | ------------------------------------ |
| `GET` | `/global/health` | 获取服务器运行状况和版本 | `{ healthy: true, version: string }` |
| `GET` | `/global/event` | 获取全域性事件SSE 流) | 事件流 |
@@ -98,7 +98,7 @@ opencode服务器公开以下API。
### 项目
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ----- | ------------------ | ------------ | ------------------------------------------ |
| `GET` | `/project` | 列出所有专案 | <a href={typesUrl}><code>专案[]</code></a> |
| `GET` | `/project/current` | 获取当前专案 | <a href={typesUrl}><code>专案</code></a> |
@@ -107,16 +107,16 @@ opencode服务器公开以下API。
### 路径和VCS
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ----- | ------- | ----------------------- | ------------------------------------------- |
| `GET` | `/path` | 获取当前路 | <a href={typesUrl}><code>路</code></a> |
| `GET` | `/vcs` | 获取当前专案的 VCS 资讯 | <a href={typesUrl}><code>VcsInfo</code></a> |
| `GET` | `/path` | 获取当前路 | <a href={typesUrl}><code>路</code></a> |
| `GET` | `/vcs` | 获取当前专案的 VCS 資訊 | <a href={typesUrl}><code>VcsInfo</code></a> |
---
### 例
### 例
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ------ | ------------------- | -------------- | --------- |
| `POST` | `/instance/dispose` | 执行当前实例项 | `boolean` |
@@ -124,9 +124,9 @@ opencode服务器公开以下API。
### 配置
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ------- | ------------------- | -------------------- | -------------------------------------------------------------------------------------- |
| `GET` | `/config` | 获取配置资讯 | <a href={typesUrl}><code>配置</code></a> |
| `GET` | `/config` | 获取配置資訊 | <a href={typesUrl}><code>配置</code></a> |
| `PATCH` | `/config` | 更新配置 | <a href={typesUrl}><code>配置</code></a> |
| `GET` | `/config/providers` | 列出提供商和默认模型 | `{ providers: `<a href={typesUrl}>提供商[]</a>`, default: { [key: string]: string } }` |
@@ -134,33 +134,33 @@ opencode服务器公开以下API。
### 提供商
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ------ | -------------------------------- | ----------------------- | --------------------------------------------------------------------------------- |
| `GET` | `/provider` | 列出所有提供商 | `{ all: `<a href={typesUrl}>提供商[]</a>`, default: {...}, connected: string[] }` |
| `GET` | `/provider/auth` | 获取提供商身份验证方法 | `{ [providerID: string]: `<a href={typesUrl}>ProviderAuthMethod[]</a>` }` |
| `POST` | `/provider/{id}/oauth/authorize` | 使用 OAuth 授提供商 | <a href={typesUrl}><code>ProviderAuthAuthorization</code></a> |
| `POST` | `/provider/{id}/oauth/authorize` | 使用 OAuth 授提供商 | <a href={typesUrl}><code>ProviderAuthAuthorization</code></a> |
| `POST` | `/provider/{id}/oauth/callback` | 处理提供商的 OAuth 回调 | `boolean` |
---
### 会话
| 方法 | 路 | 描述 | 笔记 |
| 方法 | 路 | 描述 | 筆記 |
| -------- | ---------------------------------------- | ---------------------------------- | -------------------------------------------------------------------------------- |
| `GET` | `/session` | 列出所有会话 | 返回 <a href={typesUrl}><code>Session[]</code></a> |
| `POST` | `/session` | 建立新会话 | 正文: `{ parentID?, title? }`,返回 <a href={typesUrl}><code>Session</code></a> |
| `GET` | `/session/status` | 获取所有会话的会话状态 | 返回 `{ [sessionID: string]: `<a href={typesUrl}>SessionStatus</a>` }` |
| `GET` | `/session/status` | 获取所有会话的会话狀態 | 返回 `{ [sessionID: string]: `<a href={typesUrl}>SessionStatus</a>` }` |
| `GET` | `/session/:id` | 获取会话详细信息 | 返回<a href={typesUrl}><code>会话</code></a> |
| `DELETE` | `/session/:id` | 删除会话及所有资料 | 返回`boolean` |
| `PATCH` | `/session/:id` | 更新会话性 | 正文: `{ title? }`,返回 <a href={typesUrl}><code>Session</code></a> |
| `PATCH` | `/session/:id` | 更新会话性 | 正文: `{ title? }`,返回 <a href={typesUrl}><code>Session</code></a> |
| `GET` | `/session/:id/children` | 获取会话的子会话 | 返回 <a href={typesUrl}><code>Session[]</code></a> |
| `GET` | `/session/:id/todo` | 获取会话的待办事项列表 | 返回 <a href={typesUrl}><code>Todo[]</code></a> |
| `GET` | `/session/:id/todo` | 获取会话的待辦事項列表 | 返回 <a href={typesUrl}><code>Todo[]</code></a> |
| `POST` | `/session/:id/init` | Analyze app and create `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returns `boolean` |
| `POST` | `/session/:id/fork` | 在消息中分叉有会话 | 正文: `{ messageID? }`,返回 <a href={typesUrl}><code>Session</code></a> |
| `POST` | `/session/:id/fork` | 在消息中分叉有会话 | 正文: `{ messageID? }`,返回 <a href={typesUrl}><code>Session</code></a> |
| `POST` | `/session/:id/abort` | 中止正在执行的会话 | 返回`boolean` |
| `POST` | `/session/:id/share` | 分享会话 | 返回<a href={typesUrl}><code>会话</code></a> |
| `DELETE` | `/session/:id/share` | 取消共享会话 | 返回<a href={typesUrl}><code>会话</code></a> |
| `GET` | `/session/:id/diff` | 获取本次会话的差 | 查询:`messageID?`,返回 <a href={typesUrl}><code>FileDiff[]</code></a> |
| `GET` | `/session/:id/diff` | 获取本次会话的差 | 查询:`messageID?`,返回 <a href={typesUrl}><code>FileDiff[]</code></a> |
| `POST` | `/session/:id/summarize` | 会议总结 | 正文:`{ providerID, modelID }`,返回 `boolean` |
| `POST` | `/session/:id/revert` | 回复讯息 | 正文:`{ messageID, partID? }`,返回 `boolean` |
| `POST` | `/session/:id/unrevert` | 恢复所有已恢复的消息 | 返回`boolean` |
@@ -170,20 +170,20 @@ opencode服务器公开以下API。
### 留言
| 方法 | 路 | 描述 | 笔记 |
| 方法 | 路 | 描述 | 筆記 |
| ------ | --------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET` | `/session/:id/message` | 列出会话中的消息 | 查询: `limit?`,返回 `{ info: `<a href={typesUrl}>消息</a>`, parts: `<a href={typesUrl}>Part[]</a>`}[]` |
| `POST` | `/session/:id/message` | 发送消息并等待回复 | 正文: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`,返回 `{ info: `<a href={typesUrl}>消息</a>`, parts: `<a href={typesUrl}>部分[]</a>`}` |
| `GET` | `/session/:id/message/:messageID` | 获取消息详情 | 返回 `{ info: `<a href={typesUrl}>消息</a>`, parts: `<a href={typesUrl}>部分[]</a>`}` |
| `POST` | `/session/:id/prompt_async` | 非同步传送消息(休眠等待) | 主体:与 `/session/:id/message` 相同,返回 `204 No Content` |
| `POST` | `/session/:id/command` | 执行斜命令 | 正文: `{ messageID?, agent?, model?, command, arguments }`,返回 `{ info: `<a href={typesUrl}>消息</a>`, parts: `<a href={typesUrl}>部分[]</a>`}` |
| `POST` | `/session/:id/command` | 执行斜命令 | 正文: `{ messageID?, agent?, model?, command, arguments }`,返回 `{ info: `<a href={typesUrl}>消息</a>`, parts: `<a href={typesUrl}>部分[]</a>`}` |
| `POST` | `/session/:id/shell` | 执行 shell 命令 | 正文: `{ agent, model?, command }`,返回 `{ info: `<a href={typesUrl}>消息</a>`, parts: `<a href={typesUrl}>部分[]</a>`}` |
---
### 命令
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ----- | ---------- | ------------ | ------------------------------------------ |
| `GET` | `/command` | 列出所有命令 | <a href={typesUrl}><code>命令[]</code></a> |
@@ -191,14 +191,14 @@ opencode服务器公开以下API。
### 文件
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ----- | ------------------------ | -------------------- | ----------------------------------------------------------------------------------- |
| `GET` | `/find?pattern=<pat>` | 搜索文件中的文字 | 具有 `path`、`lines`、`line_number`、`absolute_offset`、`submatches` 的匹配对像数组 |
| `GET` | `/find/file?query=<q>` | 按名称查询文件和目录 | `string[]`(路 |
| `GET` | `/find/symbol?query=<q>` | 查询工作区符 | <a href={typesUrl}><code>符[]</code></a> |
| `GET` | `/find/file?query=<q>` | 按名称查询文件和目录 | `string[]`(路 |
| `GET` | `/find/symbol?query=<q>` | 查询工作区符 | <a href={typesUrl}><code>符[]</code></a> |
| `GET` | `/file?path=<path>` | 列出文件和目录 | <a href={typesUrl}><code>FileNode[]</code></a> |
| `GET` | `/file/content?path=<p>` | 取文件 | <a href={typesUrl}><code>文件容</code></a> |
| `GET` | `/file/status` | 获取跟文件的状态 | <a href={typesUrl}><code>文件[]</code></a> |
| `GET` | `/file/content?path=<p>` | 取文件 | <a href={typesUrl}><code>文件容</code></a> |
| `GET` | `/file/status` | 获取跟文件的狀態 | <a href={typesUrl}><code>文件[]</code></a> |
#### `/find/file` 查询参数
@@ -210,9 +210,9 @@ opencode服务器公开以下API。
---
### 工具(实验
### 工具(實驗
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ----- | ------------------------------------------- | ---------------------------- | -------------------------------------------- |
| `GET` | `/experimental/tool/ids` | 列出所有工具 ID | <a href={typesUrl}><code>工具ID</code></a> |
| `GET` | `/experimental/tool?provider=<p>&model=<m>` | 列出具有模型 JSON 模式的工具 | <a href={typesUrl}><code>工具列表</code></a> |
@@ -221,18 +221,18 @@ opencode服务器公开以下API。
### LSP、格式化程式和 MCP
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ------ | ------------ | ------------------- | ------------------------------------------------------ |
| `GET` | `/lsp` | 获取 LSP 服务器状态 | <a href={typesUrl}><code>LSPStatus[]</code></a> |
| `GET` | `/formatter` | 获取格式化程式状态 | <a href={typesUrl}><code>FormatterStatus[]</code></a> |
| `GET` | `/mcp` | 获取 MCP 服务器状态 | `{ [name: string]: `<a href={typesUrl}>MCP状态</a>` }` |
| `GET` | `/lsp` | 获取 LSP 服务器狀態 | <a href={typesUrl}><code>LSPStatus[]</code></a> |
| `GET` | `/formatter` | 获取格式化程式狀態 | <a href={typesUrl}><code>FormatterStatus[]</code></a> |
| `GET` | `/mcp` | 获取 MCP 服务器狀態 | `{ [name: string]: `<a href={typesUrl}>MCP狀態</a>` }` |
| `POST` | `/mcp` | 动态添加 MCP 服务器 | 主体:`{ name, config }`,返回 MCP 状态对象 |
---
### 代理商
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ----- | -------- | ------------------ | ------------------------------------------ |
| `GET` | `/agent` | 列出所有可用的代理 | <a href={typesUrl}><code>代理[]</code></a> |
@@ -240,7 +240,7 @@ opencode服务器公开以下API。
### 日志
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ------ | ------------------------------------------- | ------ | -------------------- |
| `POST` | 身体:`{ service, level, message, extra? }` | `/log` | 写入日志。 `boolean` |
@@ -248,7 +248,7 @@ opencode服务器公开以下API。
### TUI
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ------ | ----------------------- | ----------------------------------------- | ------------ |
| `POST` | `/tui/append-prompt` | 将文字附加到提示 | `boolean` |
| `POST` | `/tui/open-help` | 开启帮助对话方块 | `boolean` |
@@ -266,7 +266,7 @@ opencode服务器公开以下API。
### 授权
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ----- | ----------- | ------------------------------------------ | --------- |
| `PUT` | `/auth/:id` | 设置身份验证凭据。正文必须与提供商架构匹配 | `boolean` |
@@ -274,7 +274,7 @@ opencode服务器公开以下API。
### 活动
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ----- | -------- | ------------------------------------------------------------------- | ------------------ |
| `GET` | `/event` | 服务器发送事件流。第一个事件是 `server.connected`,之后是总线事件。 | 服务器发送事件流。 |
@@ -282,6 +282,6 @@ opencode服务器公开以下API。
### 文档
| 方法 | 路 | 描述 | 回应 |
| 方法 | 路 | 描述 | 回应 |
| ----- | ------ | --------------- | ------------------------- |
| `GET` | `/doc` | 开启API 3.1规范 | 具有OpenAPI规范的HTML页面 |

View File

@@ -6,24 +6,24 @@ description: 分享您的 opencode 对话。
opencode 的共享功能允许您建立指向 opencode 对话的公共链接,以便您可以与蓝牙进行战斗或从其他人那里获得帮助。
:::note
任何知道链接的人都可以公访问共享对话。
任何知道链接的人都可以公访问共享对话。
:::
---
## 它是如何作的
## 它是如何作的
当您分享对话时opencode
1. 为您的会话建立唯一的公共 URL
2. 将您的对话历史记录同步到我们的服务器
2. 将您的对话歷史記錄同步到我们的服务器
3. 通过可共享链接访问对话 — `opncd.ai/s/<share-id>`
---
## 分享
opencode 支持三种控制对话共享方式的共享模式:
opencode 支持清晰控制对话共享方式的共享模式:
---
@@ -35,7 +35,7 @@ opencode 支持三种控制对话共享方式的共享模式:
/share
```
这将生成一个唯一的 URL将其复制到您的剪贴中。
这将生成一个唯一的 URL将其复制到您的剪贴簿中。
要在[配置文件](/docs/config) 中显式设置手动模式:
@@ -50,7 +50,7 @@ opencode 支持三种控制对话共享方式的共享模式:
### 自动分享
您可以通过将 [配置文件](/docs/config) 中的 `share` 选项设置为 `"auto"` 来为所有新对话启用自动共享:
您可以通过将 [config file](/docs/config) 中的 `share` 选项设置为 `"auto"` 来为所有新对话启用自动共享:
```json title="opencode.json"
{
@@ -59,13 +59,13 @@ opencode 支持三种控制对话共享方式的共享模式:
}
```
启用自动共享,每个新对话都会自动共享并生成链接。
启用自动共享,每个新对话都会自动共享并生成链接。
---
### 已禁用
您可以通过将 [配置文件](/docs/config) 中的 `share` 选项设置为 `"disabled"` 来完全禁用共享:
您可以通过将 [config file](/docs/config) 中的 `share` 选项设置为 `"disabled"` 来完全禁用共享:
```json title="opencode.json"
{
@@ -74,13 +74,13 @@ opencode 支持三种控制对话共享方式的共享模式:
}
```
为了在您的团队中针对特定项目强制执行此操作,请将其添加到您项目的 `opencode.json` 文件中,并将其提交到Git
To enforce this across your team for a given project, add it to the `opencode.json` in your project and check into Git.
---
## 取消共享
要停止共享对话并将其公共访问中删除:
要停止共享对话并将其公共访问中删除:
```
/unshare
@@ -90,39 +90,39 @@ opencode 支持三种控制对话共享方式的共享模式:
---
##
##
分享对话需要住一些事
分享对话需要住一些事
---
### 数据保留
共享对话仍然可以访问,直到您明取消共享。这
共享对话仍然可以访问,直到您明取消共享。这
包括:
- 完整的对话历史记录
- 完整的对话歷史記錄
- 所有消息和回复
- 会话元数据
---
### 建
### 建
- 仅共享不包含敏感资讯的对话。
- 分享之前查看对话容。
- 作完成取消共享对话。
- 避免共享包括专有代码或机密数据对话。
- 对于敏感项目,完全禁用共享。
- 仅共享不包含敏感資訊的对话。
- 分享之前查看对话容。
- 作完成取消共享对话。
- 避免与专有程式碼或機密数据共享对话。
- 对于敏感专案,完全禁用共享。
---
## 对于企
## 对于企
对于企部署,共享功能可以是:
对于企部署,共享功能可以是:
- **出于安全合性完全禁用**
- **出于安全合性完全禁用**
- **仅限** 仅通过 SSO 进行身份验证的用户
- **在您自己的基础设施上自行管**
- **在您自己的基礎設施上自行管**
[了解更多关于在您的组织中使用opencode的](/docs/enterprise)。

View File

@@ -1,10 +1,10 @@
---
title: 代理技
description: “通过 SKILL.md 定义可复用的行为”
title: 代理技巧》
description: “贯穿 SKILL.md 定义可重用行为”
---
代理技能使 OpenCode 能从您的库或主目录中发现可重用的指令。
技能通过原生 `skill` 工具输入导入 - 代理可以查看可用技能并可以在需要时加载完整内容。
代理让 opencode 能从您的存储库或主目录中找到可重用的指令。
技能贯穿本机 `skill` 工具输入导入 - 代理可以查看可用技能并可以在需要时加载完整内容。
---
@@ -34,7 +34,7 @@ Global definitions are also loaded from `~/.config/opencode/skills/*/SKILL.md`,
## 编写 Frontmatter
每个 `SKILL.md` 必须以 YAML frontmatter 。
识别这些位:
識別这些位:
- `name`(必填)
- `description`(必填)
@@ -50,13 +50,13 @@ Global definitions are also loaded from `~/.config/opencode/skills/*/SKILL.md`,
`name` 必须:
- 度为 164 个字元
- 为小字母字并带有单个连字元分隔符
- 不以 `-` 始或
- 不包含连续的 `--`
- 度为 164 个字元
- 为小字母字并带有單个連字元分隔符
- 不以 `-` 始或
- 不包含連續的 `--`
- 匹配包含 `SKILL.md` 的目录名
等效的正表示式:
等效的正表示式:
```text
^[a-z0-9]+(-[a-z0-9]+)*$
@@ -67,7 +67,7 @@ Global definitions are also loaded from `~/.config/opencode/skills/*/SKILL.md`,
## 遵循长度规则
`description` 必须是 1-1024 个字元。
保持足够具体,以便代理能正确选择。
保持足夠具體,以便代理能正确选择。
---
@@ -114,7 +114,7 @@ opencode 列出了 `skill` 工具描述中的可用技能。
</available_skills>
```
代理通过呼叫工具来载入技能:
代理通过呼叫工具來載入技能:
```
skill({ name: "git-release" })
@@ -139,7 +139,7 @@ Control which skills agents can access using pattern-based permissions in `openc
}
```
| 可 | 行为 |
| 可 | 行为 |
| ------- | -------------------------- |
| `allow` | 技能立即加载 |
| `deny` | 对特工隐藏技能,访问被拒绝 |
@@ -153,7 +153,7 @@ Control which skills agents can access using pattern-based permissions in `openc
为特定代理授予与全域性默认权限不同的权限。
**对于自定代理**(在代理前言中):
**对于自定代理**(在代理前言中):
```yaml
---
@@ -185,7 +185,7 @@ permission:
完全禁用不应该使用技能的特工:
**对于定代理**
**对于定代理**
```yaml
---
@@ -194,7 +194,7 @@ tools:
---
```
**对于建代理**
**对于建代理**
```json
{
@@ -208,15 +208,15 @@ tools:
}
```
禁用`<available_skills>` 部分将被完全省略。
禁用`<available_skills>` 部分将被完全省略。
---
## 解决加载问题
如果某技能有显示:
如果某技能有显示:
1. 验证 `SKILL.md` 拼写为全部大写
2. 检查 frontmatter 是否包括 `name` 和 `description`
3. 保技能名称在所有位置都是唯一的
3. 保技能名称在所有位置都是唯一的
4. 查询权限——具有`deny`的代理隐藏技能

View File

@@ -1,6 +1,6 @@
---
title: 主题
description: 选择建主题或定您自己的主题。
description: 选择建主题或定您自己的主题。
---
使用 opencode您可以从多个内建主题中进行选择使用适合您的终端主题的主题或定义您自己的自定义主题。
@@ -11,13 +11,13 @@ By default, opencode uses our own `opencode` theme.
## 终端要求
为了使主题能正确显示完整的调色板,您的终端必支持**真彩色**24 位色)。大多现代终端默认支持此功能,但您可能需要启用它:
为了使主题能正确显示完整的调色板,您的终端必支持**真彩色**24 位色)。大多现代终端默认支持此功能,但您可能需要启用它:
- **检查支持**:执行 `echo $COLORTERM` - 它应该输出 `truecolor` 或 `24bit`
- **启用真彩色**在shell配置文件中设置环境变量`COLORTERM=truecolor`
- **您的终端兼容性**确保终端模拟器支持24位颜色大多数现代终端如iTerm2、Alacritty、Kitty、Windows终端和最新版本的GNOME终端都支持
如果有真彩色支持,主题的色精度可能会降低或回落到最接近的 256 色近似值。
如果有真彩色支持,主题的色精度可能会降低或回落到最接近的 256 色近似值。
---
@@ -39,7 +39,7 @@ opencode 带有几个内建主题。
| `matrix` | 骇客风格黑底绿主题 |
| `one-dark` | Based on the [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark theme |
此外,我们还在不添加新主题。
此外,我们还在不添加新主题。
---
@@ -47,15 +47,15 @@ opencode 带有几个内建主题。
`system` 主题旨在自动适应您的最终方案。与使用固定颜色的传统主题不同_system_ 主题:
- **生成灰度**:根终端的背景色建立自定灰度,保最佳对比度。
- **生成灰度**:根终端的背景色建立自定灰度,保最佳对比度。
- **使用 ANSI 颜色**:使用标准 ANSI 颜色 (0-15) 进行语法突出显示和 UI 元素,尊重 Windows 的调色盘。
- **保留默认设置**:使用 `none` 作为文字和背景颜色以保持本机的外观。
主题合以下用户:
主题合以下用户:
- 希望 opencode 与终端的外观相匹配
- 使用自定终端配色方案
- 希望所有终端应用程序具有一致的外
- 使用自定终端配色方案
- 希望所有终端应用程序具有一致的外
---
@@ -80,14 +80,14 @@ opencode 支持灵活的基于 JSON 的主题系统,允许用户轻松创建
### 优先级
主题按以下顺序多个目录入,其中后面的目录覆盖前面的目录:
主题按以下顺序多个目录入,其中后面的目录覆盖前面的目录:
1. **建主题** - 这些主题嵌入在二进制文件中
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 `<project-root>/.opencode/themes/*.json`
4. **Current working directory** - Defined in `./.opencode/themes/*.json`
如果多个目录包含同名主题,则将使用优先顺序高的目录中的主题。
如果多个目录包含同名主题,则将使用优先顺序高的目录中的主题。
---
@@ -102,7 +102,7 @@ mkdir -p ~/.config/opencode/themes
vim ~/.config/opencode/themes/my-theme.json
```
以及对特定项目的主题。
以及对特定专案的主题。
```bash no-frame
mkdir -p .opencode/themes
@@ -140,7 +140,7 @@ vim .opencode/themes/my-theme.json
### 例子
以下是自定主题的示例:
以下是自定主题的示例:
```json title="my-theme.json"
{

View File

@@ -24,7 +24,7 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
}
```
您还可以使用通配符同时控制多个工具。例如,要求 MCP 服务器批准所有工具:
您还可以使用万用字元同时控制多个工具。例如,要求 MCP 服务器批准所有工具:
```json title="opencode.json"
{
@@ -39,15 +39,15 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
---
## 內建工具
## 內建
以下是 opencode 中可用的所有内置工具。
---
### bash
### 巴什
项目环境中执行shell命令。
专案环境中执行shell命令。
```json title="opencode.json" {4}
{
@@ -58,13 +58,13 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
}
```
这个工具允许 LLM 运行终端命令,例如:`npm install`, `git status`,或者其他任何终端命令。
This tool allows the LLM to run terminal commands like `npm install`, `git status`, or any other shell command.
---
### edit
### 編輯
使用精的字符串替换来修改有文件。
使用精的字符串替修改有文件。
```json title="opencode.json" {4}
{
@@ -75,13 +75,13 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
}
```
该工具通过替换完全匹配的文本来对文件行精确编辑。这是 LLM 修改代码的主要方式。
该工具取消替换精确的文字来匹配对文件行精确编辑。这是 LLM 修改代码的主要方式。
---
### write
###
建立新文件或覆盖有文件。
建立新文件或覆盖有文件。
```json title="opencode.json" {4}
{
@@ -92,17 +92,17 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
}
```
使用此功能可允许 LLM 创建新文件。如果文件已存在,会覆盖现有文件
使用允许 LLM 创建新文件。如果现有文件已存在,会覆盖它们
:::note
`写入`工具由`编辑`权限控制,涵盖所有文件修改(`编辑`、`写入`、`修补`、`多重编辑`)。
`write`工具由`edit`许可权控制,该许可权主题所有文件修改(`edit`、`write`、`patch`、`multiedit`)。
:::
---
### read
###
读取代码库中的文件容。
從程式碼庫中讀取文件容。
```json title="opencode.json" {4}
{
@@ -113,13 +113,13 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
}
```
该工具取文件并返回其容。它支持取大文件的特定行范围。
该工具取文件并返回其容。它支持取大文件的特定行范围。
---
### grep
使用正则表达式搜索文件容。
使用正規表示式搜索文件容。
```json title="opencode.json" {4}
{
@@ -130,13 +130,13 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
}
```
快速搜索代码库中的内容。支持完整的正则表达式语法和文件模式过
在您的程式碼庫中快速進行內容搜索。支持完整的正規表示式語法和文件模式过
---
### glob
### 全域性
通过模式匹配查文件。
通过模式匹配查文件。
```json title="opencode.json" {4}
{
@@ -147,13 +147,13 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
}
```
使用类似 **/\*.js 或 src/**/\*.ts 的通配符模式搜索文件。返回按修改时间排序的匹配文件路径
使用 `**/*.js``src/**/*.ts` 等全域性模式搜索档案。返回按时间排序的匹配档案路径修改
---
### list
### 列表
列出定路中的文件和目录。
列出定路中的文件和目录。
```json title="opencode.json" {4}
{
@@ -164,16 +164,16 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
}
```
工具用于列出目录容。它接受通配符模式来筛选结果。
工具列出目录容。它接受全域性模式來过濾結果。
---
### lsp实验性
配置的 LSP 服务器交互,以获取代码智功能,例如定义、引用、悬停信息和调用层次结构。
配置的LSP服务器交互通知计划码智功能,例如定义、引用、悬停资讯和呼叫层次结构。
:::note
只有当 OPENCODE_EXPERIMENTAL_LSP_TOOL=true(或 OPENCODE_EXPERIMENTAL=true)时,此工具才可用。
This tool is only available when `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (or `OPENCODE_EXPERIMENTAL=true`).
:::
```json title="opencode.json" {4}
@@ -187,13 +187,13 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
支持的操作包括 `goToDefinition`、`findReferences`、`hover`、`documentSymbol`、`workspaceSymbol`、`goToImplementation`、`prepareCallHierarchy`、`incomingCalls` 和 `outgoingCalls`。
要配置哪些 LSP 服务器可用于您的项目,请参阅 [LSP Servers](/docs/lsp).
To configure which LSP servers are available for your project, see [LSP Servers](/docs/lsp).
---
### patch
### 修補
对文件应用丁。
对文件应用丁。
```json title="opencode.json" {4}
{
@@ -204,17 +204,17 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
}
```
工具可将补丁文件应用到您的代码库。它可用于应用自各种来源的差异和补丁
工具将補丁文件应用到您的程式碼庫。对于应用自各種來源的差異和補丁很有帮助
:::note
`修补`工具由`编辑`权限控制,涵盖所有文件修改(`编辑`、`写入`、`修补`、`多重编辑`)。
`patch`工具由`edit`许可权控制,该许可权主题所有文件修改(`edit`、`write`、`patch`、`multiedit`)。
:::
---
### skill
### 技能
加载[技能](/docs/skills)`SKILL.md` 文件)并在对话中返回其内容。
加载[skill](/docs/skills)`SKILL.md` 档案)并在对话中返回其内容。
```json title="opencode.json" {4}
{
@@ -227,9 +227,9 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
---
### todowrite
### 待辦寫入
编码会话过程中管理待办事项列表。
編碼会话期間管理待辦事項列表。
```json title="opencode.json" {4}
{
@@ -240,17 +240,17 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
}
```
建和更新任务列表以跟踪复杂操作的进度。LLM 利用此功能来组织多步骤任务。
和更新任务列表以跟踪复杂操作期间的详细信息。LLM 使用它来组织多步骤任务。
:::note
此工具默认情况下子代理禁用,但您可以手动启用它。 [了解更多](/docs/agents/#permissions)
默认情况下子代理取消此工具,但您可以手动启用它。 [了解更多](/docs/agents/#permissions)
:::
---
### todoread
### 託多雷德
阅读现有的待办事项清单
閱讀現有的待辦事項列表
```json title="opencode.json" {4}
{
@@ -261,17 +261,17 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
}
```
读取当前待办事项列表状态。LLM 使用此信息来跟踪哪些任务处于待处理状态或已完成状态
读取当前完成待办事项列表状态。LLM 用于跟踪哪些任务待处理或已已
:::note
此工具默认情况下子代理禁用,但您可以手动启用它。 [了解更多](/docs/agents/#permissions)
默认情况下子代理取消此工具,但您可以手动启用它。 [了解更多](/docs/agents/#permissions)
:::
---
### webfetch
### 網頁抓取
获取网页内容。
获取網頁內容。
```json title="opencode.json" {4}
{
@@ -282,18 +282,18 @@ Tools allow the LLM to perform actions in your codebase. opencode comes with a s
}
```
允许LLM获取读取网页。可用于查找文档或研究在线资源
允许 LLM 获取读取网页。对于查询文件或研究线上资源很有帮助
---
### websearch
### 網路搜索
网络上搜索资料
網路上搜索資訊
:::note
只有在使用 OpenCode 提供程序时,或者当 OPENCODE_ENABLE_EXA 环境变量设置为任何真值(例如 true 或 1)时,此工具才可用。
仅当使用 opencode 提供或 `OPENCODE_ENABLE_EXA` 程序环境变量设置为任何真值(例如 `true``1`)时,此工具才可用。
在启动 OpenCode 时启用:
在启动 opencode 时启用:
```bash
OPENCODE_ENABLE_EXA=1 opencode
@@ -310,19 +310,19 @@ OPENCODE_ENABLE_EXA=1 opencode
}
```
用 Exa AI 行网搜索,查找相关信息。可用于研究特定主题、了解时事新闻或收集超出训练数据范围的信息
使用 Exa AI 行网搜索以线上查询相关资讯。对于研究主题、查询时事或收集训练超出数据范围的资讯很有帮助
无需 API 密钥——该工具无需身份验证即可直接连到 Exa AI 托管 MCP 服务。
不需要 API 密钥该工具消耗身份验证即可直接连线到 Exa AI 托管 MCP 服务。
:::tip
当您需要查找信息时,请使用`网页搜索`;当您需要从特定 URL 检索内容时,请使用`网页获取`。
当您需要查询资讯(发现)时,请使用 `websearch`;当您需要从特定 URL 检索内容(搜索)时,请使用 `webfetch`。
:::
---
### question
### 問題
在执行过程中向用户提问
在执行过程中詢問用户問題
```json title="opencode.json" {4}
{
@@ -333,20 +333,20 @@ OPENCODE_ENABLE_EXA=1 opencode
}
```
该工具允许 LLM 在执行任务期间向用户提问。它在以下方面很有用
该工具允许 LLM 在任务期间询问用户问题。它适用于
- 收集用户偏好或
- 澄清含糊不清的指
- 就实施方案做出决定
- 提供关于选择下一步方向的选项
- 收集用户偏好或
- 澄清不明確的指
- 就實施选择做出決策
- 提供选择方向
每个问题都包含标题、问题正文和选项列表。用户可以提供的选项中选择答案,也可以输入自定答案。如果有多个问题,用户可以在提交所有答案之前在不同问题之间切换
每个問題都包含標題、問題文字和選項列表。用户可以提供的選項中進行选择或輸入自定答案。当存在多个問題時,用户可以在提交所有答案之前在这些問題之间导航
---
## 自定义工具
## 定製工具
自定义工具允许您定义LLM可以调用的自定义函数。这些函数在您的配置文件中定义并且可以执行任代码。
自定义工具可以让您定义LLM可以调用自己的函式。这些在您的配置文件中定义并且可以执行任代码。
[了解更多](/docs/custom-tools)关于创建自定义工具。
@@ -360,15 +360,15 @@ MCP模型上下文协议服务器允许您集成外部工具和服务。
---
## 内部规则
## 内部結構
在内部,`grep` `通配符` 和 `罗列` 等工具底层都使用了 ripgrep。默认情况下ripgrep 会遵循 .gitignore 文件中的规则,这意味着 .gitignore 文件中列出的文件和目录将被排除在搜索和列表之外。
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` 文件。该文件内定义的目录可以不会被跳过
要包含通常会被忽略的文件,请在专案根目录中建立 `.ignore` 文件。该文件可以明确允许某些路径
```text title=".ignore"
!node_modules/
@@ -376,4 +376,4 @@ MCP模型上下文协议服务器允许您集成外部工具和服务。
!build/
```
例如,这个 `.ignore` 文件允许 ripgrep 在 `node_modules/`、`dist/` 和 `build/` 目录中搜索,即使它们在 `.gitignore` 中列出
例如, `.ignore` 档案允许 ripgrep 在 `node_modules/`、`dist/` 和 `build/` 目录中搜索,即使它们在 `.gitignore` 中。

View File

@@ -1,15 +1,15 @@
---
title: 故障排除
description: 常见问题以及如何解决它们
description: 常見問題以及如何解決它們
---
要排除 opencode 的问题,请首先检查其存储在磁上的日志和本地数据。
要排除 opencode 的问题,请首先检查其存储在磁上的日志和本地数据。
---
## 日志
文件入:
文件入:
- **macOS/Linux**: `~/.local/share/opencode/log/`
- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.local\share\opencode\log`
@@ -51,7 +51,7 @@ opencode Desktop runs a local opencode server (the `opencode-cli` sidecar) in th
### 禁用插件
如果桌面应用程序在启动时崩溃、挂起或行为常,请首先禁用插件。
如果桌面应用程序在启动時崩潰、掛起或行为常,请首先禁用插件。
#### 检查全域性配置
@@ -61,7 +61,7 @@ opencode Desktop runs a local opencode server (the `opencode-cli` sidecar) in th
- **macOS/Linux** (older installs): `~/.local/share/opencode/opencode.jsonc`
- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.config\opencode\opencode.jsonc`
如果您配置了插件,请通过删除密钥或将其设置为空数组暂时禁用它
如果您配置了插件,请通过删除密钥或将其设置为空数组暂时禁用它
```jsonc
{
@@ -77,10 +77,10 @@ opencode 还可以从磁碟加载本地外挂。暂时将它们移开(或重
- **全域性插件**
- **macOS/Linux**: `~/.config/opencode/plugins/`
- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.config\opencode\plugins`
- **项目插件**(仅当您使用每个项目配置
- **专案插件**(仅当您使用每个专案配置
- `<your-project>/.opencode/plugins/`
如果应用程序再次始工作,请一次重新启用一个插件,以找出导致问题的插件。
如果应用程序再次始工作,请一次重新启用一个插件,以找出導致問題的插件。
---
@@ -99,7 +99,7 @@ opencode 还可以从磁碟加载本地外挂。暂时将它们移开(或重
---
### 修服务器连接问题
### 修服务器连接問題
opencode Desktop 可以启动自己的本地服务器(默认配置)或连线到您的服务器 URL。
@@ -147,11 +147,11 @@ If you're experiencing slow performance, file access issues, or terminal problem
opencode 桌面仅在以下情况下显示系统通知:
- 在您的作业系统中设置为 opencode 启用了通知,并且
- 应用程序窗未聚焦。
- 应用程序窗未聚焦。
---
### 重置桌面应用程序存(最后的手段)
### 重置桌面应用程序存(最后的手段)
如果应用程序无法并且启动您无法从 UI 内部清除设置,请重置桌面应用程序的存储状态。
@@ -179,9 +179,9 @@ opencode 桌面仅在以下情况下显示系统通知:
[**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues)
在建立新问题之前,请搜索现有问题以查看您的问题是否已被告。
在建立新問題之前,请搜索現有問題以查看您的問題是否已被告。
2. **加入我们的不和**
2. **加入我们的不和**
获得实时帮助和社群讨论请加入我们的Discord服务器
@@ -191,19 +191,19 @@ opencode 桌面仅在以下情况下显示系统通知:
## 常见问题
以下是一些常见问题以及解方法。
以下是一些常見問題以及解方法。
---
### opencode 无法启动
1. 检查日中是否有错误消息
1. 检查日中是否有错误消息
2. 尝试使用 `--print-logs` 执行以查看终端中的输出
3. Ensure you have the latest version with `opencode upgrade`
---
### 身份验证问题
### 身份验证問題
1. 尝试使用 TUI 中的 `/connect` 命令重新进行身份验证
2. 检查您的API 密钥是否有效
@@ -214,12 +214,12 @@ opencode 桌面仅在以下情况下显示系统通知:
### 模型不可用
1. 检查您是否已通过提供商的身份验证
2. 验证配置中的模型名称是否正确
3. 某些模型可能需要特定的访问权限或订阅
2. 驗證配置中的模型名称是否正确
3. 某些模型可能需要特定的访问权限或訂閱
如果您遇到 `ProviderModelNotFoundError` 您很可能是错误的
在某引用模型。
模型应该像这引用:`<providerId>/<modelId>`
在某引用模型。
模型应该像这引用:`<providerId>/<modelId>`
示例:
@@ -235,10 +235,10 @@ To figure out what models you have access to, run `opencode models`
如果遇到 ProviderInitError您的配置可能无效或损坏。
要解这个问题
要解这个問題
1. 首先,按照[提供商指南](/docs/providers) 验证您的事业是否已正确设置
2. 如果问题仍然存在,请尝试清除存的配置:
2. 如果問題仍然存在,请嘗試清除存的配置:
```bash
rm -rf ~/.local/share/opencode
@@ -254,7 +254,7 @@ To figure out what models you have access to, run `opencode models`
如果您遇到 API 呼叫错误,这可能是由于过去提供包造成的。 opencode 根据需要动态安装提供包OpenAI、Anthropic、Google 等)将其缓存放在本地。
要解provider 包问题
要解provider 包問題
1. 清除provider 包缓存:
@@ -288,7 +288,7 @@ apt install -y xsel
apt install -y wl-clipboard
```
**对于无头环境:**
**对于無頭環境:**
```bash
apt install -y xvfb

View File

@@ -29,17 +29,17 @@ 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?
```
文件的容会自动添加到对话中。
文件的容会自动添加到对话中。
---
@@ -51,7 +51,7 @@ How is auth handled in @packages/functions/src/api/index.ts?
!ls -la
```
命令的出将作为工具果添加到对话中。
命令的出将作为工具果添加到对话中。
---
@@ -65,11 +65,11 @@ How is auth handled in @packages/functions/src/api/index.ts?
大多数命令还是以使用 `ctrl+x` 作为主键的键系结,其中 `ctrl+x` 是默认主键。 [了解更多](/docs/keybinds)。
以下是所有可用的斜命令:
以下是所有可用的斜命令:
---
### connect
### 连接
将提供商添加到 opencode。你可以从可用提供商中选择并添加它们的 API 密钥。
@@ -79,7 +79,7 @@ How is auth handled in @packages/functions/src/api/index.ts?
---
### compact
### 紧凑
压缩当前会话。_别名_ `/summarize`
@@ -91,9 +91,9 @@ How is auth handled in @packages/functions/src/api/index.ts?
---
### details
### 細節
工具执行详细信息。
工具执行详细信息。
```bash frame="none"
/details
@@ -103,7 +103,7 @@ How is auth handled in @packages/functions/src/api/index.ts?
---
### editor
### 編輯
开启外部编辑器来编写消息。使用`EDITOR`环境变量中设定的编辑器。 [了解更多](#editor-setup)。
@@ -115,7 +115,7 @@ How is auth handled in @packages/functions/src/api/index.ts?
---
### exit
### 退出
退出opencode。 _别名_`/quit`、`/q`
@@ -127,7 +127,7 @@ How is auth handled in @packages/functions/src/api/index.ts?
---
### export
### 导出
将当前对话汇出到 Markdown 并在默认编辑器中开启。使用 `EDITOR` 环境变数中设定的编辑器。 [了解更多](#editor-setup)。
@@ -139,9 +139,9 @@ How is auth handled in @packages/functions/src/api/index.ts?
---
### help
### 幫助
显示助对话方
显示助对话方
```bash frame="none"
/help
@@ -151,7 +151,7 @@ How is auth handled in @packages/functions/src/api/index.ts?
---
### init
### 初始化
Create or update `AGENTS.md` file. [Learn more](/docs/rules).
@@ -163,7 +163,7 @@ Create or update `AGENTS.md` file. [Learn more](/docs/rules).
---
### models
### 模型
列出可用模型。
@@ -175,7 +175,7 @@ Create or update `AGENTS.md` file. [Learn more](/docs/rules).
---
### new
### 新的
开始新的会话。 _别名_ `/clear`
@@ -187,7 +187,7 @@ Create or update `AGENTS.md` file. [Learn more](/docs/rules).
---
### redo
### 重做
删除之前重做消除的讯息。仅在使用`/undo`后可用。
@@ -206,7 +206,7 @@ Create or update `AGENTS.md` file. [Learn more](/docs/rules).
---
### sessions
### 会话
上市会话并在会话之间切换。 _别名_`/resume`、`/continue`
@@ -218,7 +218,7 @@ Create or update `AGENTS.md` file. [Learn more](/docs/rules).
---
### share
### 分享
共享当前会话。 [了解更多](/docs/share)。
@@ -230,7 +230,7 @@ Create or update `AGENTS.md` file. [Learn more](/docs/rules).
---
### themes
### 主题
列出可用的主题。
@@ -242,9 +242,9 @@ Create or update `AGENTS.md` file. [Learn more](/docs/rules).
---
### thinking
### 思維
切换对话中 thinking/reasoning 块的可视性。启用后,您可以看到支持扩展思考的模型的推理过程。
切换对话中 thinking/reasoning 块的可视性。启用后,您可以看到支持增强套件思维的模型的推理过程。
:::note
该命令仅控制是否**显示** - 不启用或取消模型的推理功能。要切换实际推理功能,请使用 `ctrl+t` 回圈切换模型变体。
@@ -256,9 +256,9 @@ Create or update `AGENTS.md` file. [Learn more](/docs/rules).
---
### undo
### 撤消
撤消对话中的最后一条消息。删除最近的用户消息、所有后续应以及任何文件更改。
撤消对话中的最后一条消息。删除最近的用户消息、所有后续应以及任何文件更改。
:::tip
所做的任何文件更改也将被恢复。
@@ -275,7 +275,7 @@ Create or update `AGENTS.md` file. [Learn more](/docs/rules).
---
### unshare
### 取消共享
取消共享当前会话。 [了解更多](/docs/share#un-sharing)。
@@ -334,7 +334,7 @@ Create or update `AGENTS.md` file. [Learn more](/docs/rules).
</TabItem>
</Tabs>
流行的编辑器选项包括:
流行的编辑器選項包括:
- `code` - Visual Studio Code
- `cursor` - 游标
@@ -369,7 +369,7 @@ Create or update `AGENTS.md` file. [Learn more](/docs/rules).
}
```
### 选项
### 選項
- `scroll_acceleration` - 启用 macOS 式滚动加速以实现平滑、自然的滚动。启用后,滚动速度会随着快速滚动滚动而增加,并在较慢的移动时保持精确。 **此设定优先于 `scroll_speed` 并在启用时覆盖它。 **
- `scroll_speed` - 控制使用滚动控制器时 TUI 滚动的速度(简单:`1`)。默认为 `3`。 **注意:如果 `scroll_acceleration.enabled` 设置为 `true`,则忽略此设置。 **
@@ -384,7 +384,7 @@ Create or update `AGENTS.md` file. [Learn more](/docs/rules).
#### 用户名称显示
您的用户名称是否出在聊天消息中。通过以下方式访问:
您的用户名称是否出在聊天消息中。通过以下方式访问:
- 命令面板:搜索“用户名称”或“隐藏用户名称”
- 该设置会自动保留,放在 TUI 会话中被记住

View File

@@ -1,5 +1,5 @@
---
title: Web
title: 網路
description: 在浏览器中使用opencode。
---
@@ -7,7 +7,7 @@ opencode 可以在浏览器中作为 Web 应用程序执行,消耗终端可以
![opencode Web - New Session](../../../assets/web/web-homepage-new-session.png)
## 入
## 入
绕过执行以下命令启动 Web 简介:
@@ -29,7 +29,7 @@ For the best experience, run `opencode web` from [WSL](/docs/windows-wsl) rather
## 配置
您可以使用命令标志或在[config file](/docs/config).conf 中配置Web服务器。
您可以使用命令标志或在[config file](/docs/config).conf 中配置Web服务器。
### 端口
@@ -39,9 +39,9 @@ For the best experience, run `opencode web` from [WSL](/docs/windows-wsl) rather
opencode web --port 4096
```
### 主
### 主
默认情况下,服务器绑定到`127.0.0.1`仅限本地主机。要使opencode在您的网路上可访问
情况默认下,服务器系结到`127.0.0.1`仅限本地主机。要使opencode在您的网路上可访问
```bash
opencode web --hostname 0.0.0.0
@@ -78,9 +78,9 @@ opencode web --mdns --mdns-domain myproject.local
opencode web --cors https://example.com
```
### 验证
### 驗證
要保护访问,请使用 `OPENCODE_SERVER_PASSWORD` 环境变设置密码:
要保护访问,请使用 `OPENCODE_SERVER_PASSWORD` 环境变设置密码:
```bash
OPENCODE_SERVER_PASSWORD=secret opencode web
@@ -90,19 +90,19 @@ The username defaults to `opencode` but can be changed with `OPENCODE_SERVER_USE
---
## 使用web界面
## 使用网络界面
启动后,web界面将提供对您的 opencode 会话的访问。
启动后,网路界面将提供对您的 opencode 会话的访问。
### 会话
从主页查看和管理您的会话。您可以查看活动会话并始新会话。
從主頁查看和管理您的会话。您可以查看活动会话并始新会话。
![opencode Web - Active Session](../../../assets/web/web-homepage-active-session.png)
### 服务器状态
### 服务器狀態
单击“查看服务器”可查看连接的服务器及其状态
单击“查看服务器”可查看连接的服务器及其狀態
![opencode Web - See Servers](../../../assets/web/web-homepage-see-servers.png)

View File

@@ -1,5 +1,5 @@
---
title: Zen
title:
description: 由 opencode 提供的精选模型列表。
---
@@ -7,10 +7,10 @@ import config from "../../../../config.mjs"
export const console = config.console
export const email = `mailto:${config.email}`
OpenCode Zen 是由 OpenCode 团队提供的一组经过测试和验证的模型列表。
Error 500 (Server Error)!!1500.Thats an error.There was an error. Please try again later.Thats all we know.
:::note
OpenCode Zen 目前处于测试阶段。
OpenCode Zen 目前处于一个测试阶段。
:::
Zen 的工作方式与 opencode 中的任何其他提供商相同。您登录 OpenCode Zen 并获得
@@ -21,31 +21,31 @@ opencode。
## 背景
市面上有很多模型,但其中只有少数几
这些模型可以很好地用作编码代理。此外,大多提供商都
配置非常不同;所以你会得到截然不同的效率和质量。
市面上有很多模型,但其中只有少數幾
这些模型可以很好地用作編碼代理。此外,大多提供商都
配置非常不同;所以你会得到截然不同的效能和質量。
:::tip
我们测试了一组与 opencode 配合良好的模型并提供商。
:::
因此,如果您通过 OpenRouter 之类的东西使用模型,您永远无法
定您是否得了您想要的模型的最佳版本。
因此,如果您使用 OpenRouter 之类的东西使用模型,您永远无法
定您是否得了您想要的模型的最佳版本。
了解决这个问题,我们做了件事:
瞭解決这个問題,我们做了件事:
1. 我们测试了一组选定的模型,并与他们的团队讨论了如何
最好执行它
2. 然我们与一些提供商合作以保这些服得到服
1. 我们測試了一組選定的模型,并与他們的團隊討論瞭如何
最好执行它
2. 然我们与一些提供商合作以保这些服得到服
正确。
3. 最后,我们对 model/provider 的组合进行了基准测试,总结了
并附上一份我们得不的推荐清单
并附上一份我们得不的推薦清單
OpenCode Zen 是一个AI网关,让您可以访问这些模型。
OpenCode Zen 是一个AI闸道器,可以让您访问这些模型。
---
## 它是如何作的
## 它是如何作的
OpenCode Zen 的工作方式与 opencode 中的任何其他功能相同。
@@ -54,7 +54,7 @@ OpenCode Zen 的工作方式与 opencode 中的任何其他功能相同。
2. 您在 TUI 中执行 `/connect` 命令,选择 OpenCode Zen然后贴上 API 密钥。
3. 在 TUI 中执行 `/models` 以查看我们推荐的模型列表。
您需要按请求付,并且您可以将分添加到您的账户中。
您需要按请求付,并且您可以将分添加到您的账户中。
---
@@ -62,7 +62,7 @@ OpenCode Zen 的工作方式与 opencode 中的任何其他功能相同。
您还可以通过以下 API 端点访问我们的模型。
| 模型 | 模型ID | 端点 | AI SDK 套件 |
| 模型 | 模型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` |
@@ -102,7 +102,7 @@ use `opencode/gpt-5.2-codex` in your config.
### 模型
您可以以下位置获取可用模型及其元数据的完整列表:
您可以以下位置获取可用模型及其元数据的完整列表:
```
https://opencode.ai/zen/v1/models
@@ -114,9 +114,9 @@ https://opencode.ai/zen/v1/models
我们支持即用即付模式。以下是**每 100 万Tokens的价格**。
| 模型 | 入 | 出 | 缓存取 | 缓存入 |
| 模型 | 入 | 出 | 缓存取 | 缓存入 |
| ---------------------------------- | ---------- | ---------- | ---------- | ---------- |
| 大泡菜 | 免 | 免 | 免 | - |
| 大泡菜 | 免 | 免 | 免 | - |
| MiniMax M2.1 免费 | 免费 | 免费 | 免费 | - |
| 迷你最大M2.1 | 0.30 美元 | 1.20 美元 | 0.10 美元 | - |
| GLM 4.7 免费 | 免费 | 免费 | 免费 | - |
@@ -153,32 +153,32 @@ https://opencode.ai/zen/v1/models
您可能会在您的使用历史记录中注意到*Claude Haiku 3.5*。这是一个[低成本模型](/docs/config/#models),用于生成会话标题。
:::note
信用卡费用按成本4.4% + 每交易 0.30 美元);除此之外我们不收取任何费用。
信用卡费用按成本4.4% + 每交易 0.30 美元);除此之外我们不收取任何费用。
:::
模型:
模型:
- GLM 4.7 免费版本在 opencode 上限时提供。团队正在利用这段时间收集反馈并改进模型。
- Kimi K2.5 在 opencode 限时免费发布。团队正在利用这段时间收集反馈并改进模型。
- MiniMax M2.1 在 opencode 限时免费供应。团队正在利用这段时间收集反馈并改进模型。
- Big Pickle 是一个隐形模型,在 opencode 上限时免费。团队正在利用这个临时收集反馈并改进模型。
<a href={email}>如果您有任何疑,请联络我们</a>。
<a href={email}>如果您有任何疑,请聯絡我们</a>。
---
### 自动重新
### 自动重新
如果您的余额低于 5 美元Zen 将自动充值 20 美元。
您可以更改自动充值金。您还可以完全禁用自动重新入。
您可以更改自动充值金。您还可以完全禁用自动重新入。
---
### 每月限额
您还可以为整个工作区和每个工作区设置每月使用限制
你的团队成员。
你的團隊成员。
例如,假设您将每月使用中断设置为 20 美元Zen 将不会使用
一个月超过 20 美元。但如果你启用了自动重新加载Zen 可能会结束
@@ -188,7 +188,7 @@ https://opencode.ai/zen/v1/models
## 隐私
我们所有的模型都在美国管。我们的提供商遵循零保留政策,不会将您的数据用于模型训练,但以下情况除外:
我们所有的模型都在美国管。我们的提供商遵循零保留政策,不会将您的数据用于模型训练,但以下情况除外:
- Big Pickle在免费期间收集可用于改进模型的数据。
- GLM 4.7 免费:在免费期间,收集可用于改进模型的数据。
@@ -201,20 +201,21 @@ https://opencode.ai/zen/v1/models
## 对于团队
Zen 也非常适合团队使用。您可以邀请您可以邀请队友,分配角色,管理团队使用的模型等。
Zen 对团队也很有效。您可以参与第三方、角色、策划
您的團隊使用的模型等等。
:::note
作为测试版的一部分,工作空目前对团队免费
作为測試版的一部分,工作空目前对團隊免費
:::
作为测试版的一部分,管理工作空目前对团队免费。我们将会
很快就会分享更多有关定价的细节
作为測試版的一部分,管理工作空目前对團隊免費。我们将会
很快就会分享更多有關定價的細節
---
### 角色
您可以邀请团队成员到您的工作区并分配角色:
您可以邀请團隊成员到您的工作区并分配角色:
- **管理员**管理模型、成员、API 密钥和设备
- **成员**仅管理自己的API 金?

View File

@@ -84,8 +84,7 @@ curl -fsSL https://opencode.ai/install | bash
- **在 Arch Linux 上使用 Paru**
```bash
sudo pacman -S opencode # Arch Linux (Stable)
paru -S opencode-bin # Arch Linux (Latest from AUR)
paru -S opencode-bin
```
#### Windows

View File

@@ -12,28 +12,7 @@ function docsAlias(pathname: string) {
const next = locale === "root" ? `/docs${tail}` : `/docs/${locale}${tail}`
if (next === pathname) return null
return {
path: next,
locale,
}
}
function cookie(locale: string) {
const value = locale === "root" ? "en" : locale
return `oc_locale=${encodeURIComponent(value)}; Path=/; Max-Age=31536000; SameSite=Lax`
}
function redirect(url: URL, path: string, locale?: string) {
const next = new URL(url.toString())
next.pathname = path
const headers = new Headers({
Location: next.toString(),
})
if (locale) headers.set("Set-Cookie", cookie(locale))
return new Response(null, {
status: 302,
headers,
})
return next
}
function localeFromCookie(header: string | null) {
@@ -80,7 +59,9 @@ function localeFromAcceptLanguage(header: string | null) {
export const onRequest = defineMiddleware((ctx, next) => {
const alias = docsAlias(ctx.url.pathname)
if (alias) {
return redirect(ctx.url, alias.path, alias.locale)
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()
@@ -90,5 +71,7 @@ export const onRequest = defineMiddleware((ctx, next) => {
localeFromAcceptLanguage(ctx.request.headers.get("accept-language"))
if (!locale || locale === "root") return next()
return redirect(ctx.url, `/docs/${locale}/`)
const url = new URL(ctx.request.url)
url.pathname = `/docs/${locale}/`
return ctx.redirect(url.toString(), 302)
})