From c97b46e7cb70e9b5e85dbe4d274d59f2a3060707 Mon Sep 17 00:00:00 2001 From: Haohao-end <2227625024@qq.com> Date: Sun, 22 Mar 2026 23:44:57 +0800 Subject: [PATCH] fix(acp): use global session list for unstable_listSessions --- packages/opencode/src/acp/agent.ts | 27 ++--- .../opencode/test/acp/list-sessions.test.ts | 102 ++++++++++++++++++ 2 files changed, 113 insertions(+), 16 deletions(-) create mode 100644 packages/opencode/test/acp/list-sessions.test.ts diff --git a/packages/opencode/src/acp/agent.ts b/packages/opencode/src/acp/agent.ts index 2a6bbbb1e4..89145e759e 100644 --- a/packages/opencode/src/acp/agent.ts +++ b/packages/opencode/src/acp/agent.ts @@ -671,29 +671,24 @@ export namespace ACP { const cursor = params.cursor ? Number(params.cursor) : undefined const limit = 100 - const sessions = await this.sdk.session - .list( - { - directory: params.cwd ?? undefined, - roots: true, - }, - { throwOnError: true }, - ) - .then((x) => x.data ?? []) + const listed = await this.sdk.experimental.session.list( + { + roots: true, + cursor, + limit, + }, + { throwOnError: true }, + ) + const sessions = listed.data ?? [] - const sorted = sessions.toSorted((a, b) => b.time.updated - a.time.updated) - const filtered = cursor ? sorted.filter((s) => s.time.updated < cursor) : sorted - const page = filtered.slice(0, limit) - - const entries: SessionInfo[] = page.map((session) => ({ + const entries: SessionInfo[] = sessions.map((session) => ({ sessionId: session.id, cwd: session.directory, title: session.title, updatedAt: new Date(session.time.updated).toISOString(), })) - const last = page[page.length - 1] - const next = filtered.length > limit && last ? String(last.time.updated) : undefined + const next = listed.response.headers.get("x-next-cursor") ?? undefined const response: ListSessionsResponse = { sessions: entries, diff --git a/packages/opencode/test/acp/list-sessions.test.ts b/packages/opencode/test/acp/list-sessions.test.ts new file mode 100644 index 0000000000..23243b4bc2 --- /dev/null +++ b/packages/opencode/test/acp/list-sessions.test.ts @@ -0,0 +1,102 @@ +import { describe, expect, test } from "bun:test" +import type { AgentSideConnection } from "@agentclientprotocol/sdk" +import type { OpencodeClient } from "@opencode-ai/sdk/v2" +import { ACP } from "../../src/acp/agent" +import type { ACPConfig } from "../../src/acp/types" + +function createAgent() { + const calls: Array | undefined> = [] + const sessions = [ + { + id: "session_2", + directory: "/tmp/two", + title: "second", + time: { updated: 1710000000000 }, + }, + { + id: "session_1", + directory: "/tmp/one", + title: "first", + time: { updated: 1700000000000 }, + }, + ] + + const sdk = { + global: { + event: async (opts?: { signal?: AbortSignal }) => ({ + stream: (async function* () { + await new Promise((resolve) => { + if (opts?.signal?.aborted) { + resolve() + return + } + opts?.signal?.addEventListener("abort", () => resolve(), { once: true }) + }) + })(), + }), + }, + experimental: { + session: { + list: async (input?: Record) => { + calls.push(input) + return { + data: sessions, + request: new Request("http://localhost/experimental/session"), + response: new Response("[]", { + headers: { + "x-next-cursor": "1700000000000", + }, + }), + } + }, + }, + }, + } as unknown as OpencodeClient + + const agent = new ACP.Agent({} as AgentSideConnection, { sdk } satisfies ACPConfig) + const stop = () => { + ;(agent as unknown as { eventAbort: AbortController }).eventAbort.abort() + } + + return { agent, calls, stop } +} + +describe("acp.agent unstable_listSessions", () => { + test("uses the global experimental session list", async () => { + const { agent, calls, stop } = createAgent() + + try { + const result = await agent.unstable_listSessions({ + cwd: "/tmp/current", + cursor: "1715000000000", + }) + + expect(calls).toEqual([ + { + roots: true, + cursor: 1715000000000, + limit: 100, + }, + ]) + expect(result).toEqual({ + sessions: [ + { + sessionId: "session_2", + cwd: "/tmp/two", + title: "second", + updatedAt: "2024-03-09T16:00:00.000Z", + }, + { + sessionId: "session_1", + cwd: "/tmp/one", + title: "first", + updatedAt: "2023-11-14T22:13:20.000Z", + }, + ], + nextCursor: "1700000000000", + }) + } finally { + stop() + } + }) +})