mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-01 03:42:04 +00:00
feat(plugin): expose session list (#56264)
This commit is contained in:
parent
4a5302817b
commit
bc5fa1ccf3
8 changed files with 79 additions and 0 deletions
|
|
@ -546,6 +546,7 @@ export const make = Effect.fn("PluginHost.make")(function* (
|
|||
},
|
||||
session: {
|
||||
hook: (name, callback, options) => hooks.register("session", name, callback, options),
|
||||
list: sessions.list,
|
||||
create: (input) =>
|
||||
sessions.create({
|
||||
id: input?.id,
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ export function host(overrides: Overrides = {}): Plugin.Context {
|
|||
},
|
||||
session: {
|
||||
hook: overrides.session?.hook ?? (() => Effect.die("unused session.hook")),
|
||||
list: overrides.session?.list ?? (() => Effect.die("unused session.list")),
|
||||
create: overrides.session?.create ?? (() => Effect.die("unused session.create")),
|
||||
get: overrides.session?.get ?? (() => Effect.die("unused session.get")),
|
||||
remove: overrides.session?.remove ?? (() => Effect.die("unused session.remove")),
|
||||
|
|
|
|||
52
packages/core/test/plugin/session-list.test.ts
Normal file
52
packages/core/test/plugin/session-list.test.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import { expect } from "bun:test"
|
||||
import { Plugin } from "@opencode/core/plugin"
|
||||
import { PluginHost } from "@opencode/core/plugin/host"
|
||||
import { PluginPromise } from "@opencode/core/plugin/promise"
|
||||
import { Session } from "@opencode/core/session"
|
||||
import { Effect } from "effect"
|
||||
import { testEffect } from "../lib/effect"
|
||||
import { PluginTestLayer } from "./fixture"
|
||||
|
||||
const it = testEffect(PluginTestLayer)
|
||||
|
||||
it.live("Effect plugins list sessions with the same pages as Core", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugins = yield* Plugin.Service
|
||||
const sessions = yield* Session.Service
|
||||
const context = yield* PluginHost.make(plugins)
|
||||
const parent = yield* context.session.create({ title: "match parent" })
|
||||
yield* sessions.create({ parentID: parent.id, title: "match child" })
|
||||
yield* context.session.create({ title: "match root" })
|
||||
yield* context.session.create({ title: "different" })
|
||||
const filter = { directory: context.location.directory, parentID: null, search: "match", limit: 1 }
|
||||
|
||||
const first = yield* context.session.list(filter)
|
||||
expect(first).toEqual(yield* sessions.list(filter))
|
||||
expect(yield* context.session.list({ cursor: first.cursor.next })).toEqual(
|
||||
yield* sessions.list({ cursor: first.cursor.next }),
|
||||
)
|
||||
}),
|
||||
)
|
||||
|
||||
it.live("Promise plugins list sessions and follow cursors", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugins = yield* Plugin.Service
|
||||
const sessions = yield* Session.Service
|
||||
const context = yield* PluginHost.make(plugins)
|
||||
const parent = yield* context.session.create({ title: "match parent" })
|
||||
yield* sessions.create({ parentID: parent.id, title: "match child" })
|
||||
yield* context.session.create({ title: "match root" })
|
||||
const roots = (yield* sessions.list({ parentID: null, search: "match" })).data.map((session) => session.id)
|
||||
|
||||
yield* PluginPromise.fromPromise({
|
||||
id: "test.session-list",
|
||||
async setup(ctx) {
|
||||
const first = await ctx.session.list({ parentID: null, search: "match", limit: 1 })
|
||||
expect(first.cursor.next).toBeDefined()
|
||||
const second = await ctx.session.list({ cursor: first.cursor.next ?? undefined, limit: 1 })
|
||||
expect([...first.data, ...second.data].map((session) => session.id)).toEqual(roots)
|
||||
await expect(ctx.session.list({ cursor: "invalid" })).rejects.toThrow()
|
||||
},
|
||||
}).effect(context)
|
||||
}),
|
||||
)
|
||||
|
|
@ -152,6 +152,7 @@ export interface SessionHooks {
|
|||
|
||||
export type SessionDomain = Pick<
|
||||
SessionApi<unknown>,
|
||||
| "list"
|
||||
| "create"
|
||||
| "get"
|
||||
| "remove"
|
||||
|
|
|
|||
|
|
@ -593,6 +593,7 @@ export function fromPromise(plugin: Plugin) {
|
|||
register(
|
||||
host.session.hook(name, (event) => Effect.promise(() => Promise.resolve(callback(event))), options),
|
||||
),
|
||||
list: adaptApiMethod(SessionEndpoints["session.list"], host.session.list),
|
||||
create: adaptApiMethod(SessionEndpoints["session.create"], host.session.create),
|
||||
get: adaptApiMethod(SessionEndpoints["session.get"], host.session.get),
|
||||
remove: adaptApiMethod(SessionEndpoints["session.remove"], host.session.remove),
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ export interface SessionHooks {
|
|||
|
||||
export type SessionDomain = Pick<
|
||||
SessionApi,
|
||||
| "list"
|
||||
| "create"
|
||||
| "get"
|
||||
| "remove"
|
||||
|
|
|
|||
|
|
@ -824,6 +824,19 @@ effect: (ctx) =>
|
|||
}),
|
||||
```
|
||||
|
||||
List sessions a page at a time. To get the next page, pass `cursor.next` back as `cursor`. The cursor remembers your
|
||||
filters, so you don't need to repeat them.
|
||||
|
||||
```ts
|
||||
effect: (ctx) =>
|
||||
Effect.gen(function* () {
|
||||
const page = yield* ctx.session.list({ directory: ctx.location.directory, limit: 20 }).pipe(Effect.orDie)
|
||||
const next = page.cursor.next
|
||||
? yield* ctx.session.list({ cursor: page.cursor.next, limit: 20 }).pipe(Effect.orDie)
|
||||
: undefined
|
||||
}),
|
||||
```
|
||||
|
||||
Remove a temporary session with `remove`. Removal stops active execution and recursively deletes child sessions.
|
||||
|
||||
```ts
|
||||
|
|
@ -852,6 +865,7 @@ Schemas: [`Session.Info`](/api#schema-Session.Info), [`Model.Ref`](/api#schema-M
|
|||
```ts
|
||||
type SessionDomain = Pick<
|
||||
SessionApi<unknown>,
|
||||
| "list"
|
||||
| "create"
|
||||
| "get"
|
||||
| "remove"
|
||||
|
|
|
|||
|
|
@ -792,6 +792,14 @@ const session = await ctx.session.get({ sessionID })
|
|||
const messages = await ctx.session.context({ sessionID })
|
||||
```
|
||||
|
||||
List sessions a page at a time. To get the next page, pass `cursor.next` back as `cursor`. The cursor remembers your
|
||||
filters, so you don't need to repeat them.
|
||||
|
||||
```ts
|
||||
const page = await ctx.session.list({ directory: ctx.location.directory, limit: 20 })
|
||||
const next = page.cursor.next ? await ctx.session.list({ cursor: page.cursor.next, limit: 20 }) : undefined
|
||||
```
|
||||
|
||||
Change the agent or model used by subsequent requests.
|
||||
|
||||
```ts
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue