99 lines
3.1 KiB
TypeScript
99 lines
3.1 KiB
TypeScript
import { describe, expect, test } from "bun:test"
|
|
import type { OpencodeClient, Session } from "@opencode-ai/sdk/v2/client"
|
|
import { createServerSession } from "./server-session"
|
|
|
|
const session = (id: string, parentID?: string): Session => ({
|
|
id,
|
|
slug: id,
|
|
projectID: "project",
|
|
directory: "/repo",
|
|
title: id,
|
|
version: "1",
|
|
parentID,
|
|
time: { created: 1, updated: 1 },
|
|
})
|
|
|
|
function setup(sessions: Record<string, Session>) {
|
|
const get: unknown[] = []
|
|
const messages: unknown[] = []
|
|
const client = {
|
|
session: {
|
|
get: async (input: unknown) => {
|
|
get.push(input)
|
|
const id = (input as { sessionID: string }).sessionID
|
|
return { data: sessions[id] }
|
|
},
|
|
messages: async (input: unknown) => {
|
|
messages.push(input)
|
|
return { data: [], response: { headers: new Headers() } }
|
|
},
|
|
diff: async () => ({ data: [] }),
|
|
todo: async () => ({ data: [] }),
|
|
},
|
|
} as unknown as OpencodeClient
|
|
return { get, messages, store: createServerSession(client) }
|
|
}
|
|
|
|
describe("server session", () => {
|
|
test("resolves lineage by session ID without directory", async () => {
|
|
const ctx = setup({ child: session("child", "root"), root: session("root") })
|
|
|
|
const result = await ctx.store.lineage.resolve("child")
|
|
|
|
expect(result.root.id).toBe("root")
|
|
expect(ctx.get).toEqual([{ sessionID: "child" }, { sessionID: "root" }])
|
|
expect(ctx.store.lineage.peek("child")).toEqual(result)
|
|
})
|
|
|
|
test("loads session content through the server client", async () => {
|
|
const ctx = setup({ root: session("root") })
|
|
|
|
await ctx.store.sync("root")
|
|
|
|
expect(ctx.get).toEqual([{ sessionID: "root" }])
|
|
expect(ctx.messages).toEqual([{ sessionID: "root", limit: 2, before: undefined }])
|
|
expect(ctx.store.data.message.root).toEqual([])
|
|
})
|
|
|
|
test("applies events without a directory store", () => {
|
|
const ctx = setup({})
|
|
ctx.store.apply({ type: "session.created", properties: { info: session("root") } })
|
|
ctx.store.apply({ type: "session.status", properties: { sessionID: "root", status: { type: "busy" } } })
|
|
|
|
expect(ctx.store.get("root")?.directory).toBe("/repo")
|
|
expect(ctx.store.data.session_working("root")).toBe(true)
|
|
})
|
|
|
|
test("preserves pinned session content under server-wide cache pressure", () => {
|
|
const ctx = setup({})
|
|
ctx.store.pin("active")
|
|
ctx.store.optimistic.add({
|
|
sessionID: "active",
|
|
message: {
|
|
id: "message",
|
|
sessionID: "active",
|
|
role: "assistant",
|
|
time: { created: 1 },
|
|
parentID: "parent",
|
|
modelID: "model",
|
|
providerID: "provider",
|
|
mode: "build",
|
|
agent: "agent",
|
|
path: { cwd: "/repo", root: "/repo" },
|
|
cost: 0,
|
|
tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
|
|
},
|
|
parts: [],
|
|
})
|
|
|
|
for (let index = 0; index < 50; index++) {
|
|
ctx.store.apply({
|
|
type: "session.status",
|
|
properties: { sessionID: `session-${index}`, status: { type: "busy" } },
|
|
})
|
|
}
|
|
|
|
expect(ctx.store.data.message.active?.map((message) => message.id)).toEqual(["message"])
|
|
})
|
|
})
|