Skip to content

Commit f9dca8d

Browse files
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 <[email protected]> * fix(test): use actual implementation instead of local duplicate Co-Authored-By: Sisyphus <[email protected]> * 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 <[email protected]> --------- Co-authored-by: Sisyphus <[email protected]>
1 parent 91c490a commit f9dca8d

File tree

2 files changed

+150
-2
lines changed

2 files changed

+150
-2
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { describe, test, expect } from "bun:test"
2+
import { resolveCategoryConfig } from "./config-handler"
3+
import type { CategoryConfig } from "../config/schema"
4+
5+
describe("Prometheus category config resolution", () => {
6+
test("resolves ultrabrain category config", () => {
7+
// #given
8+
const categoryName = "ultrabrain"
9+
10+
// #when
11+
const config = resolveCategoryConfig(categoryName)
12+
13+
// #then
14+
expect(config).toBeDefined()
15+
expect(config?.model).toBe("openai/gpt-5.2")
16+
expect(config?.temperature).toBe(0.1)
17+
})
18+
19+
test("resolves visual-engineering category config", () => {
20+
// #given
21+
const categoryName = "visual-engineering"
22+
23+
// #when
24+
const config = resolveCategoryConfig(categoryName)
25+
26+
// #then
27+
expect(config).toBeDefined()
28+
expect(config?.model).toBe("google/gemini-3-pro-preview")
29+
expect(config?.temperature).toBe(0.7)
30+
})
31+
32+
test("user categories override default categories", () => {
33+
// #given
34+
const categoryName = "ultrabrain"
35+
const userCategories: Record<string, CategoryConfig> = {
36+
ultrabrain: {
37+
model: "google/antigravity-claude-opus-4-5-thinking",
38+
temperature: 0.1,
39+
},
40+
}
41+
42+
// #when
43+
const config = resolveCategoryConfig(categoryName, userCategories)
44+
45+
// #then
46+
expect(config).toBeDefined()
47+
expect(config?.model).toBe("google/antigravity-claude-opus-4-5-thinking")
48+
expect(config?.temperature).toBe(0.1)
49+
})
50+
51+
test("returns undefined for unknown category", () => {
52+
// #given
53+
const categoryName = "nonexistent-category"
54+
55+
// #when
56+
const config = resolveCategoryConfig(categoryName)
57+
58+
// #then
59+
expect(config).toBeUndefined()
60+
})
61+
62+
test("falls back to default when user category has no entry", () => {
63+
// #given
64+
const categoryName = "ultrabrain"
65+
const userCategories: Record<string, CategoryConfig> = {
66+
"visual-engineering": {
67+
model: "custom/visual-model",
68+
},
69+
}
70+
71+
// #when
72+
const config = resolveCategoryConfig(categoryName, userCategories)
73+
74+
// #then
75+
expect(config).toBeDefined()
76+
expect(config?.model).toBe("openai/gpt-5.2")
77+
expect(config?.temperature).toBe(0.1)
78+
})
79+
80+
test("preserves all category properties (temperature, top_p, tools, etc.)", () => {
81+
// #given
82+
const categoryName = "custom-category"
83+
const userCategories: Record<string, CategoryConfig> = {
84+
"custom-category": {
85+
model: "test/model",
86+
temperature: 0.5,
87+
top_p: 0.9,
88+
maxTokens: 32000,
89+
tools: { tool1: true, tool2: false },
90+
},
91+
}
92+
93+
// #when
94+
const config = resolveCategoryConfig(categoryName, userCategories)
95+
96+
// #then
97+
expect(config).toBeDefined()
98+
expect(config?.model).toBe("test/model")
99+
expect(config?.temperature).toBe(0.5)
100+
expect(config?.top_p).toBe(0.9)
101+
expect(config?.maxTokens).toBe(32000)
102+
expect(config?.tools).toEqual({ tool1: true, tool2: false })
103+
})
104+
})

src/plugin-handlers/config-handler.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,23 @@ import type { OhMyOpenCodeConfig } from "../config";
2424
import { log } from "../shared";
2525
import { migrateAgentConfig } from "../shared/permission-compat";
2626
import { PROMETHEUS_SYSTEM_PROMPT, PROMETHEUS_PERMISSION } from "../agents/prometheus-prompt";
27+
import { DEFAULT_CATEGORIES } from "../tools/sisyphus-task/constants";
2728
import type { ModelCacheState } from "../plugin-state";
29+
import type { CategoryConfig } from "../config/schema";
2830

2931
export interface ConfigHandlerDeps {
3032
ctx: { directory: string };
3133
pluginConfig: OhMyOpenCodeConfig;
3234
modelCacheState: ModelCacheState;
3335
}
3436

37+
export function resolveCategoryConfig(
38+
categoryName: string,
39+
userCategories?: Record<string, CategoryConfig>
40+
): CategoryConfig | undefined {
41+
return userCategories?.[categoryName] ?? DEFAULT_CATEGORIES[categoryName];
42+
}
43+
3544
export function createConfigHandler(deps: ConfigHandlerDeps) {
3645
const { ctx, pluginConfig, modelCacheState } = deps;
3746

@@ -173,15 +182,50 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
173182
planConfigWithoutName as Record<string, unknown>
174183
);
175184
const prometheusOverride =
176-
pluginConfig.agents?.["Prometheus (Planner)"];
185+
pluginConfig.agents?.["Prometheus (Planner)"] as
186+
| (Record<string, unknown> & { category?: string; model?: string })
187+
| undefined;
177188
const defaultModel = config.model as string | undefined;
189+
190+
// Resolve full category config (model, temperature, top_p, tools, etc.)
191+
// Apply all category properties when category is specified, but explicit
192+
// overrides (model, temperature, etc.) will take precedence during merge
193+
const categoryConfig = prometheusOverride?.category
194+
? resolveCategoryConfig(
195+
prometheusOverride.category,
196+
pluginConfig.categories
197+
)
198+
: undefined;
199+
178200
const prometheusBase = {
179-
model: defaultModel ?? "anthropic/claude-opus-4-5",
201+
model:
202+
prometheusOverride?.model ??
203+
categoryConfig?.model ??
204+
defaultModel ??
205+
"anthropic/claude-opus-4-5",
180206
mode: "primary" as const,
181207
prompt: PROMETHEUS_SYSTEM_PROMPT,
182208
permission: PROMETHEUS_PERMISSION,
183209
description: `${configAgent?.plan?.description ?? "Plan agent"} (Prometheus - OhMyOpenCode)`,
184210
color: (configAgent?.plan?.color as string) ?? "#FF6347",
211+
// Apply category properties (temperature, top_p, tools, etc.)
212+
...(categoryConfig?.temperature !== undefined
213+
? { temperature: categoryConfig.temperature }
214+
: {}),
215+
...(categoryConfig?.top_p !== undefined
216+
? { top_p: categoryConfig.top_p }
217+
: {}),
218+
...(categoryConfig?.maxTokens !== undefined
219+
? { maxTokens: categoryConfig.maxTokens }
220+
: {}),
221+
...(categoryConfig?.tools ? { tools: categoryConfig.tools } : {}),
222+
...(categoryConfig?.thinking ? { thinking: categoryConfig.thinking } : {}),
223+
...(categoryConfig?.reasoningEffort !== undefined
224+
? { reasoningEffort: categoryConfig.reasoningEffort }
225+
: {}),
226+
...(categoryConfig?.textVerbosity !== undefined
227+
? { textVerbosity: categoryConfig.textVerbosity }
228+
: {}),
185229
};
186230

187231
agentConfig["Prometheus (Planner)"] = prometheusOverride

0 commit comments

Comments
 (0)