Просмотр исходного кода

feat(tool): increase question header and label limits (#9201)

Bowen Dwelle 1 месяц назад
Родитель
Сommit
3591372c45
2 измененных файлов с 109 добавлено и 2 удалено
  1. 2 2
      packages/opencode/src/question/index.ts
  2. 107 0
      packages/opencode/test/tool/question.test.ts

+ 2 - 2
packages/opencode/src/question/index.ts

@@ -10,7 +10,7 @@ export namespace Question {
 
   export const Option = z
     .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"),
     })
     .meta({
@@ -21,7 +21,7 @@ export namespace Question {
   export const Info = z
     .object({
       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"),
       multiple: z.boolean().optional().describe("Allow selecting multiple choices"),
       custom: z.boolean().optional().describe("Allow typing a custom answer (default: true)"),

+ 107 - 0
packages/opencode/test/tool/question.test.ts

@@ -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)
+    }
+  })
+})
+