mirror of
https://github.com/anomalyco/opencode.git
synced 2026-04-23 22:34:53 +00:00
127 lines
4.5 KiB
TypeScript
127 lines
4.5 KiB
TypeScript
import { describe, expect } from "bun:test"
|
|
import { Effect, Fiber, Layer } from "effect"
|
|
import { Tool } from "../../src/tool/tool"
|
|
import { QuestionTool } from "../../src/tool/question"
|
|
import { Question } from "../../src/question"
|
|
import { SessionID, MessageID } from "../../src/session/schema"
|
|
import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner"
|
|
import { provideTmpdirInstance } from "../fixture/fixture"
|
|
import { testEffect } from "../lib/effect"
|
|
|
|
const ctx = {
|
|
sessionID: SessionID.make("ses_test-session"),
|
|
messageID: MessageID.make("test-message"),
|
|
callID: "test-call",
|
|
agent: "test-agent",
|
|
abort: AbortSignal.any([]),
|
|
messages: [],
|
|
metadata: () => {},
|
|
ask: async () => {},
|
|
}
|
|
|
|
const it = testEffect(Layer.mergeAll(Question.defaultLayer, CrossSpawnSpawner.defaultLayer))
|
|
|
|
const pending = Effect.fn("QuestionToolTest.pending")(function* (question: Question.Interface) {
|
|
for (;;) {
|
|
const items = yield* question.list()
|
|
const item = items[0]
|
|
if (item) return item
|
|
yield* Effect.sleep("10 millis")
|
|
}
|
|
})
|
|
|
|
describe("tool.question", () => {
|
|
it.live("should successfully execute with valid question parameters", () =>
|
|
provideTmpdirInstance(() =>
|
|
Effect.gen(function* () {
|
|
const question = yield* Question.Service
|
|
const toolInfo = yield* QuestionTool
|
|
const tool = yield* Effect.promise(() => toolInfo.init())
|
|
const questions = [
|
|
{
|
|
question: "What is your favorite color?",
|
|
header: "Color",
|
|
options: [
|
|
{ label: "Red", description: "The color of passion" },
|
|
{ label: "Blue", description: "The color of sky" },
|
|
],
|
|
multiple: false,
|
|
},
|
|
]
|
|
|
|
const fiber = yield* Effect.promise(() => tool.execute({ questions }, ctx)).pipe(Effect.forkScoped)
|
|
const item = yield* pending(question)
|
|
yield* question.reply({ requestID: item.id, answers: [["Red"]] })
|
|
|
|
const result = yield* Fiber.join(fiber)
|
|
expect(result.title).toBe("Asked 1 question")
|
|
}),
|
|
),
|
|
)
|
|
|
|
it.live("should now pass with a header longer than 12 but less than 30 chars", () =>
|
|
provideTmpdirInstance(() =>
|
|
Effect.gen(function* () {
|
|
const question = yield* Question.Service
|
|
const toolInfo = yield* QuestionTool
|
|
const tool = yield* Effect.promise(() => toolInfo.init())
|
|
const questions = [
|
|
{
|
|
question: "What is your favorite animal?",
|
|
header: "This Header is Over 12",
|
|
options: [{ label: "Dog", description: "Man's best friend" }],
|
|
},
|
|
]
|
|
|
|
const fiber = yield* Effect.promise(() => tool.execute({ questions }, ctx)).pipe(Effect.forkScoped)
|
|
const item = yield* pending(question)
|
|
yield* question.reply({ requestID: item.id, answers: [["Dog"]] })
|
|
|
|
const result = yield* Fiber.join(fiber)
|
|
expect(result.output).toContain(`"What is your favorite animal?"="Dog"`)
|
|
}),
|
|
),
|
|
)
|
|
|
|
// intentionally removed the zod validation due to tool call errors, hoping prompting is gonna be good enough
|
|
// test("should throw an Error for header exceeding 30 characters", async () => {
|
|
// const tool = await QuestionTool.init()
|
|
// const questions = [
|
|
// {
|
|
// question: "What is your favorite animal?",
|
|
// header: "This Header is Definitely More Than Thirty Characters Long",
|
|
// options: [{ label: "Dog", description: "Man's best friend" }],
|
|
// },
|
|
// ]
|
|
// try {
|
|
// await tool.execute({ questions }, ctx)
|
|
// // If it reaches here, the test should fail
|
|
// expect(true).toBe(false)
|
|
// } catch (e: any) {
|
|
// expect(e).toBeInstanceOf(Error)
|
|
// expect(e.cause).toBeInstanceOf(z.ZodError)
|
|
// }
|
|
// })
|
|
|
|
// test("should throw an Error for label exceeding 30 characters", async () => {
|
|
// const tool = await QuestionTool.init()
|
|
// const questions = [
|
|
// {
|
|
// question: "A question with a very long label",
|
|
// header: "Long Label",
|
|
// options: [
|
|
// { label: "This is a very, very, very long label that will exceed the limit", description: "A description" },
|
|
// ],
|
|
// },
|
|
// ]
|
|
// try {
|
|
// await tool.execute({ questions }, ctx)
|
|
// // If it reaches here, the test should fail
|
|
// expect(true).toBe(false)
|
|
// } catch (e: any) {
|
|
// expect(e).toBeInstanceOf(Error)
|
|
// expect(e.cause).toBeInstanceOf(z.ZodError)
|
|
// }
|
|
// })
|
|
})
|