Something went wrong. Try again.
opencode v2 mirror
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126import { describe, expect } from "bun:test"import { Deferred, Effect, Fiber, Stream } from "effect"import { Agent } from "@opencode/core/agent"import { AppNodeBuilder } from "@opencode/core/effect/app-node-builder"import { LayerNode } from "@opencode/util/effect/layer-node"import { Bus } from "@opencode/core/bus"import { AbsolutePath } from "@opencode/core/schema"import { Skill } from "@opencode/core/skill"import { testEffect } from "./lib/effect"
const it = testEffect(AppNodeBuilder.build(LayerNode.group([Skill.node, Agent.node, Bus.node])))
const info = (id: string, description: string) => Skill.Info.make({ id: Skill.ID.make(id), name: Skill.Name.make(id), description, path: AbsolutePath.make(`/skills/${id}/SKILL.md`), content: `# ${id}`, })
describe("Skill", () => { it.effect("reads the current editor entry by ID", () => Effect.gen(function* () { const skill = yield* Skill.Service yield* skill.transform((editor) => editor.add(info("review", "Initial"))) yield* skill.transform((editor) => { expect(editor.get("review")).toBe(editor.list()[0]) expect(editor.get("missing")).toBeUndefined() editor.update("review", (value) => { value.description = "Updated" }) expect(editor.get("review")?.description).toBe("Updated") editor.remove("review") expect(editor.get("review")).toBeUndefined() })
expect(yield* skill.list()).toEqual([]) }), )
it.effect("registers values with last-write-wins precedence", () => Effect.gen(function* () { const skill = yield* Skill.Service yield* skill.transform((editor) => { editor.add(info("review", "First")) editor.add(info("deploy", "Deploy")) editor.add(info("review", "Second")) expect(editor.list().map((item) => item.id)).toEqual([Skill.ID.make("review"), Skill.ID.make("deploy")]) })
expect(yield* skill.list()).toEqual([info("review", "Second"), info("deploy", "Deploy")]) expect(yield* skill.get(Skill.ID.make("review"))).toEqual(info("review", "Second")) expect(yield* skill.get(Skill.ID.make("missing"))).toBeUndefined() }), )
it.effect("updates and removes registered values", () => Effect.gen(function* () { const skill = yield* Skill.Service yield* skill.transform((editor) => { editor.add(info("review", "Initial")) editor.update("review", (value) => { value.description = "Updated" value.id = Skill.ID.make("ignored") }) editor.update("missing", () => { throw new Error("unreachable") }) editor.add(info("deploy", "Deploy")) editor.remove("deploy") })
expect(yield* skill.list()).toEqual([info("review", "Updated")]) }), )
it.effect("restores earlier values when an updating transform is disposed", () => Effect.gen(function* () { const skill = yield* Skill.Service const original = info("review", "Initial") yield* skill.transform((editor) => editor.add(original)) const updated = yield* skill.transform((editor) => editor.update("review", (value) => { value.description = "Updated" }), )
expect((yield* skill.list())[0]?.description).toBe("Updated") yield* updated.dispose expect((yield* skill.list())[0]?.description).toBe("Initial") expect(original.description).toBe("Initial") }), )
it.live("publishes updates after committed values are visible", () => Effect.gen(function* () { const skill = yield* Skill.Service const bus = yield* Bus.Service const updated = yield* Deferred.make<Skill.Info[]>() const fiber = yield* bus.subscribe(Skill.Event.Updated).pipe( Stream.runForEach(() => skill.list().pipe(Effect.flatMap((values) => Deferred.succeed(updated, values)))), Effect.forkScoped, ) yield* Effect.yieldNow
yield* skill.transform((editor) => editor.add(info("review", "Visible"))) expect(yield* Deferred.await(updated).pipe(Effect.timeout("1 second"))).toEqual([info("review", "Visible")]) yield* Fiber.interrupt(fiber) }), )
it.effect("filters values by agent permissions", () => Effect.gen(function* () { const agents = yield* Agent.Service yield* agents.transform((editor) => editor.update(Agent.ID.make("reviewer"), (agent) => { agent.permissions.push({ action: "skill", resource: "deploy", effect: "deny" }) }), ) const agent = yield* agents.get(Agent.ID.make("reviewer")) expect(Skill.available([info("deploy", "Deploy")], agent!.permissions)).toEqual([]) }), )})