-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Task Description
Add a sync: boolean parameter to the task tool that enables blocking (synchronous) execution alongside our default async mode. When sync: true, the parent agent waits for the child session to complete and receives the result directly — matching upstream's blocking behavior. When sync: false (default), the current async behavior is preserved.
Context
- Upstream (
anomalyco/opencode): Task tool always blocks —await SessionPrompt.prompt()returns full result - Our fork: Task tool is always async —
trackBackgroundTask()dispatches and returnstask_idimmediately - Goal: Support both modes without losing our async default
Why
- Some tasks should block — quick lookups, single-file edits, simple questions
- Upstream-designed PM agents expect blocking behavior — sync mode enables compatibility
- Gives the LLM flexibility to choose the right mode per task
Implementation
File: packages/opencode/src/tool/task.ts
-
Add
syncparameter to the Zod schema:sync: z.boolean().optional().default(false).describe("If true, block until task completes and return result directly. Default false (async).")
-
Branch at the dispatch point (around line 300-334):
sync: true:await SessionPrompt.prompt()directly, extract text result, return it in the tool output (similar to upstream's return format withtask_resulttag)sync: false(default): Current behavior —trackBackgroundTask(), return{ task_id, status: "started" }
-
Sync mode should:
- Still respect the task timeout (
DEFAULT_TASK_TIMEOUT = 10 * 60 * 1000) - Still use task slots for concurrency control
- Release the slot when done (success or failure)
- Propagate abort signals
- NOT use
trackBackgroundTask()or event bus — result goes directly in tool response
- Still respect the task timeout (
-
The
check_tasktool remains unchanged — only relevant for async tasks
File: packages/opencode/src/tool/task.txt
Update the tool description to document the sync parameter so the LLM knows when to use it.
Key Design Decisions
sync: falseis the DEFAULT — our async behavior is preserved as-is- Sync mode bypasses the event bus entirely — no
trackBackgroundTask, no auto-wakeup needed - Sync mode still uses task slots to prevent unbounded concurrency
- Timeout applies to both modes equally
- Session creation (
Session.createNext) is the same for both modes - The
session_idparameter for resuming sessions works with both modes
Related Code
| File | Role |
|---|---|
packages/opencode/src/tool/task.ts |
Main implementation — add sync branch |
packages/opencode/src/tool/task.txt |
Tool description — document sync param |
packages/opencode/src/session/async-tasks.ts |
Async infrastructure — unchanged |
packages/opencode/src/tool/check_task.ts |
Check task tool — unchanged |
Fork Governance — .fork-features/ Updates Required
Update the async-tasks feature in .fork-features/manifest.json:
- Add
"sync"to thecriticalCodearray (to catch if sync mode is accidentally removed during upstream sync) - Add
task.txttomodifiedFilesif not already there - Update
descriptionto mention dual-mode (async default + sync option)
Absorption signals to watch: If upstream adds any async/background task concept, or if upstream adds a sync/mode/blocking parameter to their task tool, our absorption signals should catch it.
Add to upstreamTracking.absorptionSignals:
"sync.*task""blocking.*task""task.*mode"
Quality Gates (Non-Negotiable)
- TDD: Write tests for sync mode before implementing
- Test: sync mode returns result directly (not task_id)
- Test: sync mode respects timeout
- Test: async mode (default) still works as before
- Test: sync mode releases task slot on completion and failure
- Coverage: 80%+ for new sync code path
- Linting: All code passes project linting rules
- Documentation: Update task.txt, update .fork-features/manifest.json
- Local Verification:
bun testpasses,bun test .fork-features/verify.tspasses
Acceptance Criteria
-
sync: trueblocks and returns full result in tool output -
sync: false(default) preserves current async behavior exactly - Task slots enforced for both modes
- Timeout enforced for both modes
- Abort signal propagation works for both modes
- task.txt updated with sync parameter documentation
-
.fork-features/manifest.jsonupdated with new criticalCode markers and absorption signals -
bun test .fork-features/verify.tspasses - All existing tests pass + new sync mode tests
- Binary rebuilt and installed to ~/bin/opencode