fix(start-work): keep native command agents on config keys
This commit is contained in:
@@ -7,7 +7,6 @@ import { tmpdir } from "node:os"
|
||||
import { randomUUID } from "node:crypto"
|
||||
import { createStartWorkHook } from "./index"
|
||||
import { createAtlasHook } from "../atlas"
|
||||
import { getAgentDisplayName, getAgentListDisplayName } from "../../shared/agent-display-names"
|
||||
import {
|
||||
writeBoulderState,
|
||||
clearBoulderState,
|
||||
@@ -467,7 +466,7 @@ You are starting a Sisyphus work session.
|
||||
updateSpy.mockRestore()
|
||||
})
|
||||
|
||||
test("should stamp the outgoing message with Atlas list key so follow-up events keep the handoff", async () => {
|
||||
test("should stamp the outgoing message with Atlas config key so OpenCode can resolve the agent", async () => {
|
||||
// given
|
||||
const hook = createStartWorkHook(createMockPluginInput())
|
||||
const output = {
|
||||
@@ -481,8 +480,8 @@ You are starting a Sisyphus work session.
|
||||
output
|
||||
)
|
||||
|
||||
// then
|
||||
expect(output.message.agent).toBe(getAgentDisplayName("atlas"))
|
||||
// then - config key, not display name (matches no-sisyphus-gpt / boulder-continuation-injector convention)
|
||||
expect(output.message.agent).toBe("atlas")
|
||||
})
|
||||
|
||||
test("should switch to Atlas even when current session is Sisyphus (regression: #3155)", async () => {
|
||||
@@ -502,7 +501,7 @@ You are starting a Sisyphus work session.
|
||||
)
|
||||
|
||||
// atlas is registered in beforeEach, so it must be selected
|
||||
expect(output.message.agent).toBe(getAgentDisplayName("atlas"))
|
||||
expect(output.message.agent).toBe("atlas")
|
||||
expect(sessionState.getSessionAgent("ses-sisyphus-to-atlas")).toBe("atlas")
|
||||
})
|
||||
|
||||
@@ -525,7 +524,7 @@ You are starting a Sisyphus work session.
|
||||
)
|
||||
|
||||
// then
|
||||
expect(output.message.agent).toBe("Sisyphus - Ultraworker")
|
||||
expect(output.message.agent).toBe("sisyphus")
|
||||
expect(sessionState.getSessionAgent("ses-prometheus-to-sisyphus")).toBe("sisyphus")
|
||||
})
|
||||
|
||||
@@ -553,7 +552,7 @@ You are starting a Sisyphus work session.
|
||||
)
|
||||
|
||||
// then
|
||||
expect(output.message.agent).toBe("Sisyphus - Ultraworker")
|
||||
expect(output.message.agent).toBe("sisyphus")
|
||||
expect(sessionState.getSessionAgent("ses-prometheus-to-worker")).toBe("sisyphus")
|
||||
expect(readBoulderState(testDir)?.agent).toBe("sisyphus")
|
||||
})
|
||||
@@ -588,7 +587,7 @@ You are starting a Sisyphus work session.
|
||||
)
|
||||
|
||||
// then
|
||||
expect(output.message.agent).toBe("Sisyphus - Ultraworker")
|
||||
expect(output.message.agent).toBe("sisyphus")
|
||||
expect(readBoulderState(testDir)?.agent).toBe("sisyphus")
|
||||
})
|
||||
|
||||
@@ -623,7 +622,7 @@ You are starting a Sisyphus work session.
|
||||
await atlasHook.handler({ event: { type: "session.idle", properties: { sessionID: "session-123" } } })
|
||||
|
||||
// then
|
||||
expect(output.message.agent).toBe(getAgentDisplayName("atlas"))
|
||||
expect(output.message.agent).toBe("atlas")
|
||||
expect(readBoulderState(testDir)?.session_ids).toContain("session-123")
|
||||
expect(readBoulderState(testDir)?.agent).toBe("atlas")
|
||||
expect(promptAsyncMock).toHaveBeenCalledTimes(1)
|
||||
@@ -713,7 +712,7 @@ You are starting a Sisyphus work session.
|
||||
await firePendingTimers()
|
||||
|
||||
// then
|
||||
expect(output.message.agent).toBe(getAgentDisplayName("atlas"))
|
||||
expect(output.message.agent).toBe("atlas")
|
||||
expect(readBoulderState(testDir)?.session_ids).toContain("session-123")
|
||||
expect(readBoulderState(testDir)?.agent).toBe("atlas")
|
||||
expect(promptAsyncMock).toHaveBeenCalledTimes(1)
|
||||
|
||||
@@ -11,11 +11,6 @@ import {
|
||||
clearBoulderState,
|
||||
} from "../../features/boulder-state"
|
||||
import { log } from "../../shared/logger"
|
||||
import {
|
||||
getAgentDisplayName,
|
||||
getAgentListDisplayName,
|
||||
stripAgentListSortPrefix,
|
||||
} from "../../shared/agent-display-names"
|
||||
import {
|
||||
isAgentRegistered,
|
||||
updateSessionAgent,
|
||||
@@ -86,12 +81,9 @@ export function createStartWorkHook(ctx: PluginInput) {
|
||||
const activeAgent = isAgentRegistered("atlas")
|
||||
? "atlas"
|
||||
: "sisyphus"
|
||||
const activeAgentDisplayName = activeAgent === "atlas"
|
||||
? getAgentListDisplayName(activeAgent)
|
||||
: getAgentDisplayName(activeAgent)
|
||||
updateSessionAgent(input.sessionID, activeAgent)
|
||||
if (output.message) {
|
||||
output.message["agent"] = stripAgentListSortPrefix(activeAgentDisplayName)
|
||||
output.message["agent"] = activeAgent
|
||||
}
|
||||
|
||||
const existingState = readBoulderState(ctx.directory)
|
||||
|
||||
@@ -97,7 +97,7 @@ describe("applyCommandConfig", () => {
|
||||
expect(commandConfig["agents-global-skill"]?.description).toContain("Agents global skill");
|
||||
});
|
||||
|
||||
test("remaps Atlas command agents to the list display name used by runtime agent lookup", async () => {
|
||||
test("normalizes Atlas command agents to the config key OpenCode expects for native routing", async () => {
|
||||
// given
|
||||
loadBuiltinCommandsSpy.mockReturnValue({
|
||||
"start-work": {
|
||||
@@ -119,6 +119,31 @@ describe("applyCommandConfig", () => {
|
||||
|
||||
// then
|
||||
const commandConfig = config.command as Record<string, { agent?: string }>;
|
||||
expect(commandConfig["start-work"]?.agent).toBe(getAgentDisplayName("atlas"));
|
||||
expect(commandConfig["start-work"]?.agent).toBe("atlas");
|
||||
});
|
||||
|
||||
test("normalizes legacy display-name command agents back to config keys", async () => {
|
||||
// given
|
||||
loadBuiltinCommandsSpy.mockReturnValue({
|
||||
"start-work": {
|
||||
name: "start-work",
|
||||
description: "(builtin) Start work",
|
||||
template: "template",
|
||||
agent: getAgentDisplayName("atlas"),
|
||||
},
|
||||
});
|
||||
const config: Record<string, unknown> = { command: {} };
|
||||
|
||||
// when
|
||||
await applyCommandConfig({
|
||||
config,
|
||||
pluginConfig: createPluginConfig(),
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginComponents: createPluginComponents(),
|
||||
});
|
||||
|
||||
// then
|
||||
const commandConfig = config.command as Record<string, { agent?: string }>;
|
||||
expect(commandConfig["start-work"]?.agent).toBe("atlas");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { OhMyOpenCodeConfig } from "../config";
|
||||
import { getAgentDisplayName } from "../shared/agent-display-names";
|
||||
import { getAgentConfigKey } from "../shared/agent-display-names";
|
||||
import {
|
||||
loadUserCommands,
|
||||
loadProjectCommands,
|
||||
@@ -96,7 +96,7 @@ export async function applyCommandConfig(params: {
|
||||
function remapCommandAgentFields(commands: Record<string, Record<string, unknown>>): void {
|
||||
for (const cmd of Object.values(commands)) {
|
||||
if (cmd?.agent && typeof cmd.agent === "string") {
|
||||
cmd.agent = getAgentDisplayName(cmd.agent);
|
||||
cmd.agent = getAgentConfigKey(cmd.agent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ describe("createPluginInterface - command.execute.before", () => {
|
||||
)
|
||||
|
||||
// then
|
||||
expect(output.message.agent).toBe("Atlas - Plan Executor")
|
||||
expect(output.message.agent).toBe("atlas")
|
||||
expect(getSessionAgent("ses-command-atlas")).toBe("atlas")
|
||||
expect(readBoulderState(testDir)?.agent).toBe("atlas")
|
||||
})
|
||||
|
||||
@@ -87,7 +87,7 @@ describe("createChatMessageHandler - /start-work integration", () => {
|
||||
await handler(input, output)
|
||||
|
||||
// then
|
||||
expect(output.message["agent"]).toBe("Sisyphus - Ultraworker")
|
||||
expect(output.message["agent"]).toBe("sisyphus")
|
||||
expect(output.parts[0].text).toContain("<auto-slash-command>")
|
||||
expect(output.parts[0].text).toContain("Auto-Selected Plan")
|
||||
expect(output.parts[0].text).toContain("boulder.json has been created")
|
||||
@@ -116,7 +116,7 @@ describe("createChatMessageHandler - /start-work integration", () => {
|
||||
await handler(input, output)
|
||||
|
||||
// then
|
||||
expect(output.message["agent"]).toBe("Sisyphus - Ultraworker")
|
||||
expect(output.message["agent"]).toBe("sisyphus")
|
||||
expect(output.parts[0].text).toContain("<auto-slash-command>")
|
||||
expect(output.parts[0].text).toContain("Auto-Selected Plan")
|
||||
expect(output.parts[0].text).toContain("my-feature-plan")
|
||||
|
||||
Reference in New Issue
Block a user