Skip to content

fix(python): add timeout parameter to generated RPC methods#581

Open
Rasaboun wants to merge 3 commits intogithub:mainfrom
Rasaboun:fix/python-rpc-timeout-param-v2
Open

fix(python): add timeout parameter to generated RPC methods#581
Rasaboun wants to merge 3 commits intogithub:mainfrom
Rasaboun:fix/python-rpc-timeout-param-v2

Conversation

@Rasaboun
Copy link

@Rasaboun Rasaboun commented Feb 25, 2026

Summary

  • Modifies scripts/codegen/python.ts so every generated RPC method gets an optional timeout keyword argument forwarded to JsonRpcClient.request()
  • Adds a _timeout_kwargs helper in the generated file (placed after quicktype imports to avoid duplicate Optional import)
  • Regenerates python/copilot/generated/rpc.py (not hand-edited)
  • Adds 9 unit tests covering all four codegen branches: session+params, session+no-params, server+params, server+no-params

Usage

# Before (workaround via private API):
result = await session._client.request("session.fleet.start", params, timeout=600.0)

# After (typed API):
result = await session.rpc.fleet.start(params, timeout=600.0)

Motivation

FleetApi.start() inherits a hardcoded 30s timeout from JsonRpcClient.request(), but session.fleet.start is 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.start semantics

session.fleet.start blocks until the entire fleet completes and always returns started=True, making the return value meaningless. Consider making fleet.start return immediately once the fleet is deployed, and let callers wait via SESSION_IDLE events. This would also eliminate the need for large timeouts.

Test plan

  • npm run generate:python succeeds
  • rpc.py diff: timeout param on every method, _timeout_kwargs helper after quicktype imports
  • 9 unit tests pass covering all four codegen branches (pytest test_rpc_timeout.py)
  • ruff check . clean

Copilot AI review requested due to automatic review settings February 25, 2026 11:07
@Rasaboun Rasaboun requested a review from a team as a code owner February 25, 2026 11:07
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.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.ts to generate RPC methods with *, timeout: Optional[float] = None and forward the timeout via a _timeout_kwargs helper.
  • Regenerate python/copilot/generated/rpc.py to include the new timeout parameter 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
    """

Comment on lines 18 to 23
"""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
"""
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copilot uses AI. Check for mistakes.
Comment on lines 166 to 186
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 {}

`);
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
@Rasaboun Rasaboun force-pushed the fix/python-rpc-timeout-param-v2 branch from 23268e4 to 31ca763 Compare February 25, 2026 11:11
…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
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 3 changed files in this pull request and generated no new comments.

@SteveSandersonMS
Copy link
Contributor

@brettcannon This sounds good to me. Do you want to check it?

Copy link
Contributor

@brettcannon brettcannon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No red flags for me.

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.

"FleetApi.start()" uses default 30s timeout but "fleet.start" RPC blocks until fleet completes

4 participants