- Add directory parameter to session API calls (session.get, session.todo,
session.status, session.children)
- Improve agent resolver with display name support via agent-display-names
- Add tool execution visibility in event handlers with running/completed
status output
- Enhance poll-for-completion with main session status checking and
stabilization period handling
- Add normalizeSDKResponse import for consistent response handling
- Update types with Todo, ChildSession, and toast-related interfaces
🤖 Generated with OhMyOpenCode assistance
165 lines
4.6 KiB
TypeScript
165 lines
4.6 KiB
TypeScript
/// <reference types="bun-types" />
|
|
|
|
import { beforeEach, describe, expect, it, mock, spyOn } from "bun:test";
|
|
import { resolveSession } from "./session-resolver";
|
|
import type { OpencodeClient } from "./types";
|
|
|
|
const createMockClient = (overrides: {
|
|
getResult?: { error?: unknown; data?: { id: string } }
|
|
createResults?: Array<{ error?: unknown; data?: { id: string } }>
|
|
} = {}): OpencodeClient => {
|
|
const { getResult, createResults = [] } = overrides
|
|
let createCallIndex = 0
|
|
return {
|
|
session: {
|
|
get: mock((opts: { path: { id: string } }) =>
|
|
Promise.resolve(getResult ?? { data: { id: opts.path.id } })
|
|
),
|
|
create: mock(() => {
|
|
const result =
|
|
createResults[createCallIndex] ?? { data: { id: "new-session-id" } }
|
|
createCallIndex++
|
|
return Promise.resolve(result)
|
|
}),
|
|
},
|
|
} as unknown as OpencodeClient
|
|
}
|
|
|
|
describe("resolveSession", () => {
|
|
const directory = "/test-project"
|
|
|
|
beforeEach(() => {
|
|
spyOn(console, "log").mockImplementation(() => {})
|
|
spyOn(console, "error").mockImplementation(() => {})
|
|
})
|
|
|
|
it("returns provided session ID when session exists", async () => {
|
|
// given
|
|
const sessionId = "existing-session-id"
|
|
const mockClient = createMockClient({
|
|
getResult: { data: { id: sessionId } },
|
|
})
|
|
|
|
// when
|
|
const result = await resolveSession({ client: mockClient, sessionId, directory })
|
|
|
|
// then
|
|
expect(result).toBe(sessionId)
|
|
expect(mockClient.session.get).toHaveBeenCalledWith({
|
|
path: { id: sessionId },
|
|
query: { directory },
|
|
})
|
|
expect(mockClient.session.create).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it("throws error when provided session ID not found", async () => {
|
|
// given
|
|
const sessionId = "non-existent-session-id"
|
|
const mockClient = createMockClient({
|
|
getResult: { error: { message: "Session not found" } },
|
|
})
|
|
|
|
// when
|
|
const result = resolveSession({ client: mockClient, sessionId, directory })
|
|
|
|
// then
|
|
await Promise.resolve(
|
|
expect(result).rejects.toThrow(`Session not found: ${sessionId}`)
|
|
)
|
|
expect(mockClient.session.get).toHaveBeenCalledWith({
|
|
path: { id: sessionId },
|
|
query: { directory },
|
|
})
|
|
expect(mockClient.session.create).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it("creates new session when no session ID provided", async () => {
|
|
// given
|
|
const mockClient = createMockClient({
|
|
createResults: [{ data: { id: "new-session-id" } }],
|
|
})
|
|
|
|
// when
|
|
const result = await resolveSession({ client: mockClient, directory })
|
|
|
|
// then
|
|
expect(result).toBe("new-session-id")
|
|
expect(mockClient.session.create).toHaveBeenCalledWith({
|
|
body: {
|
|
title: "oh-my-opencode run",
|
|
permission: [
|
|
{ permission: "question", action: "deny", pattern: "*" },
|
|
],
|
|
},
|
|
query: { directory },
|
|
})
|
|
expect(mockClient.session.get).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it("retries session creation on failure", async () => {
|
|
// given
|
|
const mockClient = createMockClient({
|
|
createResults: [
|
|
{ error: { message: "Network error" } },
|
|
{ data: { id: "retried-session-id" } },
|
|
],
|
|
})
|
|
|
|
// when
|
|
const result = await resolveSession({ client: mockClient, directory })
|
|
|
|
// then
|
|
expect(result).toBe("retried-session-id")
|
|
expect(mockClient.session.create).toHaveBeenCalledTimes(2)
|
|
expect(mockClient.session.create).toHaveBeenCalledWith({
|
|
body: {
|
|
title: "oh-my-opencode run",
|
|
permission: [
|
|
{ permission: "question", action: "deny", pattern: "*" },
|
|
],
|
|
},
|
|
query: { directory },
|
|
})
|
|
})
|
|
|
|
it("throws after all retries exhausted", async () => {
|
|
// given
|
|
const mockClient = createMockClient({
|
|
createResults: [
|
|
{ error: { message: "Error 1" } },
|
|
{ error: { message: "Error 2" } },
|
|
{ error: { message: "Error 3" } },
|
|
],
|
|
})
|
|
|
|
// when
|
|
const result = resolveSession({ client: mockClient, directory })
|
|
|
|
// then
|
|
await Promise.resolve(
|
|
expect(result).rejects.toThrow("Failed to create session after all retries")
|
|
)
|
|
expect(mockClient.session.create).toHaveBeenCalledTimes(3)
|
|
})
|
|
|
|
it("session creation returns no ID", async () => {
|
|
// given
|
|
const mockClient = createMockClient({
|
|
createResults: [
|
|
{ data: undefined },
|
|
{ data: undefined },
|
|
{ data: undefined },
|
|
],
|
|
})
|
|
|
|
// when
|
|
const result = resolveSession({ client: mockClient, directory })
|
|
|
|
// then
|
|
await Promise.resolve(
|
|
expect(result).rejects.toThrow("Failed to create session after all retries")
|
|
)
|
|
expect(mockClient.session.create).toHaveBeenCalledTimes(3)
|
|
})
|
|
})
|