PR #1227 incorrectly removed resolved.model from the userModel chain,
assuming it was bypassing the fallback chain. However, resolved.model
contained the category's DEFAULT_CATEGORIES model (e.g., quick ->
claude-haiku-4-5), not the main session model.
Without resolved.model, when connectedProvidersCache is null and
availableModels is empty, category model resolution falls through to
systemDefaultModel (opus) instead of using the category's default.
This fix restores the original priority:
1. User category model override
2. Category default model (from resolved.model)
3. sisyphusJuniorModel
4. Fallback chain
5. System default
* refactor(lsp): migrate to vscode-jsonrpc for improved stability
Replace custom JSON-RPC implementation with vscode-jsonrpc library.
Use MessageConnection with StreamMessageReader/Writer.
Implement Bun↔Node stream bridges for compatibility.
Preserve all existing functionality (warmup, cleanup, capabilities).
Net reduction of ~60 lines while improving protocol handling.
* fix(lsp): clear timeout on successful response to prevent unhandled rejections
---------
Co-authored-by: justsisyphus <justsisyphus@users.noreply.github.com>
When delegate_task uses subagent_type, extract the matched agent's model
object and pass it explicitly to session.prompt/manager.launch. This
ensures the model is always in the correct object format regardless of
how OpenCode handles string→object conversion for plugin-registered
agents.
Closes#1225
* fix(start-work): prevent overwriting session agent if already set; inherit parent model for subagent types
* fix(model): include variant in StoredMessage model structure for better context propagation
* fix(injector): include variant in model structure for hook message injection
- Remove resolved.model from userModel in tools.ts (was bypassing fallback chain)
- Use connected providers cache in model-resolver when availableModels is empty
- Allows proper provider selection (e.g., github-copilot instead of google)
When multimodal-looker agent returns empty/malformed response, the SDK
throws 'JSON Parse error: Unexpected EOF'. This commit adds try-catch
around session.prompt() to provide user-friendly error message with
troubleshooting guidance.
- Add error handling for JSON parse errors with detailed guidance
- Add error handling for generic prompt failures
- Add test cases for both error scenarios
- Block prometheus from delegating to itself via delegate_task
- Grant delegate_task permission to prometheus when called as subagent
- Other subagents still have delegate_task disabled
- Add permission field to look_at and call_omo_agent session.create()
- Match pattern used in delegate_task and background-agent
- Add better error messages for Unauthorized failures
- Provide actionable guidance in error messages
This addresses potential session creation failures by ensuring
consistent session configuration across all tools that create
child sessions.
- Add spyOn for readConnectedProvidersCache to return connected providers
- Tests now work consistently regardless of actual provider cache state
- Fixes CI failures for category variant and unstable agent tests
- Add timing.ts module for test-only timing configuration
- Replace hardcoded wait times with getTimingConfig()
- Enable all previously skipped tests (ralph-loop, session-state, delegate-task)
- Tests now complete in ~2s instead of timing out
- Add permission: [{ permission: 'question', action: 'deny' }] to session.create()
in background-agent and delegate-task for SDK-level blocking
- Add subagent-question-blocker hook as backup layer to intercept question tool
calls in tool.execute.before event
- Ensures subagents cannot ask questions to users and must work autonomously
- Add MANDATORY section for delegate_task(subagent_type='plan') at top of ultrawork prompt
- Establish 'DELEGATE by default, work yourself only when trivial' principle
- Add parallel execution rules with anti-pattern and correct pattern examples
- Remove emoji (checkmark/cross) from PLAN_AGENT_SYSTEM_PREPEND
- Restructure workflow into clear 4-step sequence
Add mandatory sections to PLAN_AGENT_SYSTEM_PREPEND:
- Task Dependency Graph with blockers/dependents/reasons
- Parallel Execution Graph with wave structure
- Category + Skills recommendations per task
- Response format specification with exact structure
Uses ASCII art banners and visual emphasis for critical requirements.
When plan agent (plan/prometheus/planner) is invoked via delegate_task,
automatically prepend a <system> prompt instructing the agent to:
- Launch explore/librarian agents in background to gather context
- Summarize user request and list uncertainties
- Ask clarifying questions until requirements are 100% clear
- Remove mandatory model requirement from plugin initialization
- Allow OpenCode to use its built-in model fallback when user doesn't specify
- Update model-resolver to handle undefined systemDefaultModel
- Remove throw errors in config-handler, utils, atlas, delegate-task
- Add tests for optional model scenarios
Closes#1129
Co-authored-by: justsisyphus <justsisyphus@users.noreply.github.com>
* fix: generate skill/slashcommand tool descriptions synchronously when pre-provided
When skills are passed via options (pre-resolved), build the tool description
synchronously instead of fire-and-forget async. This eliminates the race
condition where the description getter returns the bare prefix before the
async cache-warming microtask completes.
Fixes#1039
* chore: changes by sisyphus-dev-ai
---------
Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
On Windows with Bun v1.3.5 and earlier, spawning LSP servers causes
a segmentation fault crash. This is a known Bun bug fixed in v1.3.6.
Added version check before LSP server spawn that:
- Detects Windows + affected Bun versions (< 1.3.6)
- Throws helpful error with upgrade instructions instead of crashing
- References the Bun issue for users to track
Closes#1047
This ensures that commands defined in src/features/builtin-commands/commands.ts
(like /start-work, /refactor, /init-deep) are visible to the slashcommand tool
and the agent. Previously, only markdown-based commands were discovered.
OpenCode downloads LSP servers (like clangd) to ~/.local/share/opencode/bin,
but isServerInstalled() only checked ~/.config/opencode/bin. This caused
LSP tools to report servers as 'not installed' even when OpenCode had
successfully downloaded them.
Add ~/.local/share/opencode/bin to the detection paths to match OpenCode's
actual behavior.
Co-authored-by: yimingll <yimingll@users.noreply.github.com>
* fix(skill): enforce agent restriction in createSkillTool
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* fix(skill): block restricted skills when agent context missing
Addresses cubic review feedback: previously agent-restricted skills
could be invoked when ctx or ctx.agent was undefined because the
guard only ran when ctx?.agent was truthy.
Changed condition from:
skill.definition.agent && ctx?.agent && skill.definition.agent !== ctx.agent
To:
skill.definition.agent && (!ctx?.agent || skill.definition.agent !== ctx.agent)
This ensures restricted skills are blocked unless the exact matching
agent is present in the context.
---------
Co-authored-by: justsisyphus <justsisyphus@users.noreply.github.com>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Remove Step 3 in model-resolver that forced first fallbackChain entry
even when unavailable, blocking system default fallback
- Add sisyphusJuniorModel option to delegate_task so agents["Sisyphus-Junior"]
model override is respected in category-based delegation
- Update tests to reflect new fallback behavior
- Add variant to ModelResolutionResult return type
- Return variant from matched fallback entry
- Add normalizeModelName() for Claude model hyphen/period differences
- Add transformModelForProvider() for github-copilot model names
- Update delegate-task to use resolved variant (user config takes priority)
- Fix test expectations for new fallback behavior
Apply case-insensitive utilities across agents, delegation, and tool
restrictions. Removes duplicate implementations from agents/utils.ts.
Agent validation now normalizes input to canonical names.
Refresh documentation across all AGENTS.md files and update configuration documentation with latest features.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Minor improvements to background task handling and session manager utilities.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Small fixes to AST-grep constants, tools, and utility functions.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Generate tool description dynamically from available categories and skills. Remove hardcoded DELEGATE_TASK_DESCRIPTION constant. Improve parameter handling with unified 'subagent_type' field replacing 'agent'.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Multiple files were hardcoding ~/.config/opencode paths instead of using
getOpenCodeConfigDir() which respects the OPENCODE_CONFIG_DIR env var.
This broke profile isolation features like OCX ghost mode, where users
set OPENCODE_CONFIG_DIR to a custom path but oh-my-opencode.json and
other configs weren't being read from that location.
Changes:
- plugin-config.ts: Use getOpenCodeConfigDir() directly
- cli/doctor/checks: Use getOpenCodeConfigDir() for auth and config checks
- tools/lsp/config.ts: Use getOpenCodeConfigDir() for LSP config paths
- command loaders: Use getOpenCodeConfigDir() for global command dirs
- hooks: Use getOpenCodeConfigDir() for hook config paths
- config-path.ts: Mark getUserConfigDir() as deprecated
- tests: Ensure OPENCODE_CONFIG_DIR is properly isolated in tests
OpenCode v1.1.30+ added HTTP-based SessionList/Read/Search/Info tools that
require localhost:4096 server. Renamed our tools to PascalCase to override
them with local file-based implementation, fixing 'Unable to connect' errors.