feat(opencode): configurable timeout for task tool - #43685
Open
georgeglarson wants to merge 4 commits into
Open
Conversation
Mirror the bash timeout pattern: surface the env var through RuntimeFlags so the Task tool can use it as the default subagent timeout when callers do not pass an explicit value. Co-Authored-By: Claude <noreply@anthropic.com>
Awaiting a subagent with no timeout meant a provider hang, SSE keepalives with no content, or a stalled download would hang the parent session with it. Adds an optional 'timeout' (ms) parameter to the Task tool, mirroring the shell tool's pattern. When the timeout fires, the subagent is cancelled and the tool returns a <task_error> block that includes the task_id so the caller can retry with a larger timeout, narrow scope, or fall back. Default is 10 minutes; overridable via OPENCODE_EXPERIMENTAL_TASK_DEFAULT_TIMEOUT_MS. Timeout only applies to the foreground path -- background tasks already return immediately. Co-Authored-By: Claude <noreply@anthropic.com>
Adds two tests: - timeout fires for a stalled subagent and returns a <task_error> block that carries the task_id, with the subagent session cancelled - a negative timeout fails the execute with an error rather than hanging Co-Authored-By: Claude <noreply@anthropic.com>
The default-10min shape had no opt-out: params.timeout ?? default meant every foreground call was capped and 'wait forever' was unexpressible. 0 now disables the race (param and OPENCODE_EXPERIMENTAL_TASK_DEFAULT_TIMEOUT_MS alike, the latter via a nonNegativeInteger flag), the validation message and <task_error> guidance say so, and a 100ms-delayed prompt proves a 0 timeout does not fire. Validation also moved ahead of the acquireUseRelease setup it short-circuits.
Contributor
|
The following comment was made by an LLM, it may be inaccurate: Found one related PR: PR #20103: feat(tool): configurable timeout protection for tool and task execution This PR is already mentioned in the description of #43685 as the broader patch that stalled. It addresses a similar goal (configurable timeout protection), but takes a wider scope covering both tool and task execution, whereas #43685 is the narrow task-only stopgap. Per the PR description, #20103 remains open but stalled with no maintainer engagement since April 2026, making #43685 a deliberate re-filing of the narrower #25141 against current No other duplicate PRs found for this specific task tool timeout feature. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue for this PR
Closes #15080
Type of change
What does this PR do?
The Task tool awaits its subagent prompt with no timeout. If the
subagent path stalls — provider hang, SSE keepalives with no content —
the parent session hangs with it.
This adds an optional
timeout(ms) parameter to the Task tool,mirroring how
bash.tsalready handles the same problem. Default 10min; the default itself is overridable with
OPENCODE_EXPERIMENTAL_TASK_DEFAULT_TIMEOUT_MS.timeout: 0waitsindefinitely (param and env var alike), so callers that manage their
own cancellation keep an opt-out. When the timeout fires, the
subagent is cancelled and the tool returns a
<task_error>block that includes the
task_idso the caller can retry with alarger timeout, narrow scope, or fall back.
This is a re-file of #25141. That PR was closed as a duplicate of
the broader #20103; #20103 has since stalled (0 reviews, no
maintainer engagement since 2026-04, last update 2026-06-11), so the
narrow patch is being re-filed against current
dev. #20103 remainsopen but stalled — this PR is deliberately the narrow task-only
stopgap, not a substitute. If maintainers prefer the broader patch
and it lands, this should close in favor of it.
The timeout only applies to the foreground path; background tasks
(
background: true) already return immediately to the caller, so atimeout there would be meaningless.
How did you verify your code works?
bun typecheckclean:bun test test/tool/task.test.ts— 23 pass, 0 fail:(20 pre-existing + 3 new: timeout-fires-and-cancels, negative-timeout rejected, timeout-0 waits indefinitely.)
The new timeout test exercises the exact claim: a subagent whose
prompt is
Effect.never(a faithful stand-in for a stalled provider),a 50 ms timeout, asserts the tool returns a
<task_error>block thatcontains the configured duration and the
task_id, that no<task_result>is produced, and that the subagent's cancel side-effectis observed. If the timeout race were removed, this test would hang.
Screenshots / recordings
Not a UI change.
Checklist