mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-22 18:25:32 -04:00
a3e2cc0dcd
Fixes #36121
97 lines
4.2 KiB
TypeScript
97 lines
4.2 KiB
TypeScript
import { afterEach, describe, expect, mock, spyOn, test } from "bun:test"
|
|
import { OpenCode, type LocationGetOutput, type ModelRef, type SessionInfo } from "@opencode-ai/client/promise"
|
|
import { resolveSessionTarget, SessionTargetMutationError } from "../src/session-target"
|
|
|
|
function location(directory: string, workspaceID?: string): LocationGetOutput {
|
|
return { directory, workspaceID, project: { id: "project", directory } }
|
|
}
|
|
|
|
function session(id: string, directory: string, workspaceID?: string, model?: ModelRef): SessionInfo {
|
|
return {
|
|
id,
|
|
projectID: "project",
|
|
title: id,
|
|
location: { directory, workspaceID },
|
|
model,
|
|
cost: 0,
|
|
tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
|
|
time: { created: 1, updated: 1 },
|
|
}
|
|
}
|
|
|
|
const prepare = async (input: { model: ModelRef | undefined; agent: string | undefined }) => ({
|
|
model: input.model,
|
|
agent: input.agent,
|
|
})
|
|
|
|
afterEach(() => mock.restore())
|
|
|
|
describe("session target resolver", () => {
|
|
test("adopts an explicit Session location and model", async () => {
|
|
const client = OpenCode.make({ baseUrl: "https://opencode.test" })
|
|
const selected = session("ses_resume", "/session", "work_1", { providerID: "openai", id: "gpt-5" })
|
|
spyOn(client.session, "get").mockResolvedValue(selected)
|
|
spyOn(client.location, "get").mockResolvedValue(location("/session", "work_1"))
|
|
|
|
const target = await resolveSessionTarget({ client, session: selected.id, prepare })
|
|
expect(target).toMatchObject({
|
|
session: { id: "ses_resume" },
|
|
location: { directory: "/session", workspaceID: "work_1" },
|
|
model: { providerID: "openai", id: "gpt-5" },
|
|
resume: true,
|
|
})
|
|
})
|
|
|
|
test("paginates to continue the exact implicit workspace", async () => {
|
|
const client = OpenCode.make({ baseUrl: "https://opencode.test" })
|
|
spyOn(client.location, "get").mockResolvedValue(location("/project"))
|
|
const explicit = Array.from({ length: 50 }, (_, index) => session(`ses_${index}`, "/project", `work_${index}`))
|
|
const list = spyOn(client.session, "list")
|
|
.mockResolvedValueOnce({ data: explicit, cursor: { next: "page_2" } })
|
|
.mockResolvedValueOnce({ data: [session("ses_implicit", "/project")], cursor: {} })
|
|
|
|
const target = await resolveSessionTarget({ client, location: { directory: "/project" }, continue: true, prepare })
|
|
expect(list).toHaveBeenCalledTimes(2)
|
|
expect(target.session.id).toBe("ses_implicit")
|
|
})
|
|
|
|
test("prepares a fresh Session at the server Location before creation", async () => {
|
|
const client = OpenCode.make({ baseUrl: "https://opencode.test" })
|
|
const order: string[] = []
|
|
spyOn(client.location, "get").mockResolvedValue(location("/server", "work_1"))
|
|
const create = spyOn(client.session, "create").mockImplementation(async (input) => {
|
|
order.push("create")
|
|
expect(input).toMatchObject({ agent: "prepared", location: { directory: "/server", workspaceID: "work_1" } })
|
|
return session("ses_fresh", "/server", "work_1")
|
|
})
|
|
|
|
await resolveSessionTarget({
|
|
client,
|
|
agent: "requested",
|
|
prepare: async (input) => {
|
|
order.push("prepare")
|
|
expect(input.location.workspaceID).toBe("work_1")
|
|
return { model: input.model, agent: "prepared" }
|
|
},
|
|
})
|
|
expect(create).toHaveBeenCalledTimes(1)
|
|
expect(order).toEqual(["prepare", "create"])
|
|
})
|
|
|
|
test("uses the agent resolved by the server for a fresh Session", async () => {
|
|
const client = OpenCode.make({ baseUrl: "https://opencode.test" })
|
|
spyOn(client.location, "get").mockResolvedValue(location("/project"))
|
|
spyOn(client.session, "create").mockResolvedValue({ ...session("ses_fresh", "/project"), agent: "review" })
|
|
|
|
const target = await resolveSessionTarget({ client, prepare })
|
|
expect(target.agent).toBe("review")
|
|
})
|
|
|
|
test("does not retry an ambiguous Session creation", async () => {
|
|
const client = OpenCode.make({ baseUrl: "https://opencode.test" })
|
|
spyOn(client.location, "get").mockResolvedValue(location("/project"))
|
|
spyOn(client.session, "create").mockRejectedValue(new Error("connection closed after create"))
|
|
await expect(resolveSessionTarget({ client, prepare })).rejects.toBeInstanceOf(SessionTargetMutationError)
|
|
})
|
|
})
|