Skip to content

Conversation

@imarshallwidjaja
Copy link
Contributor

@imarshallwidjaja imarshallwidjaja commented Jan 10, 2026

Summary

  • Fix Prometheus (Planner) ignoring category configuration and always using hardcoded fallback model
  • Add category-to-model resolution that respects user-defined categories in oh-my-opencode.json

The config schema accepts either model OR category (or both). My fix ensures that when you specify category without model, it correctly resolves the category to get the model. Before the fix, the category field was accepted by the schema but ignored at runtime.

Changes

  • Add resolveModelFromCategoryWithUserOverride() helper function that resolves category names to models (user categories take precedence over defaults)
  • Import DEFAULT_CATEGORIES and CategoryConfig type
  • Update Prometheus agent config building to use resolved category model in priority chain: override.model → resolvedCategoryModel → systemDefault → fallback
  • Add 5 BDD test cases for category resolution logic

Before: Config with "Prometheus (Planner)": { "category": "ultrabrain" } would use anthropic/claude-opus-4-5

After: Same config correctly resolves to openai/gpt-5.2 (from ultrabrain category)

Testing

bun run typecheck
bun test src/plugin-handlers/config-handler.test.ts
bun test
  • 5 new tests in config-handler.test.ts
  • All 962 tests pass
  • Manually rebuilt and used local plugin to test that config is used properly -> You end up with a "GPT 5.2 Medium" Prometheus
{
  "$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json",
  "categories": {
    "ultrabrain": {
      "model": "openai/gpt-5.2",
      "variant": "xhigh",
      "temperature": 0.1
    }
  },
  "agents": {
    "Prometheus (Planner)": {
      "category": "ultrabrain",
      "variant": "medium"
    }
  }
}

Related Issues


Summary by cubic

Fixes Prometheus (Planner) ignoring the category setting by resolving categories to full configs and applying them. When only a category is set in oh-my-opencode.json, the correct model and settings (temperature, tools, etc.) are now used.

  • Bug Fixes
    • Added category config resolver that prefers user categories over defaults.
    • Prometheus config now prioritizes: explicit model → resolved category model → system default → fallback, and applies all category properties with explicit overrides taking precedence.
    • Added 6 tests covering resolution, overrides, fallbacks, and property preservation.

Written for commit 903c189. Summary will update on new commits.

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]>
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files

Confidence score: 3/5

  • Tests in src/plugin-handlers/config-handler.test.ts stub their own resolveModelFromCategoryWithUserOverride, so regressions in the real implementation may slip through unchecked.
  • Overall change feels moderate-risk mainly because coverage on the core function is effectively missing.
  • Pay close attention to src/plugin-handlers/config-handler.test.ts - ensure it exercises the actual implementation instead of a duplicate helper.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/plugin-handlers/config-handler.test.ts">

<violation number="1" location="src/plugin-handlers/config-handler.test.ts:5">
P2: Test defines a local duplicate of `resolveModelFromCategoryWithUserOverride` instead of testing the actual implementation from `config-handler.ts`. This means changes to the real implementation won't be caught by these tests. Consider exporting the function from `config-handler.ts` and importing it here, or test through the public `createConfigHandler` API.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/plugin-handlers/config-handler.ts">

<violation number="1" location="src/plugin-handlers/config-handler.ts:37">
P1: The category resolution logic only resolves the `model` field, ignoring other critical category configuration properties like `temperature`, `top_p`, and `tools` that are defined in `CategoryConfig`. This diverges from the established pattern in `Sisyphus-Junior` (src/agents/sisyphus-junior.ts) where categories apply all relevant settings, and risks running specialized categories like "ultrabrain" (temperature: 0.1) with incorrect default temperatures.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

…heus (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]>
Gladdonilli added a commit to Gladdonilli/oh-my-opencode that referenced this pull request Jan 10, 2026
…ing and sync mode

## Summary

This commit represents the culmination of extensive debugging and refinement
of the background agent and sisyphus_task systems, building upon changes from
PRs code-yeongyu#592, code-yeongyu#610, code-yeongyu#628, code-yeongyu#638, code-yeongyu#648, code-yeongyu#649, code-yeongyu#652, and code-yeongyu#653.

## Investigation Journey

### Initial Problem
Background tasks were getting stuck indefinitely. User config model overrides
were being ignored for certain agent types.

### Root Cause Analysis
1. Discovered validateSessionHasOutput and checkSessionTodos guards were
   blocking completion even when tasks had finished
2. Found that sync mode (run_in_background=false) was NOT passing categoryModel
   to session.prompt(), while async mode was
3. Traced config loading path and found JSONC files weren't being detected
4. Analyzed kdcokenny/opencode-background-agents for reference implementation

### Trial and Error Log

**Attempt 1: Add model to resume() in manager.ts**
- Hypothesis: Resume needs to pass stored model
- Result: REVERTED - PR code-yeongyu#638 intentionally removed this; agent config handles it

**Attempt 2: Add userAgents lookup for subagent_type**
- Hypothesis: Need to look up agent model from user config
- Result: REVERTED - Agent model already applied at creation in config-handler.ts

**Attempt 3: Add categoryModel to sync mode prompt**
- Hypothesis: Sync mode missing model that async mode passes
- Result: SUCCESS - This was the actual bug

**Attempt 4: Add debug logging throughout pipeline**
- Purpose: Trace model flow through config -> agent -> prompt
- Files: 6 files with appendFileSync to omo-debug.log
- Result: Confirmed fixes working, then REMOVED all debug logging

**Attempt 5: Investigate clickable sessions**
- Hypothesis: parentID should make child sessions clickable in UI
- Result: parentID IS passed correctly, but sessions don't appear clickable
- Analysis: kdcokenny uses same approach; may be OpenCode core limitation
- Status: UNRESOLVED - Needs further investigation or OpenCode core change

## Background Agent Completion Detection (PR code-yeongyu#638)

Simplified the completion detection logic that was causing tasks to get stuck:
- Removed overly complex validateSessionHasOutput and checkSessionTodos guards
- Tasks now complete after MIN_IDLE_TIME_MS (5s) elapsed on session.idle event
- Added 15-minute global timeout (MAX_RUN_TIME_MS) to prevent runaway tasks
- Pattern follows kdcokenny/opencode-background-agents reference implementation

## Model Override Architecture (PRs code-yeongyu#610, code-yeongyu#628, code-yeongyu#638)

Established clear separation between category-based and agent-based model handling:

| Path              | Model Source                              |
|-------------------|-------------------------------------------|
| category=X        | Explicit from category config (passed)    |
| subagent_type=X   | Agent's configured model (at creation)    |
| resume            | Agent's configured model (not passed)     |

Key insight from PR code-yeongyu#638: Don't pass model in prompt body for resume/subagent -
let OpenCode use the agent's configured model set at creation time in
config-handler.ts.

## Sync Mode Category Model Fix (NEW)

Fixed critical bug where sync mode (run_in_background=false) with categories
was NOT passing the categoryModel to session.prompt():

  // BEFORE: Model not passed in sync mode
  body: { agent: agentToUse, system: systemContent, ... }

  // AFTER: Model passed when available
  body: { agent: agentToUse, ...(categoryModel ? { model: categoryModel } : {}), ... }

This ensures category model overrides work consistently in both sync and async modes.

## JSONC Config File Support

Extended config file detection to support both .json and .jsonc extensions:
- getUserConfigDir() now checks for oh-my-opencode.jsonc first
- Both cross-platform (~/.config) and Windows (%APPDATA%) paths support JSONC
- Enables comments in config files for better documentation

## Test Improvements

- Increased sync resume test timeout from 5s to 10s
- Test was flaky because timeout = MIN_STABILITY_TIME_MS (race condition)
- Added clarifying comments about timing requirements

## Code Cleanup

- Removed unused 'os' imports from plugin-config.ts and config-handler.ts
- Removed ALL debug logging (hardcoded paths, appendFileSync calls)
- Added PR code-yeongyu#638 reference comments for future maintainers

## Verified Test Results (8/8 category + subagent tests pass)

| Test              | Type        | Mode  | Result |
|-------------------|-------------|-------|--------|
| quick             | category    | async | ✅     |
| ultrabrain        | category    | async | ✅     |
| most-capable      | category    | async | ✅     |
| quick             | category    | sync  | ✅     |
| librarian         | subagent    | async | ✅     |
| Metis             | subagent    | async | ✅     |
| oracle            | subagent    | sync  | ✅     |
| quick + git-master| category    | async | ✅     |

## Known Issues & Future Work

### 1. Explore Agent Hangs on Non-Exploration Tasks
The explore agent hung when given a simple math query (5+5). This is NOT a
regression - explore is a specialized codebase search agent (contextual grep)
designed for queries like 'Where is X implemented?' not general Q&A.

When given non-exploration tasks, it attempts to search for non-existent
patterns and may hang indefinitely due to no max_steps limit.

**Recommendation**: Add max_steps: 10 to explore agent config in future PR.

### 2. Clickable Child Sessions Not Working
Sessions created via sisyphus_task pass parentID correctly, but don't appear
as clickable child sessions in OpenCode's sidebar UI. Investigation showed:
- parentID IS being passed to session.create()
- kdcokenny/opencode-background-agents uses identical approach
- Sessions exist and complete, just not rendered as clickable in UI

**Recommendation**: May require OpenCode core change or UI setting discovery.

### 3. Prometheus Agent Correctly Blocked
Prometheus (Planner) is a primary agent and correctly rejected when called
via sisyphus_task with subagent_type. This is expected behavior - primary
agents should only be invoked directly, not via task delegation.

## Files Changed

- src/features/background-agent/manager.ts - PR code-yeongyu#638 reference comment
- src/tools/sisyphus-task/tools.ts - Sync mode categoryModel fix
- src/tools/sisyphus-task/tools.test.ts - Test timeout increase
- src/shared/config-path.ts - JSONC extension support
- src/plugin-config.ts - Cleanup unused import
- src/plugin-handlers/config-handler.ts - Cleanup unused import
Copy link
Contributor

@jkoelker jkoelker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tested this works as expected.

Image

@code-yeongyu code-yeongyu merged commit f9dca8d into code-yeongyu:dev Jan 12, 2026
3 checks passed
@imarshallwidjaja imarshallwidjaja deleted the fix/resolve-category-to-model-for-Prometheus-(Planner)-agent branch January 13, 2026 00:06
kdcokenny pushed a commit that referenced this pull request Jan 13, 2026
…#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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants