Skip to content

Commit d4036c5

Browse files
Python: Migrate GitHub Copilot package to SDK 0.2.x (#5107)
* Python: Migrate GitHub Copilot package to SDK 0.2.x Replace all imports from the non-existent copilot.types module with correct SDK 0.2.x module paths (copilot.session, copilot.client, copilot.tools, copilot.generated.session_events). Fix PermissionRequest attribute access from dict-style .get() to dataclass attribute access. Add OTel telemetry support to Copilot samples via configure_otel_providers and document new telemetry environment variables in samples README. * Python: Fix remaining copilot.types import in sample validation script * Python: Include model in default_options for telemetry span attributes * Python: Address review feedback on log_level and session kwargs typing * Python: Scope PR to SDK 0.2.x migration only, remove net-new OTel features - Remove RawGitHubCopilotAgent split and AgentTelemetryLayer inheritance - Remove TelemetryConfig plumbing and OTLP/file telemetry settings - Remove configure_otel_providers() calls from samples - Remove telemetry env var rows from samples README - Retain only: import path fixes, PermissionRequest attribute access fix, log_level default fix, session kwargs typed fix, dependency pin * Python: Update tests for SDK 0.2.x API changes - SubprocessConfig replaces CopilotClientOptions dict - create_session and resume_session now use keyword args - send and send_and_wait take plain string prompt instead of MessageOptions - on_permission_request is always required; deny-all fallback replaces omission * Python: Pin github-copilot-sdk to >=0.2.0,<=0.2.0 Tighten the upper bound from <0.3.0 to <=0.2.0 to avoid pulling in 0.2.1+ which has breaking API changes relative to 0.2.0. The lower bound stays at >=0.2.0 since this migration requires the 0.2.x import paths; 0.1.x would fail at import time. * Python: Pin github-copilot-sdk to >=0.2.1,<=0.2.1 --------- Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
1 parent 790a759 commit d4036c5

12 files changed

Lines changed: 113 additions & 112 deletions

File tree

python/packages/github_copilot/agent_framework_github_copilot/_agent.py

Lines changed: 45 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import logging
88
import sys
99
from collections.abc import AsyncIterable, Awaitable, Callable, MutableMapping, Sequence
10-
from typing import Any, ClassVar, Generic, Literal, TypedDict, cast, overload
10+
from typing import Any, ClassVar, Generic, Literal, TypedDict, overload
1111

1212
from agent_framework import (
1313
AgentMiddlewareTypes,
@@ -29,20 +29,11 @@
2929
from agent_framework.exceptions import AgentException
3030

3131
try:
32-
from copilot import CopilotClient, CopilotSession
32+
from copilot import CopilotClient, CopilotSession, SubprocessConfig
3333
from copilot.generated.session_events import PermissionRequest, SessionEvent, SessionEventType
34-
from copilot.types import (
35-
CopilotClientOptions,
36-
MCPServerConfig,
37-
MessageOptions,
38-
PermissionRequestResult,
39-
ResumeSessionConfig,
40-
SessionConfig,
41-
SystemMessageConfig,
42-
ToolInvocation,
43-
ToolResult,
44-
)
45-
from copilot.types import Tool as CopilotTool
34+
from copilot.session import MCPServerConfig, PermissionRequestResult, SystemMessageConfig
35+
from copilot.tools import Tool as CopilotTool
36+
from copilot.tools import ToolInvocation, ToolResult
4637
except ImportError as _copilot_import_error:
4738
raise ImportError(
4839
"GitHubCopilotAgent requires the 'github-copilot-sdk' package, which is only available on Python 3.11+. "
@@ -64,6 +55,14 @@
6455
logger = logging.getLogger("agent_framework.github_copilot")
6556

6657

58+
def _deny_all_permissions(
59+
_request: PermissionRequest,
60+
_invocation: dict[str, str],
61+
) -> PermissionRequestResult:
62+
"""Default permission handler that denies all requests."""
63+
return PermissionRequestResult()
64+
65+
6766
class GitHubCopilotSettings(TypedDict, total=False):
6867
"""GitHub Copilot model settings.
6968
@@ -274,16 +273,13 @@ async def start(self) -> None:
274273
return
275274

276275
if self._client is None:
277-
client_options: CopilotClientOptions = {}
278-
cli_path = self._settings.get("cli_path")
279-
if cli_path:
280-
client_options["cli_path"] = cli_path
276+
cli_path = self._settings.get("cli_path") or None
277+
log_level = self._settings.get("log_level") or None
281278

282-
log_level = self._settings.get("log_level")
279+
subprocess_kwargs: dict[str, Any] = {"cli_path": cli_path}
283280
if log_level:
284-
client_options["log_level"] = log_level # type: ignore[typeddict-item]
285-
286-
self._client = CopilotClient(client_options if client_options else None)
281+
subprocess_kwargs["log_level"] = log_level
282+
self._client = CopilotClient(SubprocessConfig(**subprocess_kwargs))
287283

288284
try:
289285
await self._client.start()
@@ -407,10 +403,9 @@ async def _run_impl(
407403
prompt = "\n".join([message.text for message in context_messages])
408404
if session_context.instructions:
409405
prompt = "\n".join(session_context.instructions) + "\n" + prompt
410-
message_options = cast(MessageOptions, {"prompt": prompt})
411406

412407
try:
413-
response_event = await copilot_session.send_and_wait(message_options, timeout=timeout)
408+
response_event = await copilot_session.send_and_wait(prompt, timeout=timeout)
414409
except Exception as ex:
415410
raise AgentException(f"GitHub Copilot request failed: {ex}") from ex
416411

@@ -489,7 +484,6 @@ async def _stream_updates(
489484
prompt = "\n".join([message.text for message in context_messages])
490485
if session_context.instructions:
491486
prompt = "\n".join(session_context.instructions) + "\n" + prompt
492-
message_options = cast(MessageOptions, {"prompt": prompt})
493487

494488
queue: asyncio.Queue[AgentResponseUpdate | Exception | None] = asyncio.Queue()
495489

@@ -550,7 +544,7 @@ def event_handler(event: SessionEvent) -> None:
550544
unsubscribe = copilot_session.on(event_handler)
551545

552546
try:
553-
await copilot_session.send(message_options)
547+
await copilot_session.send(prompt)
554548

555549
while (item := await queue.get()) is not None:
556550
if isinstance(item, Exception):
@@ -730,43 +724,35 @@ async def _create_session(
730724
raise RuntimeError("GitHub Copilot client not initialized. Call start() first.")
731725

732726
opts = runtime_options or {}
733-
config: SessionConfig = {"streaming": streaming}
734-
735-
model = opts.get("model") or self._settings.get("model")
736-
if model:
737-
config["model"] = model # type: ignore[typeddict-item]
738-
739-
system_message = opts.get("system_message") or self._default_options.get("system_message")
740-
if system_message:
741-
config["system_message"] = system_message
742-
743-
if self._tools:
744-
config["tools"] = self._prepare_tools(self._tools)
745-
746-
permission_handler = opts.get("on_permission_request") or self._permission_handler
747-
if permission_handler:
748-
config["on_permission_request"] = permission_handler
749-
750-
mcp_servers = opts.get("mcp_servers") or self._mcp_servers
751-
if mcp_servers:
752-
config["mcp_servers"] = mcp_servers
753-
754-
return await self._client.create_session(config)
727+
model = opts.get("model") or self._settings.get("model") or None
728+
system_message = opts.get("system_message") or self._default_options.get("system_message") or None
729+
permission_handler: PermissionHandlerType = (
730+
opts.get("on_permission_request") or self._permission_handler or _deny_all_permissions
731+
)
732+
mcp_servers = opts.get("mcp_servers") or self._mcp_servers or None
733+
tools = self._prepare_tools(self._tools) if self._tools else None
734+
735+
return await self._client.create_session(
736+
on_permission_request=permission_handler,
737+
streaming=streaming,
738+
model=model or None,
739+
system_message=system_message or None,
740+
tools=tools or None,
741+
mcp_servers=mcp_servers or None,
742+
)
755743

756744
async def _resume_session(self, session_id: str, streaming: bool) -> CopilotSession:
757745
"""Resume an existing Copilot session by ID."""
758746
if not self._client:
759747
raise RuntimeError("GitHub Copilot client not initialized. Call start() first.")
760748

761-
config: ResumeSessionConfig = {"streaming": streaming}
762-
763-
if self._tools:
764-
config["tools"] = self._prepare_tools(self._tools)
749+
permission_handler: PermissionHandlerType = self._permission_handler or _deny_all_permissions
750+
tools = self._prepare_tools(self._tools) if self._tools else None
765751

766-
if self._permission_handler:
767-
config["on_permission_request"] = self._permission_handler
768-
769-
if self._mcp_servers:
770-
config["mcp_servers"] = self._mcp_servers
771-
772-
return await self._client.resume_session(session_id, config)
752+
return await self._client.resume_session(
753+
session_id,
754+
on_permission_request=permission_handler,
755+
streaming=streaming,
756+
tools=tools or None,
757+
mcp_servers=self._mcp_servers or None,
758+
)

python/packages/github_copilot/pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ classifiers = [
2424
]
2525
dependencies = [
2626
"agent-framework-core>=1.0.0,<2",
27-
"github-copilot-sdk>=0.1.31,<0.1.33; python_version >= '3.11'",
27+
"github-copilot-sdk>=0.2.1,<=0.2.1; python_version >= '3.11'",
2828
]
2929

3030
[tool.uv]
@@ -102,3 +102,4 @@ interpreter = "posix"
102102
[build-system]
103103
requires = ["flit-core >= 3.11,<4.0"]
104104
build-backend = "flit_core.buildapi"
105+

0 commit comments

Comments
 (0)