feat(tool): increase question header and label limits (#9201)
This commit is contained in:
@@ -10,7 +10,7 @@ export namespace Question {
|
|||||||
|
|
||||||
export const Option = z
|
export const Option = z
|
||||||
.object({
|
.object({
|
||||||
label: z.string().describe("Display text (1-5 words, concise)"),
|
label: z.string().max(30).describe("Display text (1-5 words, concise)"),
|
||||||
description: z.string().describe("Explanation of choice"),
|
description: z.string().describe("Explanation of choice"),
|
||||||
})
|
})
|
||||||
.meta({
|
.meta({
|
||||||
@@ -21,7 +21,7 @@ export namespace Question {
|
|||||||
export const Info = z
|
export const Info = z
|
||||||
.object({
|
.object({
|
||||||
question: z.string().describe("Complete question"),
|
question: z.string().describe("Complete question"),
|
||||||
header: z.string().max(12).describe("Very short label (max 12 chars)"),
|
header: z.string().max(30).describe("Very short label (max 30 chars)"),
|
||||||
options: z.array(Option).describe("Available choices"),
|
options: z.array(Option).describe("Available choices"),
|
||||||
multiple: z.boolean().optional().describe("Allow selecting multiple choices"),
|
multiple: z.boolean().optional().describe("Allow selecting multiple choices"),
|
||||||
custom: z.boolean().optional().describe("Allow typing a custom answer (default: true)"),
|
custom: z.boolean().optional().describe("Allow typing a custom answer (default: true)"),
|
||||||
|
|||||||
107
packages/opencode/test/tool/question.test.ts
Normal file
107
packages/opencode/test/tool/question.test.ts
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import { describe, expect, test, spyOn, beforeEach, afterEach } from "bun:test"
|
||||||
|
import { z } from "zod"
|
||||||
|
import { QuestionTool } from "../../src/tool/question"
|
||||||
|
import * as QuestionModule from "../../src/question"
|
||||||
|
|
||||||
|
const ctx = {
|
||||||
|
sessionID: "test-session",
|
||||||
|
messageID: "test-message",
|
||||||
|
callID: "test-call",
|
||||||
|
agent: "test-agent",
|
||||||
|
abort: AbortSignal.any([]),
|
||||||
|
metadata: () => {},
|
||||||
|
ask: async () => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("tool.question", () => {
|
||||||
|
let askSpy: any;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
askSpy = spyOn(QuestionModule.Question, "ask").mockImplementation(async () => {
|
||||||
|
return []
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
askSpy.mockRestore()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should successfully execute with valid question parameters", async () => {
|
||||||
|
const tool = await QuestionTool.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,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
askSpy.mockResolvedValueOnce([["Red"]])
|
||||||
|
|
||||||
|
const result = await tool.execute(
|
||||||
|
{ questions },
|
||||||
|
ctx,
|
||||||
|
)
|
||||||
|
expect(askSpy).toHaveBeenCalledTimes(1)
|
||||||
|
expect(result.title).toBe("Asked 1 question")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should now pass with a header longer than 12 but less than 30 chars", async () => {
|
||||||
|
const tool = await QuestionTool.init()
|
||||||
|
const questions = [
|
||||||
|
{
|
||||||
|
question: "What is your favorite animal?",
|
||||||
|
header: "This Header is Over 12",
|
||||||
|
options: [{ label: "Dog", description: "Man's best friend" }],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
askSpy.mockResolvedValueOnce([["Dog"]])
|
||||||
|
|
||||||
|
const result = await tool.execute({ questions }, ctx)
|
||||||
|
expect(result.output).toContain(`"What is your favorite animal?"="Dog"`)
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
Reference in New Issue
Block a user