fix(tools): make watch_task poll until terminal state - #571
Merged
Conversation
watch_task advertised a poll-until-terminal watch with pollIntervalSeconds and timeoutMinutes controls, but the executor did a single app.inject and returned an immediate snapshot. TERMINAL_TASK_STATES was exported "for the watch_task tool" yet referenced nowhere — the polling was never implemented. Add a dedicated watchTask poller in optio-tool-executor and dispatch to it from executeToolCall. It polls GET /api/tasks/:id every pollIntervalSeconds (clamped to [2s, 60s]) until the task reaches a TERMINAL_TASK_STATES value or timeoutMinutes elapses (clamped to [1m, 30m]). Returns the final observed state on success; on timeout returns the last-observed state clearly flagged as "still <state> after timeout". A non-2xx lookup is surfaced immediately. Also lower the schema timeoutMinutes max to 30 to match the executor cap. Fixes #547
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.
Summary
watch_taskis advertised to the Optio assistant as a long-running watch that polls a task until it reaches a terminal state, honoringpollIntervalSecondsandtimeoutMinutes. In reality the executor did a singleapp.injecttoGET /api/tasks/:idand returned an immediate one-shot snapshot — the poll/timeout params were serialized into a query string that the route ignores.TERMINAL_TASK_STATESwas even exported frompackages/shared/src/optio-tools.tswith the comment "for the watch_task tool", but it was dead code — referenced nowhere. The polling was never implemented.This is the real-poll fix (the preferred option in #547), not a description downgrade.
Changes
apps/api/src/services/optio-tool-executor.ts: new exportedwatchTaskhelper that pollsGET /api/tasks/:ideverypollIntervalSeconds(clamped to[2s, 60s]) until the task's state is inTERMINAL_TASK_STATESortimeoutMinuteselapses (clamped to[1m, 30m]— never blocks longer than the 30m hard cap).{ watch: "terminal", state, polls, task }).{ watch: "timeout", message: "Task still <state> after <n> minute timeout", ... }), reported as a normal (non-error) result so the assistant can relay it.executeToolCallnow dispatcheswatch_taskto this poller instead of the generic one-shot inject path.sleep/now) so tests drive the loop deterministically with no real waits.packages/shared/src/optio-tools.ts: lowered thetimeoutMinutesschemamaximumfrom 60 to 30 to match the executor's hard cap (removes contract drift).TERMINAL_TASK_STATESis now actually used.apps/api/src/services/optio-tool-executor.test.ts: added an 11-casewatchTasksuite — waits through non-terminal states then returns terminal; already-terminal returns immediately; timeout returns last-observed state; poll interval respected and clamped (min/max); non-2xx surfaced immediately; missing id rejected without an API call; dispatch throughexecuteToolCall.Testing
cd apps/api && npx tsc --noEmit— cleanpnpm turbo typecheck— 12/12 passcd packages/shared && npx vitest run— 440 passcd apps/api && npx vitest run— 2177 pass (executor suite now 23 tests)pnpm format:check— cleanFixes #547