import { describe, expect } from "bun:test" import { Effect, Exit, Scope } from "effect" import { AgentV2 } from "@opencode-ai/core/agent" import { testEffect } from "./lib/effect" const it = testEffect(AgentV2.locationLayer) describe("AgentV2", () => { it.effect("starts without agents", () => Effect.gen(function* () { const agent = yield* AgentV2.Service expect(yield* agent.all()).toEqual([]) expect(yield* agent.get(AgentV2.ID.make("build"))).toBeUndefined() }), ) it.effect("materializes replayable agent transforms", () => Effect.gen(function* () { const agent = yield* AgentV2.Service const id = AgentV2.ID.make("reviewer") const transform = yield* agent.transform() yield* transform((editor) => editor.update(id, (info) => { info.description = "Reviews code" info.mode = "subagent" }), ) expect(yield* agent.get(id)).toMatchObject({ id, description: "Reviews code", mode: "subagent" }) expect((yield* agent.all()).map((info) => info.id)).toEqual([id]) }), ) it.effect("rebuilds state when a transform is replaced", () => Effect.gen(function* () { const agent = yield* AgentV2.Service const id = AgentV2.ID.make("reviewer") const transform = yield* agent.transform() yield* transform((editor) => editor.update(id, (info) => { info.description = "Old description" info.hidden = true }), ) yield* transform((editor) => editor.update(id, (info) => { info.description = "New description" }), ) expect(yield* agent.get(id)).toMatchObject({ description: "New description", hidden: false }) }), ) it.effect("removes a transform contribution when its scope closes", () => Effect.gen(function* () { const agent = yield* AgentV2.Service const id = AgentV2.ID.make("scoped") const scope = yield* Scope.make() const transform = yield* agent.transform().pipe(Scope.provide(scope)) yield* transform((editor) => editor.update(id, () => {})) expect(yield* agent.get(id)).toBeDefined() yield* Scope.close(scope, Exit.void) expect(yield* agent.get(id)).toBeUndefined() }), ) it.effect("applies direct agent updates", () => Effect.gen(function* () { const agent = yield* AgentV2.Service const id = AgentV2.ID.make("build") yield* agent.update((editor) => editor.update(id, (info) => { info.mode = "primary" info.hidden = true }), ) expect(yield* agent.get(id)).toMatchObject({ id, mode: "primary", hidden: true }) }), ) it.effect("creates agents with runtime defaults and supports direct removal", () => Effect.gen(function* () { const agent = yield* AgentV2.Service const id = AgentV2.ID.make("custom") yield* agent.update((editor) => editor.update(id, () => {})) expect(yield* agent.get(id)).toEqual(AgentV2.Info.empty(id)) yield* agent.update((editor) => editor.remove(id)) expect(yield* agent.get(id)).toBeUndefined() }), ) })