fix(delegate-task): reject stray backend-style categories
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
declare const require: (name: string) => any
|
||||
const { afterEach, beforeEach, describe, expect, mock, spyOn, test } = require("bun:test")
|
||||
import { resolveCategoryExecution } from "./category-resolver"
|
||||
import type { ExecutorContext } from "./executor-types"
|
||||
import * as availableModels from "./available-models"
|
||||
|
||||
describe("resolveCategoryExecution unknown category handling", () => {
|
||||
beforeEach(() => {
|
||||
mock.restore()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
mock.restore()
|
||||
})
|
||||
|
||||
test("#given unknown category #when resolving category execution #then it rejects before fetching available models", async () => {
|
||||
//#given
|
||||
const availableModelsSpy = spyOn(availableModels, "getAvailableModelsForDelegateTask")
|
||||
const executorContext: ExecutorContext = {
|
||||
client: {} as ExecutorContext["client"],
|
||||
manager: {} as ExecutorContext["manager"],
|
||||
directory: "/tmp/test",
|
||||
userCategories: {},
|
||||
sisyphusJuniorModel: undefined,
|
||||
}
|
||||
const args = {
|
||||
category: "backend-engineer",
|
||||
prompt: "test prompt",
|
||||
description: "Test task",
|
||||
run_in_background: false,
|
||||
load_skills: [],
|
||||
blockedBy: undefined,
|
||||
enableSkillTools: false,
|
||||
}
|
||||
|
||||
//#when
|
||||
const result = await resolveCategoryExecution(args, executorContext, undefined, "anthropic/claude-sonnet-4-6")
|
||||
|
||||
//#then
|
||||
expect(result.error).toContain('Unknown category: "backend-engineer"')
|
||||
expect(availableModelsSpy).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -45,12 +45,26 @@ export async function resolveCategoryExecution(
|
||||
): Promise<CategoryResolutionResult> {
|
||||
const { client, userCategories, sisyphusJuniorModel } = executorCtx
|
||||
|
||||
const availableModels = await getAvailableModelsForDelegateTask(client)
|
||||
|
||||
const categoryName = args.category!
|
||||
const enabledCategories = mergeCategories(userCategories)
|
||||
const categoryExists = enabledCategories[categoryName] !== undefined
|
||||
|
||||
if (!categoryExists) {
|
||||
const allCategoryNames = Object.keys(enabledCategories).join(", ")
|
||||
return {
|
||||
agentToUse: "",
|
||||
categoryModel: undefined,
|
||||
categoryPromptAppend: undefined,
|
||||
maxPromptTokens: undefined,
|
||||
modelInfo: undefined,
|
||||
actualModel: undefined,
|
||||
isUnstableAgent: false,
|
||||
error: `Unknown category: "${categoryName}". Available: ${allCategoryNames}`,
|
||||
}
|
||||
}
|
||||
|
||||
const availableModels = await getAvailableModelsForDelegateTask(client)
|
||||
|
||||
const resolved = resolveCategoryConfig(categoryName, {
|
||||
userCategories,
|
||||
inheritedModel,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
declare const require: (name: string) => any
|
||||
const { describe, expect, test } = require("bun:test")
|
||||
import { createDelegateTask } from "./tools"
|
||||
|
||||
describe("createDelegateTask schema", () => {
|
||||
test("#given category arg #when tool is created #then category is constrained to available enum values", () => {
|
||||
//#given
|
||||
const toolDefinition = createDelegateTask({ manager: {} as never, client: {} as never, directory: "/tmp/test" })
|
||||
|
||||
//#when
|
||||
const categorySchema = toolDefinition.args.category as unknown as {
|
||||
def: {
|
||||
type: string
|
||||
innerType: {
|
||||
def: { type: string }
|
||||
options: string[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#then
|
||||
expect(categorySchema.def.type).toBe("optional")
|
||||
expect(categorySchema.def.innerType.def.type).toBe("enum")
|
||||
expect(categorySchema.def.innerType.options).toContain("quick")
|
||||
expect(categorySchema.def.innerType.options).toContain("deep")
|
||||
expect(categorySchema.def.innerType.options).toContain("ultrabrain")
|
||||
})
|
||||
})
|
||||
@@ -101,7 +101,7 @@ export function createDelegateTask(options: DelegateTaskToolOptions): ToolDefini
|
||||
description: tool.schema.string().describe("Short task description (3-5 words)"),
|
||||
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."),
|
||||
category: tool.schema.string().optional().describe(`REQUIRED if subagent_type not provided. Do NOT provide both category and subagent_type.`),
|
||||
category: tool.schema.enum(categoryNames).optional().describe(`REQUIRED if subagent_type not provided. Do NOT provide both category and subagent_type.`),
|
||||
subagent_type: tool.schema.string().optional().describe("REQUIRED if category not provided. Do NOT provide both category and subagent_type. Must be a callable non-primary agent name returned by app.agents()."),
|
||||
session_id: tool.schema.string().optional().describe("Existing Task session to continue"),
|
||||
command: tool.schema.string().optional().describe("The command that triggered this task"),
|
||||
|
||||
Reference in New Issue
Block a user