Merge pull request #2797 from code-yeongyu/fix/2353-model-selection-persistence
fix(plugin): preserve selected model across messages
This commit is contained in:
@@ -7,8 +7,10 @@ import * as shared from "../shared"
|
||||
import * as sisyphusJunior from "../agents/sisyphus-junior"
|
||||
import type { OhMyOpenCodeConfig } from "../config"
|
||||
import * as agentLoader from "../features/claude-code-agent-loader"
|
||||
import * as sessionState from "../features/claude-code-session-state"
|
||||
import * as skillLoader from "../features/opencode-skill-loader"
|
||||
import { getAgentDisplayName } from "../shared/agent-display-names"
|
||||
import * as sessionModelState from "../shared/session-model-state"
|
||||
import { applyAgentConfig } from "./agent-config-handler"
|
||||
import type { PluginComponents } from "./plugin-components-loader"
|
||||
|
||||
@@ -53,6 +55,8 @@ describe("applyAgentConfig builtin override protection", () => {
|
||||
let discoverOpencodeProjectSkillsSpy: ReturnType<typeof spyOn>
|
||||
let loadUserAgentsSpy: ReturnType<typeof spyOn>
|
||||
let loadProjectAgentsSpy: ReturnType<typeof spyOn>
|
||||
let getMainSessionIDSpy: ReturnType<typeof spyOn>
|
||||
let getSessionModelSpy: ReturnType<typeof spyOn>
|
||||
let migrateAgentConfigSpy: ReturnType<typeof spyOn>
|
||||
let logSpy: ReturnType<typeof spyOn>
|
||||
|
||||
@@ -123,6 +127,8 @@ describe("applyAgentConfig builtin override protection", () => {
|
||||
|
||||
loadUserAgentsSpy = spyOn(agentLoader, "loadUserAgents").mockReturnValue({})
|
||||
loadProjectAgentsSpy = spyOn(agentLoader, "loadProjectAgents").mockReturnValue({})
|
||||
getMainSessionIDSpy = spyOn(sessionState, "getMainSessionID").mockReturnValue(undefined)
|
||||
getSessionModelSpy = spyOn(sessionModelState, "getSessionModel").mockReturnValue(undefined)
|
||||
|
||||
migrateAgentConfigSpy = spyOn(shared, "migrateAgentConfig").mockImplementation(
|
||||
(config: Record<string, unknown>) => config,
|
||||
@@ -140,6 +146,8 @@ describe("applyAgentConfig builtin override protection", () => {
|
||||
discoverOpencodeProjectSkillsSpy.mockRestore()
|
||||
loadUserAgentsSpy.mockRestore()
|
||||
loadProjectAgentsSpy.mockRestore()
|
||||
getMainSessionIDSpy.mockRestore()
|
||||
getSessionModelSpy.mockRestore()
|
||||
migrateAgentConfigSpy.mockRestore()
|
||||
logSpy.mockRestore()
|
||||
})
|
||||
@@ -166,6 +174,56 @@ describe("applyAgentConfig builtin override protection", () => {
|
||||
expect(result[BUILTIN_SISYPHUS_DISPLAY_NAME]).toEqual(builtinSisyphusConfig)
|
||||
})
|
||||
|
||||
test("reuses the main session model when config.model is missing", async () => {
|
||||
// given
|
||||
const createBuiltinAgentsMock = agents.createBuiltinAgents as unknown as {
|
||||
mock: { calls: unknown[][] }
|
||||
}
|
||||
getMainSessionIDSpy.mockReturnValue("ses_main")
|
||||
getSessionModelSpy.mockReturnValue({ providerID: "openai", modelID: "gpt-5.4" })
|
||||
|
||||
const config: Record<string, unknown> = {
|
||||
agent: {},
|
||||
}
|
||||
|
||||
// when
|
||||
await applyAgentConfig({
|
||||
config,
|
||||
pluginConfig: createPluginConfig(),
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginComponents: createPluginComponents(),
|
||||
})
|
||||
|
||||
// then
|
||||
expect(createBuiltinAgentsMock.mock.calls).toHaveLength(1)
|
||||
expect(createBuiltinAgentsMock.mock.calls[0]?.[3]).toBe("openai/gpt-5.4")
|
||||
expect(createBuiltinAgentsMock.mock.calls[0]?.[9]).toBe("openai/gpt-5.4")
|
||||
})
|
||||
|
||||
test("prefers config.model over the persisted main session model when both exist", async () => {
|
||||
// given
|
||||
const createBuiltinAgentsMock = agents.createBuiltinAgents as unknown as {
|
||||
mock: { calls: unknown[][] }
|
||||
}
|
||||
getMainSessionIDSpy.mockReturnValue("ses_main")
|
||||
getSessionModelSpy.mockReturnValue({ providerID: "openai", modelID: "gpt-5.4" })
|
||||
|
||||
const config = createBaseConfig()
|
||||
|
||||
// when
|
||||
await applyAgentConfig({
|
||||
config,
|
||||
pluginConfig: createPluginConfig(),
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginComponents: createPluginComponents(),
|
||||
})
|
||||
|
||||
// then
|
||||
expect(createBuiltinAgentsMock.mock.calls).toHaveLength(1)
|
||||
expect(createBuiltinAgentsMock.mock.calls[0]?.[3]).toBe("anthropic/claude-opus-4-6")
|
||||
expect(createBuiltinAgentsMock.mock.calls[0]?.[9]).toBe("anthropic/claude-opus-4-6")
|
||||
})
|
||||
|
||||
test("filters user agents whose key differs from a builtin key only by case", async () => {
|
||||
// given
|
||||
loadUserAgentsSpy.mockReturnValue({
|
||||
|
||||
@@ -2,8 +2,10 @@ import { createBuiltinAgents } from "../agents";
|
||||
import { createSisyphusJuniorAgentWithOverrides } from "../agents/sisyphus-junior";
|
||||
import type { OhMyOpenCodeConfig } from "../config";
|
||||
import { log, migrateAgentConfig } from "../shared";
|
||||
import { getMainSessionID } from "../features/claude-code-session-state";
|
||||
import { AGENT_NAME_MAP } from "../shared/migration";
|
||||
import { getAgentDisplayName } from "../shared/agent-display-names";
|
||||
import { getSessionModel } from "../shared/session-model-state";
|
||||
import {
|
||||
discoverConfigSourceSkills,
|
||||
discoverOpencodeGlobalSkills,
|
||||
@@ -27,6 +29,28 @@ type AgentConfigRecord = Record<string, Record<string, unknown> | undefined> & {
|
||||
plan?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
function resolveCurrentModel(config: Record<string, unknown>): string | undefined {
|
||||
const configModel = config.model;
|
||||
if (typeof configModel === "string") {
|
||||
const trimmedModel = configModel.trim();
|
||||
if (trimmedModel.length > 0) {
|
||||
return trimmedModel;
|
||||
}
|
||||
}
|
||||
|
||||
const mainSessionID = getMainSessionID();
|
||||
if (!mainSessionID) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const sessionModel = getSessionModel(mainSessionID);
|
||||
if (!sessionModel?.providerID || !sessionModel.modelID) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return `${sessionModel.providerID}/${sessionModel.modelID}`;
|
||||
}
|
||||
|
||||
function getConfiguredDefaultAgent(config: Record<string, unknown>): string | undefined {
|
||||
const defaultAgent = config.default_agent;
|
||||
if (typeof defaultAgent !== "string") return undefined;
|
||||
@@ -77,7 +101,7 @@ export async function applyAgentConfig(params: {
|
||||
|
||||
const browserProvider =
|
||||
params.pluginConfig.browser_automation_engine?.provider ?? "playwright";
|
||||
const currentModel = params.config.model as string | undefined;
|
||||
const currentModel = resolveCurrentModel(params.config);
|
||||
const disabledSkills = new Set<string>(params.pluginConfig.disabled_skills ?? []);
|
||||
const useTaskSystem = params.pluginConfig.experimental?.task_system ?? false;
|
||||
const disableOmoEnv = params.pluginConfig.experimental?.disable_omo_env ?? false;
|
||||
|
||||
Reference in New Issue
Block a user