Commit Graph

1527 Commits

Author SHA1 Message Date
YeonGyu-Kim 888e54fb9b feat(compaction): add delegated agent sessions section with resume directive
Adds §8 to compaction prompt instructing the LLM to preserve spawned agent
session IDs and resume them post-compaction instead of starting fresh.
Injects actual TaskHistory data when BackgroundManager is available.
2026-02-13 17:40:29 +09:00
YeonGyu-Kim c727800501 feat(background-agent): add TaskHistory class for persistent task tracking
In-memory tracker that survives BackgroundManager's cleanup cycles.
Records agent delegations with defensive copies, MAX 100 cap per parent,
undefined-safe upsert, and newline-sanitized formatForCompaction output.
2026-02-13 17:40:12 +09:00
YeonGyu-Kim 71eadc5a4b fix(doctor): oMoMoMoMo branding, remove providers check, fix comment-checker detection
Rename header to oMoMoMoMo Doctor to match installation guide branding.
Remove providers check entirely — no longer meaningful for diagnostics.
Fix comment-checker detection by resolving @code-yeongyu/comment-checker package path
in addition to PATH lookup.
2026-02-13 17:35:36 +09:00
YeonGyu-Kim fe5c0ad8c2 refactor(doctor): redesign with 3-tier output and consolidated checks
Consolidate 16 separate checks into 5 (system, config, providers, tools, models).
Add 3-tier formatting: default (problems-only), --status (dashboard), --verbose (deep diagnostics).
Read actual loaded plugin version from opencode cache directory.
Check environment variables for provider authentication.
2026-02-13 17:29:38 +09:00
YeonGyu-Kim d16073aa59 refactor: remove redundant subagent-question-blocker hook
Replace PreToolUse hook-based question tool blocking with the existing
tools parameter approach (tools: { question: false }) which physically
removes the tool from the LLM's toolset before inference.

The hook was redundant because every session.prompt() call already passes
question: false via the tools parameter. OpenCode converts this to a
PermissionNext deny rule and deletes the tool from the toolset, preventing
the LLM from even seeing it. The hook only fired after the LLM already
called the tool, wasting tokens.

Changes:
- Remove subagent-question-blocker hook invocation from PreToolUse chain
- Remove hook registration from create-session-hooks.ts
- Delete src/hooks/subagent-question-blocker/ directory (dead code)
- Remove hook from HookNameSchema and barrel export
- Fix sync-executor.ts missing question: false in tools parameter
- Add regression tests for both the removal and the tools parameter
2026-02-13 14:55:46 +09:00
YeonGyu-Kim a26a362ecb fix(tool-execute-before): resolve subagent_type for TUI display
OpenCode TUI reads input.subagent_type to display task type. When
subagent_type was missing (e.g., category-only or session continuation),
TUI showed 'Unknown Task'.

Fix:
- category provided: always set subagent_type to 'sisyphus-junior'
  (previously only when subagent_type was absent)
- session_id continuation: resolve agent from session's first message
- fallback to 'continue' if session has no agent info
2026-02-13 12:02:40 +09:00
YeonGyu-Kim 923b2fa056 feat(plugin): add session agent resolver for subagent_type lookup 2026-02-13 12:02:27 +09:00
YeonGyu-Kim 9c43e10055 perf(comment-checker): add hard process reap and global semaphore to prevent CPU runaway 2026-02-13 11:58:46 +09:00
YeonGyu-Kim 91d96765dc perf(todo-continuation): add cooldown and stagnation cap to prevent re-injection loops 2026-02-13 11:54:32 +09:00
YeonGyu-Kim d381305620 Merge pull request #1794 from solssak/fix/isGptModel-proxy-providers
Expand isGptModel to detect GPT models behind proxy providers
2026-02-13 11:52:59 +09:00
YeonGyu-Kim 68f184a7ea Merge branch 'perf/rules-injector-parse-cache' into dev 2026-02-13 11:47:56 +09:00
YeonGyu-Kim b99ba4f529 perf(rules-injector): add mtime-based parse cache and dirty-write gate 2026-02-13 11:46:45 +09:00
YeonGyu-Kim 06393ef1ae perf(directory-injectors): skip writeFileSync when no new paths injected 2026-02-13 11:44:07 +09:00
HyunJun CHOI 2fa94e8ef8 fix: detect GPT models behind proxy providers (litellm, ollama) in isGptModel
isGptModel only matched openai/ and github-copilot/gpt- prefixes, causing
models like litellm/gpt-5.2 to fall into the Claude code path. This
injected Claude-specific thinking config, which the opencode runtime
translated into a reasoningSummary API parameter — rejected by OpenAI.

Extract model name after provider prefix and match against GPT model
name patterns (gpt-*, o1, o3, o4).

Closes #1788

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-02-13 11:38:00 +09:00
YeonGyu-Kim 00217f5a73 Merge pull request #821 from devxoul/prompt-append-file-uri
feat: add file:// URI support in agent prompt_append
2026-02-13 11:30:27 +09:00
YeonGyu-Kim e9bc78b9a0 feat(agents): add file:// URI support in prompt_append configuration
Port devxoul's PR #821 feature to current codebase structure.
Supports absolute, relative, ~/home paths with percent-encoding.
Gracefully handles malformed URIs and missing files with warnings.

Co-authored-by: devxoul <devxoul@gmail.com>
2026-02-13 11:25:40 +09:00
YeonGyu-Kim a7b5d04990 Merge pull request #1807 from code-yeongyu/fix/skills-sources-schema
fix schema generation and implement skills.sources runtime loading
2026-02-13 11:22:11 +09:00
YeonGyu-Kim 9068fcdbbc fix(skills): normalize windows separators for source globs 2026-02-13 11:17:18 +09:00
YeonGyu-Kim 20ae857869 Merge pull request #1758 from devxoul/lookat-remote-block
Block remote URLs in look_at file_path
2026-02-13 11:08:53 +09:00
YeonGyu-Kim 9adf3bdac5 feat(skills): load config sources in runtime discovery 2026-02-13 11:08:46 +09:00
YeonGyu-Kim 9b53cac570 feat: include subagent in task_metadata when resuming sessions
When delegate-task resumes a session via session_id, the response
task_metadata now includes a subagent field identifying which agent
was running in the resumed session. This allows the parent agent to
know what type of subagent it is continuing.

- sync-continuation: uses resumeAgent extracted from session messages
- background-continuation: uses task.agent from BackgroundTask object
- Gracefully omits subagent when agent info is unavailable
2026-02-12 19:09:15 +09:00
YeonGyu-Kim 7cd5c2dea3 test(background-agent): use createMockTask in session.error tests 2026-02-12 18:26:47 +09:00
YeonGyu-Kim 956d15add0 fix(background-agent): handle session.error and prevent zombie queue starts
Marks background tasks as error on session.error to release concurrency immediately, and skips/removes error tasks from queues to avoid zombie starts.
2026-02-12 18:26:03 +09:00
YeonGyu-Kim e6fcf7c4bb fix(auth): add multi-layer auth injection for desktop app compatibility
Desktop app sets OPENCODE_SERVER_PASSWORD which activates basicAuth on
the server, but the SDK client provided to plugins lacks auth headers.
The previous setConfig-only approach may silently fail depending on SDK
version.

Add belt-and-suspenders fallback chain:
1. setConfig headers (existing)
2. request interceptors
3. fetch wrapper via getConfig/setConfig
4. mutable _config.fetch wrapper
5. top-level client.fetch wrapper

Replace console.warn with structured log() for better diagnostics.
2026-02-12 18:12:54 +09:00
YeonGyu-Kim 1db170baf4 fix(run): pass directory to event.subscribe for session-scoped events
The SSE event stream subscription was missing the directory parameter,
causing the OpenCode server to only emit global events (heartbeat,
connected, toast) but not session-scoped events (session.idle,
session.status, tool.execute, message.updated, message.part.updated).

Without session events:
- hasReceivedMeaningfulWork stays false (no message/tool events)
- mainSessionIdle never updates (no session.idle/status events)
- pollForCompletion either hangs or exits for unrelated reasons

Fix: Pass { directory } to client.event.subscribe(), matching the
pattern already used by client.session.promptAsync().

Also adds a stabilization period (10s) after first meaningful work
as defense-in-depth against early exit race conditions.
2026-02-12 11:52:31 +09:00
YeonGyu-Kim 454acf757c fix: use case-insensitive matching for prometheus agent detection in prometheus-md-only hook
The hook used exact string equality (agentName !== "prometheus") which fails
when display names like "Prometheus (Plan Builder)" are stored in session state.
Replace with case-insensitive substring matching via isPrometheusAgent() helper,
consistent with the pattern used in keyword-detector hook.

Closes #1764 (Bug 3)
2026-02-12 03:36:58 +09:00
YeonGyu-Kim 69494d7e5b fix: improve error message for marketplace plugin commands
- Detect namespaced commands (containing ':') from Claude marketplace plugins
- Provide clear error message explaining marketplace plugins are not supported
- Point users to .claude/commands/ as alternative for custom commands
- Fixes issue where /daplug:run-prompt gave ambiguous 'command not found'

Closes #1682
2026-02-12 03:05:55 +09:00
Jeon Suyeol d33799db9f block remote URLs in look-at file_path validation 2026-02-11 18:50:51 +09:00
YeonGyu-Kim 8bcf9b893c Merge pull request #1754 from code-yeongyu/fix/issue-1745-auto-update-pin
fix: respect user-pinned plugin version, skip auto-update when explicitly pinned
2026-02-11 16:07:57 +09:00
YeonGyu-Kim f64a7112bf fix: guard output.output in tool after-hooks for MCP tools (#1720)
MCP tool responses can have undefined output.output, causing TypeError
crashes in tool.execute.after hooks.

Changes:
- comment-checker/hook.ts: guard output.output with ?? '' before toLowerCase()
- edit-error-recovery/hook.ts: guard output.output with ?? '' before toLowerCase()
- task-resume-info/hook.ts: extract output.output ?? '' into outputText before all string operations
- Added tests for undefined output.output in edit-error-recovery and task-resume-info
2026-02-11 15:49:56 +09:00
YeonGyu-Kim 688528cf99 fix: respect user-pinned plugin version, skip auto-update when explicitly pinned
When a user pins oh-my-opencode to a specific version (e.g., oh-my-opencode@3.4.0),
the auto-update checker now respects that choice and only shows a notification toast
instead of overwriting the pinned version with latest.

- Skip updatePinnedVersion() when pluginInfo.isPinned is true
- Show update-available toast only (notification, no modification)
- Added comprehensive tests for pinned/unpinned/autoUpdate scenarios

Fixes #1745
2026-02-11 15:39:15 +09:00
YeonGyu-Kim 724ba70d1b feat(categories): add disable field to CategoryConfigSchema
Allow individual categories to be disabled via `disable: true` in
config. Introduce shared `mergeCategories()` utility to centralize
category merging and disabled filtering across all 7 consumption sites.
2026-02-11 13:52:20 +09:00
YeonGyu-Kim c611ea3d00 fix(auto-update): revert config pin on install failure to prevent version mismatch
When bun install fails after updating the config pin, the config now shows the
new version but the actual package is the old one. Add revertPinnedVersion() to
roll back the config entry on install failure, keeping config and installed
version in sync.

Ref #1472
2026-02-11 13:52:20 +09:00
YeonGyu-Kim cd0e2e5190 fix(subagent): remove permission.question=deny override that caused zombie sessions
Child session creation was injecting permission: { question: 'deny' } which
conflicted with OpenCode's child session permission handling, causing subagent
sessions to hang with 0 messages after creation (zombie state).

Remove the permission override from all session creators (BackgroundManager,
sync-session-creator, call-omo-agent) and rely on prompt-level tool restrictions
(tools.question=false) to maintain the intended policy.

Closes #1711
2026-02-11 13:52:20 +09:00
YeonGyu-Kim 73c0fc9bb5 feat(atlas): add notepad reading step to boulder verification reminders
Instructs the orchestrator to read subagent notepad files
(.sisyphus/notepads/{planName}/) after task completion, ensuring
learnings, issues, and problems are propagated to subsequent delegations.
2026-02-11 13:52:20 +09:00
YeonGyu-Kim f7436903f0 fix: guard session_ids with optional chaining to prevent crash
boulderState?.session_ids.includes() only guards boulderState, not
session_ids. If boulder.json is corrupted or missing the field,
session_ids is undefined and .includes() crashes silently, losing
subagent results.

Changes:
- readBoulderState: validate parsed JSON is object, default session_ids to []
- atlas hook line 427: boulderState?.session_ids?.includes
- atlas hook line 655: boulderState?.session_ids?.includes
- prometheus-md-only line 93: boulderState?.session_ids?.includes
- appendSessionId: guard with ?. and initialize to [] if missing

Fixes #1672
2026-02-11 13:27:18 +09:00
YeonGyu-Kim ebbb65c770 test: add validation tests for readBoulderState session_ids handling
Add tests for corrupted/incomplete boulder.json:
- null JSON value returns null
- primitive JSON value returns null
- missing session_ids defaults to []
- non-array session_ids defaults to []
- empty object defaults session_ids to []
- appendSessionId with missing session_ids does not crash

Refs #1672
2026-02-11 13:25:39 +09:00
YeonGyu-Kim 6cac55f51e fix(look-at): revert to sync prompt to fix race condition with async polling
df0b9f76 regressed look_at from synchronous prompt (session.prompt) to
async prompt (session.promptAsync) + pollSessionUntilIdle polling. This
introduced a race condition where the poller fires before the server
registers the session as busy, causing it to return immediately with no
messages available.

Fix: restore promptSyncWithModelSuggestionRetry (blocking HTTP call) and
remove polling entirely. Catch prompt errors gracefully and still attempt
to fetch messages, since session.prompt may throw even on success.
2026-02-11 09:59:00 +09:00
YeonGyu-Kim 005f22f20b fix(atlas): await injectBoulderContinuation and handle errors
The async call was fire-and-forget with no error handling. Now properly
awaited with try/catch that logs failures and increments promptFailureCount.
2026-02-11 00:45:51 +09:00
YeonGyu-Kim fdc60bc543 fix(skill-mcp): redact sensitive query params from URLs in error messages
API keys passed as query parameters (exaApiKey, tokens, secrets) were
exposed in thrown error messages. Now replaces them with ***REDACTED***.
2026-02-11 00:45:51 +09:00
YeonGyu-Kim 7b9e37ea71 fix(cli-run): handle retry status type as non-idle in event handlers
Session status 'retry' was unhandled, leaving mainSessionIdle=true
during retries which could cause premature completion detection.
2026-02-11 00:45:51 +09:00
YeonGyu-Kim 38382b02cd fix(config-migration): always apply migration in-memory and track backup success
Migration changes were only applied to rawConfig if file write succeeded,
leaving the running process on stale config. Also stops logging backup
path when the backup copy itself failed.
2026-02-11 00:45:51 +09:00
YeonGyu-Kim 2f24e18567 fix(git-worktree): use trimEnd instead of trim to preserve leading whitespace
Git status porcelain output uses leading spaces for status indicators;
trim() was stripping them which could break parsing.
2026-02-11 00:45:51 +09:00
YeonGyu-Kim 31395d7b0f fix(cli): add backup and crash recovery to auth-plugins config write
Creates .bak before writeFileSync; on failure restores from backup
and returns a descriptive error instead of corrupting the config.
2026-02-11 00:45:51 +09:00
YeonGyu-Kim 95db665ff5 fix(ralph-loop): only scan text parts for completion tags and handle both API shapes
Reasoning parts could contain completion-like text triggering false
positives. Also handles session.messages returning either an array
or {data: [...]} shape.
2026-02-11 00:45:51 +09:00
YeonGyu-Kim a7de6c1ace fix(agents): wire useTaskSystem config flag into Sisyphus and Hephaestus
The experimental.task_system flag was defined in config but never
passed through to agent creation, so the task system prompt switch
was always off.
2026-02-11 00:45:51 +09:00
YeonGyu-Kim 4df19fae0c fix(mcp): restore x-api-key header for EXA websearch alongside query param
The header-based auth was removed during refactoring; some MCP server
implementations require it. Now sends both query param and header.
2026-02-11 00:45:51 +09:00
YeonGyu-Kim 623e456518 fix(atlas): correct plan path from .sisyphus/tasks/*.yaml to .sisyphus/plans/*.md
The verification reminder template was pointing at the wrong directory;
actual plan files are stored under .sisyphus/plans/ as markdown.
2026-02-11 00:45:51 +09:00
YeonGyu-Kim 76def5dac5 fix(model-suggestion-retry): add 120s timeout to promptAsync call
Wraps promptAsync with Promise.race to prevent indefinite hangs
when the interactive prompt never resolves.
2026-02-11 00:45:51 +09:00
YeonGyu-Kim 3bb9b8d7d7 fix(delegate-task): ensure subagentSessions cleanup on all exit paths
Added outer finally block so subagentSessions.delete(syncSessionID)
runs even on early return from sendSyncPrompt error.
2026-02-11 00:45:51 +09:00