69 lines
2.4 KiB
TypeScript
69 lines
2.4 KiB
TypeScript
import { describe, expect, test } from "bun:test"
|
|
import { Effect, Layer, ManagedRuntime } from "effect"
|
|
import path from "path"
|
|
import { Agent } from "../../src/agent/agent"
|
|
import { PlanFile } from "../../src/kilocode/plan-file"
|
|
import { Instance } from "../../src/kilocode/instance"
|
|
import { provideTestInstance } from "../fixture/fixture"
|
|
import { Session } from "../../src/session/session"
|
|
import { MessageID } from "../../src/session/schema"
|
|
import { PlanExitTool } from "../../src/tool/plan"
|
|
import { Tool } from "../../src/tool/tool"
|
|
import { Truncate } from "../../src/tool/truncate"
|
|
import { tmpdir } from "../fixture/fixture"
|
|
|
|
const rt = ManagedRuntime.make(Layer.mergeAll(Agent.defaultLayer, Session.defaultLayer, Truncate.defaultLayer))
|
|
|
|
async function init() {
|
|
return rt.runPromise(
|
|
Effect.gen(function* () {
|
|
const info = yield* PlanExitTool
|
|
return yield* Tool.init(info)
|
|
}),
|
|
)
|
|
}
|
|
|
|
describe("PlanFile", () => {
|
|
test("plan_exit accepts custom paths from plan agent", async () => {
|
|
await using tmp = await tmpdir({ git: true })
|
|
await provideTestInstance({
|
|
directory: tmp.path,
|
|
fn: async () => {
|
|
const session = await rt.runPromise(Session.Service.use((svc) => svc.create({})))
|
|
const tool = await init()
|
|
const result = await rt.runPromise(
|
|
tool.execute(
|
|
{ path: ".plans/fix.md" },
|
|
{
|
|
sessionID: session.id,
|
|
messageID: MessageID.make("msg_plan_exit"),
|
|
agent: "plan",
|
|
abort: AbortSignal.any([]),
|
|
messages: [],
|
|
metadata: () => Effect.void,
|
|
ask: () => Effect.void,
|
|
},
|
|
),
|
|
)
|
|
|
|
expect(result.metadata.plan.replaceAll(path.sep, "/")).toBe(".plans/fix.md")
|
|
expect(result.output.replaceAll(path.sep, "/")).toContain(".plans/fix.md")
|
|
},
|
|
})
|
|
})
|
|
|
|
test("rejects custom plan paths outside the worktree", async () => {
|
|
await using tmp = await tmpdir({ git: true })
|
|
await provideTestInstance({
|
|
directory: tmp.path,
|
|
fn: async () => {
|
|
expect(PlanFile.resolve("../../etc/shadow", Instance.current)).toBeUndefined()
|
|
expect(PlanFile.resolve("/tmp/evil.md", Instance.current)).toBeUndefined()
|
|
expect(PlanFile.resolve(".plans/fix.md", Instance.current)).toBe(
|
|
path.join(Instance.worktree, ".plans", "fix.md"),
|
|
)
|
|
},
|
|
})
|
|
})
|
|
})
|