|
|
@@ -1,69 +1,73 @@
|
|
|
-import { describe, expect, test } from "bun:test"
|
|
|
-import path from "path"
|
|
|
-import { Effect } from "effect"
|
|
|
-import { Agent } from "../../src/agent/agent"
|
|
|
-import { Instance } from "../../src/project/instance"
|
|
|
+import { describe, expect } from "bun:test"
|
|
|
+import { Effect, Layer } from "effect"
|
|
|
+import type { Agent } from "../../src/agent/agent"
|
|
|
+import { NamedError } from "@opencode-ai/core/util/error"
|
|
|
+import { Skill } from "../../src/skill"
|
|
|
+import { Permission } from "../../src/permission"
|
|
|
import { SystemPrompt } from "../../src/session/system"
|
|
|
-import { provideInstance, tmpdir } from "../fixture/fixture"
|
|
|
+import { testEffect } from "../lib/effect"
|
|
|
|
|
|
-function load<A>(dir: string, fn: (svc: Agent.Interface) => Effect.Effect<A>) {
|
|
|
- return Effect.runPromise(provideInstance(dir)(Agent.Service.use(fn)).pipe(Effect.provide(Agent.defaultLayer)))
|
|
|
-}
|
|
|
-
|
|
|
-describe("session.system", () => {
|
|
|
- test("skills output is sorted by name and stable across calls", async () => {
|
|
|
- await using tmp = await tmpdir({
|
|
|
- git: true,
|
|
|
- init: async (dir) => {
|
|
|
- for (const [name, description] of [
|
|
|
- ["zeta-skill", "Zeta skill."],
|
|
|
- ["alpha-skill", "Alpha skill."],
|
|
|
- ["middle-skill", "Middle skill."],
|
|
|
- ]) {
|
|
|
- const skillDir = path.join(dir, ".opencode", "skill", name)
|
|
|
- await Bun.write(
|
|
|
- path.join(skillDir, "SKILL.md"),
|
|
|
- `---
|
|
|
-name: ${name}
|
|
|
-description: ${description}
|
|
|
----
|
|
|
+const skills: Skill.Info[] = [
|
|
|
+ {
|
|
|
+ name: "zeta-skill",
|
|
|
+ description: "Zeta skill.",
|
|
|
+ location: "/tmp/zeta-skill/SKILL.md",
|
|
|
+ content: "# zeta-skill",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "alpha-skill",
|
|
|
+ description: "Alpha skill.",
|
|
|
+ location: "/tmp/alpha-skill/SKILL.md",
|
|
|
+ content: "# alpha-skill",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "middle-skill",
|
|
|
+ description: "Middle skill.",
|
|
|
+ location: "/tmp/middle-skill/SKILL.md",
|
|
|
+ content: "# middle-skill",
|
|
|
+ },
|
|
|
+]
|
|
|
|
|
|
-# ${name}
|
|
|
-`,
|
|
|
- )
|
|
|
- }
|
|
|
- },
|
|
|
- })
|
|
|
-
|
|
|
- const home = process.env.OPENCODE_TEST_HOME
|
|
|
- process.env.OPENCODE_TEST_HOME = tmp.path
|
|
|
+const build: Agent.Info = {
|
|
|
+ name: "build",
|
|
|
+ mode: "primary",
|
|
|
+ permission: Permission.fromConfig({ "*": "allow" }),
|
|
|
+ options: {},
|
|
|
+}
|
|
|
|
|
|
- try {
|
|
|
- await Instance.provide({
|
|
|
- directory: tmp.path,
|
|
|
- fn: async () => {
|
|
|
- const build = await load(tmp.path, (svc) => svc.get("build"))
|
|
|
- const runSkills = Effect.gen(function* () {
|
|
|
- const svc = yield* SystemPrompt.Service
|
|
|
- return yield* svc.skills(build!)
|
|
|
- }).pipe(Effect.provide(SystemPrompt.defaultLayer))
|
|
|
+const it = testEffect(
|
|
|
+ SystemPrompt.layer.pipe(
|
|
|
+ Layer.provide(
|
|
|
+ Layer.succeed(
|
|
|
+ Skill.Service,
|
|
|
+ Skill.Service.of({
|
|
|
+ get: (name) => Effect.succeed(skills.find((skill) => skill.name === name)),
|
|
|
+ all: () => Effect.succeed(skills),
|
|
|
+ dirs: () => Effect.succeed([]),
|
|
|
+ available: () => Effect.succeed(skills),
|
|
|
+ }),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+)
|
|
|
|
|
|
- const first = await Effect.runPromise(runSkills)
|
|
|
- const second = await Effect.runPromise(runSkills)
|
|
|
+describe("session.system", () => {
|
|
|
+ it.effect("skills output is sorted by name and stable across calls", () =>
|
|
|
+ Effect.gen(function* () {
|
|
|
+ const prompt = yield* SystemPrompt.Service
|
|
|
+ const first = yield* prompt.skills(build)
|
|
|
+ const second = yield* prompt.skills(build)
|
|
|
+ const output = first ?? (yield* Effect.fail(new NamedError.Unknown({ message: "missing skills output" })))
|
|
|
|
|
|
- expect(first).toBe(second)
|
|
|
+ expect(first).toBe(second)
|
|
|
|
|
|
- const alpha = first!.indexOf("<name>alpha-skill</name>")
|
|
|
- const middle = first!.indexOf("<name>middle-skill</name>")
|
|
|
- const zeta = first!.indexOf("<name>zeta-skill</name>")
|
|
|
+ const alpha = output.indexOf("<name>alpha-skill</name>")
|
|
|
+ const middle = output.indexOf("<name>middle-skill</name>")
|
|
|
+ const zeta = output.indexOf("<name>zeta-skill</name>")
|
|
|
|
|
|
- expect(alpha).toBeGreaterThan(-1)
|
|
|
- expect(middle).toBeGreaterThan(alpha)
|
|
|
- expect(zeta).toBeGreaterThan(middle)
|
|
|
- },
|
|
|
- })
|
|
|
- } finally {
|
|
|
- process.env.OPENCODE_TEST_HOME = home
|
|
|
- }
|
|
|
- })
|
|
|
+ expect(alpha).toBeGreaterThan(-1)
|
|
|
+ expect(middle).toBeGreaterThan(alpha)
|
|
|
+ expect(zeta).toBeGreaterThan(middle)
|
|
|
+ }),
|
|
|
+ )
|
|
|
})
|