fix(config): resolve category to model for Prometheus (Planner) agent (#652)
* fix(config): resolve category to model for Prometheus (Planner) agent When Prometheus (Planner) was configured with only a category (e.g., "ultrabrain") and no explicit model, the category was ignored and the agent fell back to the hardcoded default "anthropic/claude-opus-4-5". Add resolveModelFromCategoryWithUserOverride() helper that checks user categories first, then DEFAULT_CATEGORIES, to resolve category names to their corresponding models. Apply this resolution when building the Prometheus agent configuration. Co-Authored-By: Sisyphus <sisyphus@mengmota.com> * fix(test): use actual implementation instead of local duplicate Co-Authored-By: Sisyphus <sisyphus@mengmota.com> * fix(config): apply all category properties, not just model for Prometheus (Planner) The resolveModelFromCategoryWithUserOverride() helper only extracted the model field from CategoryConfig, ignoring critical properties like temperature, top_p, tools, maxTokens, thinking, reasoningEffort, and textVerbosity. This caused categories like "ultrabrain" (temperature: 0.1) to run with incorrect default temperatures. Refactor resolveModelFromCategoryWithUserOverride() to resolveCategoryConfig() that returns the full CategoryConfig. Update Prometheus (Planner) configuration to apply all category properties (temperature, top_p, tools, etc.) when a category is specified, matching the pattern established in Sisyphus-Junior. Explicit overrides still take precedence during merge. Co-Authored-By: Sisyphus <sisyphus@mengmota.com> --------- Co-authored-by: Sisyphus <sisyphus@mengmota.com>
This commit is contained in:
parent
91c490a358
commit
f9dca8d877
104
src/plugin-handlers/config-handler.test.ts
Normal file
104
src/plugin-handlers/config-handler.test.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import { describe, test, expect } from "bun:test"
|
||||
import { resolveCategoryConfig } from "./config-handler"
|
||||
import type { CategoryConfig } from "../config/schema"
|
||||
|
||||
describe("Prometheus category config resolution", () => {
|
||||
test("resolves ultrabrain category config", () => {
|
||||
// #given
|
||||
const categoryName = "ultrabrain"
|
||||
|
||||
// #when
|
||||
const config = resolveCategoryConfig(categoryName)
|
||||
|
||||
// #then
|
||||
expect(config).toBeDefined()
|
||||
expect(config?.model).toBe("openai/gpt-5.2")
|
||||
expect(config?.temperature).toBe(0.1)
|
||||
})
|
||||
|
||||
test("resolves visual-engineering category config", () => {
|
||||
// #given
|
||||
const categoryName = "visual-engineering"
|
||||
|
||||
// #when
|
||||
const config = resolveCategoryConfig(categoryName)
|
||||
|
||||
// #then
|
||||
expect(config).toBeDefined()
|
||||
expect(config?.model).toBe("google/gemini-3-pro-preview")
|
||||
expect(config?.temperature).toBe(0.7)
|
||||
})
|
||||
|
||||
test("user categories override default categories", () => {
|
||||
// #given
|
||||
const categoryName = "ultrabrain"
|
||||
const userCategories: Record<string, CategoryConfig> = {
|
||||
ultrabrain: {
|
||||
model: "google/antigravity-claude-opus-4-5-thinking",
|
||||
temperature: 0.1,
|
||||
},
|
||||
}
|
||||
|
||||
// #when
|
||||
const config = resolveCategoryConfig(categoryName, userCategories)
|
||||
|
||||
// #then
|
||||
expect(config).toBeDefined()
|
||||
expect(config?.model).toBe("google/antigravity-claude-opus-4-5-thinking")
|
||||
expect(config?.temperature).toBe(0.1)
|
||||
})
|
||||
|
||||
test("returns undefined for unknown category", () => {
|
||||
// #given
|
||||
const categoryName = "nonexistent-category"
|
||||
|
||||
// #when
|
||||
const config = resolveCategoryConfig(categoryName)
|
||||
|
||||
// #then
|
||||
expect(config).toBeUndefined()
|
||||
})
|
||||
|
||||
test("falls back to default when user category has no entry", () => {
|
||||
// #given
|
||||
const categoryName = "ultrabrain"
|
||||
const userCategories: Record<string, CategoryConfig> = {
|
||||
"visual-engineering": {
|
||||
model: "custom/visual-model",
|
||||
},
|
||||
}
|
||||
|
||||
// #when
|
||||
const config = resolveCategoryConfig(categoryName, userCategories)
|
||||
|
||||
// #then
|
||||
expect(config).toBeDefined()
|
||||
expect(config?.model).toBe("openai/gpt-5.2")
|
||||
expect(config?.temperature).toBe(0.1)
|
||||
})
|
||||
|
||||
test("preserves all category properties (temperature, top_p, tools, etc.)", () => {
|
||||
// #given
|
||||
const categoryName = "custom-category"
|
||||
const userCategories: Record<string, CategoryConfig> = {
|
||||
"custom-category": {
|
||||
model: "test/model",
|
||||
temperature: 0.5,
|
||||
top_p: 0.9,
|
||||
maxTokens: 32000,
|
||||
tools: { tool1: true, tool2: false },
|
||||
},
|
||||
}
|
||||
|
||||
// #when
|
||||
const config = resolveCategoryConfig(categoryName, userCategories)
|
||||
|
||||
// #then
|
||||
expect(config).toBeDefined()
|
||||
expect(config?.model).toBe("test/model")
|
||||
expect(config?.temperature).toBe(0.5)
|
||||
expect(config?.top_p).toBe(0.9)
|
||||
expect(config?.maxTokens).toBe(32000)
|
||||
expect(config?.tools).toEqual({ tool1: true, tool2: false })
|
||||
})
|
||||
})
|
||||
@ -24,7 +24,9 @@ import type { OhMyOpenCodeConfig } from "../config";
|
||||
import { log } from "../shared";
|
||||
import { migrateAgentConfig } from "../shared/permission-compat";
|
||||
import { PROMETHEUS_SYSTEM_PROMPT, PROMETHEUS_PERMISSION } from "../agents/prometheus-prompt";
|
||||
import { DEFAULT_CATEGORIES } from "../tools/sisyphus-task/constants";
|
||||
import type { ModelCacheState } from "../plugin-state";
|
||||
import type { CategoryConfig } from "../config/schema";
|
||||
|
||||
export interface ConfigHandlerDeps {
|
||||
ctx: { directory: string };
|
||||
@ -32,6 +34,13 @@ export interface ConfigHandlerDeps {
|
||||
modelCacheState: ModelCacheState;
|
||||
}
|
||||
|
||||
export function resolveCategoryConfig(
|
||||
categoryName: string,
|
||||
userCategories?: Record<string, CategoryConfig>
|
||||
): CategoryConfig | undefined {
|
||||
return userCategories?.[categoryName] ?? DEFAULT_CATEGORIES[categoryName];
|
||||
}
|
||||
|
||||
export function createConfigHandler(deps: ConfigHandlerDeps) {
|
||||
const { ctx, pluginConfig, modelCacheState } = deps;
|
||||
|
||||
@ -173,15 +182,50 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
|
||||
planConfigWithoutName as Record<string, unknown>
|
||||
);
|
||||
const prometheusOverride =
|
||||
pluginConfig.agents?.["Prometheus (Planner)"];
|
||||
pluginConfig.agents?.["Prometheus (Planner)"] as
|
||||
| (Record<string, unknown> & { category?: string; model?: string })
|
||||
| undefined;
|
||||
const defaultModel = config.model as string | undefined;
|
||||
|
||||
// Resolve full category config (model, temperature, top_p, tools, etc.)
|
||||
// Apply all category properties when category is specified, but explicit
|
||||
// overrides (model, temperature, etc.) will take precedence during merge
|
||||
const categoryConfig = prometheusOverride?.category
|
||||
? resolveCategoryConfig(
|
||||
prometheusOverride.category,
|
||||
pluginConfig.categories
|
||||
)
|
||||
: undefined;
|
||||
|
||||
const prometheusBase = {
|
||||
model: defaultModel ?? "anthropic/claude-opus-4-5",
|
||||
model:
|
||||
prometheusOverride?.model ??
|
||||
categoryConfig?.model ??
|
||||
defaultModel ??
|
||||
"anthropic/claude-opus-4-5",
|
||||
mode: "primary" as const,
|
||||
prompt: PROMETHEUS_SYSTEM_PROMPT,
|
||||
permission: PROMETHEUS_PERMISSION,
|
||||
description: `${configAgent?.plan?.description ?? "Plan agent"} (Prometheus - OhMyOpenCode)`,
|
||||
color: (configAgent?.plan?.color as string) ?? "#FF6347",
|
||||
// Apply category properties (temperature, top_p, tools, etc.)
|
||||
...(categoryConfig?.temperature !== undefined
|
||||
? { temperature: categoryConfig.temperature }
|
||||
: {}),
|
||||
...(categoryConfig?.top_p !== undefined
|
||||
? { top_p: categoryConfig.top_p }
|
||||
: {}),
|
||||
...(categoryConfig?.maxTokens !== undefined
|
||||
? { maxTokens: categoryConfig.maxTokens }
|
||||
: {}),
|
||||
...(categoryConfig?.tools ? { tools: categoryConfig.tools } : {}),
|
||||
...(categoryConfig?.thinking ? { thinking: categoryConfig.thinking } : {}),
|
||||
...(categoryConfig?.reasoningEffort !== undefined
|
||||
? { reasoningEffort: categoryConfig.reasoningEffort }
|
||||
: {}),
|
||||
...(categoryConfig?.textVerbosity !== undefined
|
||||
? { textVerbosity: categoryConfig.textVerbosity }
|
||||
: {}),
|
||||
};
|
||||
|
||||
agentConfig["Prometheus (Planner)"] = prometheusOverride
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user