Skip to content

feat(slim): Full oh-my-opencode-slim presets system + bug fixes#194

Merged
itsmylife44 merged 5 commits intomainfrom
feature/slim-presets-system
Apr 15, 2026
Merged

feat(slim): Full oh-my-opencode-slim presets system + bug fixes#194
itsmylife44 merged 5 commits intomainfrom
feature/slim-presets-system

Conversation

@itsmylife44
Copy link
Copy Markdown
Owner

@itsmylife44 itsmylife44 commented Apr 15, 2026

Summary

  • Implement complete oh-my-opencode-slim v0.9.12 presets system with all features
  • Fix critical bugs found in Oracle deep review
  • Fix MCP toggle state clobbering bug in dashboard

Changes

New Features (oh-my-opencode-slim)

  • Presets system - Named presets instead of just agents
  • Model array support - string | {id, variant}[] format
  • External model passthrough - Models not in availableModels kept as-is
  • Multiplexer config - Unified tmux + zellij support
  • Interview config - Browser-based Q&A for feature planning
  • Todo continuation - Auto-continue on incomplete todos
  • Provider options - Provider-specific model options
  • Websearch config - { provider: "exa" | "tavily" }
  • retry_on_empty - Retry on silent 0-token responses

Bug Fixes (Oracle Deep Review)

  • manualPlan now excludes council agent (schema compliance)
  • External model passthrough for fallback chains, manualPlan, master_fallback
  • Council requires both master AND presets (schema compliance)
  • Fail-fast when no models available (no more placeholder models)
  • Empty arrays preserved for skills/mcps to allow disabling defaults
  • Truthy checks fixed to !== undefined for optional strings
  • Default arrays cloned to prevent mutation leaks
  • Prototype pollution protection via Object.create(null)
  • interview.outputFolder minLength validation

Bug Fix (Dashboard)

  • MCP toggle clobbering - /api/agent-config now deep merges instead of full replace, preserving MCP states set via /api/user/config

Testing

  • 164 unit tests passing
  • TypeScript typecheck passing

Note

Medium Risk
Medium risk because it rewrites the Slim config generator semantics (model resolution, presets, fallback/manualPlan/council handling) and changes the /api/agent-config persistence behavior to merge stored overrides, which could affect generated configs and user settings.

Overview
Adds a full presets-capable oh-my-opencode-slim config generator (v0.9.12-aligned), including support for named presets, array-style model configs with variants, default per-agent skills/mcps, provider options, unified multiplexer (and legacy tmux conversion), plus new interview, todoContinuation, websearch, and retry_on_empty fields.

Changes model handling to prefix only models found in availableModels (external IDs pass through) across agent models, manualPlan, fallback chains, and council master_fallback, and switches to fail-fast (buildSlimConfig returns null) when no models can be resolved without explicit overrides; council emission is tightened to require both master and non-empty presets.

Fixes dashboard override clobbering by making PUT /api/agent-config fetch and shallow-merge existing stored overrides with incoming updates so unrelated top-level keys (e.g., MCP server config) are preserved; updates/extends unit tests to match the new external-model passthrough and fail-fast behaviors.

Reviewed by Cursor Bugbot for commit bc6031c. Bugbot is set up for automated code reviews on this repo. Configure here.

- Add presets-based config generation (modern oh-my-opencode-slim approach)
- Fix external model overrides being silently ignored (now passed through as-is)
- Fix council presets with only master override being dropped
- Add model array support (string | {id, variant}[])
- Add websearch config support ({ provider: 'exa' | 'tavily' })
- Add multiplexer unified config (tmux + zellij)
- Add interview config for browser-based Q&A flow
- Add todoContinuation for auto-continue on incomplete todos
- Add provider-specific options support
- Add retry_on_empty for silent 0-token responses
- Add default skills/MCPs per agent
- Fix misleading type imports
HIGH priority fixes:
- Fix manualPlan to exclude council agent (schema compliance)
- Fix external model passthrough for fallback chains, manualPlan, master_fallback
- Enforce council requires both master AND presets (schema compliance)
- Remove unresolved placeholder models - fail fast if no models available

MEDIUM priority fixes:
- Allow explicit empty arrays to disable default skills/MCPs
- Fix truthy checks to use !== undefined for optional strings
- Clone default arrays to prevent mutation leaks
- Protect against prototype pollution via Object.create(null)

LOW priority fixes:
- Remove dead code (unreachable agentConfigs.length check)
- Validate interview.outputFolder minLength 1

Update tests to reflect new external model passthrough behavior
The /api/agent-config endpoint was doing full replacement of overrides,
which clobbered state saved by /api/user/config (e.g., MCP toggle states).

Added deepMergeOverrides() helper that:
- Recursively merges nested objects
- Replaces arrays (not merged)
- Preserves fields not being updated

Now both endpoints can coexist without overwriting each other's changes.
Comment thread dashboard/src/lib/config-generators/oh-my-opencode-slim.ts Outdated
Comment thread dashboard/src/app/api/agent-config/route.ts
1. Fix truthy check in processModelConfig (line 76-77)
   - Changed 'item.variant &&' to 'item.variant !== undefined'
   - Consistent with all other variant checks in the file

2. Replace deep merge with shallow merge in agent-config API
   - Deep merge prevented users from removing agent overrides
   - Shallow merge preserves unrelated top-level keys (mcpServers)
   - While fully replacing keys being updated (agents)
@itsmylife44 itsmylife44 merged commit 3587ab4 into main Apr 15, 2026
1 check passed
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit bc6031c. Configure here.

},
update: {
overrides: JSON.parse(JSON.stringify(validated)),
overrides: JSON.parse(JSON.stringify(mergedOverrides)),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Read-modify-write race can still lose MCP state

Medium Severity

The new read-then-write pattern in the PUT handler introduces a TOCTOU race with /api/user/config, which writes to the same agentModelOverride row. If a user toggles an MCP via /api/user/config between the findUnique read and the upsert write here, the MCP change is silently overwritten by stale existingOverrides. This is the same class of data loss the PR intends to fix — now probabilistic instead of deterministic. A database-level atomic merge (e.g., a transaction with row locking or a JSON merge in SQL) would eliminate the window entirely.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit bc6031c. Configure here.

source: Record<string, unknown>
): Record<string, unknown> {
return { ...target, ...source };
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unnecessary wrapper function over simple spread

Low Severity

shallowMergeOverrides is a named function wrapping { ...target, ...source } — a single-expression spread that is universally understood. It's called exactly once. The call site already has a comment explaining the merge intent, making the function's doc-comment redundant. The extra indirection slightly increases cognitive load without adding any abstraction value; inlining the spread at the call site would be clearer.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit bc6031c. Configure here.

itsmylife44 pushed a commit that referenced this pull request Apr 15, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.1.76](dashboard-v0.1.75...dashboard-v0.1.76)
(2026-04-15)


### Features

* **slim:** Full oh-my-opencode-slim presets system + bug fixes
([#194](#194))
([3587ab4](3587ab4))


### Bug Fixes

* add missing oauth-import-normalization module
([c7e56fa](c7e56fa))
* **api:** eliminate race condition with optimistic concurrency
([0a4ee97](0a4ee97))
* force clean checkout and no-cache on self-hosted runner
([f70d672](f70d672))
* refresh buttons now bypass server cache for update checks
([6aa1c53](6aa1c53))
* run tag-contributors for build-existing-tag action
([2cb998c](2cb998c))
* update version.json for build-existing-tag action
([b423665](b423665))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

1 participant