feat(client): add root promise entrypoint

This commit is contained in:
Dax Raad 2026-07-10 01:09:06 -04:00
commit 6a85f0d3db
4 changed files with 156 additions and 56 deletions

View file

@ -16,22 +16,15 @@ network. Its types and methods are generated from the same contract as the
## Install
```sh
bun add @opencode-ai/client
bun add @opencode-ai/client@next
```
The package has two entrypoints:
- `@opencode-ai/client/promise` uses `fetch` and returns Promises or async
iterables. It has no Effect runtime dependency.
- `@opencode-ai/client/effect` returns Effects and Streams, decodes values into
the V2 schema types, and requires an `HttpClient` service from Effect.
## Promise client
## Create a client
Create a client with the server URL, then call methods grouped by API resource:
```ts
import { OpenCode } from "@opencode-ai/client/promise"
import { OpenCode } from "@opencode-ai/client"
const client = OpenCode.make({
baseUrl: "http://localhost:4096",
@ -47,11 +40,28 @@ await client.session.prompt({
})
```
## Headers and requests
Pass default authentication or application headers to `OpenCode.make` with
`headers`. You can also supply a custom `fetch` implementation. Each operation
accepts request options as its final argument for an `AbortSignal` or
per-request headers.
```ts
const client = OpenCode.make({
baseUrl: "https://opencode.example.com",
headers: {
authorization: `Bearer ${process.env.OPENCODE_TOKEN}`,
},
})
await client.session.list(undefined, {
signal: AbortSignal.timeout(10_000),
})
```
## Stream events
Streaming endpoints return async iterables:
```ts
@ -60,11 +70,17 @@ for await (const event of client.event.subscribe()) {
}
```
## Effect client
## Effect
Install the `effect` peer dependency when using the Effect entrypoint. The
client uses canonical V2 values such as `Location.Ref` and `Session.ID`, and
returns typed failures in the Effect error channel.
OpenCode provides a first-class Effect client through the
`@opencode-ai/client/effect` entrypoint. It returns typed Effects and Streams
and decodes responses into OpenCode schema values.
```sh
bun add @opencode-ai/client@next effect
```
### Create a client
```ts
import { AbsolutePath, Location, OpenCode } from "@opencode-ai/client/effect"
@ -89,3 +105,41 @@ const session = await Effect.runPromise(
Streaming operations, including `client.event.subscribe()` and
`client.session.log(...)`, return Effect `Stream` values.
### Service
`Service` discovers and manages the local OpenCode background service from a
Node application:
- `Service.discover()` returns a healthy registered endpoint without starting
a process.
- `Service.start()` reuses a compatible service or starts one when needed.
- `Service.stop()` stops the registered service.
- `Service.headers(endpoint)` creates the authentication headers for a client.
```sh
bun add @effect/platform-node
```
```ts
import { NodeFileSystem } from "@effect/platform-node"
import { OpenCode, Service } from "@opencode-ai/client/effect"
import { Effect } from "effect"
import { FetchHttpClient } from "effect/unstable/http"
const program = Effect.gen(function* () {
const endpoint = yield* Service.start()
const client = yield* OpenCode.make({
baseUrl: endpoint.url,
headers: Service.headers(endpoint),
})
return yield* client.health.get()
})
const health = await Effect.runPromise(
program.pipe(
Effect.provide(FetchHttpClient.layer),
Effect.provide(NodeFileSystem.layer),
),
)
```