2026-02-14 14:01:20 +09:00
|
|
|
/// <reference types="bun-types" />
|
|
|
|
|
|
|
|
|
|
import { describe, it, expect, spyOn, afterEach } from "bun:test"
|
2026-02-02 10:49:33 +09:00
|
|
|
import type { OhMyOpenCodeConfig } from "../../config"
|
2026-02-14 14:01:20 +09:00
|
|
|
import { resolveRunAgent, waitForEventProcessorShutdown } from "./runner"
|
2026-02-02 10:49:33 +09:00
|
|
|
|
|
|
|
|
const createConfig = (overrides: Partial<OhMyOpenCodeConfig> = {}): OhMyOpenCodeConfig => ({
|
|
|
|
|
...overrides,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("resolveRunAgent", () => {
|
|
|
|
|
it("uses CLI agent over env and config", () => {
|
|
|
|
|
// given
|
|
|
|
|
const config = createConfig({ default_run_agent: "prometheus" })
|
|
|
|
|
const env = { OPENCODE_DEFAULT_AGENT: "Atlas" }
|
|
|
|
|
|
|
|
|
|
// when
|
|
|
|
|
const agent = resolveRunAgent(
|
|
|
|
|
{ message: "test", agent: "Hephaestus" },
|
|
|
|
|
config,
|
|
|
|
|
env
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// then
|
|
|
|
|
expect(agent).toBe("hephaestus")
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it("uses env agent over config", () => {
|
|
|
|
|
// given
|
|
|
|
|
const config = createConfig({ default_run_agent: "prometheus" })
|
|
|
|
|
const env = { OPENCODE_DEFAULT_AGENT: "Atlas" }
|
|
|
|
|
|
|
|
|
|
// when
|
|
|
|
|
const agent = resolveRunAgent({ message: "test" }, config, env)
|
|
|
|
|
|
|
|
|
|
// then
|
|
|
|
|
expect(agent).toBe("atlas")
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it("uses config agent over default", () => {
|
|
|
|
|
// given
|
|
|
|
|
const config = createConfig({ default_run_agent: "Prometheus" })
|
|
|
|
|
|
|
|
|
|
// when
|
|
|
|
|
const agent = resolveRunAgent({ message: "test" }, config, {})
|
|
|
|
|
|
|
|
|
|
// then
|
|
|
|
|
expect(agent).toBe("prometheus")
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it("falls back to sisyphus when none set", () => {
|
|
|
|
|
// given
|
|
|
|
|
const config = createConfig()
|
|
|
|
|
|
|
|
|
|
// when
|
|
|
|
|
const agent = resolveRunAgent({ message: "test" }, config, {})
|
|
|
|
|
|
|
|
|
|
// then
|
|
|
|
|
expect(agent).toBe("sisyphus")
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it("skips disabled sisyphus for next available core agent", () => {
|
|
|
|
|
// given
|
|
|
|
|
const config = createConfig({ disabled_agents: ["sisyphus"] })
|
|
|
|
|
|
|
|
|
|
// when
|
|
|
|
|
const agent = resolveRunAgent({ message: "test" }, config, {})
|
|
|
|
|
|
|
|
|
|
// then
|
|
|
|
|
expect(agent).toBe("hephaestus")
|
|
|
|
|
})
|
|
|
|
|
})
|
2026-02-14 14:01:20 +09:00
|
|
|
|
|
|
|
|
describe("waitForEventProcessorShutdown", () => {
|
|
|
|
|
let consoleLogSpy: ReturnType<typeof spyOn<typeof console, "log">> | null = null
|
|
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
|
if (consoleLogSpy) {
|
|
|
|
|
consoleLogSpy.mockRestore()
|
|
|
|
|
consoleLogSpy = null
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it("returns quickly when event processor completes", async () => {
|
|
|
|
|
//#given
|
|
|
|
|
const eventProcessor = new Promise<void>((resolve) => {
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
resolve()
|
|
|
|
|
}, 25)
|
|
|
|
|
})
|
|
|
|
|
consoleLogSpy = spyOn(console, "log").mockImplementation(() => {})
|
|
|
|
|
const start = performance.now()
|
|
|
|
|
|
|
|
|
|
//#when
|
|
|
|
|
await waitForEventProcessorShutdown(eventProcessor, 200)
|
|
|
|
|
|
|
|
|
|
//#then
|
|
|
|
|
const elapsed = performance.now() - start
|
|
|
|
|
expect(elapsed).toBeLessThan(200)
|
|
|
|
|
expect(console.log).not.toHaveBeenCalledWith(
|
|
|
|
|
"[run] Event stream did not close within 200ms after abort; continuing shutdown.",
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it("times out and continues when event processor does not complete", async () => {
|
|
|
|
|
//#given
|
|
|
|
|
const eventProcessor = new Promise<void>(() => {})
|
|
|
|
|
const spy = spyOn(console, "log").mockImplementation(() => {})
|
|
|
|
|
consoleLogSpy = spy
|
2026-02-16 00:18:53 +09:00
|
|
|
const timeoutMs = 200
|
2026-02-14 14:01:20 +09:00
|
|
|
const start = performance.now()
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
//#when
|
|
|
|
|
await waitForEventProcessorShutdown(eventProcessor, timeoutMs)
|
|
|
|
|
|
|
|
|
|
//#then
|
|
|
|
|
const elapsed = performance.now() - start
|
2026-02-16 00:18:53 +09:00
|
|
|
expect(elapsed).toBeGreaterThanOrEqual(timeoutMs - 10)
|
|
|
|
|
expect(spy.mock.calls.length).toBeGreaterThanOrEqual(1)
|
2026-02-14 14:01:20 +09:00
|
|
|
} finally {
|
|
|
|
|
spy.mockRestore()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
})
|