Compare commits

...
Author SHA1 Message Date
Kit Langton 3369c08ffa docs(plugin): update current API examples 2026-08-27 15:00:32 -04:00
2 changed files with 38 additions and 12 deletions
+21 -7
View File
@@ -5,7 +5,9 @@ The Promise plugin API at `@opencode-ai/plugin` is the async/await equivalent of
- `hook` installs behavior at an OpenCode extension point.
- `reload` reruns every transform hook for a stateful domain.
The only difference from the Effect API is the async boundary: hook callbacks, hook registration, `reload`, and `Registration.dispose` use Promises instead of Effects.
The Promise API uses Promises instead of Effects for setup, runtime hook
callbacks, hook registration, `reload`, and `Registration.dispose`. Transform
draft callbacks remain synchronous.
## Defining A Plugin
@@ -46,12 +48,15 @@ await registration.dispose()
## Transform Hooks
Transform hooks contribute to stateful domains. The draft editor is synchronous; the callback may be `async` when it needs to await other work:
Transform hooks contribute to stateful domains. The draft editor is synchronous,
so load asynchronous data before registering a transform or reloading its domain:
```ts
const description = await loadReviewerDescription()
await ctx.agent.transform((agent) => {
agent.update("reviewer", (item) => {
item.description = "Reviews code for regressions"
item.description = description
item.mode = "subagent"
})
})
@@ -64,8 +69,12 @@ ctx.agent.transform
ctx.catalog.transform
ctx.command.transform
ctx.integration.transform
ctx.mcp.transform
ctx.reference.transform
ctx.skill.transform
ctx.tool.transform
ctx.vcs.transform
ctx.websearch.transform
```
## Runtime Hooks
@@ -81,7 +90,7 @@ await ctx.aisdk.hook("sdk", async (event) => {
await ctx.aisdk.hook("language", (event) => {
if (event.model.providerID !== "xai") return
event.language = event.sdk.responses(event.model.api.id)
event.language = event.sdk.responses(event.model.modelID)
})
```
@@ -94,14 +103,15 @@ await ctx.session.hook("context", (event) => {
})
```
Promise tools use executable tool values with async executors. Registration
supplies the tool's name and options separately:
Promise tools use complete executable tool values with async executors:
```ts
import { Schema } from "effect"
await ctx.tool.transform((tools) => {
tools.add("echo", {
tools.add({
name: "echo",
options: { codemode: false },
description: "Echo text",
input: Schema.Struct({ text: Schema.String }),
output: Schema.Struct({ text: Schema.String }),
@@ -132,6 +142,10 @@ ctx.agent.reload()
ctx.catalog.reload()
ctx.command.reload()
ctx.integration.reload()
ctx.mcp.reload()
ctx.reference.reload()
ctx.skill.reload()
ctx.tool.reload()
ctx.vcs.reload()
ctx.websearch.reload()
```
+17 -5
View File
@@ -31,7 +31,9 @@ Registrations are owned by the plugin scope. Closing the scope removes them auto
## Transform Hooks
Transform hooks contribute to stateful domains:
Transform hooks contribute to stateful domains. Their draft callbacks are
synchronous, so load effectful data before registering a transform or reloading
its domain:
```ts
yield *
@@ -52,8 +54,12 @@ ctx.agent.transform
ctx.catalog.transform
ctx.command.transform
ctx.integration.transform
ctx.mcp.transform
ctx.reference.transform
ctx.skill.transform
ctx.tool.transform
ctx.vcs.transform
ctx.websearch.transform
```
## Runtime Hooks
@@ -72,10 +78,12 @@ yield *
)
yield *
ctx.aisdk.hook("language", (event) => {
if (event.model.providerID !== "xai") return
event.language = event.sdk.responses(event.model.api.id)
})
ctx.aisdk.hook("language", (event) =>
Effect.sync(() => {
if (event.model.providerID !== "xai") return
event.language = event.sdk.responses(event.model.modelID)
}),
)
```
Hooks run sequentially in registration order. Later hooks observe mutations made by earlier hooks.
@@ -117,6 +125,10 @@ ctx.agent.reload()
ctx.catalog.reload()
ctx.command.reload()
ctx.integration.reload()
ctx.mcp.reload()
ctx.reference.reload()
ctx.skill.reload()
ctx.tool.reload()
ctx.vcs.reload()
ctx.websearch.reload()
```