fix: logo 右半部分从 CODING 改为 CODE
去掉难以正确渲染的 N 和 G 字母,右半部分简化为 CODE(4 字母), 与左半部分 AIR 组合为 AIR CODE。
This commit is contained in:
154
packages/core/test/skill/guidance.test.ts
Normal file
154
packages/core/test/skill/guidance.test.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
import path from "path"
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { AgentV2 } from "@opencode-ai/core/agent"
|
||||
import { PluginBoot } from "@opencode-ai/core/plugin/boot"
|
||||
import { AbsolutePath } from "@opencode-ai/core/schema"
|
||||
import { SkillV2 } from "@opencode-ai/core/skill"
|
||||
import { SystemContext } from "@opencode-ai/core/system-context"
|
||||
import { SkillGuidance } from "@opencode-ai/core/skill/guidance"
|
||||
import { it } from "../lib/effect"
|
||||
|
||||
const build = AgentV2.ID.make("build")
|
||||
const effect = new SkillV2.Info({
|
||||
name: "effect",
|
||||
description: "Build applications with Effect",
|
||||
location: AbsolutePath.make(path.resolve("/skills/effect/SKILL.md")),
|
||||
content: "Effect guidance",
|
||||
})
|
||||
const hidden = new SkillV2.Info({
|
||||
name: "hidden",
|
||||
location: AbsolutePath.make(path.resolve("/skills/hidden/SKILL.md")),
|
||||
content: "Undescribed guidance",
|
||||
})
|
||||
const denied = new SkillV2.Info({
|
||||
name: "denied",
|
||||
description: "Must not be advertised",
|
||||
location: AbsolutePath.make(path.resolve("/skills/denied/SKILL.md")),
|
||||
content: "Denied guidance",
|
||||
})
|
||||
|
||||
const layer = (list: () => SkillV2.Info[], wait: () => void = () => {}) =>
|
||||
SkillGuidance.layer.pipe(
|
||||
Layer.provide(Layer.mock(SkillV2.Service, { list: () => Effect.succeed(list()) })),
|
||||
Layer.provide(Layer.mock(PluginBoot.Service, { wait: () => Effect.sync(wait) })),
|
||||
)
|
||||
|
||||
describe("SkillGuidance", () => {
|
||||
it.effect("renders described agent skills and reconciles the complete available list", () => {
|
||||
const agent = new AgentV2.Info({
|
||||
...AgentV2.Info.empty(build),
|
||||
permissions: [{ action: "skill", resource: "denied", effect: "deny" }],
|
||||
})
|
||||
let skills = [hidden, denied, effect]
|
||||
let waited = 0
|
||||
return Effect.gen(function* () {
|
||||
const guidance = yield* SkillGuidance.Service
|
||||
const initialized = yield* guidance
|
||||
.load({ id: agent.id, info: agent })
|
||||
.pipe(Effect.flatMap(SystemContext.initialize))
|
||||
|
||||
expect(waited).toBe(1)
|
||||
expect(initialized.baseline).toBe(
|
||||
[
|
||||
"Skills provide specialized instructions and workflows for specific tasks.",
|
||||
"Use the skill tool to load a skill when a task matches its description.",
|
||||
"<available_skills>",
|
||||
" <skill>",
|
||||
" <name>effect</name>",
|
||||
" <description>Build applications with Effect</description>",
|
||||
" </skill>",
|
||||
"</available_skills>",
|
||||
].join("\n"),
|
||||
)
|
||||
|
||||
skills = []
|
||||
expect(
|
||||
yield* guidance
|
||||
.load({ id: agent.id, info: agent })
|
||||
.pipe(Effect.flatMap((context) => SystemContext.reconcile(context, initialized.snapshot))),
|
||||
).toMatchObject({
|
||||
_tag: "Updated",
|
||||
text: expect.stringContaining("No skills are currently available."),
|
||||
})
|
||||
}).pipe(
|
||||
Effect.provide(
|
||||
layer(
|
||||
() => skills,
|
||||
() => waited++,
|
||||
),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
it.effect("omits guidance when the selected agent denies all skills", () => {
|
||||
const agent = new AgentV2.Info({
|
||||
...AgentV2.Info.empty(build),
|
||||
permissions: [{ action: "skill", resource: "*", effect: "deny" }],
|
||||
})
|
||||
return Effect.gen(function* () {
|
||||
const guidance = yield* SkillGuidance.Service
|
||||
expect(
|
||||
yield* guidance.load({ id: agent.id, info: agent }).pipe(Effect.flatMap(SystemContext.initialize)),
|
||||
).toEqual({
|
||||
baseline: "",
|
||||
snapshot: {},
|
||||
})
|
||||
}).pipe(Effect.provide(layer(() => [effect])))
|
||||
})
|
||||
|
||||
it.effect("omits guidance when a resource-specific denial follows the global denial", () => {
|
||||
const agent = new AgentV2.Info({
|
||||
...AgentV2.Info.empty(build),
|
||||
permissions: [
|
||||
{ action: "skill", resource: "*", effect: "deny" },
|
||||
{ action: "skill", resource: "hidden", effect: "deny" },
|
||||
],
|
||||
})
|
||||
return Effect.gen(function* () {
|
||||
const guidance = yield* SkillGuidance.Service
|
||||
expect(
|
||||
yield* guidance.load({ id: agent.id, info: agent }).pipe(Effect.flatMap(SystemContext.initialize)),
|
||||
).toEqual({
|
||||
baseline: "",
|
||||
snapshot: {},
|
||||
})
|
||||
}).pipe(Effect.provide(layer(() => [effect])))
|
||||
})
|
||||
|
||||
it.effect("retains specifically allowed skills after a global denial", () => {
|
||||
const agent = new AgentV2.Info({
|
||||
...AgentV2.Info.empty(build),
|
||||
permissions: [
|
||||
{ action: "skill", resource: "*", effect: "deny" },
|
||||
{ action: "skill", resource: "effect", effect: "allow" },
|
||||
],
|
||||
})
|
||||
return Effect.gen(function* () {
|
||||
const guidance = yield* SkillGuidance.Service
|
||||
expect(
|
||||
(yield* guidance.load({ id: agent.id, info: agent }).pipe(Effect.flatMap(SystemContext.initialize))).baseline,
|
||||
).toContain("<name>effect</name>")
|
||||
}).pipe(Effect.provide(layer(() => [effect])))
|
||||
})
|
||||
|
||||
it.effect("omits guidance when a specifically allowed skill is denied again", () => {
|
||||
const agent = new AgentV2.Info({
|
||||
...AgentV2.Info.empty(build),
|
||||
permissions: [
|
||||
{ action: "skill", resource: "*", effect: "deny" },
|
||||
{ action: "skill", resource: "effect", effect: "allow" },
|
||||
{ action: "skill", resource: "effect", effect: "deny" },
|
||||
],
|
||||
})
|
||||
return Effect.gen(function* () {
|
||||
const guidance = yield* SkillGuidance.Service
|
||||
expect(
|
||||
yield* guidance.load({ id: agent.id, info: agent }).pipe(Effect.flatMap(SystemContext.initialize)),
|
||||
).toEqual({
|
||||
baseline: "",
|
||||
snapshot: {},
|
||||
})
|
||||
}).pipe(Effect.provide(layer(() => [effect])))
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user