fix(python): add timeout parameter to generated RPC methods#581
fix(python): add timeout parameter to generated RPC methods#581Rasaboun wants to merge 3 commits intogithub:mainfrom
Conversation
Every generated async RPC method now accepts an optional `timeout` keyword argument that is forwarded to `JsonRpcClient.request()`. This lets callers override the default 30s timeout for long-running RPCs like `session.fleet.start` without bypassing the typed API. Fixes github#539
Add tests for PlanApi.read (session, no params) and ModelsApi.list (server, no params) to exercise all four codegen branches.
There was a problem hiding this comment.
Pull request overview
This PR updates the Python RPC code generator and regenerated output so every typed RPC method can accept an optional keyword-only timeout argument, forwarding it to JsonRpcClient.request() when provided. This addresses long-running RPCs (notably session.fleet.start) that routinely exceed the client’s default timeout.
Changes:
- Update
scripts/codegen/python.tsto generate RPC methods with*, timeout: Optional[float] = Noneand forward the timeout via a_timeout_kwargshelper. - Regenerate
python/copilot/generated/rpc.pyto include the newtimeoutparameter across all generated RPC methods. - Add Python unit tests validating timeout forwarding behavior for several generated-method shapes.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
scripts/codegen/python.ts |
Adjusts Python RPC codegen to include a timeout kw-only parameter and forward it to the JSON-RPC client. |
python/copilot/generated/rpc.py |
Regenerated output reflecting the new timeout kw-only parameter and forwarding behavior. |
python/test_rpc_timeout.py |
Adds unit tests for timeout forwarding (currently missing coverage for server-scoped methods with params). |
Comments suppressed due to low confidence (1)
python/test_rpc_timeout.py:23
- The class docstring claims there is no “server-scoped with params” method to test, but the generated RPC includes server-scoped methods with params (e.g.,
ToolsApi.list(self, params: ToolsListParams, ...)). This documentation is incorrect and should be updated to reflect the actual API surface.
"""Tests for timeout forwarding across all four codegen branches:
- session-scoped with params
- session-scoped without params
- server-scoped with params (not tested — no server+params method exists yet)
- server-scoped without params
"""
| """Tests for timeout forwarding across all four codegen branches: | ||
| - session-scoped with params | ||
| - session-scoped without params | ||
| - server-scoped with params (not tested — no server+params method exists yet) | ||
| - server-scoped without params | ||
| """ |
There was a problem hiding this comment.
Tests currently cover session+params, session+no-params, and server+no-params branches, but they do not cover the server-scoped + params branch (which exists, e.g., ToolsApi.list(params: ToolsListParams, *, timeout=...)). Add a test that calls a server-scoped method with params and asserts that timeout is forwarded when provided (and omitted when not).
| const lines: string[] = []; | ||
| lines.push(`""" | ||
| AUTO-GENERATED FILE - DO NOT EDIT | ||
| Generated from: api.schema.json | ||
| """ | ||
|
|
||
| from typing import TYPE_CHECKING | ||
| from typing import TYPE_CHECKING, Optional | ||
|
|
||
| if TYPE_CHECKING: | ||
| from ..jsonrpc import JsonRpcClient | ||
|
|
||
| `); | ||
|
|
||
| lines.push(` | ||
| def _timeout_kwargs(timeout: Optional[float]) -> dict: | ||
| """Build keyword arguments for optional timeout forwarding.""" | ||
| if timeout is not None: | ||
| return {"timeout": timeout} | ||
| return {} | ||
|
|
||
| `); |
There was a problem hiding this comment.
The generator adds Optional to the initial from typing import TYPE_CHECKING, Optional, but quicktype also emits from typing import Any, Optional, ... later. This produces redundant imports and places _timeout_kwargs before the main import block in the generated file, which is inconsistent with other generated Python modules (e.g., session_events.py imports first, then helper functions). Consider moving _timeout_kwargs to after the quicktype-generated imports (or otherwise ensuring Optional is only imported once) so the generated preamble stays clean and conventional.
23268e4 to
31ca763
Compare
…test - Move _timeout_kwargs helper after the quicktype-generated import block to avoid duplicate Optional import and keep preamble conventional - Add ToolsApi.list tests covering the server-scoped + params branch - All four codegen branches now have test coverage
|
@brettcannon This sounds good to me. Do you want to check it? |
brettcannon
left a comment
There was a problem hiding this comment.
No red flags for me.
Summary
scripts/codegen/python.tsso every generated RPC method gets an optionaltimeoutkeyword argument forwarded toJsonRpcClient.request()_timeout_kwargshelper in the generated file (placed after quicktype imports to avoid duplicateOptionalimport)python/copilot/generated/rpc.py(not hand-edited)Usage
Motivation
FleetApi.start()inherits a hardcoded 30s timeout fromJsonRpcClient.request(), butsession.fleet.startis a blocking RPC that only returns once the fleet completes — routinely >30s. Users are forced to bypass the typed API.Fixes #539
Note on
fleet.startsemanticssession.fleet.startblocks until the entire fleet completes and always returnsstarted=True, making the return value meaningless. Consider makingfleet.startreturn immediately once the fleet is deployed, and let callers wait viaSESSION_IDLEevents. This would also eliminate the need for large timeouts.Test plan
npm run generate:pythonsucceedsrpc.pydiff:timeoutparam on every method,_timeout_kwargshelper after quicktype importspytest test_rpc_timeout.py)ruff check .clean