Dax Raad 5 месяцев назад
Родитель
Сommit
f6bc9238df

+ 8 - 2
packages/plugin/src/example.ts

@@ -1,9 +1,15 @@
 import { Plugin } from "./index"
 
-export const ExamplePlugin: Plugin = async ({ client, $ }) => {
+export const ExamplePlugin: Plugin = async ({
+  client: _client,
+  $: _shell,
+  project: _project,
+  directory: _directory,
+  worktree: _worktree,
+}) => {
   return {
     permission: {},
-    async "chat.params"(input, output) {
+    async "chat.params"(_input, output) {
       output.topP = 1
     },
   }

+ 55 - 0
packages/sdk/js/example/example.ts

@@ -0,0 +1,55 @@
+import { createOpencodeClient, createOpencodeServer } from "@opencode-ai/sdk"
+
+const server = await createOpencodeServer()
+const client = createOpencodeClient({ baseUrl: server.url })
+
+const input = await Array.fromAsync(new Bun.Glob("packages/core/*.ts").scan())
+
+const tasks: Promise<void>[] = []
+for await (const file of input) {
+  console.log("processing", file)
+  const session = await client.session.create()
+  tasks.push(
+    client.session.prompt({
+      path: { id: session.data.id },
+      body: {
+        parts: [
+          {
+            type: "file",
+            mime: "text/plain",
+            url: `file://${file}`,
+          },
+          {
+            type: "text",
+            text: `Write tests for every public function in this file.`,
+          },
+        ],
+      },
+    }),
+  )
+  console.log("done", file)
+}
+
+await Promise.all(
+  input.map(async (file) => {
+    const session = await client.session.create()
+    console.log("processing", file)
+    await client.session.prompt({
+      path: { id: session.data.id },
+      body: {
+        parts: [
+          {
+            type: "file",
+            mime: "text/plain",
+            url: `file://${file}`,
+          },
+          {
+            type: "text",
+            text: `Write tests for every public function in this file.`,
+          },
+        ],
+      },
+    })
+    console.log("done", file)
+  }),
+)

+ 8 - 6
packages/web/src/content/docs/docs/plugins.mdx

@@ -26,7 +26,7 @@ Plugins are loaded from:
 ### Basic structure
 
 ```js title=".opencode/plugin/example.js"
-export const MyPlugin = async ({ app, client, $ }) => {
+export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
   console.log("Plugin initialized!")
 
   return {
@@ -37,7 +37,9 @@ export const MyPlugin = async ({ app, client, $ }) => {
 
 The plugin function receives:
 
-- `app`: The opencode application instance.
+- `project`: The current project information.
+- `directory`: The current working directory.
+- `worktree`: The git worktree path.
 - `client`: An opencode SDK client for interacting with the AI.
 - `$`: Bun's [shell API](https://bun.com/docs/runtime/shell) for executing commands.
 
@@ -50,7 +52,7 @@ For TypeScript plugins, you can import types from the plugin package:
 ```ts title="my-plugin.ts" {1}
 import type { Plugin } from "@opencode-ai/plugin"
 
-export const MyPlugin: Plugin = async ({ app, client, $ }) => {
+export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
   return {
     // Type-safe hook implementations
   }
@@ -70,7 +72,7 @@ Here are some examples of plugins you can use to extend opencode.
 Send notifications when certain events occur:
 
 ```js title=".opencode/plugin/notification.js"
-export const NotificationPlugin = async ({ client, $ }) => {
+export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => {
   return {
     event: async ({ event }) => {
       // Send notification on session completion
@@ -91,13 +93,13 @@ We are using `osascript` to run AppleScript on macOS. Here we are using it to se
 Prevent opencode from reading `.env` files:
 
 ```javascript title=".opencode/plugin/env-protection.js"
-export const EnvProtection = async ({ client, $ }) => {
+export const EnvProtection = async ({ project, client, $, directory, worktree }) => {
   return {
     "tool.execute.before": async (input, output) => {
       if (input.tool === "read" && output.args.filePath.includes(".env")) {
         throw new Error("Do not read .env files")
       }
-    }
+    },
   }
 }
 ```

+ 66 - 17
packages/web/src/content/docs/docs/sdk.mdx

@@ -10,6 +10,8 @@ The opencode [JS/TS SDK](https://www.npmjs.com/package/@opencode-ai/sdk) provide
 
 [Learn more](/docs/server) about how the opencode server works.
 
+> **Note**: Many API endpoints now require a `directory` query parameter to specify the working directory context.
+
 ---
 
 ## Install
@@ -65,12 +67,12 @@ server.close()
 
 #### Options
 
-| 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`        |
+| 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`      |
 
 ---
 
@@ -80,7 +82,7 @@ The SDK includes TypeScript definitions for all API types. Import them directly:
 
 ```typescript
 import type { Session, Message, Part } from "@opencode-ai/sdk"
-````
+```
 
 All types are generated from the server's OpenAPI specification and available in the <a href={typesUrl}>types file</a>.
 
@@ -108,18 +110,63 @@ The SDK exposes all server APIs through a type-safe client interface.
 
 ### App
 
-| Method       | Description        | Response                                |
-| ------------ | ------------------ | --------------------------------------- |
-| `app.get()`  | Get app info       | <a href={typesUrl}><code>App</code></a> |
-| `app.init()` | Initialize the app | `boolean`                               |
+| Method         | Description               | Response                                    |
+| -------------- | ------------------------- | ------------------------------------------- |
+| `app.log()`    | Write a log entry         | `boolean`                                   |
+| `app.agents()` | List all available agents | <a href={typesUrl}><code>Agent[]</code></a> |
+
+---
+
+#### Examples
+
+```javascript
+// Log an entry
+await client.app.log({
+  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   | <a href={typesUrl}><code>Project[]</code></a> |
+| `project.current()` | Get current project | <a href={typesUrl}><code>Project</code></a>   |
+
+---
+
+#### Examples
+
+```javascript
+// List all projects
+const projects = await client.project.list()
+
+// Get current project
+const currentProject = await client.project.current()
+```
+
+---
+
+### Path
+
+| Method       | Description      | Response                                 |
+| ------------ | ---------------- | ---------------------------------------- |
+| `path.get()` | Get current path | <a href={typesUrl}><code>Path</code></a> |
 
 ---
 
 #### Examples
 
 ```javascript
-const app = await client.app.get()
-await client.app.init()
+// Get current path information
+const pathInfo = await client.path.get()
 ```
 
 ---
@@ -159,7 +206,7 @@ const { providers, default: defaults } = await client.config.providers()
 | `session.summarize({ id, providerID, modelID })`              | Summarize session                  | Returns `boolean`                                                                                                       |
 | `session.messages({ id })`                                    | List messages in a session         | Returns `{ info: `<a href={typesUrl}><code>Message</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}[]` |
 | `session.message({ id, messageID })`                          | Get message details                | Returns `{ info: `<a href={typesUrl}><code>Message</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}`   |
-| `session.chat({ id, ...chatInput })`                          | Send chat message                  | Returns <a href={typesUrl}><code>Message</code></a>                                                                     |
+| `session.prompt({ id, ...promptInput })`                      | Send prompt message                | Returns <a href={typesUrl}><code>Message</code></a>                                                                     |
 | `session.shell({ id, agent, command })`                       | Run a shell command                | Returns <a href={typesUrl}><code>Message</code></a>                                                                     |
 | `session.revert({ id, messageID, partID? })`                  | Revert a message                   | Returns <a href={typesUrl}><code>Session</code></a>                                                                     |
 | `session.unrevert({ id })`                                    | Restore reverted messages          | Returns <a href={typesUrl}><code>Session</code></a>                                                                     |
@@ -175,10 +222,12 @@ const session = await client.session.create({ title: "My session" })
 const sessions = await client.session.list()
 
 // Send messages
-const message = await client.session.chat({
+const message = await client.session.prompt({
   id: session.id,
-  providerID: "anthropic",
-  modelID: "claude-3-5-sonnet-20241022",
+  model: {
+    providerID: "anthropic",
+    modelID: "claude-3-5-sonnet-20241022",
+  },
   parts: [{ type: "text", text: "Hello!" }],
 })
 ```