import { describe, expect, test } from "bun:test" import type { OpencodeClient } from "@opencode-ai/sdk/v2/client" import type { McpApi, McpListInput, McpResourceCatalogInput, SessionApi, SessionInfo, SessionListInput, } from "@opencode-ai/client/promise" import { QueryClient } from "@tanstack/solid-query" import { canDisposeDirectory, pickDirectoriesToEvict } from "./global-sync/eviction" import { estimateRootSessionTotal, loadRootSessions } from "./global-sync/session-load" import { loadActiveSessionsQuery, loadMcpQuery, loadMcpResourcesQuery, seedActiveSessionStatuses } from "./server-sync" import { ServerScope } from "@/utils/server-scope" import { createServerSession } from "./server-session" describe("MCP queries", () => { test("loads current servers for the requested location", async () => { const calls: unknown[] = [] const queryClient = new QueryClient() const result = await queryClient.fetchQuery( loadMcpQuery(ServerScope.local, "/project", { list: async (input: McpListInput = {}) => { calls.push(input) return { location: { directory: "/project", project: { id: "project", directory: "/project" } }, data: [ { name: "docs", status: { status: "connected" } }, { name: "search", status: { status: "pending" } }, ], } }, } as unknown as McpApi), ) expect(calls).toEqual([{ location: { directory: "/project" } }]) expect(result).toEqual({ docs: { status: "connected" }, search: { status: "pending" } }) }) test("loads and keys the current resource catalog", async () => { const calls: unknown[] = [] const queryClient = new QueryClient() const result = await queryClient.fetchQuery( loadMcpResourcesQuery(ServerScope.local, "/project", { resource: { catalog: async (input: McpResourceCatalogInput = {}) => { calls.push(input) return { location: { directory: "/project", project: { id: "project", directory: "/project" } }, data: { resources: [{ server: "docs", name: "Guide", uri: "docs://guide" }], templates: [], }, } }, }, } as unknown as McpApi), ) expect(calls).toEqual([{ location: { directory: "/project" } }]) expect(result).toEqual({ "docs:docs://guide": { server: "docs", name: "Guide", uri: "docs://guide" } }) }) }) describe("active session query", () => { test("loads active sessions immediately and once per server cache", async () => { let calls = 0 const queryClient = new QueryClient() const options = loadActiveSessionsQuery(ServerScope.local, { active: async () => { calls++ return { ses_running: { type: "running" } } }, }) expect(await queryClient.fetchQuery(options)).toEqual({ ses_running: { type: "running" } }) expect(await queryClient.fetchQuery(options)).toEqual({ ses_running: { type: "running" } }) expect(calls).toBe(1) expect(options.enabled).toBe(true) expect([...options.queryKey]).toEqual([ServerScope.local, "activeSessions"]) }) test("does not overwrite statuses already written by events", () => { const session = createServerSession({} as OpencodeClient) session.set("session_status", "ses_retry", { type: "retry", attempt: 2, message: "retrying", next: 10 }) seedActiveSessionStatuses(session, { ses_running: { type: "running" }, ses_retry: { type: "running" }, }) expect(session.data.session_status.ses_running).toEqual({ type: "busy" }) expect(session.data.session_status.ses_retry).toEqual({ type: "retry", attempt: 2, message: "retrying", next: 10, }) }) }) describe("pickDirectoriesToEvict", () => { test("keeps pinned stores and evicts idle stores", () => { const now = 5_000 const picks = pickDirectoriesToEvict({ stores: ["a", "b", "c", "d"], state: new Map([ ["a", { lastAccessAt: 1_000 }], ["b", { lastAccessAt: 4_900 }], ["c", { lastAccessAt: 4_800 }], ["d", { lastAccessAt: 3_000 }], ]), pins: new Set(["a"]), max: 2, ttl: 1_500, now, }) expect(picks).toEqual(["d", "c"]) }) }) describe("loadRootSessions", () => { test("loads and normalizes a limited page of root sessions", async () => { const calls: SessionListInput[] = [] const result = await loadRootSessions({ api: { list: async (query = {}) => { calls.push(query) return { data: [sessionInfo("session-1")], cursor: {} } }, } satisfies Pick, directory: "dir", limit: 10, }) expect(result.data).toEqual([ expect.objectContaining({ id: "session-1", directory: "dir", slug: "session-1", version: "" }), ]) expect(result.limited).toBe(true) expect(calls).toEqual([{ directory: "dir", parentID: null, limit: 10, order: "desc" }]) }) test("propagates list failures", () => { expect( loadRootSessions({ api: { list: async () => { throw new Error("failed") }, } satisfies Pick, directory: "dir", limit: 25, }), ).rejects.toThrow("failed") }) }) function sessionInfo(id: string) { return { id, projectID: "project-1", agent: "build", model: { id: "model-1", providerID: "provider-1" }, cost: 0, tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } }, time: { created: 1, updated: 1 }, title: id, location: { directory: "dir" }, } as SessionInfo } describe("estimateRootSessionTotal", () => { test("keeps exact total for full fetches", () => { expect(estimateRootSessionTotal({ count: 42, limit: 10, limited: false })).toBe(42) }) test("marks has-more for full-limit limited fetches", () => { expect(estimateRootSessionTotal({ count: 10, limit: 10, limited: true })).toBe(11) }) test("keeps exact total when limited fetch is under limit", () => { expect(estimateRootSessionTotal({ count: 9, limit: 10, limited: true })).toBe(9) }) }) describe("canDisposeDirectory", () => { test("rejects pinned or inflight directories", () => { expect( canDisposeDirectory({ directory: "dir", hasStore: true, pinned: true, booting: false, loadingSessions: false, }), ).toBe(false) expect( canDisposeDirectory({ directory: "dir", hasStore: true, pinned: false, booting: true, loadingSessions: false, }), ).toBe(false) expect( canDisposeDirectory({ directory: "dir", hasStore: true, pinned: false, booting: false, loadingSessions: true, }), ).toBe(false) }) test("accepts idle unpinned directory store", () => { expect( canDisposeDirectory({ directory: "dir", hasStore: true, pinned: false, booting: false, loadingSessions: false, }), ).toBe(true) }) })