From afd42bf46dbd0cbdde727b26e1bffbf409fe0e5c Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Tue, 2 Sep 2025 19:39:38 -0400 Subject: [PATCH] docs: fix SDK usage to use path/query/body, correct return types, and update examples --- packages/web/src/content/docs/docs/sdk.mdx | 235 ++++++++++----------- 1 file changed, 117 insertions(+), 118 deletions(-) diff --git a/packages/web/src/content/docs/docs/sdk.mdx b/packages/web/src/content/docs/docs/sdk.mdx index 02b4d6e6..ecadec8c 100644 --- a/packages/web/src/content/docs/docs/sdk.mdx +++ b/packages/web/src/content/docs/docs/sdk.mdx @@ -1,16 +1,17 @@ --- title: SDK -description: JS SDK for the opencode server. +description: Type-safe JS client for opencode server. --- import config from "../../../../config.mjs" export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts` -The opencode [JS/TS SDK](https://www.npmjs.com/package/@opencode-ai/sdk) provides a type-safe client for interacting with the opencode server. You can use it to build custom integrations and control opencode programmatically. +The opencode JS/TS SDK provides a type-safe client for interacting with the server. +Use it to build integrations and control opencode programmatically. -[Learn more](/docs/server) about how the opencode server works. +[Learn more](/docs/server) about how the server works. -> **Note**: Many API endpoints now require a `directory` query parameter to specify the working directory context. +> Note: Most endpoints accept a directory query parameter for working directory context. --- @@ -26,25 +27,26 @@ npm install @opencode-ai/sdk ## Create client -Create a client instance to connect to your opencode server: +Create a client instance to connect to your server: ```javascript import { createOpencodeClient } from "@opencode-ai/sdk" const client = createOpencodeClient({ baseUrl: "http://localhost:4096", + responseStyle: "data", }) ``` #### Options -| Option | Type | Description | Default | -| --------------- | ---------- | --------------------------------- | ----------------------- | -| `baseUrl` | `string` | URL of the opencode 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 returning | `false` | +| 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` | --- @@ -65,7 +67,7 @@ console.log(`Server running at ${server.url}`) server.close() ``` -You can also pass a configuration object to customize the server behavior. The server will still pick up your `opencode.json` file as usual, but you can override or add additional configuration inline: +You can pass a configuration object to customize server behavior. The server still picks up your `opencode.json`, but you can override or add configuration inline: ```javascript import { createOpencodeServer } from "@opencode-ai/sdk" @@ -109,13 +111,13 @@ All types are generated from the server's OpenAPI specification and available in ## Errors -The SDK throws typed errors that you can catch and handle: +The SDK can throw errors that you can catch and handle: ```typescript try { - const session = await client.session.get({ id: "invalid-id" }) + await client.session.get({ path: { id: "invalid-id" } }) } catch (error) { - console.error("Failed to get session:", error.message) + console.error("Failed to get session:", (error as Error).message) } ``` @@ -123,7 +125,7 @@ try { ## APIs -The SDK exposes all server APIs through a type-safe client interface. +The SDK exposes all server APIs through a type-safe client. --- @@ -139,15 +141,20 @@ The SDK exposes all server APIs through a type-safe client interface. #### Examples ```javascript -// Log an entry +// Write a log entry await client.app.log({ - service: "my-app", - level: "info", - message: "Operation completed", + body: { + service: "my-app", + level: "info", + message: "Operation completed", + }, + query: { directory: "/path/to/project" }, }) // List available agents -const agents = await client.app.agents() +const agents = await client.app.agents({ + query: { directory: "/path/to/project" }, +}) ``` --- @@ -165,10 +172,14 @@ const agents = await client.app.agents() ```javascript // List all projects -const projects = await client.project.list() +const projects = await client.project.list({ + query: { directory: "/path/to/project" }, +}) // Get current project -const currentProject = await client.project.current() +const currentProject = await client.project.current({ + query: { directory: "/path/to/project" }, +}) ``` --- @@ -185,7 +196,9 @@ const currentProject = await client.project.current() ```javascript // Get current path information -const pathInfo = await client.path.get() +const pathInfo = await client.path.get({ + query: { directory: "/path/to/project" }, +}) ``` --- @@ -202,34 +215,40 @@ const pathInfo = await client.path.get() #### Examples ```javascript -const config = await client.config.get() -const { providers, default: defaults } = await client.config.providers() +const config = await client.config.get({ + query: { directory: "/path/to/project" }, +}) + +const { providers, default: defaults } = await client.config.providers({ + query: { directory: "/path/to/project" }, +}) ``` --- ### Sessions -| Method | Description | Notes | -| ------------------------------------------------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| `session.list()` | List sessions | Returns Session[] | -| `session.get({ id })` | Get session | Returns Session | -| `session.children({ id })` | List child sessions | Returns Session[] | -| `session.create({ parentID?, title? })` | Create session | Returns Session | -| `session.delete({ id })` | Delete session | Returns `boolean` | -| `session.update({ id, title? })` | Update session properties | Returns Session | -| `session.init({ id, messageID, providerID, modelID })` | Analyze app and create `AGENTS.md` | Returns `boolean` | -| `session.abort({ id })` | Abort a running session | Returns `boolean` | -| `session.share({ id })` | Share session | Returns Session | -| `session.unshare({ id })` | Unshare session | Returns Session | -| `session.summarize({ id, providerID, modelID })` | Summarize session | Returns `boolean` | -| `session.messages({ id })` | List messages in a session | Returns `{ info: `Message`, parts: `Part[]`}[]` | -| `session.message({ id, messageID })` | Get message details | Returns `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ id, ...promptInput })` | Send prompt message | Returns Message | -| `session.shell({ id, agent, command })` | Run a shell command | Returns Message | -| `session.revert({ id, messageID, partID? })` | Revert a message | Returns Session | -| `session.unrevert({ id })` | Restore reverted messages | Returns Session | -| `session.permissions.respond({ id, permissionID, response })` | Respond to a permission request | Returns `boolean` | +| 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 | Returns `{ info: `AssistantMessage`, parts: `Part[]`}` | +| `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` | --- @@ -237,17 +256,23 @@ const { providers, default: defaults } = await client.config.providers() ```javascript // Create and manage sessions -const session = await client.session.create({ title: "My session" }) -const sessions = await client.session.list() +const session = await client.session.create({ + body: { title: "My session" }, + query: { directory: "/path/to/project" }, +}) -// Send messages -const message = await client.session.prompt({ - id: session.id, - model: { - providerID: "anthropic", - modelID: "claude-3-5-sonnet-20241022", +const sessions = await client.session.list({ + query: { directory: "/path/to/project" }, +}) + +// 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!" }], }, - parts: [{ type: "text", text: "Hello!" }], + query: { directory: "/path/to/project" }, }) ``` @@ -257,11 +282,11 @@ const message = await client.session.prompt({ | Method | Description | Response | | ------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------- | -| `find.text({ pattern })` | Search for text in files | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `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 by name | `string[]` (file paths) | | `find.symbols({ query })` | Find workspace symbols | Symbol[] | -| `file.read({ path })` | Read a file | `{ type: "raw" \| "patch", content: string }` | -| `file.status()` | Get status for tracked files | File[] | +| `file.read({ query })` | Read a file | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | Get status for tracked files | File[] | --- @@ -269,64 +294,34 @@ const message = await client.session.prompt({ ```javascript // Search and read files -const textResults = await client.find.text({ pattern: "function.*opencode" }) -const files = await client.find.files({ query: "*.ts" }) -const content = await client.file.read({ path: "src/index.ts" }) -``` - ---- - -### Logging - -| Method | Description | Response | -| ------------------------------------------------ | --------------- | --------- | -| `log.write({ service, level, message, extra? })` | Write log entry | `boolean` | - ---- - -#### Examples - -```javascript -await client.log.write({ - service: "my-app", - level: "info", - message: "Operation completed", +const textResults = await client.find.text({ + query: { pattern: "function.*opencode", directory: "/path/to/project" }, }) -``` ---- +const files = await client.find.files({ + query: { query: "*.ts", directory: "/path/to/project" }, +}) -### Agents - -| Method | Description | Response | -| -------------- | ------------------------- | ------------------------------------------- | -| `agent.list()` | List all available agents | Agent[] | - ---- - -#### Examples - -```javascript -const agents = await client.agent.list() +const content = await client.file.read({ + query: { path: "src/index.ts", directory: "/path/to/project" }, +}) ``` --- ### TUI -| Method | Description | Response | -| --------------------------------------------- | --------------------------------- | ---------------------- | -| `tui.appendPrompt({ text })` | 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({ command })` | Execute a command | `boolean` | -| `tui.showToast({ title?, message, variant })` | Show toast notification | `boolean` | -| `tui.control.next()` | Wait for the next control request | Control request object | -| `tui.control.response({ body })` | Respond to a control request | `boolean` | +| 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` | --- @@ -334,10 +329,12 @@ const agents = await client.agent.list() ```javascript // Control TUI interface -await client.tui.appendPrompt({ text: "Add this to prompt" }) +await client.tui.appendPrompt({ + body: { text: "Add this to prompt" }, +}) + await client.tui.showToast({ - message: "Task completed", - variant: "success", + body: { message: "Task completed", variant: "success" }, }) ``` @@ -345,9 +342,9 @@ await client.tui.showToast({ ### Auth -| Method | Description | Response | -| ------------------------------- | ------------------------------ | --------- | -| `auth.set({ id, ...authData })` | Set authentication credentials | `boolean` | +| Method | Description | Response | +| ------------------- | ------------------------------ | --------- | +| `auth.set({ ... })` | Set authentication credentials | `boolean` | --- @@ -355,9 +352,9 @@ await client.tui.showToast({ ```javascript await client.auth.set({ - id: "anthropic", - type: "api", - key: "your-api-key", + path: { id: "anthropic" }, + body: { type: "api", key: "your-api-key" }, + query: { directory: "/path/to/project" }, }) ``` @@ -375,7 +372,9 @@ await client.auth.set({ ```javascript // Listen to real-time events -const events = await client.event.subscribe() +const events = await client.event.subscribe({ + query: { directory: "/path/to/project" }, +}) for await (const event of events.stream) { console.log("Event:", event.type, event.properties) }