SDK
opencode JS/TS SDK는 서버와 상호작용하기 위한 타입 안정성 클라이언트를 제공합니다. 이를 사용하여 통합을 구축하고 opencode를 프로그래밍 방식으로 제어하세요.
서버 작동 방식에 대해 자세히 알아보려면 자세히 알아보기를 참조하세요. 예제는 커뮤니티에서 구축한 프로젝트를 확인하세요.
설치
npm에서 SDK를 설치하세요:
npm install @opencode-ai/sdk
클라이언트 생성
opencode 인스턴스를 만듭니다:
import { createOpencode } from "@opencode-ai/sdk"
const { client } = await createOpencode()
이렇게 하면 서버와 클라이언트가 모두 시작됩니다.
옵션
| Option | Type | Description | Default |
|---|---|---|---|
hostname | string | Server hostname | 127.0.0.1 |
port | number | Server port | 4096 |
signal | AbortSignal | Abort signal for cancellation | undefined |
timeout | number | Timeout in ms for server start | 5000 |
config | Config | Configuration object | {} |
설정
동작을 사용자 정의하기 위해 설정 객체를 전달할 수 있습니다. 인스턴스는 여전히 opencode.json을 사용하지만, 인라인으로 설정을 재정의하거나 추가할 수 있습니다:
import { createOpencode } from "@opencode-ai/sdk"
const opencode = await createOpencode({
hostname: "127.0.0.1",
port: 4096,
config: {
model: "anthropic/claude-3-5-sonnet-20241022",
},
})
console.log(`Server running at ${opencode.server.url}`)
opencode.server.close()
클라이언트만 사용
이미 실행 중인 opencode 인스턴스가 있는 경우, 클라이언트 인스턴스를 만들어 연결할 수 있습니다:
import { createOpencodeClient } from "@opencode-ai/sdk"
const client = createOpencodeClient({
baseUrl: "http://localhost:4096",
})
옵션
| Option | Type | Description | Default |
|---|---|---|---|
baseUrl | string | URL of the server | http://localhost:4096 |
fetch | function | Custom fetch implementation | globalThis.fetch |
parseAs | string | Response parsing method | auto |
responseStyle | string | Return style: data or fields | fields |
throwOnError | boolean | Throw errors instead of return | false |
타입
SDK에는 모든 API 타입에 대한 TypeScript 정의가 포함되어 있습니다. 직접 가져오세요:
import type { Session, Message, Part } from "@opencode-ai/sdk"
모든 타입은 서버의 OpenAPI 사양에서 생성되며 types 파일에서 사용할 수 있습니다.
오류
SDK는 잡아서 처리할 수 있는 오류를 던질 수 있습니다:
try {
await client.session.get({ path: { id: "invalid-id" } })
} catch (error) {
console.error("Failed to get session:", (error as Error).message)
}
구조화된 출력
JSON 스키마로 format을 지정하여 모델에서 구조화된 JSON 출력을 요청할 수 있습니다. 모델은 StructuredOutput 도구를 사용하여 스키마와 일치하는 검증된 JSON을 반환합니다.
기본 사용법
const result = await client.session.prompt({
path: { id: sessionId },
body: {
parts: [{ type: "text", text: "Research Anthropic and provide company info" }],
format: {
type: "json_schema",
schema: {
type: "object",
properties: {
company: { type: "string", description: "Company name" },
founded: { type: "number", description: "Year founded" },
products: {
type: "array",
items: { type: "string" },
description: "Main products",
},
},
required: ["company", "founded"],
},
},
},
})
// Access the structured output
console.log(result.data.info.structured_output)
// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] }
출력 형식 타입
| Type | Description |
|---|---|
text | Default. Standard text response (no structured output) |
json_schema | Returns validated JSON matching the provided schema |
JSON Schema 형식
type: 'json_schema'를 사용할 때 다음을 제공하세요:
| Field | Type | Description |
|---|---|---|
type | 'json_schema' | Required. Specifies JSON schema mode |
schema | object | Required. JSON Schema object defining the output structure |
retryCount | number | Optional. Number of validation retries (default: 2) |
오류 처리
모든 재시도 후에도 모델이 유효한 구조화된 출력을 생성하지 못하면 응답에 StructuredOutputError가 포함됩니다:
if (result.data.info.error?.name === "StructuredOutputError") {
console.error("Failed to produce structured output:", result.data.info.error.message)
console.error("Attempts:", result.data.info.error.retries)
}
모범 사례
- 명확한 설명 제공 - 모델이 어떤 데이터를 추출해야 하는지 이해할 수 있도록 스키마 속성에 명확한 설명을 제공하세요
required사용 - 반드시 존재해야 하는 필드를 지정하세요- 스키마를 집중 - 복잡한 중첩 스키마는 모델이 올바르게 채우기 어려울 수 있습니다
- 적절한
retryCount설정 - 복잡한 스키마에는 늘리고, 단순한 스키마에는 줄이세요
APIs
SDK는 타입 안정성 클라이언트를 통해 모든 서버 API를 노출합니다.
Global
| Method | Description | Response |
|---|---|---|
global.health() | Check server health and version | { healthy: true, version: string } |
예제
const health = await client.global.health()
console.log(health.data.version)
App
| Method | Description | Response |
|---|---|---|
app.log() | Write a log entry | boolean |
app.agents() | List all available agents | Agent[] |
예제
// Write a log entry
await client.app.log({
body: {
service: "my-app",
level: "info",
message: "Operation completed",
},
})
// List available agents
const agents = await client.app.agents()
Project
| Method | Description | Response |
|---|---|---|
project.list() | List all projects | Project[] |
project.current() | Get current project | Project |
예제
// List all projects
const projects = await client.project.list()
// Get current project
const currentProject = await client.project.current()
Path
| Method | Description | Response |
|---|---|---|
path.get() | Get current path | Path |
예제
// Get current path information
const pathInfo = await client.path.get()
Config
| Method | Description | Response |
|---|---|---|
config.get() | Get config info | Config |
config.providers() | List providers and default models | { providers: Provider[], default: { [key: string]: string } } |
예제
const config = await client.config.get()
const { providers, default: defaults } = await client.config.providers()
Sessions
| Method | Description | Notes |
|---|---|---|
session.list() | List sessions | Returns Session[] |
session.get({ path }) | Get session | Returns Session |
session.children({ path }) | List child sessions | Returns Session[] |
session.create({ body }) | Create session | Returns Session |
session.delete({ path }) | Delete session | Returns boolean |
session.update({ path, body }) | Update session properties | Returns Session |
session.init({ path, body }) | Analyze app and create AGENTS.md | Returns boolean |
session.abort({ path }) | Abort a running session | Returns boolean |
session.share({ path }) | Share session | Returns Session |
session.unshare({ path }) | Unshare session | Returns Session |
session.summarize({ path, body }) | Summarize session | Returns boolean |
session.messages({ path }) | List messages in a session | Returns { info: Message, parts: Part[] }[] |
session.message({ path }) | Get message details | Returns { info: Message, parts: Part[] } |
session.prompt({ path, body }) | Send prompt message | body.noReply: true returns UserMessage (context only). Default returns AssistantMessage with AI response. Supports body.outputFormat for structured output |
session.command({ path, body }) | Send command to session | Returns { info: AssistantMessage, parts: Part[] } |
session.shell({ path, body }) | Run a shell command | Returns AssistantMessage |
session.revert({ path, body }) | Revert a message | Returns Session |
session.unrevert({ path }) | Restore reverted messages | Returns Session |
postSessionByIdPermissionsByPermissionId({ path, body }) | Respond to a permission request | Returns boolean |
예제
// Create and manage sessions
const session = await client.session.create({
body: { title: "My session" },
})
const sessions = await client.session.list()
// Send a prompt message
const result = await client.session.prompt({
path: { id: session.id },
body: {
model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" },
parts: [{ type: "text", text: "Hello!" }],
},
})
// Inject context without triggering AI response (useful for plugins)
await client.session.prompt({
path: { id: session.id },
body: {
noReply: true,
parts: [{ type: "text", text: "You are a helpful assistant." }],
},
})
Files
| Method | Description | Response |
|---|---|---|
find.text({ query }) | Search for text in files | Array of match objects with path, lines, line_number, absolute_offset, submatches |
find.files({ query }) | Find files and directories by name | string[] (paths) |
find.symbols({ query }) | Find workspace symbols | Symbol[] |
file.read({ query }) | Read a file | { type: "raw" | "patch", content: string } |
file.status({ query? }) | Get status for tracked files | File[] |
find.files는 몇 가지 선택적 쿼리 필드를 지원합니다:
type:"file"또는"directory"directory: 검색의 프로젝트 루트 재정의limit: 최대 결과 수 (1–200)
예제
// Search and read files
const textResults = await client.find.text({
query: { pattern: "function.*opencode" },
})
const files = await client.find.files({
query: { query: "*.ts", type: "file" },
})
const directories = await client.find.files({
query: { query: "packages", type: "directory", limit: 20 },
})
const content = await client.file.read({
query: { path: "src/index.ts" },
})
TUI
| Method | Description | Response |
|---|---|---|
tui.appendPrompt({ body }) | Append text to the prompt | boolean |
tui.openHelp() | Open the help dialog | boolean |
tui.openSessions() | Open the session selector | boolean |
tui.openThemes() | Open the theme selector | boolean |
tui.openModels() | Open the model selector | boolean |
tui.submitPrompt() | Submit the current prompt | boolean |
tui.clearPrompt() | Clear the prompt | boolean |
tui.executeCommand({ body }) | Execute a command | boolean |
tui.showToast({ body }) | Show toast notification | boolean |
예제
// Control TUI interface
await client.tui.appendPrompt({
body: { text: "Add this to prompt" },
})
await client.tui.showToast({
body: { message: "Task completed", variant: "success" },
})
Auth
| Method | Description | Response |
|---|---|---|
auth.set({ ... }) | Set authentication credentials | boolean |
예제
await client.auth.set({
path: { id: "anthropic" },
body: { type: "api", key: "your-api-key" },
})
Events
| Method | Description | Response |
|---|---|---|
event.subscribe() | Server-sent events stream | Server-sent events stream |
예제
// Listen to real-time events
const events = await client.event.subscribe()
for await (const event of events.stream) {
console.log("Event:", event.type, event.properties)
}