fix: parse waiting_for_user task status and return it from wait() - #8
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces the WAITING_FOR_USER task status to the Python SDK, allowing the wait() and run() methods to stop polling and return control to the caller when user input is required. It also bumps the SDK version to 0.3.2 and adds corresponding unit tests. A review comment identifies an issue in the README documentation snippet where result.task_id is incorrectly used instead of result.info.task_id.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
The backend's task status enum includes waiting_for_user, which the /v1/chat/tasks endpoints can return, but TaskStatus omitted it, so tasks.get()/wait()/run() raised a pydantic ValidationError on any task that paused for user input. - Add WAITING_FOR_USER to TaskStatus. - wait()/run() stop polling and return on waiting_for_user as well as on the terminal states. The status is not terminal, but the task can only advance once this caller sends the next turn via append(), so a passive poller would otherwise spin to timeout. _TERMINAL_STATUSES still mirrors the backend's terminal set (completed, failed) and PAUSED keeps polling. - Document the status and the append-to-resume flow; cover parsing and the wait() return in unit tests.
bb9eea8 to
69e92d9
Compare
rogercloud
left a comment
There was a problem hiding this comment.
Approve
Root-cause fix, not a patch: the backend emits waiting_for_user in the status field, but TaskStatus omitted it, so any task paused for user input crashed the parse layer with a pydantic ValidationError. Adding the enum value is the minimal correct fix.
The terminal-vs-returnable distinction is modeled well: _WAIT_RETURN_STATUSES = _TERMINAL_STATUSES | {WAITING_FOR_USER} cleanly separates "terminal" from "wait() should hand back to the caller". WAITING_FOR_USER is non-terminal but can only advance once this caller append()s the next turn, so a passive poller would otherwise spin to timeout — returning early is correct, while PAUSED rightly keeps polling. The reasoning is documented thoroughly in the docstrings/comments and fits the existing strict-parse style.
Verified locally:
pytest tests/unit/→ 217 passed (+2), matching the PR description.- New tests are meaningful:
test_waiting_for_user_returns_to_callerasserts polling stops exactly when the status appears (2 polls);test_waiting_for_user_acceptedasserts the parse layer no longer raises. - The earlier README finding (
result.task_id→result.info.task_id) is fixed;RunResultexposes onlyoutput/status, so the corrected snippet is right.
No blocking issues. LGTM.
|
Follow-up ownership:
This merged PR remains the client foundation. The follow-ups add no parallel transport-specific client facade and do not require rewriting this PR's history. |
The backend's task status enum includes
waiting_for_user, and the/v1/chat/tasksendpoints serialize it into thestatusfield, butTaskStatusomitted it. Any task that paused for user input madetasks.get()/tasks.wait()/tasks.run()raise a pydanticValidationErrorin the parse layer instead of returning a usable status.Changes
WAITING_FOR_USERtoTaskStatus, matching the backend enum (6 values).wait()/run()stop polling and return theTaskInfoonwaiting_for_useras well as on the terminal states. It is not terminal, but the task can only advance once this caller sends the next turn viaappend(), so a passive poller would otherwise spin to timeout._TERMINAL_STATUSESstill mirrors the backend's terminal set (completed,failed), andPAUSEDkeeps polling (another caller can resume it).wait()return in unit tests.Verification
ruff+mypy --strictclean;pytest217 passed (+2). The added enum value andwait()/run()return are checked against the canonical backend contract.