| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- import { describe, expect, test } from "bun:test"
- import { LayerNode } from "@kirincode-ai/core/effect/layer-node"
- import { Effect, Layer } from "effect"
- import type { Agent } from "../../src/agent/agent"
- import { NamedError } from "@kirincode-ai/core/util/error"
- import { Skill } from "../../src/skill"
- import { Permission } from "../../src/permission"
- import type { Provider } from "../../src/provider/provider"
- import { SystemPrompt } from "../../src/session/system"
- import { MCP } from "../../src/mcp"
- import { testEffect } from "../lib/effect"
- 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: "manual-skill",
- location: "/tmp/manual-skill/SKILL.md",
- content: "# manual-skill",
- },
- ]
- const build: Agent.Info = {
- name: "build",
- mode: "primary",
- permission: Permission.fromConfig({ "*": "allow" }),
- options: {},
- }
- const it = testEffect(
- LayerNode.compile(SystemPrompt.node, [
- [
- MCP.node,
- Layer.mock(MCP.Service, {
- instructions: () =>
- Effect.succeed([
- {
- name: "guide-server",
- instructions: "Use lookup before mutate.",
- tools: [],
- },
- {
- name: "tool-server",
- instructions: "Prefer search before update.",
- tools: ["tool-server_search", "tool-server_update"],
- },
- ]),
- }),
- ],
- [
- Skill.node,
- Layer.succeed(
- Skill.Service,
- Skill.Service.of({
- get: (name) => Effect.succeed(skills.find((skill) => skill.name === name)),
- require: (name) => {
- const info = skills.find((skill) => skill.name === name)
- if (info) return Effect.succeed(info)
- return Effect.fail(new Skill.NotFoundError({ name, available: skills.map((skill) => skill.name) }))
- },
- all: () => Effect.succeed(skills),
- dirs: () => Effect.succeed([]),
- available: () => Effect.succeed(skills),
- }),
- ),
- ],
- ]),
- )
- describe("session.system", () => {
- test("selects the Meta prompt for Muse Spark model IDs", () => {
- expect(SystemPrompt.provider({ api: { id: "meta/muse-spark-preview" } } as Provider.Model)[0]).toContain(
- "Meta Muse Spark",
- )
- })
- 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)
- 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)
- expect(output).not.toContain("manual-skill")
- }),
- )
- it.effect("MCP output includes connected server instructions", () =>
- Effect.gen(function* () {
- const prompt = yield* SystemPrompt.Service
- const output = yield* prompt.mcp(build)
- expect(output).toBe(
- [
- "<mcp_instructions>",
- ' <server name="guide-server">',
- " Use lookup before mutate.",
- " </server>",
- ' <server name="tool-server">',
- " Prefer search before update.",
- " </server>",
- "</mcp_instructions>",
- ].join("\n"),
- )
- }),
- )
- it.effect("MCP output omits servers when all advertised tools are denied", () =>
- Effect.gen(function* () {
- const prompt = yield* SystemPrompt.Service
- const output = yield* prompt.mcp(build, Permission.fromConfig({ "tool-server_*": "deny" }))
- expect(output).toBe(
- [
- "<mcp_instructions>",
- ' <server name="guide-server">',
- " Use lookup before mutate.",
- " </server>",
- "</mcp_instructions>",
- ].join("\n"),
- )
- }),
- )
- })
|