Skip to content

Commit 56c52a3

Browse files
Phase A: SessionConfig/ResumeSessionConfig renames
- on_exit_plan_mode -> on_exit_plan_mode_request (handler kwarg + TypedDict field) - on_auto_mode_switch -> on_auto_mode_switch_request (handler kwarg + TypedDict field) - CopilotSession.get_messages() -> get_events() (returns SessionEvent[], not messages) - ProviderConfig.max_input_tokens -> max_prompt_tokens (matches wire key maxPromptTokens) Mirrors PR #1357 Phase A (TypeScript SDK API review). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 581abad commit 56c52a3

17 files changed

Lines changed: 69 additions & 69 deletions

python/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ asyncio.run(main())
103103
- ✅ Full JSON-RPC protocol support
104104
- ✅ stdio and TCP transports
105105
- ✅ Real-time streaming events
106-
- ✅ Session history with `get_messages()`
106+
- ✅ Session history with `get_events()`
107107
- ✅ Type hints throughout
108108
- ✅ Async/await native
109109
- ✅ Async context manager support for automatic resource cleanup

python/copilot/client.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,8 +1377,8 @@ async def create_session(
13771377
on_event: Callable[[SessionEvent], None] | None = None,
13781378
commands: list[CommandDefinition] | None = None,
13791379
on_elicitation_request: ElicitationHandler | None = None,
1380-
on_exit_plan_mode: ExitPlanModeHandler | None = None,
1381-
on_auto_mode_switch: AutoModeSwitchHandler | None = None,
1380+
on_exit_plan_mode_request: ExitPlanModeHandler | None = None,
1381+
on_auto_mode_switch_request: AutoModeSwitchHandler | None = None,
13821382
create_session_fs_handler: CreateSessionFsHandler | None = None,
13831383
github_token: str | None = None,
13841384
remote_session: RemoteSessionMode | None = None,
@@ -1520,8 +1520,8 @@ async def create_session(
15201520

15211521
# Enable elicitation request callback if handler provided
15221522
payload["requestElicitation"] = bool(on_elicitation_request)
1523-
payload["requestExitPlanMode"] = bool(on_exit_plan_mode)
1524-
payload["requestAutoModeSwitch"] = bool(on_auto_mode_switch)
1523+
payload["requestExitPlanMode"] = bool(on_exit_plan_mode_request)
1524+
payload["requestAutoModeSwitch"] = bool(on_auto_mode_switch_request)
15251525

15261526
# Serialize commands (name + description only) into payload
15271527
if commands:
@@ -1664,10 +1664,10 @@ async def create_session(
16641664
session._register_user_input_handler(on_user_input_request)
16651665
if on_elicitation_request:
16661666
session._register_elicitation_handler(on_elicitation_request)
1667-
if on_exit_plan_mode:
1668-
session._register_exit_plan_mode_handler(on_exit_plan_mode)
1669-
if on_auto_mode_switch:
1670-
session._register_auto_mode_switch_handler(on_auto_mode_switch)
1667+
if on_exit_plan_mode_request:
1668+
session._register_exit_plan_mode_handler(on_exit_plan_mode_request)
1669+
if on_auto_mode_switch_request:
1670+
session._register_auto_mode_switch_handler(on_auto_mode_switch_request)
16711671
if hooks:
16721672
session._register_hooks(hooks)
16731673
if transform_callbacks:
@@ -1756,8 +1756,8 @@ async def resume_session(
17561756
on_event: Callable[[SessionEvent], None] | None = None,
17571757
commands: list[CommandDefinition] | None = None,
17581758
on_elicitation_request: ElicitationHandler | None = None,
1759-
on_exit_plan_mode: ExitPlanModeHandler | None = None,
1760-
on_auto_mode_switch: AutoModeSwitchHandler | None = None,
1759+
on_exit_plan_mode_request: ExitPlanModeHandler | None = None,
1760+
on_auto_mode_switch_request: AutoModeSwitchHandler | None = None,
17611761
create_session_fs_handler: CreateSessionFsHandler | None = None,
17621762
github_token: str | None = None,
17631763
remote_session: RemoteSessionMode | None = None,
@@ -1914,8 +1914,8 @@ async def resume_session(
19141914

19151915
# Enable elicitation request callback if handler provided
19161916
payload["requestElicitation"] = bool(on_elicitation_request)
1917-
payload["requestExitPlanMode"] = bool(on_exit_plan_mode)
1918-
payload["requestAutoModeSwitch"] = bool(on_auto_mode_switch)
1917+
payload["requestExitPlanMode"] = bool(on_exit_plan_mode_request)
1918+
payload["requestAutoModeSwitch"] = bool(on_auto_mode_switch_request)
19191919

19201920
# Serialize commands (name + description only) into payload
19211921
if commands:
@@ -2017,10 +2017,10 @@ async def resume_session(
20172017
session._register_user_input_handler(on_user_input_request)
20182018
if on_elicitation_request:
20192019
session._register_elicitation_handler(on_elicitation_request)
2020-
if on_exit_plan_mode:
2021-
session._register_exit_plan_mode_handler(on_exit_plan_mode)
2022-
if on_auto_mode_switch:
2023-
session._register_auto_mode_switch_handler(on_auto_mode_switch)
2020+
if on_exit_plan_mode_request:
2021+
session._register_exit_plan_mode_handler(on_exit_plan_mode_request)
2022+
if on_auto_mode_switch_request:
2023+
session._register_auto_mode_switch_handler(on_auto_mode_switch_request)
20242024
if hooks:
20252025
session._register_hooks(hooks)
20262026
if transform_callbacks:
@@ -2548,8 +2548,8 @@ def _convert_provider_to_wire_format(
25482548
wire_provider["modelId"] = provider["model_id"]
25492549
if "wire_model" in provider:
25502550
wire_provider["wireModel"] = provider["wire_model"]
2551-
if "max_input_tokens" in provider:
2552-
wire_provider["maxPromptTokens"] = provider["max_input_tokens"]
2551+
if "max_prompt_tokens" in provider:
2552+
wire_provider["maxPromptTokens"] = provider["max_prompt_tokens"]
25532553
if "max_output_tokens" in provider:
25542554
wire_provider["maxOutputTokens"] = provider["max_output_tokens"]
25552555
if "azure" in provider:

python/copilot/session.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,7 @@ class ProviderConfig(TypedDict, total=False):
937937
# triggers conversation compaction before sending a request when the prompt
938938
# (system message, history, tool definitions, user message) would exceed
939939
# this limit.
940-
max_input_tokens: int
940+
max_prompt_tokens: int
941941
# Overrides the resolved model's default max output tokens. When hit, the
942942
# model stops generating and returns a truncated response.
943943
max_output_tokens: int
@@ -1027,9 +1027,9 @@ class SessionConfig(TypedDict, total=False):
10271027
# When provided, the server calls back to this client for form-based UI dialogs.
10281028
on_elicitation_request: ElicitationHandler
10291029
# Handler for exit-plan-mode requests from the server.
1030-
on_exit_plan_mode: ExitPlanModeHandler
1030+
on_exit_plan_mode_request: ExitPlanModeHandler
10311031
# Handler for auto-mode-switch requests from the server.
1032-
on_auto_mode_switch: AutoModeSwitchHandler
1032+
on_auto_mode_switch_request: AutoModeSwitchHandler
10331033
# Handler factory for session-scoped sessionFs operations.
10341034
create_session_fs_handler: CreateSessionFsHandler
10351035

@@ -1117,9 +1117,9 @@ class ResumeSessionConfig(TypedDict, total=False):
11171117
# Handler for elicitation requests from the server.
11181118
on_elicitation_request: ElicitationHandler
11191119
# Handler for exit-plan-mode requests from the server.
1120-
on_exit_plan_mode: ExitPlanModeHandler
1120+
on_exit_plan_mode_request: ExitPlanModeHandler
11211121
# Handler for auto-mode-switch requests from the server.
1122-
on_auto_mode_switch: AutoModeSwitchHandler
1122+
on_auto_mode_switch_request: AutoModeSwitchHandler
11231123
# Handler factory for session-scoped sessionFs operations.
11241124
create_session_fs_handler: CreateSessionFsHandler
11251125

@@ -2252,7 +2252,7 @@ async def _handle_hooks_invoke(self, hook_type: str, input_data: Any) -> Any:
22522252
)
22532253
return None
22542254

2255-
async def get_messages(self) -> list[SessionEvent]:
2255+
async def get_events(self) -> list[SessionEvent]:
22562256
"""
22572257
Retrieve all events and messages from this session's history.
22582258
@@ -2267,7 +2267,7 @@ async def get_messages(self) -> list[SessionEvent]:
22672267
22682268
Example:
22692269
>>> from copilot.generated.session_events import AssistantMessageData
2270-
>>> events = await session.get_messages()
2270+
>>> events = await session.get_events()
22712271
>>> for event in events:
22722272
... match event.data:
22732273
... case AssistantMessageData() as data:

python/e2e/test_error_resilience_e2e.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ async def test_should_throw_when_getting_messages_from_disconnected_session(
3030
await session.disconnect()
3131

3232
with pytest.raises(Exception):
33-
await session.get_messages()
33+
await session.get_events()
3434

3535
async def test_should_handle_double_abort_without_error(self, ctx: E2ETestContext):
3636
session = await ctx.client.create_session(

python/e2e/test_event_fidelity_e2e.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ async def test_should_preserve_message_order_in_getmessages_after_tool_use(
207207
try:
208208
await session.send_and_wait("Read the file 'order.txt' and tell me what the number is.")
209209

210-
messages = await session.get_messages()
210+
messages = await session.get_events()
211211
types = [m.type.value for m in messages]
212212

213213
# Verify complete event ordering contract:

python/e2e/test_mode_handlers_e2e.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ async def test_should_invoke_exit_plan_mode_handler_when_model_uses_tool(
7575
):
7676
exit_plan_mode_requests = []
7777

78-
async def on_exit_plan_mode(request, invocation):
78+
async def on_exit_plan_mode_request(request, invocation):
7979
exit_plan_mode_requests.append(request)
8080
assert invocation["session_id"] == session.session_id
8181
return {
@@ -87,7 +87,7 @@ async def on_exit_plan_mode(request, invocation):
8787
session = await mode_ctx.client.create_session(
8888
github_token=MODE_HANDLER_TOKEN,
8989
on_permission_request=PermissionHandler.approve_all,
90-
on_exit_plan_mode=on_exit_plan_mode,
90+
on_exit_plan_mode_request=on_exit_plan_mode_request,
9191
)
9292

9393
try:
@@ -139,15 +139,15 @@ async def test_should_invoke_auto_mode_switch_handler_when_rate_limited(
139139
):
140140
auto_mode_switch_requests = []
141141

142-
async def on_auto_mode_switch(request, invocation):
142+
async def on_auto_mode_switch_request(request, invocation):
143143
auto_mode_switch_requests.append(request)
144144
assert invocation["session_id"] == session.session_id
145145
return "yes"
146146

147147
session = await mode_ctx.client.create_session(
148148
github_token=MODE_HANDLER_TOKEN,
149149
on_permission_request=PermissionHandler.approve_all,
150-
on_auto_mode_switch=on_auto_mode_switch,
150+
on_auto_mode_switch_request=on_auto_mode_switch_request,
151151
)
152152

153153
try:

python/e2e/test_pending_work_resume_e2e.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ async def blocking_external_tool(args):
481481
)
482482

483483
# Verify resume event: continue_pending_work=False and session_was_active=True
484-
messages = await session2.get_messages()
484+
messages = await session2.get_events()
485485
resume_events = [m for m in messages if isinstance(m.data, SessionResumeData)]
486486
assert len(resume_events) == 1, "Expected exactly one session.resume event"
487487
resume_event = resume_events[0]
@@ -549,7 +549,7 @@ async def test_should_report_continuependingwork_true_in_resume_event(
549549
continue_pending_work=True,
550550
)
551551

552-
messages = await resumed_session.get_messages()
552+
messages = await resumed_session.get_events()
553553
resume_events = [m for m in messages if isinstance(m.data, SessionResumeData)]
554554
assert len(resume_events) == 1, "Expected exactly one session.resume event"
555555
resume_event = resume_events[0]

python/e2e/test_rpc_event_side_effects_e2e.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ async def test_should_emit_snapshot_rewind_event_and_remove_events_on_truncate(
215215
try:
216216
await session.send_and_wait("Say SNAPSHOT_REWIND_TARGET exactly.", timeout=60.0)
217217

218-
events = await session.get_messages()
218+
events = await session.get_events()
219219
user_msgs = [e for e in events if isinstance(e.data, UserMessageData)]
220220
assert len(user_msgs) >= 1
221221
first_user_event_id = str(user_msgs[0].id)
@@ -236,7 +236,7 @@ def on_event(event):
236236
assert evt.data.events_removed >= 1
237237
assert evt.data.up_to_event_id.lower() == first_user_event_id.lower()
238238

239-
messages_after = await session.get_messages()
239+
messages_after = await session.get_events()
240240
assert not any(e.id == user_msgs[0].id for e in messages_after)
241241
except Exception as exc:
242242
if "unhandled method" in str(exc).lower():
@@ -257,7 +257,7 @@ async def test_should_allow_session_use_after_truncate(self, ctx: E2ETestContext
257257
try:
258258
await session.send_and_wait("Say SNAPSHOT_REWIND_TARGET exactly.", timeout=60.0)
259259

260-
events = await session.get_messages()
260+
events = await session.get_events()
261261
user_msgs = [e for e in events if isinstance(e.data, UserMessageData)]
262262
assert len(user_msgs) >= 1
263263
first_user_event_id = str(user_msgs[0].id)

python/e2e/test_rpc_session_state_e2e.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ async def test_should_fork_session_with_persisted_messages(self, ctx: E2ETestCon
171171
assert initial_answer is not None
172172
assert "FORK_SOURCE_ALPHA" in (initial_answer.data.content or "")
173173

174-
source_messages = await session.get_messages()
174+
source_messages = await session.get_events()
175175
source_conversation = _conversation_messages(source_messages)
176176
assert any(
177177
role == "user" and content == source_prompt for role, content in source_conversation
@@ -192,18 +192,18 @@ async def test_should_fork_session_with_persisted_messages(self, ctx: E2ETestCon
192192
on_permission_request=PermissionHandler.approve_all,
193193
)
194194
try:
195-
forked_messages = await forked_session.get_messages()
195+
forked_messages = await forked_session.get_events()
196196
forked_conversation = _conversation_messages(forked_messages)
197197
assert forked_conversation[: len(source_conversation)] == source_conversation
198198

199199
fork_answer = await forked_session.send_and_wait(fork_prompt, timeout=60.0)
200200
assert fork_answer is not None
201201
assert "FORK_CHILD_BETA" in (fork_answer.data.content or "")
202202

203-
source_after_fork = _conversation_messages(await session.get_messages())
203+
source_after_fork = _conversation_messages(await session.get_events())
204204
assert all(content != fork_prompt for _, content in source_after_fork)
205205

206-
fork_after_prompt = _conversation_messages(await forked_session.get_messages())
206+
fork_after_prompt = _conversation_messages(await forked_session.get_events())
207207
assert any(
208208
role == "user" and content == fork_prompt for role, content in fork_after_prompt
209209
)
@@ -241,7 +241,7 @@ async def test_should_handle_forking_session_without_persisted_events(
241241
on_permission_request=PermissionHandler.approve_all,
242242
)
243243
try:
244-
assert _conversation_messages(await forked_session.get_messages()) == []
244+
assert _conversation_messages(await forked_session.get_events()) == []
245245
finally:
246246
await forked_session.disconnect()
247247
finally:
@@ -506,7 +506,7 @@ async def test_should_fork_session_to_event_id_excluding_boundary_event(
506506
await session.send_and_wait(first_prompt, timeout=60.0)
507507
await session.send_and_wait(second_prompt, timeout=60.0)
508508

509-
source_events = await session.get_messages()
509+
source_events = await session.get_events()
510510
second_user_event = next(
511511
(
512512
e
@@ -531,7 +531,7 @@ async def test_should_fork_session_to_event_id_excluding_boundary_event(
531531
on_permission_request=PermissionHandler.approve_all,
532532
)
533533
try:
534-
forked_events = await forked_session.get_messages()
534+
forked_events = await forked_session.get_events()
535535
forked_ids = {str(e.id) for e in forked_events}
536536
assert boundary_event_id not in forked_ids, (
537537
"toEventId is exclusive — boundary event must not be in forked session"

python/e2e/test_rpc_shell_and_fleet_e2e.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ def record_fleet_completion(invocation: ToolInvocation) -> ToolResult:
128128
async def _wait_for_messages(timeout: float = 120.0):
129129
deadline = asyncio.get_event_loop().time() + timeout
130130
while asyncio.get_event_loop().time() < deadline:
131-
messages = await session.get_messages()
131+
messages = await session.get_events()
132132
if any(
133133
isinstance(m.data, AssistantMessageData)
134134
and "fleet task" in (m.data.content or "").lower()

0 commit comments

Comments
 (0)