anomalyco / anomalyco/opencode
[FEATURE]: add wait built-in tool with countdown in footer
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
[FEATURE]: add wait built-in tool with countdown in footer
Summary
Add a Core built-in wait tool that blocks for N seconds while publishing
Tool.Progress updates, and render a countdown in the TUI footer instead of
the generic spinner.
Why
Claude Code has a WAIT tool that blocks (in tool-call queue, async to the
agent loop) and shows countdown in footer — useful for:
- CI / deployment wait loops (wait N seconds then check status)
- Avoiding busy-poll
bash: sleep 1; check - First real consumer of the
Tool.Progressevent (currently defined but unused)
We already have all the infrastructure:
Tool.Progressevent schema (packages/schema/src/session-event.ts:331-340)- TUI footer spinner (
packages/tui/src/component/prompt/index.tsx:1515-1594) - App reducer already handles
session.tool.progress(packages/app/src/context/server-session-v2-reducer.ts:276) Tool.make+permission.assertpattern (seewebfetch.ts)Effect.genfor time-based orchestration- Async tool execution via
FiberSet.run(packages/core/src/session/runner/llm.ts:278) —waitruns in parallel with sibling tool calls in the same turn, like all other tools
Proposed contract
Input: { seconds: 1..600, reason?: string }
Output: { waited: number, reason?: string }
Hard cap 600s to discourage wait(seconds=86400) (Claude Code removed wait
after abuse — same model here).
Implementation sketch
packages/core/src/tool/wait.ts— new built-inEffect.genwith 1Hz ticker publishingTool.Progresswith{ remainingSeconds, totalSeconds, reason }instructured/metadatapermission.assert({ action: "wait", resources: [] })— every call requires approval unless allowlisted (same aswebfetch)- Built-in registered in
packages/core/src/tool/builtins.ts+ new location node
packages/tui/src/component/prompt/index.tsx— matchprogress.structured.type === "wait"→⠋ 12s remaining (reason); fallback to generic spinner for non-wait toolspackages/app/src/...—RunningToolPart(or wherever running tool is rendered) reads metadata; ifstructured.type === "wait"show12s remaining. App reducer already passes metadata through (packages/app/src/context/server-session-v2-reducer.ts:282).- Tests: extend
packages/core/test/session-tool-progress.test.tswith wait-specific cases (cap enforcement, permission gating, progress event cadence)
Out of scope (future)
- Stage 3: URL polling source (
wait({ url, expect: 2xx })) - Stage 4: pluggable sources via
opencode.tools.register
Open questions (to resolve during impl)
- How exactly to publish
Tool.Progressfrom insideTool.makeexecute— the publisher lives inrunner/publish-llm-event.ts; need to verify the channel exposed to tool leaves. May need a new lightweightctx.progress.emit(structured)accessor. - Permission resource for
wait(webfetch uses URL; wait has no resource —[]?). - Footer vs timeline rendering trade-off (TUI has both — pick one or both).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read the existing Tool.Progress schema in packages/schema/src/session-event.ts, the webfetch Tool.make and permission.assert pattern, and the footer rendering in packages/tui/src/component/prompt/index.tsx. Trace progress handling through packages/app/src/context/server-session-v2-reducer.ts and tool execution in packages/core/src/session/runner/llm.ts. Done means the wait tool, registration, rendering, permission behavior, and cases in packages/core/test/session-tool-progress.test.ts are defined and tested.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, developer-experience, frontend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100