02f2725154
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com> Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com> Co-authored-by: Dax Raad <d@ironbay.co> Co-authored-by: Dax <mail@thdxr.com> Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com> Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Co-authored-by: Nabs <nabil@instafork.com> Co-authored-by: usrnk1 <7547651+usrnk1@users.noreply.github.com> Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com> Co-authored-by: Aarav Sareen <96787824+arvsrn@users.noreply.github.com> Co-authored-by: Brendan Allan <git@brendonovich.dev> Co-authored-by: Victor Navarro <vn4varro@gmail.com> Co-authored-by: Vladimir Glafirov <vglafirov@gitlab.com> Co-authored-by: AidenGeunGeun <eastlandwyvern@gmail.com> Co-authored-by: Mark <geraint0923@users.noreply.github.com> Co-authored-by: Aiden Cline <aidenpcline@gmail.com> Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com> Co-authored-by: opencode <opencode@sst.dev> Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com> Co-authored-by: David Hill <1879069+iamdavidhill@users.noreply.github.com> Co-authored-by: Jay <air@live.ca> Co-authored-by: Jay <53023+jayair@users.noreply.github.com> Co-authored-by: BB84 <110078428+BB-84C@users.noreply.github.com> Co-authored-by: Dustin Deus <deusdustin@gmail.com> Co-authored-by: Frank <frank@anoma.ly> Co-authored-by: Jack <jack@anoma.ly> Co-authored-by: Sebastian <hasta84@gmail.com> Co-authored-by: Jérôme Benoit <jerome.benoit@sap.com> Co-authored-by: Test User <test@test.com> Co-authored-by: Simon Klee <hello@simonklee.dk> Co-authored-by: Rahul A Mistry <149420892+ProdigyRahul@users.noreply.github.com> Co-authored-by: Qiping Li <liqiping1991@gmail.com> Co-authored-by: liqiping <liqiping@msh.team> Co-authored-by: OpeOginni <107570612+OpeOginni@users.noreply.github.com> Co-authored-by: Matthias Reso <13337103+mreso@users.noreply.github.com> Co-authored-by: tobwen <1864057+tobwen@users.noreply.github.com> Co-authored-by: Daniel Polito <danielbpolito@gmail.com> Co-authored-by: opencode <noreply@opencode.ai>
114 lines
3.9 KiB
TypeScript
114 lines
3.9 KiB
TypeScript
import { describe, expect, test } from "bun:test"
|
|
import { createApiForServer, createSdkForServer } from "./server"
|
|
import { createCompatibleApi } from "./server-compat"
|
|
|
|
function setup(protocol: "v1" | "v2" | Promise<"v1" | "v2">) {
|
|
const requests: Request[] = []
|
|
const fetcher = Object.assign(
|
|
async (input: string | URL | Request, init?: RequestInit) => {
|
|
const request = new Request(input, init)
|
|
requests.push(request)
|
|
if (request.method === "PATCH") {
|
|
return Response.json({
|
|
id: "ses_1",
|
|
slug: "ses_1",
|
|
projectID: "project",
|
|
directory: "/repo",
|
|
title: "Session",
|
|
version: "1",
|
|
time: { created: 1, updated: 1 },
|
|
})
|
|
}
|
|
if (request.method === "POST" && request.url.endsWith("/prompt_async"))
|
|
return new Response(undefined, { status: 204 })
|
|
if (request.method === "POST" && request.url.endsWith("/prompt")) {
|
|
return Response.json({
|
|
admittedSeq: 1,
|
|
id: "msg_1",
|
|
sessionID: "ses_1",
|
|
timeCreated: 1,
|
|
type: "user",
|
|
data: { text: "hello" },
|
|
delivery: "steer",
|
|
})
|
|
}
|
|
if (request.method === "GET") return Response.json([])
|
|
return new Response(undefined, { status: 204 })
|
|
},
|
|
{ preconnect: globalThis.fetch.preconnect },
|
|
)
|
|
const server = { url: "http://localhost:4096" }
|
|
const api = createCompatibleApi({
|
|
protocol: typeof protocol === "string" ? Promise.resolve(protocol) : protocol,
|
|
current: createApiForServer({ server, fetch: fetcher }),
|
|
legacy: (directory) => createSdkForServer({ server, fetch: fetcher, directory, throwOnError: true }),
|
|
directory: "/repo",
|
|
})
|
|
return { api, requests }
|
|
}
|
|
|
|
describe("createCompatibleApi", () => {
|
|
test("routes V1 archive through the legacy session update", async () => {
|
|
const { api, requests } = setup("v1")
|
|
await api.session.archive({ sessionID: "ses_1", directory: "/repo" })
|
|
|
|
const url = new URL(requests[0]!.url)
|
|
expect(url.pathname).toBe("/session/ses_1")
|
|
expect(requests[0]!.headers.get("x-opencode-directory")).toBe("%2Frepo")
|
|
expect(requests[0]!.method).toBe("PATCH")
|
|
expect(await requests[0]!.json()).toMatchObject({ time: { archived: expect.any(Number) } })
|
|
})
|
|
|
|
test("converts current prompts to the V1 prompt contract", async () => {
|
|
const { api, requests } = setup("v1")
|
|
await api.session.prompt({
|
|
sessionID: "ses_1",
|
|
id: "msg_1",
|
|
text: "hello",
|
|
agent: "build",
|
|
model: { providerID: "provider", modelID: "model" },
|
|
})
|
|
|
|
expect(new URL(requests[0]!.url).pathname).toBe("/session/ses_1/prompt_async")
|
|
expect(await requests[0]!.json()).toMatchObject({
|
|
messageID: "msg_1",
|
|
agent: "build",
|
|
model: { providerID: "provider", modelID: "model" },
|
|
parts: [{ type: "text", text: "hello" }],
|
|
})
|
|
})
|
|
|
|
test("keeps V2 session actions on the current API", async () => {
|
|
const { api, requests } = setup("v2")
|
|
await api.session.archive({ sessionID: "ses_1" })
|
|
|
|
expect(new URL(requests[0]!.url).pathname).toBe("/api/session/ses_1/archive")
|
|
expect(requests[0]!.method).toBe("POST")
|
|
})
|
|
|
|
test("resolves protocol detection once across implementation methods", async () => {
|
|
let detections = 0
|
|
const resolved = Promise.resolve<"v1" | "v2">("v2")
|
|
const protocol = new Proxy(resolved, {
|
|
get(target, property) {
|
|
if (property !== "then") return Reflect.get(target, property, target)
|
|
detections++
|
|
return target.then.bind(target)
|
|
},
|
|
})
|
|
const { api } = setup(protocol)
|
|
|
|
await api.session.archive({ sessionID: "ses_1" })
|
|
await api.session.list()
|
|
|
|
expect(detections).toBe(1)
|
|
})
|
|
|
|
test("uses the global V1 session search endpoint", async () => {
|
|
const { api, requests } = setup("v1")
|
|
await api.session.list({ parentID: null, search: "session", limit: 50 })
|
|
|
|
expect(new URL(requests[0]!.url).pathname).toBe("/experimental/session")
|
|
})
|
|
})
|