Skip to content

Commit c252a04

Browse files
Phase B: RuntimeConnection discriminated config + CopilotClientOptions
Mirrors PR #1343 Phase 9 (.NET) and PR #1357 Phase I (TypeScript). Removes the flat `SubprocessConfig` / `ExternalServerConfig` split in favour of a `RuntimeConnection` discriminated hierarchy, with process-management options moved to a new `CopilotClientOptions` dataclass. Public API: * `RuntimeConnection` abstract base with static factories `stdio()`, `tcp()`, `uri()`. * `ChildProcessRuntimeConnection` intermediate base carrying `path` and `args` shared by Stdio + Tcp. * `StdioRuntimeConnection`, `TcpRuntimeConnection`, `UriRuntimeConnection` concrete subclasses; pattern-match / `isinstance` on the class to branch on the transport. * `CopilotClientOptions(connection=..., working_directory=..., log_level=..., env=..., github_token=..., base_directory=..., use_logged_in_user=..., telemetry=..., session_fs=..., session_idle_timeout_seconds=..., enable_remote_sessions=...)`. * `CopilotClient(options=CopilotClientOptions(...) | None, *, auto_start=..., on_list_models=...)`. Renames: * `copilot_home` → `base_directory` * `remote` → `enable_remote_sessions` * `CopilotClient.actual_port` → `CopilotClient.runtime_port` * `CopilotClient.on(...)` → `CopilotClient.on_lifecycle(...)` * `tcp_connection_token` moves off `CopilotClientOptions` and onto the variant: `TcpRuntimeConnection.connection_token` / `UriRuntimeConnection.connection_token` * `use_stdio` bool is gone — the variant class IS the discriminator. Migration: * All hand-written code that previously branched on `isinstance(config, ExternalServerConfig)` now branches on the runtime-connection variant via `isinstance(connection, UriRuntimeConnection)` / `StdioRuntimeConnection` etc., giving proper type narrowing in pyright/mypy without relying on Literal-based tagged-union narrowing. * Samples, scenarios, README, and tests updated in lock-step. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 56c52a3 commit c252a04

61 files changed

Lines changed: 1875 additions & 1520 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

python/README.md

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ asyncio.run(main())
113113
### CopilotClient
114114

115115
```python
116-
from copilot import CopilotClient, SubprocessConfig
116+
from copilot import CopilotClient
117117
from copilot.session import PermissionHandler
118118

119119
async with CopilotClient() as client:
@@ -133,40 +133,44 @@ async with CopilotClient() as client:
133133
> **Note:** For manual lifecycle management, see [Manual Resource Management](#manual-resource-management) above.
134134
135135
```python
136-
from copilot import CopilotClient, ExternalServerConfig
136+
from copilot import CopilotClient, CopilotClientOptions, RuntimeConnection
137137

138138
# Connect to an existing CLI server
139-
client = CopilotClient(ExternalServerConfig(url="localhost:3000"))
139+
client = CopilotClient(
140+
CopilotClientOptions(connection=RuntimeConnection.uri("localhost:3000"))
141+
)
140142
```
141143

142144
**CopilotClient Constructor:**
143145

144146
```python
145147
CopilotClient(
146-
config=None, # SubprocessConfig | ExternalServerConfig | None
148+
options=None, # CopilotClientOptions | None
147149
*,
148-
auto_start=True, # auto-start server on first use
150+
auto_start=True, # auto-start server on first use
149151
on_list_models=None, # custom handler for list_models()
150152
)
151153
```
152154

153-
**SubprocessConfig**spawn a local CLI process:
155+
**CopilotClientOptions**configure the client:
154156

155-
- `cli_path` (str | None): Path to CLI executable (default: `COPILOT_CLI_PATH` env var, or bundled binary)
156-
- `cli_args` (list[str]): Extra arguments for the CLI executable
157-
- `cwd` (str | None): Working directory for CLI process (default: current dir)
158-
- `use_stdio` (bool): Use stdio transport instead of TCP (default: True)
159-
- `port` (int): Server port for TCP mode (default: 0 for random)
160-
- `log_level` (str): Log level (default: "info")
161-
- `env` (dict | None): Environment variables for the CLI process
157+
- `connection` (RuntimeConnection | None): How to reach the runtime. Use
158+
`RuntimeConnection.stdio(...)`, `RuntimeConnection.tcp(...)`, or
159+
`RuntimeConnection.uri(...)`. Defaults to a stdio connection with the bundled binary.
160+
- `working_directory` (str | None): Working directory for the CLI process (default: current dir).
161+
- `log_level` (str): Log level (default: "info").
162+
- `env` (dict | None): Environment variables for the CLI process.
162163
- `github_token` (str | None): GitHub token for authentication. When provided, takes priority over other auth methods.
163-
- `copilot_home` (str | None): Base directory for Copilot data (session state, config, etc.). Sets `COPILOT_HOME` on the spawned CLI process. When `None`, the CLI defaults to `~/.copilot`. Useful in restricted environments where only specific directories are writable. Ignored when using `ExternalServerConfig`.
164+
- `base_directory` (str | None): Base directory for Copilot data (session state, config, etc.). Sets `COPILOT_HOME` on the spawned CLI process. When `None`, the CLI defaults to `~/.copilot`. Useful in restricted environments where only specific directories are writable. Ignored when using a `UriRuntimeConnection`.
164165
- `use_logged_in_user` (bool | None): Whether to use logged-in user for authentication (default: True, but False when `github_token` is provided).
165166
- `telemetry` (dict | None): OpenTelemetry configuration for the CLI process. Providing this enables telemetry — no separate flag needed. See [Telemetry](#telemetry) below.
167+
- `enable_remote_sessions` (bool): Enable remote/cloud session support (default: False).
166168

167-
**ExternalServerConfig** — connect to an existing CLI server:
169+
**RuntimeConnection variants:**
168170

169-
- `url` (str): Server URL (e.g., `"localhost:8080"`, `"http://127.0.0.1:9000"`, or just `"8080"`).
171+
- `RuntimeConnection.stdio(path=None, args=None)` — spawn a local CLI process and talk over stdio.
172+
- `RuntimeConnection.tcp(port=0, connection_token=None, path=None, args=None)` — spawn a local CLI in TCP mode.
173+
- `RuntimeConnection.uri(url, connection_token=None)` — connect to an existing CLI server (e.g. `"localhost:8080"`).
170174

171175
**`CopilotClient.create_session()`:**
172176

@@ -197,10 +201,10 @@ await client.set_foreground_session_id("session-123")
197201
def on_lifecycle(event):
198202
print(f"{event.type}: {event.sessionId}")
199203

200-
unsubscribe = client.on(on_lifecycle)
204+
unsubscribe = client.on_lifecycle(on_lifecycle)
201205

202206
# Subscribe to specific event type
203-
unsubscribe = client.on("session.foreground", lambda e: print(f"Foreground: {e.sessionId}"))
207+
unsubscribe = client.on_lifecycle("session.foreground", lambda e: print(f"Foreground: {e.sessionId}"))
204208

205209
# Later, to stop receiving events:
206210
unsubscribe()
@@ -531,9 +535,9 @@ async with await client.create_session(
531535
The SDK supports OpenTelemetry for distributed tracing. Provide a `telemetry` config to enable trace export and automatic W3C Trace Context propagation.
532536

533537
```python
534-
from copilot import CopilotClient, SubprocessConfig
538+
from copilot import CopilotClient, CopilotClientOptions
535539

536-
client = CopilotClient(SubprocessConfig(
540+
client = CopilotClient(CopilotClientOptions(
537541
telemetry={
538542
"otlp_endpoint": "http://localhost:4318",
539543
},

python/copilot/__init__.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@
55
"""
66

77
from .client import (
8+
ChildProcessRuntimeConnection,
89
CloudSessionOptions,
910
CloudSessionRepository,
1011
CopilotClient,
11-
ExternalServerConfig,
12+
CopilotClientOptions,
1213
ModelCapabilitiesOverride,
1314
ModelLimitsOverride,
1415
ModelSupportsOverride,
1516
ModelVisionLimitsOverride,
1617
RemoteSessionMode,
17-
SubprocessConfig,
18+
RuntimeConnection,
19+
StdioRuntimeConnection,
20+
TcpRuntimeConnection,
21+
UriRuntimeConnection,
1822
)
1923
from .session import (
2024
AutoModeSwitchHandler,
@@ -62,10 +66,12 @@
6266
"AutoModeSwitchHandler",
6367
"AutoModeSwitchRequest",
6468
"AutoModeSwitchResponse",
69+
"ChildProcessRuntimeConnection",
6570
"CommandDefinition",
6671
"CloudSessionOptions",
6772
"CloudSessionRepository",
6873
"CopilotClient",
74+
"CopilotClientOptions",
6975
"CopilotSession",
7076
"CreateSessionFsHandler",
7177
"ElicitationHandler",
@@ -75,14 +81,14 @@
7581
"ExitPlanModeHandler",
7682
"ExitPlanModeRequest",
7783
"ExitPlanModeResult",
78-
"ExternalServerConfig",
7984
"InputOptions",
8085
"ModelCapabilitiesOverride",
8186
"ModelLimitsOverride",
8287
"ModelSupportsOverride",
8388
"ModelVisionLimitsOverride",
8489
"ProviderConfig",
8590
"RemoteSessionMode",
91+
"RuntimeConnection",
8692
"SessionCapabilities",
8793
"SessionFsCapabilities",
8894
"SessionFsConfig",
@@ -93,11 +99,13 @@
9399
"create_session_fs_adapter",
94100
"SessionUiApi",
95101
"SessionUiCapabilities",
96-
"SubprocessConfig",
102+
"StdioRuntimeConnection",
103+
"TcpRuntimeConnection",
97104
"Tool",
98105
"ToolBinaryResult",
99106
"ToolInvocation",
100107
"ToolResult",
108+
"UriRuntimeConnection",
101109
"convert_mcp_call_tool_result",
102110
"define_tool",
103111
]

0 commit comments

Comments
 (0)