Skip to content

Conversation

@Gladdonilli
Copy link
Contributor

@Gladdonilli Gladdonilli commented Jan 9, 2026

Summary

  • Fix background tasks that hang indefinitely due to missing sessionStatus in polling loop
  • Add silent notification system that injects completion messages into tool output instead of interrupting chat
  • Fix TypeScript TS2742 errors with explicit ToolDefinition type annotations

Changes

Completion Detection (PR #592 re-implementation)

  • Remove early continue when sessionStatus is undefined - allows fall-through to message-based detection
  • Add stability detection: complete when message count unchanged for 3 consecutive polls (after 10s minimum runtime)
  • Add lastMsgCount and stablePolls fields to BackgroundTask interface
  • Add MIN_STABILITY_TIME_MS constant (10 seconds)

Silent Notification System (new feature)

  • Add PendingNotification interface and pendingNotifications map to BackgroundManager
  • Add hasPendingNotifications() and consumePendingNotifications() methods
  • Replace session.prompt() with storing notifications for later injection
  • Add tool.execute.after hook handler that injects pending notifications into tool output
  • Wire up hook in src/index.ts

Other Fixes

  • Change task retention from 200ms to 5 minutes for background_output retrieval
  • Fix formatTaskResult to sort messages by time descending (matches sync pattern)
  • Add String() wrapper for localeCompare to handle non-string time values
  • Fix TS2742 by adding explicit ToolDefinition type annotations to skill and slashcommand exports

Testing

  • Tested with 8 parallel background tasks (4 quick + 4 explore)
  • All tasks complete in ~14-15 seconds
  • Silent notifications successfully injected into tool output
  • bun run typecheck passes
  • bun run build succeeds

Files Modified

File Change
src/features/background-agent/types.ts Add lastMsgCount, stablePolls fields
src/features/background-agent/manager.ts Add stability detection, silent notification storage, 5-min retention
src/features/background-agent/index.ts Export PendingNotification type
src/hooks/background-notification/index.ts Add tool.execute.after handler
src/index.ts Wire up notification hook
src/tools/background-task/tools.ts Fix formatTaskResult sorting
src/tools/skill/tools.ts Add : ToolDefinition type annotation
src/tools/slashcommand/tools.ts Add : ToolDefinition type annotation

Summary by cubic

Fixes background tasks that could hang and adds silent, inline notifications injected into tool outputs. Improves completion detection, keeps results available longer, and resolves TypeScript typing errors.

  • Bug Fixes

    • Allow message-based completion when sessionStatus is missing.
    • Add stability detection (complete after 3 unchanged polls, after 10s).
    • Retain completed tasks for 5 minutes for background_output retrieval.
    • Sort assistant messages by newest first; handle non-string times safely.
  • New Features

    • Silent notifications: store pending messages and inject them via a tool.execute.after hook (no chat interruption).
    • Export PendingNotification and add hasPendingNotifications/consumePendingNotifications helpers.
    • Add explicit ToolDefinition annotations for skill and slashcommand to fix TS2742.

Written for commit 9e81260. Summary will update on new commits.

- 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.
@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 8 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

ReinaMacCredy added a commit to ReinaMacCredy/oh-my-opencode that referenced this pull request Jan 9, 2026
Apply upstream PR code-yeongyu#628 by @Gladdonilli

- Fix background tasks that hang indefinitely due to missing sessionStatus
- Add silent notification system via tool.execute.after hook injection
- Add stability detection (3 consecutive stable polls after 10s minimum)
- Change task retention from 200ms to 5 minutes for background_output
- Fix formatTaskResult to sort messages by time descending
- Fix TS2742 by adding explicit ToolDefinition type annotations

Co-authored-by: Gladdonilli <tianyi35@illinois.edu>
@Gladdonilli
Copy link
Contributor Author

new alternative method found + more issues identified, moving to a new pr

@Gladdonilli Gladdonilli closed this Jan 9, 2026
Gladdonilli added a commit to Gladdonilli/oh-my-opencode that referenced this pull request Jan 9, 2026
- 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 code-yeongyu#592: Stability detection mechanism
- PR code-yeongyu#610: Model parameter passing (partially)
- PR code-yeongyu#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.
code-yeongyu pushed a commit that referenced this pull request Jan 10, 2026
…ion (#638)

* 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
ReinaMacCredy added a commit to ReinaMacCredy/oh-my-opencode that referenced this pull request Jan 10, 2026
Apply upstream PR code-yeongyu#628 by @Gladdonilli

- Fix background tasks that hang indefinitely due to missing sessionStatus
- Add silent notification system via tool.execute.after hook injection
- Add stability detection (3 consecutive stable polls after 10s minimum)
- Change task retention from 200ms to 5 minutes for background_output
- Fix formatTaskResult to sort messages by time descending
- Fix TS2742 by adding explicit ToolDefinition type annotations

Co-authored-by: Gladdonilli <tianyi35@illinois.edu>
Gladdonilli added a commit to Gladdonilli/oh-my-opencode that referenced this pull request Jan 10, 2026
…ing and sync mode

## Summary

This commit represents the culmination of extensive debugging and refinement
of the background agent and sisyphus_task systems, building upon changes from
PRs code-yeongyu#592, code-yeongyu#610, code-yeongyu#628, code-yeongyu#638, code-yeongyu#648, code-yeongyu#649, code-yeongyu#652, and code-yeongyu#653.

## Investigation Journey

### Initial Problem
Background tasks were getting stuck indefinitely. User config model overrides
were being ignored for certain agent types.

### Root Cause Analysis
1. Discovered validateSessionHasOutput and checkSessionTodos guards were
   blocking completion even when tasks had finished
2. Found that sync mode (run_in_background=false) was NOT passing categoryModel
   to session.prompt(), while async mode was
3. Traced config loading path and found JSONC files weren't being detected
4. Analyzed kdcokenny/opencode-background-agents for reference implementation

### Trial and Error Log

**Attempt 1: Add model to resume() in manager.ts**
- Hypothesis: Resume needs to pass stored model
- Result: REVERTED - PR code-yeongyu#638 intentionally removed this; agent config handles it

**Attempt 2: Add userAgents lookup for subagent_type**
- Hypothesis: Need to look up agent model from user config
- Result: REVERTED - Agent model already applied at creation in config-handler.ts

**Attempt 3: Add categoryModel to sync mode prompt**
- Hypothesis: Sync mode missing model that async mode passes
- Result: SUCCESS - This was the actual bug

**Attempt 4: Add debug logging throughout pipeline**
- Purpose: Trace model flow through config -> agent -> prompt
- Files: 6 files with appendFileSync to omo-debug.log
- Result: Confirmed fixes working, then REMOVED all debug logging

**Attempt 5: Investigate clickable sessions**
- Hypothesis: parentID should make child sessions clickable in UI
- Result: parentID IS passed correctly, but sessions don't appear clickable
- Analysis: kdcokenny uses same approach; may be OpenCode core limitation
- Status: UNRESOLVED - Needs further investigation or OpenCode core change

## Background Agent Completion Detection (PR code-yeongyu#638)

Simplified the completion detection logic that was causing tasks to get stuck:
- Removed overly complex validateSessionHasOutput and checkSessionTodos guards
- Tasks now complete after MIN_IDLE_TIME_MS (5s) elapsed on session.idle event
- Added 15-minute global timeout (MAX_RUN_TIME_MS) to prevent runaway tasks
- Pattern follows kdcokenny/opencode-background-agents reference implementation

## Model Override Architecture (PRs code-yeongyu#610, code-yeongyu#628, code-yeongyu#638)

Established clear separation between category-based and agent-based model handling:

| Path              | Model Source                              |
|-------------------|-------------------------------------------|
| category=X        | Explicit from category config (passed)    |
| subagent_type=X   | Agent's configured model (at creation)    |
| resume            | Agent's configured model (not passed)     |

Key insight from PR code-yeongyu#638: Don't pass model in prompt body for resume/subagent -
let OpenCode use the agent's configured model set at creation time in
config-handler.ts.

## Sync Mode Category Model Fix (NEW)

Fixed critical bug where sync mode (run_in_background=false) with categories
was NOT passing the categoryModel to session.prompt():

  // BEFORE: Model not passed in sync mode
  body: { agent: agentToUse, system: systemContent, ... }

  // AFTER: Model passed when available
  body: { agent: agentToUse, ...(categoryModel ? { model: categoryModel } : {}), ... }

This ensures category model overrides work consistently in both sync and async modes.

## JSONC Config File Support

Extended config file detection to support both .json and .jsonc extensions:
- getUserConfigDir() now checks for oh-my-opencode.jsonc first
- Both cross-platform (~/.config) and Windows (%APPDATA%) paths support JSONC
- Enables comments in config files for better documentation

## Test Improvements

- Increased sync resume test timeout from 5s to 10s
- Test was flaky because timeout = MIN_STABILITY_TIME_MS (race condition)
- Added clarifying comments about timing requirements

## Code Cleanup

- Removed unused 'os' imports from plugin-config.ts and config-handler.ts
- Removed ALL debug logging (hardcoded paths, appendFileSync calls)
- Added PR code-yeongyu#638 reference comments for future maintainers

## Verified Test Results (8/8 category + subagent tests pass)

| Test              | Type        | Mode  | Result |
|-------------------|-------------|-------|--------|
| quick             | category    | async | ✅     |
| ultrabrain        | category    | async | ✅     |
| most-capable      | category    | async | ✅     |
| quick             | category    | sync  | ✅     |
| librarian         | subagent    | async | ✅     |
| Metis             | subagent    | async | ✅     |
| oracle            | subagent    | sync  | ✅     |
| quick + git-master| category    | async | ✅     |

## Known Issues & Future Work

### 1. Explore Agent Hangs on Non-Exploration Tasks
The explore agent hung when given a simple math query (5+5). This is NOT a
regression - explore is a specialized codebase search agent (contextual grep)
designed for queries like 'Where is X implemented?' not general Q&A.

When given non-exploration tasks, it attempts to search for non-existent
patterns and may hang indefinitely due to no max_steps limit.

**Recommendation**: Add max_steps: 10 to explore agent config in future PR.

### 2. Clickable Child Sessions Not Working
Sessions created via sisyphus_task pass parentID correctly, but don't appear
as clickable child sessions in OpenCode's sidebar UI. Investigation showed:
- parentID IS being passed to session.create()
- kdcokenny/opencode-background-agents uses identical approach
- Sessions exist and complete, just not rendered as clickable in UI

**Recommendation**: May require OpenCode core change or UI setting discovery.

### 3. Prometheus Agent Correctly Blocked
Prometheus (Planner) is a primary agent and correctly rejected when called
via sisyphus_task with subagent_type. This is expected behavior - primary
agents should only be invoked directly, not via task delegation.

## Files Changed

- src/features/background-agent/manager.ts - PR code-yeongyu#638 reference comment
- src/tools/sisyphus-task/tools.ts - Sync mode categoryModel fix
- src/tools/sisyphus-task/tools.test.ts - Test timeout increase
- src/shared/config-path.ts - JSONC extension support
- src/plugin-config.ts - Cleanup unused import
- src/plugin-handlers/config-handler.ts - Cleanup unused import
renekris pushed a commit to renekris/oh-my-glm that referenced this pull request Jan 10, 2026
- 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 code-yeongyu#592: Stability detection mechanism
- PR code-yeongyu#610: Model parameter passing (partially)
- PR code-yeongyu#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.
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