Skip to content

fix(opencode): add configurable timeout to Task tool#36755

Open
rajarshighoshal wants to merge 4 commits into
anomalyco:devfrom
rajarshighoshal:task-tool-timeout
Open

fix(opencode): add configurable timeout to Task tool#36755
rajarshighoshal wants to merge 4 commits into
anomalyco:devfrom
rajarshighoshal:task-tool-timeout

Conversation

@rajarshighoshal

Copy link
Copy Markdown

Issue for this PR

Closes #15080
Related: #11865 (same underlying symptom — subagent hangs forever with no way for the caller to recover)

Type of change

  • New feature
  • Bug fix
  • Refactor / code improvement
  • Documentation

What does this PR do?

Adds an optional timeout parameter (milliseconds) to the Task tool, mirroring the Bash tool's existing timeout support (packages/opencode/src/tool/shell.ts) almost line for line:

  • timeout added to the Task tool's parameter schema, typed as PositiveInt (same type Bash uses).
  • If omitted, falls back to a new RuntimeFlags.taskDefaultTimeoutMs (env OPENCODE_EXPERIMENTAL_TASK_DEFAULT_TIMEOUT_MS), defaulting to 5 minutes if that's unset.
  • The existing Effect.raceFirst(background.wait(...), background.waitForPromotion(...)) wait is now raced against an Effect.sleep timeout via Effect.raceAll, same discriminated-result pattern the Bash tool uses.
  • On timeout: cancels the child session (reusing the exact cancel / background.cancel(nextSession.id) calls already used for abort-handling) and fails with a message telling the caller to retry with a larger timeout — consistent with how this file already fails on "Task cancelled" / "Task failed".
  • Negative timeouts are rejected the same way Bash rejects them.

I picked 5 minutes as the fallback default rather than copying Bash's 2-minute default, because subagent tasks are inherently longer-running than shell commands (multi-step exploration/reasoning) — a 2-minute default would misfire on completely normal Task usage. Open to tuning this if maintainers disagree.

task.txt (the tool's prose description) is intentionally left untouched — shell/prompt.ts is the only place that documents timeout in prose (and only there because it dynamically renders the resolved default into the description), and task.txt doesn't document any of its other schema fields in prose either. The per-field JSON schema description carries the docs, same as task_id/command already do.

How did you verify your code works?

  • Added 3 new tests to packages/opencode/test/tool/task.test.ts: timeout terminates the task and cancels the child session, negative timeout is rejected, and RuntimeFlags.taskDefaultTimeoutMs is honored when timeout is omitted. All follow the file's existing stubOps/seed/layer test conventions.
  • bun test test/tool/task.test.ts test/permission-task.test.ts — 65 pass, 0 fail.
  • bun test test/tool/ (full tool suite) — 339 pass, 0 fail, after updating the one wire-shape snapshot (parameters.test.ts.snap) that needed the new timeout field.
  • bun run typecheck in packages/opencode, and the full monorepo bun turbo typecheck (30/30 packages) via the pre-push hook — both clean.
  • oxlint — no new warnings introduced by this change (verified the diff against a full-repo lint pass).

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Task subagents had no timeout, so a hung subagent blocked the parent
session indefinitely with no way to recover. Adds an optional
timeout parameter (milliseconds), a RuntimeFlags-backed default, and
a cancel-and-fail-on-timeout path, mirroring the Bash tool's existing
timeout implementation.

Closes anomalyco#15080
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Potential Duplicate Found

PR #20103: feat(tool): configurable timeout protection for tool and task execution
#20103

Why it's related: This PR appears to address the exact same feature — configurable timeout protection for task execution. The current PR (36755) is implementing task tool timeout, which overlaps directly with the scope of PR #20103.

Please verify the status and content of PR #20103 to confirm whether it was already merged, closed, or abandoned before proceeding with the current implementation.

@rajarshighoshal

Copy link
Copy Markdown
Author

Thanks for the flag. Checked both:

This PR is narrower (task tool only, no global non-task-tool timeout), has no merge conflicts with dev, and passes locally (unit tests + typecheck). The repo's full CI (typecheck/test/nix-eval) requires maintainer approval to run on a first-time contributor's PR, so it hasn't executed yet.

One thing worth flagging regardless of which lands: @maiterth noted on #25141 that some subagent hangs may actually be a permission-prompt (ask) not bubbling up correctly two subagent layers deep — a timeout would mask that case rather than fix it. Worth a maintainer sanity-check on whether that's a separate bug before treating a Task-tool timeout as the full fix.

Happy to help rebase #20103's broader approach onto current dev if a maintainer prefers it — otherwise this one's ready to merge as-is pending CI approval.

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.

[FEATURE]: Add configurable timeout parameter to the Task tool

1 participant