Merge pull request #3166 from code-yeongyu/fix/delegate-description-optional
fix(delegate-task): make description optional with auto-generation from prompt
This commit is contained in:
@@ -1366,9 +1366,10 @@ describe("sisyphus-task", () => {
|
|||||||
)).rejects.toThrow("Invalid arguments: 'run_in_background' parameter is REQUIRED")
|
)).rejects.toThrow("Invalid arguments: 'run_in_background' parameter is REQUIRED")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("#given category without description #when executing #then throws required parameter error", async () => {
|
test("#given category without description #when executing #then auto-generates description from prompt", async () => {
|
||||||
// given
|
// given
|
||||||
const { createDelegateTask } = require("./tools")
|
const { createDelegateTask } = require("./tools")
|
||||||
|
let capturedTitle: string | undefined
|
||||||
const mockManager = { launch: async () => ({}) }
|
const mockManager = { launch: async () => ({}) }
|
||||||
const mockClient = {
|
const mockClient = {
|
||||||
app: { agents: async () => ({ data: [] }) },
|
app: { agents: async () => ({ data: [] }) },
|
||||||
@@ -1383,16 +1384,114 @@ describe("sisyphus-task", () => {
|
|||||||
const tool = createDelegateTask({ manager: mockManager, client: mockClient })
|
const tool = createDelegateTask({ manager: mockManager, client: mockClient })
|
||||||
|
|
||||||
// when
|
// when
|
||||||
// then
|
try {
|
||||||
await expect(tool.execute(
|
await tool.execute(
|
||||||
{
|
{
|
||||||
prompt: "Do something",
|
prompt: "Fix the broken unit tests in parser module",
|
||||||
category: "quick",
|
category: "quick",
|
||||||
run_in_background: false,
|
run_in_background: false,
|
||||||
load_skills: [],
|
load_skills: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sessionID: "parent-session",
|
||||||
|
messageID: "parent-message",
|
||||||
|
agent: "sisyphus",
|
||||||
|
abort: new AbortController().signal,
|
||||||
|
metadata: async (meta: { title?: string }) => { capturedTitle = meta.title },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
// execution may fail due to incomplete mocks — we only care about the title
|
||||||
|
}
|
||||||
|
|
||||||
|
// then — description auto-generated from first 4 words of prompt
|
||||||
|
expect(capturedTitle).toBe("Fix the broken unit")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("#given empty description #when executing #then auto-generates description from prompt", async () => {
|
||||||
|
// given
|
||||||
|
const { createDelegateTask } = require("./tools")
|
||||||
|
let capturedTitle: string | undefined
|
||||||
|
const mockManager = { launch: async () => ({}) }
|
||||||
|
const mockClient = {
|
||||||
|
app: { agents: async () => ({ data: [] }) },
|
||||||
|
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
|
||||||
|
session: {
|
||||||
|
create: async () => ({ data: { id: "test-session" } }),
|
||||||
|
prompt: async () => ({ data: {} }),
|
||||||
|
promptAsync: async () => ({ data: {} }),
|
||||||
|
messages: async () => ({ data: [] }),
|
||||||
},
|
},
|
||||||
{ sessionID: "parent-session", messageID: "parent-message", agent: "sisyphus", abort: new AbortController().signal }
|
}
|
||||||
)).rejects.toThrow("Invalid arguments: 'description' parameter is REQUIRED")
|
const tool = createDelegateTask({ manager: mockManager, client: mockClient })
|
||||||
|
|
||||||
|
// when
|
||||||
|
try {
|
||||||
|
await tool.execute(
|
||||||
|
{
|
||||||
|
description: " ",
|
||||||
|
prompt: "Refactor authentication module completely",
|
||||||
|
category: "quick",
|
||||||
|
run_in_background: false,
|
||||||
|
load_skills: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sessionID: "parent-session",
|
||||||
|
messageID: "parent-message",
|
||||||
|
agent: "sisyphus",
|
||||||
|
abort: new AbortController().signal,
|
||||||
|
metadata: async (meta: { title?: string }) => { capturedTitle = meta.title },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
// execution may fail due to incomplete mocks
|
||||||
|
}
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(capturedTitle).toBe("Refactor authentication module completely")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("#given explicit description #when executing #then preserves provided description", async () => {
|
||||||
|
// given
|
||||||
|
const { createDelegateTask } = require("./tools")
|
||||||
|
let capturedTitle: string | undefined
|
||||||
|
const mockManager = { launch: async () => ({}) }
|
||||||
|
const mockClient = {
|
||||||
|
app: { agents: async () => ({ data: [] }) },
|
||||||
|
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
|
||||||
|
session: {
|
||||||
|
create: async () => ({ data: { id: "test-session" } }),
|
||||||
|
prompt: async () => ({ data: {} }),
|
||||||
|
promptAsync: async () => ({ data: {} }),
|
||||||
|
messages: async () => ({ data: [] }),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const tool = createDelegateTask({ manager: mockManager, client: mockClient })
|
||||||
|
|
||||||
|
// when
|
||||||
|
try {
|
||||||
|
await tool.execute(
|
||||||
|
{
|
||||||
|
description: "My custom task name",
|
||||||
|
prompt: "Do something else entirely",
|
||||||
|
category: "quick",
|
||||||
|
run_in_background: false,
|
||||||
|
load_skills: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sessionID: "parent-session",
|
||||||
|
messageID: "parent-message",
|
||||||
|
agent: "sisyphus",
|
||||||
|
abort: new AbortController().signal,
|
||||||
|
metadata: async (meta: { title?: string }) => { capturedTitle = meta.title },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
// execution may fail due to incomplete mocks
|
||||||
|
}
|
||||||
|
|
||||||
|
// then — explicit description preserved
|
||||||
|
expect(capturedTitle).toBe("My custom task name")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("#given explicit run_in_background=false #when executing #then sync execution succeeds", async () => {
|
test("#given explicit run_in_background=false #when executing #then sync execution succeeds", async () => {
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ export function createDelegateTask(options: DelegateTaskToolOptions): ToolDefini
|
|||||||
description,
|
description,
|
||||||
args: {
|
args: {
|
||||||
load_skills: tool.schema.array(tool.schema.string()).describe("Skill names to inject. REQUIRED - pass [] if no skills needed."),
|
load_skills: tool.schema.array(tool.schema.string()).describe("Skill names to inject. REQUIRED - pass [] if no skills needed."),
|
||||||
description: tool.schema.string().describe("Short task description (3-5 words)"),
|
description: tool.schema.string().optional().describe("Short task description (3-5 words). Auto-generated from prompt if omitted."),
|
||||||
prompt: tool.schema.string().describe("Full detailed prompt for the agent"),
|
prompt: tool.schema.string().describe("Full detailed prompt for the agent"),
|
||||||
run_in_background: tool.schema.boolean().describe("REQUIRED. true=async (returns task_id), false=sync (waits). Use false for task delegation, true ONLY for parallel exploration."),
|
run_in_background: tool.schema.boolean().describe("REQUIRED. true=async (returns task_id), false=sync (waits). Use false for task delegation, true ONLY for parallel exploration."),
|
||||||
category: tool.schema.string().optional().describe(`REQUIRED if subagent_type not provided. Do NOT provide both category and subagent_type.`),
|
category: tool.schema.string().optional().describe(`REQUIRED if subagent_type not provided. Do NOT provide both category and subagent_type.`),
|
||||||
@@ -118,13 +118,14 @@ export function createDelegateTask(options: DelegateTaskToolOptions): ToolDefini
|
|||||||
}
|
}
|
||||||
args.subagent_type = SISYPHUS_JUNIOR_AGENT
|
args.subagent_type = SISYPHUS_JUNIOR_AGENT
|
||||||
}
|
}
|
||||||
|
// Auto-generate description from prompt when missing or empty
|
||||||
|
if (!args.description || typeof args.description !== "string" || args.description.trim() === "") {
|
||||||
|
const words = (args.prompt || "").trim().split(/\s+/)
|
||||||
|
args.description = words.slice(0, 4).join(" ") || "Delegated task"
|
||||||
|
}
|
||||||
await ctx.metadata?.({
|
await ctx.metadata?.({
|
||||||
title: args.description,
|
title: args.description,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!args.description || typeof args.description !== "string") {
|
|
||||||
throw new Error(`Invalid arguments: 'description' parameter is REQUIRED. Provide a short (3-5 words) task description.`)
|
|
||||||
}
|
|
||||||
if (args.run_in_background === undefined) {
|
if (args.run_in_background === undefined) {
|
||||||
throw new Error(`Invalid arguments: 'run_in_background' parameter is REQUIRED. Specify run_in_background=false for task delegation, or run_in_background=true for parallel exploration.`)
|
throw new Error(`Invalid arguments: 'run_in_background' parameter is REQUIRED. Specify run_in_background=false for task delegation, or run_in_background=true for parallel exploration.`)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user