fix(agent): sanitize backslash/quote from agent name in launch() and background-executor
Agent names like \hephaestus\ cause 'Agent not found' errors because sanitizeSubagentType() was only called in subagent-resolver.ts but not in the direct manager.launch() path or background-executor.ts. - manager.ts: strip leading/trailing backslash/quote chars from input.agent before validation so \hephaestus\ → hephaestus - background-executor.ts: call sanitizeSubagentType(args.subagent_type) instead of passing raw value to manager.launch() - agent-display-names.ts: reuse sanitizeSubagentType in stripAgentListSortPrefix - Add unit tests for all three fix points Fixes: sessions dying with 'Agent not found: \hephaestus\'
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
/// <reference types="bun-types" />
|
||||
import { describe, test, expect, mock } from "bun:test"
|
||||
mock.module("../../shared/frontmatter", () => ({
|
||||
parseFrontmatter: () => ({ frontmatter: {}, content: "" }),
|
||||
}))
|
||||
mock.module("js-yaml", () => ({
|
||||
load: () => ({}),
|
||||
}))
|
||||
import type { BackgroundManager } from "../../features/background-agent"
|
||||
import type { PluginInput } from "@opencode-ai/plugin"
|
||||
import { executeBackground } from "./background-executor"
|
||||
@@ -100,6 +106,35 @@ describe("executeBackground", () => {
|
||||
expect(launchArgs.fallbackChain).toEqual(fallbackChain)
|
||||
})
|
||||
|
||||
test("sanitizes subagent_type before passing to background manager launch", async () => {
|
||||
//#given
|
||||
const wrappedArgs = {
|
||||
...testArgs,
|
||||
subagent_type: "\\hephaestus\\",
|
||||
}
|
||||
launchMock.mockResolvedValueOnce({
|
||||
id: "test-task-id",
|
||||
sessionId: "sub-session",
|
||||
description: "Test task",
|
||||
agent: "hephaestus",
|
||||
status: "pending",
|
||||
})
|
||||
|
||||
//#when
|
||||
await executeBackground(wrappedArgs, testContext, mockManager, mockClient)
|
||||
|
||||
//#then
|
||||
const latestCall = [...launchMock.mock.calls].pop()
|
||||
if (!latestCall) {
|
||||
throw new Error("Expected background manager launch to be called")
|
||||
}
|
||||
const launchArgs = latestCall[0]
|
||||
if (!launchArgs) {
|
||||
throw new Error("Expected launch arguments")
|
||||
}
|
||||
expect(launchArgs.agent).toBe("hephaestus")
|
||||
})
|
||||
|
||||
test("keeps launched background task alive when parent aborts before session id resolves", async () => {
|
||||
//#given - parent abort after launch should stop waiting, not fail the background task
|
||||
const abortController = new AbortController()
|
||||
|
||||
@@ -8,6 +8,7 @@ import { resolveMessageContext } from "../../features/hook-message-injector"
|
||||
import { getSessionAgent } from "../../features/claude-code-session-state"
|
||||
import { getMessageDir } from "./message-dir"
|
||||
import { getSessionTools } from "../../shared/session-tools-store"
|
||||
import { sanitizeSubagentType } from "../delegate-task/subagent-discovery"
|
||||
|
||||
export async function executeBackground(
|
||||
args: CallOmoAgentArgs,
|
||||
@@ -47,7 +48,7 @@ export async function executeBackground(
|
||||
const task = await manager.launch({
|
||||
description: args.description,
|
||||
prompt: args.prompt,
|
||||
agent: args.subagent_type,
|
||||
agent: sanitizeSubagentType(args.subagent_type),
|
||||
parentSessionId: toolContext.sessionID,
|
||||
parentMessageId: toolContext.messageID,
|
||||
parentAgent,
|
||||
|
||||
Reference in New Issue
Block a user