Use regex /\.sisyphus[/\\]/i instead of checking first path segment. This fixes Windows paths where ctx.directory is parent of the actual project (e.g., project\.sisyphus\drafts\...).
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Revert messages.transform-only approach (experimental hook unreliable)
- Inject context in chat.message after claudeCodeHooks runs
- Order: keywordDetector → claudeCodeHooks → contextInjector
- Works independently of claude-code-hooks being enabled/disabled
- Ultrawork content now reliably injected to model
- Remove contextInjector call from chat.message hook chain
- Context injection now only happens in messages.transform hook
- This ensures UI displays original user message while model receives prepended context
- Fixes bug where commit message promised clone behavior but implementation mutated directly
Replace brittle string checks with robust path.resolve/relative validation:
- Fix Windows backslash paths (.sisyphus\plans\x.md) being incorrectly blocked
- Fix case-sensitive extension check (.MD now accepted)
- Add workspace confinement (block paths outside root even if containing .sisyphus)
- Block nested .sisyphus directories (only first segment allowed)
- Block path traversal attempts (.sisyphus/../secrets.md)
- Use ALLOWED_EXTENSIONS and ALLOWED_PATH_PREFIX constants (case-insensitive)
The new isAllowedFile() uses Node's path module for cross-platform compatibility
instead of string includes/endsWith which failed on Windows separators.
- keyword-detector now registers keywords to ContextCollector
- context-injector consumes and injects via chat.message hook
- Removed keyword detection logic from claude-code-hooks
- Hook order: keyword-detector → context-injector → claude-code-hooks
- ultrawork now works even when claude-code-hooks is disabled
- Add env var check to getCliConfigDir() for config directory override
- Update detectExistingConfigDir() to include env var path in locations
- Add comprehensive tests (7 test cases)
- Document in README
Closes#627
* fix(lsp): cleanup orphaned LSP servers on session.deleted
When parallel background agent tasks complete, their LSP servers (for
repos cloned to /tmp/) remain running until a 5-minute idle timeout.
This causes memory accumulation with heavy parallel Sisyphus usage,
potentially leading to OOM crashes.
This change adds cleanupTempDirectoryClients() to LSPServerManager
(matching the pattern used by SkillMcpManager.disconnectSession())
and calls it on session.deleted events.
The cleanup targets idle LSP clients (refCount=0) for temporary
directories (/tmp/, /var/folders/) where agent tasks clone repos.
* chore: retrigger CI checks
The author name "Named by [YeonGyu Kim]" in the Sisyphus role section
causes LLMs to sometimes infer Korean language output, even when the
user's locale is en-US.
This happens because the model sees a Korean name in the system prompt
and may interpret it as a signal to respond in Korean.
Removing the author attribution from the runtime prompt fixes this issue.
The attribution is preserved in README, LICENSE, and package.json.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix: background task completion detection and silent notifications
- Fix TS2742 by adding explicit ToolDefinition type annotations
- Add stability detection (3 consecutive stable polls after 10s minimum)
- Remove early continue when sessionStatus is undefined
- Add silent notification system via tool.execute.after hook injection
- Change task retention from 200ms to 5 minutes for background_output retrieval
- Fix formatTaskResult to sort messages by time descending
Fixes hanging background tasks that never complete due to missing sessionStatus.
* fix: improve background task completion detection and message extraction
- Add stability-based completion detection (10s min + 3 stable polls)
- Fix message extraction to recognize 'reasoning' parts from thinking models
- Switch from promptAsync() to prompt() for proper agent initialization
- Remove model parameter from prompt body (use agent's configured model)
- Add fire-and-forget prompt pattern for sisyphus_task sync mode
- Add silent notification via tool.execute.after hook injection
- Fix indentation issues in manager.ts and index.ts
Incorporates fixes from:
- PR #592: Stability detection mechanism
- PR #610: Model parameter passing (partially)
- PR #628: Completion detection improvements
Known limitation: Thinking models (e.g. claude-*-thinking-*) cause
JSON Parse errors in child sessions. Use non-thinking models for
background agents until OpenCode core resolves this.
* fix: add tool_result handling and pendingByParent tracking for resume/external tasks
Addresses code review feedback from PR #638:
P1: Add tool_result type to validateSessionHasOutput() to prevent
false negatives for tool-only background tasks that would otherwise
timeout after 30 minutes despite having valid results.
P2: Add pendingByParent tracking to resume() and registerExternalTask()
to prevent premature 'ALL COMPLETE' notifications when mixing
launched and resumed tasks.
* fix: address code review feedback - log messages, model passthrough, sorting, race condition
- Fix misleading log messages: 'promptAsync' -> 'prompt (fire-and-forget)'
- Restore model passthrough in launch() for Sisyphus category configs
- Fix call-omo-agent sorting: use time.created number instead of String(time)
- Fix race condition: check promptError inside polling loop, not just after 100ms
OpenCode uses @agent-name syntax for agent invocation, not /command.
The /plan command does not exist - it should be @plan to invoke
the Prometheus planner agent.
- Add test for starting new loop while previous loop active (different session)
- Add test for restarting loop in same session
- Verifies startLoop properly overwrites state and resets iteration
When parentAgent is undefined, omit the agent field entirely from
session.prompt body instead of passing undefined. This prevents the
OpenCode SDK from falling back to defaultAgent(), which would change
the parent session's agent context.
Changes:
- manager.ts: Build prompt body conditionally, only include agent/model
when defined
- background-task/tools.ts: Use ctx.agent as primary source for
parentAgent (consistent with sisyphus-task)
- registerExternalTask: Add parentAgent parameter support
- Added tests for agent context preservation scenarios
When user has a prerelease version (e.g., 3.0.0-beta.1) installed
without pinning the version in config (just 'oh-my-opencode' without @version),
auto-update was incorrectly downgrading to the latest stable version.
Now checks if currentVersion is a prerelease before auto-updating,
preventing unintended downgrades regardless of pinning status.
Convert static agent exports to factory functions for consistency:
- Metis: add createMetisAgent(model) factory function
- Update agentSources to use createMetisAgent, createMomusAgent
This ensures model overrides work consistently across all agents.
Previously, orchestrator-sisyphus agent had hardcoded model and didn't
accept model parameter, making config overrides ineffective.
- Add model param to OrchestratorContext interface
- Use ctx?.model ?? DEFAULT_MODEL pattern (consistent with Sisyphus)
- Pass model override from config to createOrchestratorSisyphusAgent
* fix: prevent auto-update from downgrading prerelease/dist-tag versions
The auto-update checker was incorrectly updating pinned prerelease versions
(e.g., 3.0.0-beta.1) and dist-tags (e.g., @beta) to the stable latest version
from npm, effectively downgrading users who opted into beta.
Added isPrereleaseOrDistTag() check that skips auto-update when:
- Version contains '-' (prerelease like 3.0.0-beta.1)
- Version is a dist-tag (non-semver like beta, next, canary)
Fixes#613
* refactor: export version helpers and import in tests
Address review feedback: export isPrereleaseVersion, isDistTag, and
isPrereleaseOrDistTag from index.ts and import them in tests instead
of duplicating the logic.
Add missing agent names to Zod schema:
- BuiltinAgentNameSchema
- OverridableAgentNameSchema
- AgentOverridesSchema
This allows orchestrator-sisyphus and Momus (Plan Reviewer) to be
properly validated in oh-my-opencode.json config files.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>