fix(agent-variant): resolve variant based on current model, not static config (#1179)
This commit is contained in:
15
src/index.ts
15
src/index.ts
@@ -40,7 +40,7 @@ import {
|
|||||||
contextCollector,
|
contextCollector,
|
||||||
createContextInjectorMessagesTransformHook,
|
createContextInjectorMessagesTransformHook,
|
||||||
} from "./features/context-injector";
|
} from "./features/context-injector";
|
||||||
import { applyAgentVariant, resolveAgentVariant } from "./shared/agent-variant";
|
import { applyAgentVariant, resolveAgentVariant, resolveVariantForModel } from "./shared/agent-variant";
|
||||||
import { createFirstMessageVariantGate } from "./shared/first-message-variant";
|
import { createFirstMessageVariantGate } from "./shared/first-message-variant";
|
||||||
import {
|
import {
|
||||||
discoverUserClaudeSkills,
|
discoverUserClaudeSkills,
|
||||||
@@ -384,13 +384,22 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
|
|||||||
|
|
||||||
const message = (output as { message: { variant?: string } }).message
|
const message = (output as { message: { variant?: string } }).message
|
||||||
if (firstMessageVariantGate.shouldOverride(input.sessionID)) {
|
if (firstMessageVariantGate.shouldOverride(input.sessionID)) {
|
||||||
const variant = resolveAgentVariant(pluginConfig, input.agent)
|
const variant = input.model && input.agent
|
||||||
|
? resolveVariantForModel(pluginConfig, input.agent, input.model)
|
||||||
|
: resolveAgentVariant(pluginConfig, input.agent)
|
||||||
if (variant !== undefined) {
|
if (variant !== undefined) {
|
||||||
message.variant = variant
|
message.variant = variant
|
||||||
}
|
}
|
||||||
firstMessageVariantGate.markApplied(input.sessionID)
|
firstMessageVariantGate.markApplied(input.sessionID)
|
||||||
} else {
|
} else {
|
||||||
applyAgentVariant(pluginConfig, input.agent, message)
|
if (input.model && input.agent && message.variant === undefined) {
|
||||||
|
const variant = resolveVariantForModel(pluginConfig, input.agent, input.model)
|
||||||
|
if (variant !== undefined) {
|
||||||
|
message.variant = variant
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
applyAgentVariant(pluginConfig, input.agent, message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await keywordDetector?.["chat.message"]?.(input, output);
|
await keywordDetector?.["chat.message"]?.(input, output);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, test } from "bun:test"
|
import { describe, expect, test } from "bun:test"
|
||||||
import type { OhMyOpenCodeConfig } from "../config"
|
import type { OhMyOpenCodeConfig } from "../config"
|
||||||
import { applyAgentVariant, resolveAgentVariant } from "./agent-variant"
|
import { applyAgentVariant, resolveAgentVariant, resolveVariantForModel } from "./agent-variant"
|
||||||
|
|
||||||
describe("resolveAgentVariant", () => {
|
describe("resolveAgentVariant", () => {
|
||||||
test("returns undefined when agent name missing", () => {
|
test("returns undefined when agent name missing", () => {
|
||||||
@@ -81,3 +81,117 @@ describe("applyAgentVariant", () => {
|
|||||||
expect(message.variant).toBe("max")
|
expect(message.variant).toBe("max")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("resolveVariantForModel", () => {
|
||||||
|
test("returns correct variant for anthropic provider", () => {
|
||||||
|
// #given
|
||||||
|
const config = {} as OhMyOpenCodeConfig
|
||||||
|
const model = { providerID: "anthropic", modelID: "claude-opus-4-5" }
|
||||||
|
|
||||||
|
// #when
|
||||||
|
const variant = resolveVariantForModel(config, "sisyphus", model)
|
||||||
|
|
||||||
|
// #then
|
||||||
|
expect(variant).toBe("max")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns correct variant for openai provider", () => {
|
||||||
|
// #given
|
||||||
|
const config = {} as OhMyOpenCodeConfig
|
||||||
|
const model = { providerID: "openai", modelID: "gpt-5.2" }
|
||||||
|
|
||||||
|
// #when
|
||||||
|
const variant = resolveVariantForModel(config, "sisyphus", model)
|
||||||
|
|
||||||
|
// #then
|
||||||
|
expect(variant).toBe("medium")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns undefined for provider with no variant in chain", () => {
|
||||||
|
// #given
|
||||||
|
const config = {} as OhMyOpenCodeConfig
|
||||||
|
const model = { providerID: "google", modelID: "gemini-3-pro" }
|
||||||
|
|
||||||
|
// #when
|
||||||
|
const variant = resolveVariantForModel(config, "sisyphus", model)
|
||||||
|
|
||||||
|
// #then
|
||||||
|
expect(variant).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns undefined for provider not in chain", () => {
|
||||||
|
// #given
|
||||||
|
const config = {} as OhMyOpenCodeConfig
|
||||||
|
const model = { providerID: "unknown-provider", modelID: "some-model" }
|
||||||
|
|
||||||
|
// #when
|
||||||
|
const variant = resolveVariantForModel(config, "sisyphus", model)
|
||||||
|
|
||||||
|
// #then
|
||||||
|
expect(variant).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns undefined for unknown agent", () => {
|
||||||
|
// #given
|
||||||
|
const config = {} as OhMyOpenCodeConfig
|
||||||
|
const model = { providerID: "anthropic", modelID: "claude-opus-4-5" }
|
||||||
|
|
||||||
|
// #when
|
||||||
|
const variant = resolveVariantForModel(config, "nonexistent-agent", model)
|
||||||
|
|
||||||
|
// #then
|
||||||
|
expect(variant).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns variant for zai-coding-plan provider without variant", () => {
|
||||||
|
// #given
|
||||||
|
const config = {} as OhMyOpenCodeConfig
|
||||||
|
const model = { providerID: "zai-coding-plan", modelID: "glm-4.7" }
|
||||||
|
|
||||||
|
// #when
|
||||||
|
const variant = resolveVariantForModel(config, "sisyphus", model)
|
||||||
|
|
||||||
|
// #then
|
||||||
|
expect(variant).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("falls back to category chain when agent has no requirement", () => {
|
||||||
|
// #given
|
||||||
|
const config = {
|
||||||
|
agents: {
|
||||||
|
"custom-agent": { category: "ultrabrain" },
|
||||||
|
},
|
||||||
|
} as OhMyOpenCodeConfig
|
||||||
|
const model = { providerID: "openai", modelID: "gpt-5.2-codex" }
|
||||||
|
|
||||||
|
// #when
|
||||||
|
const variant = resolveVariantForModel(config, "custom-agent", model)
|
||||||
|
|
||||||
|
// #then
|
||||||
|
expect(variant).toBe("xhigh")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns correct variant for oracle agent with openai", () => {
|
||||||
|
// #given
|
||||||
|
const config = {} as OhMyOpenCodeConfig
|
||||||
|
const model = { providerID: "openai", modelID: "gpt-5.2" }
|
||||||
|
|
||||||
|
// #when
|
||||||
|
const variant = resolveVariantForModel(config, "oracle", model)
|
||||||
|
|
||||||
|
// #then
|
||||||
|
expect(variant).toBe("high")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns correct variant for oracle agent with anthropic", () => {
|
||||||
|
// #given
|
||||||
|
const config = {} as OhMyOpenCodeConfig
|
||||||
|
const model = { providerID: "anthropic", modelID: "claude-opus-4-5" }
|
||||||
|
|
||||||
|
// #when
|
||||||
|
const variant = resolveVariantForModel(config, "oracle", model)
|
||||||
|
|
||||||
|
// #then
|
||||||
|
expect(variant).toBe("max")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { OhMyOpenCodeConfig } from "../config"
|
import type { OhMyOpenCodeConfig } from "../config"
|
||||||
import { findCaseInsensitive } from "./case-insensitive"
|
import { findCaseInsensitive } from "./case-insensitive"
|
||||||
|
import { AGENT_MODEL_REQUIREMENTS, CATEGORY_MODEL_REQUIREMENTS } from "./model-requirements"
|
||||||
|
|
||||||
export function resolveAgentVariant(
|
export function resolveAgentVariant(
|
||||||
config: OhMyOpenCodeConfig,
|
config: OhMyOpenCodeConfig,
|
||||||
@@ -29,6 +30,43 @@ export function resolveAgentVariant(
|
|||||||
return config.categories?.[categoryName]?.variant
|
return config.categories?.[categoryName]?.variant
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resolveVariantForModel(
|
||||||
|
config: OhMyOpenCodeConfig,
|
||||||
|
agentName: string,
|
||||||
|
currentModel: { providerID: string; modelID: string },
|
||||||
|
): string | undefined {
|
||||||
|
const agentRequirement = AGENT_MODEL_REQUIREMENTS[agentName]
|
||||||
|
if (agentRequirement) {
|
||||||
|
return findVariantInChain(agentRequirement.fallbackChain, currentModel.providerID)
|
||||||
|
}
|
||||||
|
|
||||||
|
const agentOverrides = config.agents as
|
||||||
|
| Record<string, { category?: string }>
|
||||||
|
| undefined
|
||||||
|
const agentOverride = agentOverrides ? findCaseInsensitive(agentOverrides, agentName) : undefined
|
||||||
|
const categoryName = agentOverride?.category
|
||||||
|
if (categoryName) {
|
||||||
|
const categoryRequirement = CATEGORY_MODEL_REQUIREMENTS[categoryName]
|
||||||
|
if (categoryRequirement) {
|
||||||
|
return findVariantInChain(categoryRequirement.fallbackChain, currentModel.providerID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
function findVariantInChain(
|
||||||
|
fallbackChain: { providers: string[]; model: string; variant?: string }[],
|
||||||
|
providerID: string,
|
||||||
|
): string | undefined {
|
||||||
|
for (const entry of fallbackChain) {
|
||||||
|
if (entry.providers.includes(providerID)) {
|
||||||
|
return entry.variant
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
export function applyAgentVariant(
|
export function applyAgentVariant(
|
||||||
config: OhMyOpenCodeConfig,
|
config: OhMyOpenCodeConfig,
|
||||||
agentName: string | undefined,
|
agentName: string | undefined,
|
||||||
|
|||||||
Reference in New Issue
Block a user