fix(agents): strip ZWSP ordering prefixes in session state, config lookups, and override protection

Prevent ZWSP sort prefixes from leaking into stored agent names, config
key lookups, and override-protection normalization. Ensures prefixed
list-display names resolve correctly throughout the pipeline.

🤖 Generated with [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) assistance
This commit is contained in:
YeonGyu-Kim
2026-04-06 18:07:26 +09:00
parent 178b635d72
commit e62d5d7a22
5 changed files with 62 additions and 4 deletions
+26
View File
@@ -9,6 +9,7 @@ import { createAutoSlashCommandHook } from "../hooks/auto-slash-command"
import { createStartWorkHook } from "../hooks/start-work"
import { readBoulderState } from "../features/boulder-state"
import { _resetForTesting, setMainSession, subagentSessions, registerAgentName, updateSessionAgent, getSessionAgent } from "../features/claude-code-session-state"
import { getAgentListDisplayName } from "../shared/agent-display-names"
import { clearSessionModel, getSessionModel, setSessionModel } from "../shared/session-model-state"
type ChatMessagePart = { type: string; text?: string; [key: string]: unknown }
@@ -374,6 +375,31 @@ describe("createChatMessageHandler - TUI variant passthrough", () => {
expect(getSessionModel("test-session")).toEqual({ providerID: "openai", modelID: "gpt-5.4" })
})
test("treats prefixed list-display agent names as explicit model overrides", async () => {
//#given
setMainSession("test-session")
setSessionModel("test-session", { providerID: "openai", modelID: "gpt-5.4" })
const args = createMockHandlerArgs({
shouldOverride: false,
pluginConfig: {
agents: {
prometheus: { model: "anthropic/claude-opus-4-6" },
},
},
})
const handler = createChatMessageHandler(args)
const input = createMockInput(getAgentListDisplayName("prometheus"))
const output = createMockOutput()
//#when
await handler(input, output)
//#then
expect(output.message["model"]).toBeUndefined()
expect(getSessionModel("test-session")).toEqual({ providerID: "openai", modelID: "gpt-5.4" })
expect(getSessionAgent("test-session")).toBe("Prometheus (Plan Builder)")
})
test("respects a mid-conversation model switch instead of reusing the previous stored model", async () => {
//#given
setMainSession("test-session")
+4 -2
View File
@@ -2,6 +2,7 @@ import type { OhMyOpenCodeConfig } from "../config"
import type { PluginContext } from "./types"
import { hasConnectedProvidersCache } from "../shared"
import { getAgentConfigKey } from "../shared/agent-display-names"
import { getSessionModel, setSessionModel } from "../shared/session-model-state"
import { getMainSessionID, setSessionAgent, subagentSessions } from "../features/claude-code-session-state"
import { applyUltraworkModelOverrideOnMessage } from "./ultrawork-model-override"
@@ -46,11 +47,12 @@ function hasExplicitAgentModelOverride(
pluginConfig: OhMyOpenCodeConfig
): boolean {
const configuredAgents = pluginConfig.agents
if (!agent || !configuredAgents || !(agent in configuredAgents)) {
const normalizedAgent = typeof agent === "string" ? getAgentConfigKey(agent) : undefined
if (!normalizedAgent || !configuredAgents || !(normalizedAgent in configuredAgents)) {
return false
}
const configuredAgent = configuredAgents[agent as keyof typeof configuredAgents]
const configuredAgent = configuredAgents[normalizedAgent as keyof typeof configuredAgents]
const configuredModel = configuredAgent?.model
return typeof configuredModel === "string" && configuredModel.trim().length > 0
}