718884210b
- fix(hooks): skip todo continuation when agent has pending question (#1888) Add pending-question-detection module that walks messages backwards to detect unanswered question tool_use, preventing CONTINUATION_PROMPT injection while awaiting user response. - fix(config): allow custom agent names in disabled_agents (#1693) Change disabled_agents schema from BuiltinAgentNameSchema to z.string() and add filterDisabledAgents helper in agent-config-handler to filter user, project, and plugin agents with case-insensitive matching. - fix(agents): change primary agents mode to 'all' (#1891) Update Sisyphus, Hephaestus, and Atlas agent modes from 'primary' to 'all' so they are available for @mention routing and task() delegation in addition to direct chat.
101 lines
2.6 KiB
TypeScript
101 lines
2.6 KiB
TypeScript
/// <reference types="bun-types" />
|
|
import { describe, expect, test } from "bun:test"
|
|
|
|
import { hasUnansweredQuestion } from "./pending-question-detection"
|
|
|
|
describe("hasUnansweredQuestion", () => {
|
|
test("given empty messages, returns false", () => {
|
|
expect(hasUnansweredQuestion([])).toBe(false)
|
|
})
|
|
|
|
test("given null-ish input, returns false", () => {
|
|
expect(hasUnansweredQuestion(undefined as never)).toBe(false)
|
|
})
|
|
|
|
test("given last assistant message with question tool_use, returns true", () => {
|
|
const messages = [
|
|
{ info: { role: "user" } },
|
|
{
|
|
info: { role: "assistant" },
|
|
parts: [
|
|
{ type: "tool_use", name: "question" },
|
|
],
|
|
},
|
|
]
|
|
expect(hasUnansweredQuestion(messages)).toBe(true)
|
|
})
|
|
|
|
test("given last assistant message with question tool-invocation, returns true", () => {
|
|
const messages = [
|
|
{ info: { role: "user" } },
|
|
{
|
|
info: { role: "assistant" },
|
|
parts: [
|
|
{ type: "tool-invocation", toolName: "question" },
|
|
],
|
|
},
|
|
]
|
|
expect(hasUnansweredQuestion(messages)).toBe(true)
|
|
})
|
|
|
|
test("given user message after question (answered), returns false", () => {
|
|
const messages = [
|
|
{
|
|
info: { role: "assistant" },
|
|
parts: [
|
|
{ type: "tool_use", name: "question" },
|
|
],
|
|
},
|
|
{ info: { role: "user" } },
|
|
]
|
|
expect(hasUnansweredQuestion(messages)).toBe(false)
|
|
})
|
|
|
|
test("given assistant message with non-question tool, returns false", () => {
|
|
const messages = [
|
|
{ info: { role: "user" } },
|
|
{
|
|
info: { role: "assistant" },
|
|
parts: [
|
|
{ type: "tool_use", name: "bash" },
|
|
],
|
|
},
|
|
]
|
|
expect(hasUnansweredQuestion(messages)).toBe(false)
|
|
})
|
|
|
|
test("given assistant message with no parts, returns false", () => {
|
|
const messages = [
|
|
{ info: { role: "user" } },
|
|
{ info: { role: "assistant" } },
|
|
]
|
|
expect(hasUnansweredQuestion(messages)).toBe(false)
|
|
})
|
|
|
|
test("given role on message directly (not in info), returns true for question", () => {
|
|
const messages = [
|
|
{ role: "user" },
|
|
{
|
|
role: "assistant",
|
|
parts: [
|
|
{ type: "tool_use", name: "question" },
|
|
],
|
|
},
|
|
]
|
|
expect(hasUnansweredQuestion(messages)).toBe(true)
|
|
})
|
|
|
|
test("given mixed tools including question, returns true", () => {
|
|
const messages = [
|
|
{
|
|
info: { role: "assistant" },
|
|
parts: [
|
|
{ type: "tool_use", name: "bash" },
|
|
{ type: "tool_use", name: "question" },
|
|
],
|
|
},
|
|
]
|
|
expect(hasUnansweredQuestion(messages)).toBe(true)
|
|
})
|
|
})
|