fix(ralph-loop): send registered agent display name on continue
Continuation injector previously called normalizeAgentForPromptKey, which collapsed agent inputs like "Sisyphus - Ultraworker" or "sisyphus" down to the lowercase config key (e.g. "sisyphus"). OpenCode's promptAsync rejects that with "Agent not found", so the ralph-loop continue prompt silently failed to dispatch on parent sessions whose inherited message used a known display name. Switch to normalizeAgentForPrompt and add a small wrapper that: - preserves any agent string already in canonical " - " display form verbatim (covers ZWSP-prefixed inheritance and user-defined custom agents) - otherwise normalizes config keys / legacy parenthesized names to the registered display name OpenCode expects. Update the existing regression tests so that ZWSP-prefixed and clean inherited agents both assert the registered display name reaches promptAsync.
This commit is contained in:
@@ -59,7 +59,7 @@ describe("ralph-loop continuation prompt injector", () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
test("#given inherited message agent has ZWSP prefix #when injecting continuation prompt #then promptAsync receives normalized agent", async () => {
|
test("#given inherited message agent has ZWSP prefix #when injecting continuation prompt #then promptAsync receives registered display agent", async () => {
|
||||||
// given
|
// given
|
||||||
let promptBody: { agent?: string; noReply?: boolean } | undefined
|
let promptBody: { agent?: string; noReply?: boolean } | undefined
|
||||||
let promptPart:
|
let promptPart:
|
||||||
@@ -103,14 +103,14 @@ describe("ralph-loop continuation prompt injector", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(promptBody?.agent).toBe("sisyphus")
|
expect(promptBody?.agent).toBe("Sisyphus - Ultraworker")
|
||||||
expect(promptBody?.agent).not.toContain("\u200b")
|
expect(promptBody?.agent).not.toContain("\u200b")
|
||||||
expect(promptBody?.noReply).toBeUndefined()
|
expect(promptBody?.noReply).toBeUndefined()
|
||||||
expect(promptPart?.synthetic).toBe(true)
|
expect(promptPart?.synthetic).toBe(true)
|
||||||
expect(promptPart?.metadata?.compaction_continue).toBe(true)
|
expect(promptPart?.metadata?.compaction_continue).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("#given inherited message agent has no ZWSP prefix #when injecting continuation prompt #then promptAsync receives normalized agent", async () => {
|
test("#given inherited message agent has no ZWSP prefix #when injecting continuation prompt #then promptAsync receives registered display agent", async () => {
|
||||||
// given
|
// given
|
||||||
let promptBody: { agent?: string } | undefined
|
let promptBody: { agent?: string } | undefined
|
||||||
const ctx = {
|
const ctx = {
|
||||||
@@ -136,7 +136,7 @@ describe("ralph-loop continuation prompt injector", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(promptBody?.agent).toBe("sisyphus")
|
expect(promptBody?.agent).toBe("Sisyphus - Ultraworker")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("#given inherited message model includes variant #when injecting continuation prompt #then promptAsync receives variant as a top-level field", async () => {
|
test("#given inherited message model includes variant #when injecting continuation prompt #then promptAsync receives variant as a top-level field", async () => {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
normalizeSDKResponse,
|
normalizeSDKResponse,
|
||||||
resolveInheritedPromptTools,
|
resolveInheritedPromptTools,
|
||||||
} from "../../shared"
|
} from "../../shared"
|
||||||
import { normalizeAgentForPromptKey } from "../../shared/agent-display-names"
|
import { normalizeAgentForPrompt, stripAgentListSortPrefix } from "../../shared/agent-display-names"
|
||||||
import { promptAsyncAfterSessionIdle } from "../shared/prompt-async-gate"
|
import { promptAsyncAfterSessionIdle } from "../shared/prompt-async-gate"
|
||||||
|
|
||||||
type MessageInfo = {
|
type MessageInfo = {
|
||||||
@@ -60,6 +60,23 @@ function createPromptAsyncError(prefix: string, error: unknown): Error {
|
|||||||
return new Error(`${prefix}: ${describePromptAsyncError(error)}`)
|
return new Error(`${prefix}: ${describePromptAsyncError(error)}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeInheritedAgentForPrompt(agent: string | undefined): string | undefined {
|
||||||
|
if (typeof agent !== "string") {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const inheritedAgent = stripAgentListSortPrefix(agent).trim()
|
||||||
|
if (!inheritedAgent) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inheritedAgent.includes(" - ")) {
|
||||||
|
return inheritedAgent
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalizeAgentForPrompt(inheritedAgent)
|
||||||
|
}
|
||||||
|
|
||||||
export async function injectContinuationPrompt(
|
export async function injectContinuationPrompt(
|
||||||
ctx: PluginInput,
|
ctx: PluginInput,
|
||||||
options: {
|
options: {
|
||||||
@@ -113,7 +130,7 @@ export async function injectContinuationPrompt(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const inheritedTools = resolveInheritedPromptTools(sourceSessionID, tools)
|
const inheritedTools = resolveInheritedPromptTools(sourceSessionID, tools)
|
||||||
const cleanAgent = normalizeAgentForPromptKey(agent)
|
const cleanAgent = normalizeInheritedAgentForPrompt(agent)
|
||||||
|
|
||||||
const launchModel = model
|
const launchModel = model
|
||||||
? { providerID: model.providerID, modelID: model.modelID }
|
? { providerID: model.providerID, modelID: model.modelID }
|
||||||
|
|||||||
Reference in New Issue
Block a user