refactor(delegate-task): enhance delegation with dynamic descriptions

Generate tool description dynamically from available categories and skills. Remove hardcoded DELEGATE_TASK_DESCRIPTION constant. Improve parameter handling with unified 'subagent_type' field replacing 'agent'.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
justsisyphus
2026-01-22 22:46:23 +09:00
parent 0edfc7f36a
commit aa2b052d28
4 changed files with 281 additions and 184 deletions
+32 -60
View File
@@ -1,5 +1,5 @@
import { describe, test, expect } from "bun:test"
import { DEFAULT_CATEGORIES, CATEGORY_PROMPT_APPENDS, CATEGORY_DESCRIPTIONS, DELEGATE_TASK_DESCRIPTION } from "./constants"
import { DEFAULT_CATEGORIES, CATEGORY_PROMPT_APPENDS, CATEGORY_DESCRIPTIONS } from "./constants"
import { resolveCategoryConfig } from "./tools"
import type { CategoryConfig } from "../../config/schema"
@@ -70,19 +70,6 @@ describe("sisyphus-task", () => {
})
})
describe("DELEGATE_TASK_DESCRIPTION", () => {
test("documents background parameter as required with default false", () => {
// #given / #when / #then
expect(DELEGATE_TASK_DESCRIPTION).toContain("background")
expect(DELEGATE_TASK_DESCRIPTION).toContain("Default: false")
})
test("warns about parallel exploration usage", () => {
// #given / #when / #then
expect(DELEGATE_TASK_DESCRIPTION).toContain("5+")
})
})
describe("category delegation config validation", () => {
test("returns error when systemDefaultModel is not configured", async () => {
// #given a mock client with no model in config
@@ -118,7 +105,7 @@ describe("sisyphus-task", () => {
prompt: "Do something",
category: "ultrabrain",
run_in_background: false,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
@@ -333,7 +320,7 @@ describe("sisyphus-task", () => {
prompt: "Do something",
category: "ultrabrain",
run_in_background: true,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
@@ -394,7 +381,7 @@ describe("sisyphus-task", () => {
prompt: "Do something",
category: "unspecified-high",
run_in_background: true,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
@@ -451,7 +438,7 @@ describe("sisyphus-task", () => {
prompt: "Do something",
category: "unspecified-high",
run_in_background: false,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
@@ -466,14 +453,7 @@ describe("sisyphus-task", () => {
})
describe("skills parameter", () => {
test("DELEGATE_TASK_DESCRIPTION documents skills parameter with empty array option", () => {
// #given / #when / #then
expect(DELEGATE_TASK_DESCRIPTION).toContain("skills")
expect(DELEGATE_TASK_DESCRIPTION).toContain("Array of skill names")
expect(DELEGATE_TASK_DESCRIPTION).toContain("[] (empty array) if no skills needed")
})
test("skills parameter is required - returns error when not provided", async () => {
test("skills parameter is required - throws error when not provided", async () => {
// #given
const { createDelegateTask } = require("./tools")
@@ -501,7 +481,8 @@ describe("sisyphus-task", () => {
}
// #when - skills not provided (undefined)
const result = await tool.execute(
// #then - should throw error about missing skills
await expect(tool.execute(
{
description: "Test task",
prompt: "Do something",
@@ -509,14 +490,10 @@ describe("sisyphus-task", () => {
run_in_background: false,
},
toolContext
)
// #then - should return error about missing skills
expect(result).toContain("skills")
expect(result).toContain("REQUIRED")
)).rejects.toThrow("IT IS HIGHLY RECOMMENDED")
})
test("null skills returns error", async () => {
test("null skills throws error", async () => {
// #given
const { createDelegateTask } = require("./tools")
@@ -544,22 +521,17 @@ describe("sisyphus-task", () => {
}
// #when - null passed
const result = await tool.execute(
// #then - should throw error about null
await expect(tool.execute(
{
description: "Test task",
prompt: "Do something",
category: "ultrabrain",
run_in_background: false,
skills: null,
load_skills: null,
},
toolContext
)
// #then - should return error about null
expect(result).toContain("Invalid arguments")
expect(result).toContain("skills=null")
expect(result).toContain("not allowed")
expect(result).toContain("skills=[]")
)).rejects.toThrow("IT IS HIGHLY RECOMMENDED")
})
test("empty array [] is allowed and proceeds without skill content", async () => {
@@ -597,14 +569,14 @@ describe("sisyphus-task", () => {
abort: new AbortController().signal,
}
// #when - empty array skills passed
// #when - empty array passed
await tool.execute(
{
description: "Test task",
prompt: "Do something",
category: "ultrabrain",
run_in_background: false,
skills: [],
load_skills: [],
},
toolContext
)
@@ -670,7 +642,7 @@ describe("sisyphus-task", () => {
prompt: "Continue the task",
resume: "ses_resume_test",
run_in_background: false,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
@@ -725,7 +697,7 @@ describe("sisyphus-task", () => {
prompt: "Continue in background",
resume: "ses_bg_resume",
run_in_background: true,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
@@ -780,7 +752,7 @@ describe("sisyphus-task", () => {
prompt: "Do something",
category: "ultrabrain",
run_in_background: false,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
@@ -840,7 +812,7 @@ describe("sisyphus-task", () => {
prompt: "Do something",
category: "ultrabrain",
run_in_background: false,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
@@ -893,7 +865,7 @@ describe("sisyphus-task", () => {
prompt: "Do something",
category: "ultrabrain",
run_in_background: false,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
@@ -947,7 +919,7 @@ describe("sisyphus-task", () => {
prompt: "test",
category: "custom-cat",
run_in_background: false,
skills: []
load_skills: ["git-master"]
}, toolContext)
// #then
@@ -1012,14 +984,14 @@ describe("sisyphus-task", () => {
prompt: "Do something visual",
category: "visual-engineering",
run_in_background: false,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
// #then - should launch as background BUT wait for and return actual result
expect(launchCalled).toBe(true)
expect(result).toContain("UNSTABLE AGENT")
expect(result).toContain("SUPERVISED TASK COMPLETED")
expect(result).toContain("Gemini task completed successfully")
}, { timeout: 20000 })
@@ -1070,7 +1042,7 @@ describe("sisyphus-task", () => {
prompt: "Do something visual",
category: "visual-engineering",
run_in_background: true, // User explicitly says true - normal background
skills: [],
load_skills: ["git-master"],
},
toolContext
)
@@ -1131,7 +1103,7 @@ describe("sisyphus-task", () => {
prompt: "Do something smart",
category: "ultrabrain",
run_in_background: false,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
@@ -1195,14 +1167,14 @@ describe("sisyphus-task", () => {
prompt: "Do something artistic",
category: "artistry",
run_in_background: false,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
// #then - should launch as background BUT wait for and return actual result
expect(launchCalled).toBe(true)
expect(result).toContain("UNSTABLE AGENT")
expect(result).toContain("SUPERVISED TASK COMPLETED")
expect(result).toContain("Artistry result here")
}, { timeout: 20000 })
@@ -1259,14 +1231,14 @@ describe("sisyphus-task", () => {
prompt: "Write something",
category: "writing",
run_in_background: false,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
// #then - should launch as background BUT wait for and return actual result
expect(launchCalled).toBe(true)
expect(result).toContain("UNSTABLE AGENT")
expect(result).toContain("SUPERVISED TASK COMPLETED")
expect(result).toContain("Writing result here")
}, { timeout: 20000 })
@@ -1329,14 +1301,14 @@ describe("sisyphus-task", () => {
prompt: "Do something",
category: "my-unstable-cat",
run_in_background: false,
skills: [],
load_skills: ["git-master"],
},
toolContext
)
// #then - should launch as background BUT wait for and return actual result
expect(launchCalled).toBe(true)
expect(result).toContain("UNSTABLE AGENT")
expect(result).toContain("SUPERVISED TASK COMPLETED")
expect(result).toContain("Custom unstable result")
}, { timeout: 20000 })
})