- 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.
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
/// <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)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user