Merge pull request #1873 from code-yeongyu/fix/first-message-variant-override
fix: preserve user-selected variant on first message instead of overriding with fallback chain default
This commit is contained in:
commit
a9dd6d2ce8
118
src/plugin/chat-message.test.ts
Normal file
118
src/plugin/chat-message.test.ts
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import { describe, test, expect } from "bun:test"
|
||||||
|
|
||||||
|
import { createChatMessageHandler } from "./chat-message"
|
||||||
|
|
||||||
|
type ChatMessagePart = { type: string; text?: string; [key: string]: unknown }
|
||||||
|
type ChatMessageHandlerOutput = { message: Record<string, unknown>; parts: ChatMessagePart[] }
|
||||||
|
|
||||||
|
function createMockHandlerArgs(overrides?: {
|
||||||
|
pluginConfig?: Record<string, unknown>
|
||||||
|
shouldOverride?: boolean
|
||||||
|
}) {
|
||||||
|
const appliedSessions: string[] = []
|
||||||
|
return {
|
||||||
|
ctx: { client: { tui: { showToast: async () => {} } } } as any,
|
||||||
|
pluginConfig: (overrides?.pluginConfig ?? {}) as any,
|
||||||
|
firstMessageVariantGate: {
|
||||||
|
shouldOverride: () => overrides?.shouldOverride ?? false,
|
||||||
|
markApplied: (sessionID: string) => { appliedSessions.push(sessionID) },
|
||||||
|
},
|
||||||
|
hooks: {
|
||||||
|
stopContinuationGuard: null,
|
||||||
|
keywordDetector: null,
|
||||||
|
claudeCodeHooks: null,
|
||||||
|
autoSlashCommand: null,
|
||||||
|
startWork: null,
|
||||||
|
ralphLoop: null,
|
||||||
|
} as any,
|
||||||
|
_appliedSessions: appliedSessions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMockInput(agent?: string, model?: { providerID: string; modelID: string }) {
|
||||||
|
return {
|
||||||
|
sessionID: "test-session",
|
||||||
|
agent,
|
||||||
|
model,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMockOutput(variant?: string): ChatMessageHandlerOutput {
|
||||||
|
const message: Record<string, unknown> = {}
|
||||||
|
if (variant !== undefined) {
|
||||||
|
message["variant"] = variant
|
||||||
|
}
|
||||||
|
return { message, parts: [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("createChatMessageHandler - first message variant", () => {
|
||||||
|
test("first message: sets variant from fallback chain when user has no selection", async () => {
|
||||||
|
//#given - first message, no user-selected variant, hephaestus with medium in chain
|
||||||
|
const args = createMockHandlerArgs({ shouldOverride: true })
|
||||||
|
const handler = createChatMessageHandler(args)
|
||||||
|
const input = createMockInput("hephaestus", { providerID: "openai", modelID: "gpt-5.3-codex" })
|
||||||
|
const output = createMockOutput() // no variant set
|
||||||
|
|
||||||
|
//#when
|
||||||
|
await handler(input, output)
|
||||||
|
|
||||||
|
//#then - should set variant from fallback chain
|
||||||
|
expect(output.message["variant"]).toBeDefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("first message: preserves user-selected variant when already set", async () => {
|
||||||
|
//#given - first message, user already selected "xhigh" variant in OpenCode UI
|
||||||
|
const args = createMockHandlerArgs({ shouldOverride: true })
|
||||||
|
const handler = createChatMessageHandler(args)
|
||||||
|
const input = createMockInput("hephaestus", { providerID: "openai", modelID: "gpt-5.3-codex" })
|
||||||
|
const output = createMockOutput("xhigh") // user selected xhigh
|
||||||
|
|
||||||
|
//#when
|
||||||
|
await handler(input, output)
|
||||||
|
|
||||||
|
//#then - user's xhigh must be preserved, not overwritten to "medium"
|
||||||
|
expect(output.message["variant"]).toBe("xhigh")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("first message: preserves user-selected 'high' variant", async () => {
|
||||||
|
//#given - user selected "high" variant
|
||||||
|
const args = createMockHandlerArgs({ shouldOverride: true })
|
||||||
|
const handler = createChatMessageHandler(args)
|
||||||
|
const input = createMockInput("hephaestus", { providerID: "openai", modelID: "gpt-5.3-codex" })
|
||||||
|
const output = createMockOutput("high")
|
||||||
|
|
||||||
|
//#when
|
||||||
|
await handler(input, output)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(output.message["variant"]).toBe("high")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("subsequent message: does not override existing variant", async () => {
|
||||||
|
//#given - not first message, variant already set
|
||||||
|
const args = createMockHandlerArgs({ shouldOverride: false })
|
||||||
|
const handler = createChatMessageHandler(args)
|
||||||
|
const input = createMockInput("hephaestus", { providerID: "openai", modelID: "gpt-5.3-codex" })
|
||||||
|
const output = createMockOutput("xhigh")
|
||||||
|
|
||||||
|
//#when
|
||||||
|
await handler(input, output)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(output.message["variant"]).toBe("xhigh")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("first message: marks gate as applied regardless of variant presence", async () => {
|
||||||
|
//#given - first message with user-selected variant
|
||||||
|
const args = createMockHandlerArgs({ shouldOverride: true })
|
||||||
|
const handler = createChatMessageHandler(args)
|
||||||
|
const input = createMockInput("hephaestus", { providerID: "openai", modelID: "gpt-5.3-codex" })
|
||||||
|
const output = createMockOutput("xhigh")
|
||||||
|
|
||||||
|
//#when
|
||||||
|
await handler(input, output)
|
||||||
|
|
||||||
|
//#then - gate should still be marked as applied
|
||||||
|
expect(args._appliedSessions).toContain("test-session")
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -56,12 +56,14 @@ export function createChatMessageHandler(args: {
|
|||||||
const message = output.message
|
const message = output.message
|
||||||
|
|
||||||
if (firstMessageVariantGate.shouldOverride(input.sessionID)) {
|
if (firstMessageVariantGate.shouldOverride(input.sessionID)) {
|
||||||
const variant =
|
if (message["variant"] === undefined) {
|
||||||
input.model && input.agent
|
const variant =
|
||||||
? resolveVariantForModel(pluginConfig, input.agent, input.model)
|
input.model && input.agent
|
||||||
: resolveAgentVariant(pluginConfig, input.agent)
|
? resolveVariantForModel(pluginConfig, input.agent, input.model)
|
||||||
if (variant !== undefined) {
|
: resolveAgentVariant(pluginConfig, input.agent)
|
||||||
message["variant"] = variant
|
if (variant !== undefined) {
|
||||||
|
message["variant"] = variant
|
||||||
|
}
|
||||||
}
|
}
|
||||||
firstMessageVariantGate.markApplied(input.sessionID)
|
firstMessageVariantGate.markApplied(input.sessionID)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user