Blocking fixes:
- B1: Return empty restrictions for unknown/custom agents instead of
EXPLORATION_AGENT_DENYLIST, allowing custom agents full tool access
- B2: Use Object.create(null) consistently across all 5 agent-loading
result objects to prevent prototype pollution
- B3: Add code comment documenting custom agent bash access trust model
- B4: Mock getOpenCodeConfigDir in opencode-config-agents-reader tests
to prevent global config dir leakage
Non-blocking fixes:
- N1: Use resolveAgentDefinitionPaths with project boundary enforcement
in opencode-config-agents-reader for path containment
- N2: Add session-scoped 30s TTL cache to resolveCallableAgents to
avoid redundant SDK IPC calls per tool invocation
- N3: Extract shared parseToolsConfig into src/shared/parse-tools-config.ts
replacing 4 duplicated local implementations
- N4: Add .min(1) to AgentDefinitionPathSchema rejecting empty paths
- N5: Add resolve-agent-definition-paths.test.ts covering tilde expansion,
relative paths, boundary enforcement, and null containmentDir
- N6: Validate agent mode against allowed values instead of bare type
assertion in opencode-config-agents-reader
Wave 1 of agent definitions enhancement (PR #2299):
Schema & Configuration:
- Add agent_definitions field to oh-my-opencode config schema
- Support list of file paths to .md or .json agent definition files
- Add to PARTIAL_STRING_ARRAY_KEYS for Set-union merge semantics
- Implement eager path resolution in loadPluginConfig() before merging
Path Resolution:
- Create resolve-agent-definition-paths.ts helper
- User-level paths resolve from ~/.config/opencode/ (no containment)
- Project-level paths resolve from project root (with containment check)
- Homedir expansion, absolute/relative path handling
JSON Agent Loader:
- Create parseJsonAgentFile() for .json/.jsonc agent definitions
- Validate required fields (name, prompt)
- Support tools as string (comma-separated) or array
- Map model via mapClaudeModelToOpenCode()
- Comprehensive test suite (7 test cases, all passing)
Type Extensions:
- Extend AgentScope: add 'definition-file' and 'opencode-config'
- Add AgentJsonDefinition interface for JSON agent schema
All automated checks passing:
- lsp_diagnostics clean on all changed files
- json-agent-loader.test.ts: 7/7 passing
- Full typecheck: zero new errors
- QA evidence saved to .sisyphus/evidence/
- Add legacy plugin startup warning when oh-my-opencode config detected
- Update CLI installer and TUI installer for new package name
- Split monolithic config-manager.test.ts into focused test modules
- Add plugin config detection tests for legacy name fallback
- Update processed-command-store to use plugin-identity constants
- Add claude-code-plugin-loader discovery test for both config names
- Update chat-params and ultrawork-db tests for plugin identity
Part of #2823
- Registry-based model family detection (provider-agnostic)
- Variant and reasoningEffort ladder downgrade logic
- Three-tier resolution: metadata override → family heuristic → unknown drop
- Comprehensive test suite covering all model families
Add support for object-style entries in fallback_models arrays, enabling
per-model configuration of variant, reasoningEffort, temperature, top_p,
maxTokens, and thinking settings.
- Zod schema for FallbackModelObject with full validation
- normalizeFallbackModels() and flattenToFallbackModelStrings() utilities
- Provider-agnostic model resolution pipeline with fallback chain
- Session prompt params state management
- Fallback chain construction with prefix-match lookup
- Integration across delegate-task, background-agent, and plugin layers
Add centralized plugin identity constants to support migration from
oh-my-opencode to oh-my-openagent. Includes both current and legacy
names for backward compatibility.
🤖 Generated with assistance of OhMyOpenCode
- New context-limit-resolver.ts with resolveActualContextLimit() shared helper
- Anthropic provider detection now uses .includes('anthropic') instead of hard-coded IDs
- Both context-window-monitor and dynamic-truncator use the shared resolver
- Added missing test cases: Anthropic+1M disabled+cached limit, non-Anthropic without cache
Implement full fallback_models support across all integration points:
1. Model Resolution Pipeline (src/shared/model-resolution-pipeline.ts)
- Add userFallbackModels to ModelResolutionRequest
- Process user fallback_models before hardcoded fallback chain
- Support both connected provider and availability checking modes
2. Agent Utils (src/agents/utils.ts)
- Update applyModelResolution to accept userFallbackModels
- Inject fallback_models for all builtin agents (sisyphus, oracle, etc.)
- Support both single string and array formats
3. Model Resolver (src/shared/model-resolver.ts)
- Add userFallbackModels to ExtendedModelResolutionInput type
- Pass through to resolveModelPipeline
4. Delegate Task Executor (src/tools/delegate-task/executor.ts)
- Extract category fallback_models configuration
- Pass to model resolution pipeline
- Register session category for runtime-fallback hook
5. Session Category Registry (src/shared/session-category-registry.ts)
- New module: maps sessionID -> category
- Used by runtime-fallback to lookup category fallback_models
- Auto-cleanup support
6. Runtime Fallback Hook (src/hooks/runtime-fallback/index.ts)
- Check SessionCategoryRegistry first for category fallback_models
- Fallback to agent-level configuration
- Import and use SessionCategoryRegistry
Test Results:
- runtime-fallback: 24/24 tests passing
- model-resolver: 46/46 tests passing
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Add src/shared/opencode-storage-paths.ts with consolidated constants
- Update imports in hook-message-injector and session-manager
- Add src/shared/opencode-storage-detection.ts with isSqliteBackend()
- Add OPENCODE_SQLITE_VERSION constant
- Export all from shared/index.ts
- Make id field optional in all Todo interfaces (TodoInfo, Todo, TodoItem)
- Fix null-unsafe comparisons in todo-sync.ts to handle missing ids
- Add test case for todos without id field preservation
- All tests pass and typecheck clean
Add findCaseInsensitive, includesCaseInsensitive, findByNameCaseInsensitive,
and equalsIgnoreCase functions for consistent case-insensitive lookups across
the codebase. Enables 'Oracle', 'oracle', 'ORACLE' to work interchangeably.
Implement resolveModelWithFallback() that tries: 1) user override, 2) fuzzy match from requirements chain against available models, 3) system default. Export new model utilities from shared index.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
BREAKING CHANGE: Model resolution overhauled
- Created centralized model-resolver.ts with priority chain:
userModel → inheritedModel → systemDefaultModel
- Removed model field from all 7 DEFAULT_CATEGORIES entries
- Removed DEFAULT_MODEL constants from 10 agents
- Removed singleton agent exports (use factories instead)
- Made CategoryConfigSchema.model optional
- CLI no longer generates model overrides
- Empty strings treated as unset (uses fallback)
Users must now:
1. Use factory functions (createOracleAgent, etc.) instead of singletons
2. Provide model explicitly or use systemDefaultModel
3. Configure category models explicitly if needed
Fixes model fallback bug where hardcoded defaults overrode
user's OpenCode configured model.
- Add shared/system-directive.ts with SYSTEM_DIRECTIVE_PREFIX constant
- Unify all system message prefixes to [SYSTEM DIRECTIVE: OH-MY-OPENCODE - ...]
- Add isSystemDirective() filter to keyword-detector to skip system messages
- Update prometheus-md-only tests to use new prefix constants
Allow optional model variant config for agents and categories.
Propagate category variants into task model payloads so
category-driven runs inherit provider-specific variants.
Closes: #647