agent-framework-github-copilot 1.0.0b260127__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Microsoft Corporation.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE
@@ -0,0 +1,37 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-framework-github-copilot
3
+ Version: 1.0.0b260127
4
+ Summary: GitHub Copilot integration for Microsoft Agent Framework.
5
+ Author-email: Microsoft <af-support@microsoft.com>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Typing :: Typed
18
+ License-File: LICENSE
19
+ Requires-Dist: agent-framework-core
20
+ Requires-Dist: github-copilot-sdk>=0.1.0
21
+ Project-URL: homepage, https://aka.ms/agent-framework
22
+ Project-URL: issues, https://github.com/microsoft/agent-framework/issues
23
+ Project-URL: release_notes, https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true
24
+ Project-URL: source, https://github.com/microsoft/agent-framework/tree/main/python
25
+
26
+ # Get Started with Microsoft Agent Framework GitHub Copilot
27
+
28
+ Please install this package via pip:
29
+
30
+ ```bash
31
+ pip install agent-framework-github-copilot --pre
32
+ ```
33
+
34
+ ## GitHub Copilot Agent
35
+
36
+ The GitHub Copilot agent enables integration with GitHub Copilot, allowing you to interact with Copilot's agentic capabilities through the Agent Framework.
37
+
@@ -0,0 +1,11 @@
1
+ # Get Started with Microsoft Agent Framework GitHub Copilot
2
+
3
+ Please install this package via pip:
4
+
5
+ ```bash
6
+ pip install agent-framework-github-copilot --pre
7
+ ```
8
+
9
+ ## GitHub Copilot Agent
10
+
11
+ The GitHub Copilot agent enables integration with GitHub Copilot, allowing you to interact with Copilot's agentic capabilities through the Agent Framework.
@@ -0,0 +1,18 @@
1
+ # Copyright (c) Microsoft. All rights reserved.
2
+
3
+ import importlib.metadata
4
+
5
+ from ._agent import GithubCopilotAgent, GithubCopilotOptions
6
+ from ._settings import GithubCopilotSettings
7
+
8
+ try:
9
+ __version__ = importlib.metadata.version(__name__)
10
+ except importlib.metadata.PackageNotFoundError:
11
+ __version__ = "0.0.0"
12
+
13
+ __all__ = [
14
+ "GithubCopilotAgent",
15
+ "GithubCopilotOptions",
16
+ "GithubCopilotSettings",
17
+ "__version__",
18
+ ]
@@ -0,0 +1,528 @@
1
+ # Copyright (c) Microsoft. All rights reserved.
2
+
3
+ import asyncio
4
+ import contextlib
5
+ import logging
6
+ import sys
7
+ from collections.abc import AsyncIterable, Callable, MutableMapping, Sequence
8
+ from typing import Any, ClassVar, Generic, TypedDict
9
+
10
+ from agent_framework import (
11
+ AgentMiddlewareTypes,
12
+ AgentResponse,
13
+ AgentResponseUpdate,
14
+ AgentThread,
15
+ BaseAgent,
16
+ ChatMessage,
17
+ Content,
18
+ ContextProvider,
19
+ Role,
20
+ normalize_messages,
21
+ )
22
+ from agent_framework._tools import AIFunction, ToolProtocol
23
+ from agent_framework._types import normalize_tools
24
+ from agent_framework.exceptions import ServiceException, ServiceInitializationError
25
+ from copilot import CopilotClient, CopilotSession
26
+ from copilot.generated.session_events import SessionEvent, SessionEventType
27
+ from copilot.types import (
28
+ CopilotClientOptions,
29
+ MCPServerConfig,
30
+ PermissionRequest,
31
+ PermissionRequestResult,
32
+ ResumeSessionConfig,
33
+ SessionConfig,
34
+ ToolInvocation,
35
+ ToolResult,
36
+ )
37
+ from copilot.types import Tool as CopilotTool
38
+ from pydantic import ValidationError
39
+
40
+ from ._settings import GithubCopilotSettings
41
+
42
+ if sys.version_info >= (3, 13):
43
+ from typing import TypeVar
44
+ else:
45
+ from typing_extensions import TypeVar
46
+
47
+
48
+ DEFAULT_TIMEOUT_SECONDS: float = 60.0
49
+ """Default timeout in seconds for Copilot requests."""
50
+
51
+ PermissionHandlerType = Callable[[PermissionRequest, dict[str, str]], PermissionRequestResult]
52
+ """Type for permission request handlers."""
53
+
54
+ logger = logging.getLogger("agent_framework.github_copilot")
55
+
56
+
57
+ class GithubCopilotOptions(TypedDict, total=False):
58
+ """GitHub Copilot-specific options."""
59
+
60
+ instructions: str
61
+ """System message to append to the session."""
62
+
63
+ cli_path: str
64
+ """Path to the Copilot CLI executable. Defaults to GITHUB_COPILOT_CLI_PATH environment variable
65
+ or 'copilot' in PATH."""
66
+
67
+ model: str
68
+ """Model to use (e.g., "gpt-5", "claude-sonnet-4"). Defaults to GITHUB_COPILOT_MODEL environment variable."""
69
+
70
+ timeout: float
71
+ """Request timeout in seconds. Defaults to GITHUB_COPILOT_TIMEOUT environment variable or 60 seconds."""
72
+
73
+ log_level: str
74
+ """CLI log level. Defaults to GITHUB_COPILOT_LOG_LEVEL environment variable."""
75
+
76
+ on_permission_request: PermissionHandlerType
77
+ """Permission request handler.
78
+ Called when Copilot requests permission to perform an action (shell, read, write, etc.).
79
+ Takes a PermissionRequest and context dict, returns PermissionRequestResult.
80
+ If not provided, all permission requests will be denied by default.
81
+ """
82
+
83
+ mcp_servers: dict[str, MCPServerConfig]
84
+ """MCP (Model Context Protocol) server configurations.
85
+ A dictionary mapping server names to their configurations.
86
+ Supports both local (stdio) and remote (HTTP/SSE) servers.
87
+ """
88
+
89
+
90
+ TOptions = TypeVar(
91
+ "TOptions",
92
+ bound=TypedDict, # type: ignore[valid-type]
93
+ default="GithubCopilotOptions",
94
+ covariant=True,
95
+ )
96
+
97
+
98
+ class GithubCopilotAgent(BaseAgent, Generic[TOptions]):
99
+ """A GitHub Copilot Agent.
100
+
101
+ This agent wraps the GitHub Copilot SDK to provide Copilot agentic capabilities
102
+ within the Agent Framework. It supports both streaming and non-streaming responses,
103
+ custom tools, and session management.
104
+
105
+ The agent can be used as an async context manager to ensure proper cleanup:
106
+
107
+ Examples:
108
+ Basic usage:
109
+
110
+ .. code-block:: python
111
+
112
+ async with GithubCopilotAgent() as agent:
113
+ response = await agent.run("Hello, world!")
114
+ print(response)
115
+
116
+ With explicitly typed options:
117
+
118
+ .. code-block:: python
119
+
120
+ from agent_framework_github_copilot import GithubCopilotAgent, GithubCopilotOptions
121
+
122
+ agent: GithubCopilotAgent[GithubCopilotOptions] = GithubCopilotAgent(
123
+ default_options={"model": "claude-sonnet-4", "timeout": 120}
124
+ )
125
+
126
+ With tools:
127
+
128
+ .. code-block:: python
129
+
130
+ def get_weather(city: str) -> str:
131
+ return f"Weather in {city} is sunny"
132
+
133
+
134
+ async with GithubCopilotAgent(tools=[get_weather]) as agent:
135
+ response = await agent.run("What's the weather in Seattle?")
136
+ """
137
+
138
+ AGENT_PROVIDER_NAME: ClassVar[str] = "github.copilot"
139
+
140
+ def __init__(
141
+ self,
142
+ *,
143
+ client: CopilotClient | None = None,
144
+ id: str | None = None,
145
+ name: str | None = None,
146
+ description: str | None = None,
147
+ context_provider: ContextProvider | None = None,
148
+ middleware: Sequence[AgentMiddlewareTypes] | None = None,
149
+ tools: ToolProtocol
150
+ | Callable[..., Any]
151
+ | MutableMapping[str, Any]
152
+ | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]]
153
+ | None = None,
154
+ default_options: TOptions | None = None,
155
+ env_file_path: str | None = None,
156
+ env_file_encoding: str | None = None,
157
+ ) -> None:
158
+ """Initialize the GitHub Copilot Agent.
159
+
160
+ Keyword Args:
161
+ client: Optional pre-configured CopilotClient instance. If not provided,
162
+ a new client will be created using the other parameters.
163
+ id: ID of the GithubCopilotAgent.
164
+ name: Name of the GithubCopilotAgent.
165
+ description: Description of the GithubCopilotAgent.
166
+ context_provider: Context Provider, to be used by the agent.
167
+ middleware: Agent middleware used by the agent.
168
+ tools: Tools to use for the agent. Can be functions, ToolProtocol instances,
169
+ or tool definition dicts. These are converted to Copilot SDK tools internally.
170
+ default_options: Default options for the agent. Can include cli_path, model,
171
+ timeout, log_level, etc.
172
+ env_file_path: Optional path to .env file for loading configuration.
173
+ env_file_encoding: Encoding of the .env file, defaults to 'utf-8'.
174
+
175
+ Raises:
176
+ ServiceInitializationError: If required configuration is missing or invalid.
177
+ """
178
+ super().__init__(
179
+ id=id,
180
+ name=name,
181
+ description=description,
182
+ context_provider=context_provider,
183
+ middleware=list(middleware) if middleware else None,
184
+ )
185
+
186
+ self._client = client
187
+ self._owns_client = client is None
188
+
189
+ # Parse options
190
+ opts: dict[str, Any] = dict(default_options) if default_options else {}
191
+ instructions = opts.pop("instructions", None)
192
+ cli_path = opts.pop("cli_path", None)
193
+ model = opts.pop("model", None)
194
+ timeout = opts.pop("timeout", None)
195
+ log_level = opts.pop("log_level", None)
196
+ on_permission_request: PermissionHandlerType | None = opts.pop("on_permission_request", None)
197
+ mcp_servers: dict[str, MCPServerConfig] | None = opts.pop("mcp_servers", None)
198
+
199
+ try:
200
+ self._settings = GithubCopilotSettings(
201
+ cli_path=cli_path,
202
+ model=model,
203
+ timeout=timeout,
204
+ log_level=log_level,
205
+ env_file_path=env_file_path,
206
+ env_file_encoding=env_file_encoding,
207
+ )
208
+ except ValidationError as ex:
209
+ raise ServiceInitializationError("Failed to create GitHub Copilot settings.", ex) from ex
210
+
211
+ self._instructions = instructions
212
+ self._tools = normalize_tools(tools)
213
+ self._permission_handler = on_permission_request
214
+ self._mcp_servers = mcp_servers
215
+ self._default_options = opts
216
+ self._started = False
217
+
218
+ async def __aenter__(self) -> "GithubCopilotAgent[TOptions]":
219
+ """Start the agent when entering async context."""
220
+ await self.start()
221
+ return self
222
+
223
+ async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
224
+ """Stop the agent when exiting async context."""
225
+ await self.stop()
226
+
227
+ async def start(self) -> None:
228
+ """Start the Copilot client.
229
+
230
+ This method initializes the Copilot client and establishes a connection
231
+ to the Copilot CLI server. It is called automatically when using the
232
+ agent as an async context manager.
233
+
234
+ Raises:
235
+ ServiceException: If the client fails to start.
236
+ """
237
+ if self._started:
238
+ return
239
+
240
+ if self._client is None:
241
+ client_options: CopilotClientOptions = {}
242
+ if self._settings.cli_path:
243
+ client_options["cli_path"] = self._settings.cli_path
244
+ if self._settings.log_level:
245
+ client_options["log_level"] = self._settings.log_level # type: ignore[typeddict-item]
246
+
247
+ self._client = CopilotClient(client_options if client_options else None)
248
+
249
+ try:
250
+ await self._client.start()
251
+ self._started = True
252
+ except Exception as ex:
253
+ raise ServiceException(f"Failed to start GitHub Copilot client: {ex}") from ex
254
+
255
+ async def stop(self) -> None:
256
+ """Stop the Copilot client and clean up resources.
257
+
258
+ Stops the Copilot client if owned by this agent. The client handles
259
+ session cleanup internally. Called automatically when using the agent
260
+ as an async context manager.
261
+ """
262
+ if self._client and self._owns_client:
263
+ with contextlib.suppress(Exception):
264
+ await self._client.stop()
265
+
266
+ self._started = False
267
+
268
+ async def run(
269
+ self,
270
+ messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
271
+ *,
272
+ thread: AgentThread | None = None,
273
+ options: TOptions | None = None,
274
+ **kwargs: Any,
275
+ ) -> AgentResponse:
276
+ """Get a response from the agent.
277
+
278
+ This method returns the final result of the agent's execution
279
+ as a single AgentResponse object. The caller is blocked until
280
+ the final result is available.
281
+
282
+ Args:
283
+ messages: The message(s) to send to the agent.
284
+
285
+ Keyword Args:
286
+ thread: The conversation thread associated with the message(s).
287
+ options: Runtime options (model, timeout, etc.).
288
+ kwargs: Additional keyword arguments.
289
+
290
+ Returns:
291
+ An agent response item.
292
+
293
+ Raises:
294
+ ServiceException: If the request fails.
295
+ """
296
+ if not self._started:
297
+ await self.start()
298
+
299
+ if not thread:
300
+ thread = self.get_new_thread()
301
+
302
+ opts: dict[str, Any] = dict(options) if options else {}
303
+ timeout = opts.pop("timeout", None) or self._settings.timeout or DEFAULT_TIMEOUT_SECONDS
304
+
305
+ session = await self._get_or_create_session(thread, streaming=False)
306
+ input_messages = normalize_messages(messages)
307
+ prompt = "\n".join([message.text for message in input_messages])
308
+
309
+ try:
310
+ response_event = await session.send_and_wait({"prompt": prompt}, timeout=timeout)
311
+ except Exception as ex:
312
+ raise ServiceException(f"GitHub Copilot request failed: {ex}") from ex
313
+
314
+ response_messages: list[ChatMessage] = []
315
+ response_id: str | None = None
316
+
317
+ # send_and_wait returns only the final ASSISTANT_MESSAGE event;
318
+ # other events (deltas, tool calls) are handled internally by the SDK.
319
+ if response_event and response_event.type == SessionEventType.ASSISTANT_MESSAGE:
320
+ message_id = response_event.data.message_id
321
+
322
+ if response_event.data.content:
323
+ response_messages.append(
324
+ ChatMessage(
325
+ role=Role.ASSISTANT,
326
+ contents=[Content.from_text(response_event.data.content)],
327
+ message_id=message_id,
328
+ raw_representation=response_event,
329
+ )
330
+ )
331
+ response_id = message_id
332
+
333
+ return AgentResponse(messages=response_messages, response_id=response_id)
334
+
335
+ async def run_stream(
336
+ self,
337
+ messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
338
+ *,
339
+ thread: AgentThread | None = None,
340
+ options: TOptions | None = None,
341
+ **kwargs: Any,
342
+ ) -> AsyncIterable[AgentResponseUpdate]:
343
+ """Run the agent as a stream.
344
+
345
+ This method will return the intermediate steps and final results of the
346
+ agent's execution as a stream of AgentResponseUpdate objects to the caller.
347
+
348
+ Args:
349
+ messages: The message(s) to send to the agent.
350
+
351
+ Keyword Args:
352
+ thread: The conversation thread associated with the message(s).
353
+ options: Runtime options (model, timeout, etc.).
354
+ kwargs: Additional keyword arguments.
355
+
356
+ Yields:
357
+ An agent response update for each delta.
358
+
359
+ Raises:
360
+ ServiceException: If the request fails.
361
+ """
362
+ if not self._started:
363
+ await self.start()
364
+
365
+ if not thread:
366
+ thread = self.get_new_thread()
367
+
368
+ session = await self._get_or_create_session(thread, streaming=True)
369
+ input_messages = normalize_messages(messages)
370
+ prompt = "\n".join([message.text for message in input_messages])
371
+
372
+ queue: asyncio.Queue[AgentResponseUpdate | Exception | None] = asyncio.Queue()
373
+
374
+ def event_handler(event: SessionEvent) -> None:
375
+ if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:
376
+ if event.data.delta_content:
377
+ update = AgentResponseUpdate(
378
+ role=Role.ASSISTANT,
379
+ contents=[Content.from_text(event.data.delta_content)],
380
+ response_id=event.data.message_id,
381
+ message_id=event.data.message_id,
382
+ raw_representation=event,
383
+ )
384
+ queue.put_nowait(update)
385
+ elif event.type == SessionEventType.SESSION_IDLE:
386
+ queue.put_nowait(None)
387
+ elif event.type == SessionEventType.SESSION_ERROR:
388
+ error_msg = event.data.message or "Unknown error"
389
+ queue.put_nowait(ServiceException(f"GitHub Copilot session error: {error_msg}"))
390
+
391
+ unsubscribe = session.on(event_handler)
392
+
393
+ try:
394
+ await session.send({"prompt": prompt})
395
+
396
+ while (item := await queue.get()) is not None:
397
+ if isinstance(item, Exception):
398
+ raise item
399
+ yield item
400
+ finally:
401
+ unsubscribe()
402
+
403
+ def _prepare_tools(
404
+ self,
405
+ tools: list[ToolProtocol | MutableMapping[str, Any]],
406
+ ) -> list[CopilotTool]:
407
+ """Convert Agent Framework tools to Copilot SDK tools.
408
+
409
+ Args:
410
+ tools: List of Agent Framework tools.
411
+
412
+ Returns:
413
+ List of Copilot SDK tools.
414
+ """
415
+ copilot_tools: list[CopilotTool] = []
416
+
417
+ for tool in tools:
418
+ if isinstance(tool, ToolProtocol):
419
+ match tool:
420
+ case AIFunction():
421
+ copilot_tools.append(self._ai_function_to_copilot_tool(tool)) # type: ignore
422
+ case _:
423
+ logger.debug(f"Unsupported tool type: {type(tool)}")
424
+ elif isinstance(tool, CopilotTool):
425
+ copilot_tools.append(tool)
426
+
427
+ return copilot_tools
428
+
429
+ def _ai_function_to_copilot_tool(self, ai_func: AIFunction[Any, Any]) -> CopilotTool:
430
+ """Convert an AIFunction to a Copilot SDK tool."""
431
+
432
+ async def handler(invocation: ToolInvocation) -> ToolResult:
433
+ args = invocation.get("arguments", {})
434
+ try:
435
+ if ai_func.input_model:
436
+ args_instance = ai_func.input_model(**args)
437
+ result = await ai_func.invoke(arguments=args_instance)
438
+ else:
439
+ result = await ai_func.invoke(arguments=args)
440
+ return ToolResult(
441
+ textResultForLlm=str(result),
442
+ resultType="success",
443
+ )
444
+ except Exception as e:
445
+ return ToolResult(
446
+ textResultForLlm=f"Error: {e}",
447
+ resultType="failure",
448
+ error=str(e),
449
+ )
450
+
451
+ return CopilotTool(
452
+ name=ai_func.name,
453
+ description=ai_func.description,
454
+ handler=handler,
455
+ parameters=ai_func.parameters(),
456
+ )
457
+
458
+ async def _get_or_create_session(
459
+ self,
460
+ thread: AgentThread,
461
+ streaming: bool = False,
462
+ ) -> CopilotSession:
463
+ """Get an existing session or create a new one for the thread.
464
+
465
+ Args:
466
+ thread: The conversation thread.
467
+ streaming: Whether to enable streaming for the session.
468
+
469
+ Returns:
470
+ A CopilotSession instance.
471
+
472
+ Raises:
473
+ ServiceException: If the session cannot be created.
474
+ """
475
+ if not self._client:
476
+ raise ServiceException("GitHub Copilot client not initialized. Call start() first.")
477
+
478
+ try:
479
+ if thread.service_thread_id:
480
+ return await self._resume_session(thread.service_thread_id, streaming)
481
+
482
+ session = await self._create_session(streaming)
483
+ thread.service_thread_id = session.session_id
484
+ return session
485
+ except Exception as ex:
486
+ raise ServiceException(f"Failed to create GitHub Copilot session: {ex}") from ex
487
+
488
+ async def _create_session(self, streaming: bool) -> CopilotSession:
489
+ """Create a new Copilot session."""
490
+ if not self._client:
491
+ raise ServiceException("GitHub Copilot client not initialized. Call start() first.")
492
+
493
+ config: SessionConfig = {"streaming": streaming}
494
+
495
+ if self._settings.model:
496
+ config["model"] = self._settings.model # type: ignore[typeddict-item]
497
+
498
+ if self._instructions:
499
+ config["system_message"] = {"mode": "append", "content": self._instructions}
500
+
501
+ if self._tools:
502
+ config["tools"] = self._prepare_tools(self._tools)
503
+
504
+ if self._permission_handler:
505
+ config["on_permission_request"] = self._permission_handler
506
+
507
+ if self._mcp_servers:
508
+ config["mcp_servers"] = self._mcp_servers
509
+
510
+ return await self._client.create_session(config)
511
+
512
+ async def _resume_session(self, session_id: str, streaming: bool) -> CopilotSession:
513
+ """Resume an existing Copilot session by ID."""
514
+ if not self._client:
515
+ raise ServiceException("GitHub Copilot client not initialized. Call start() first.")
516
+
517
+ config: ResumeSessionConfig = {"streaming": streaming}
518
+
519
+ if self._tools:
520
+ config["tools"] = self._prepare_tools(self._tools)
521
+
522
+ if self._permission_handler:
523
+ config["on_permission_request"] = self._permission_handler
524
+
525
+ if self._mcp_servers:
526
+ config["mcp_servers"] = self._mcp_servers
527
+
528
+ return await self._client.resume_session(session_id, config)
@@ -0,0 +1,49 @@
1
+ # Copyright (c) Microsoft. All rights reserved.
2
+
3
+ from typing import ClassVar
4
+
5
+ from agent_framework._pydantic import AFBaseSettings
6
+
7
+
8
+ class GithubCopilotSettings(AFBaseSettings):
9
+ """GitHub Copilot model settings.
10
+
11
+ The settings are first loaded from environment variables with the prefix 'GITHUB_COPILOT_'.
12
+ If the environment variables are not found, the settings can be loaded from a .env file
13
+ with the encoding 'utf-8'. If the settings are not found in the .env file, the settings
14
+ are ignored; however, validation will fail alerting that the settings are missing.
15
+
16
+ Keyword Args:
17
+ cli_path: Path to the Copilot CLI executable.
18
+ Can be set via environment variable GITHUB_COPILOT_CLI_PATH.
19
+ model: Model to use (e.g., "gpt-5", "claude-sonnet-4").
20
+ Can be set via environment variable GITHUB_COPILOT_MODEL.
21
+ timeout: Request timeout in seconds.
22
+ Can be set via environment variable GITHUB_COPILOT_TIMEOUT.
23
+ log_level: CLI log level.
24
+ Can be set via environment variable GITHUB_COPILOT_LOG_LEVEL.
25
+ env_file_path: If provided, the .env settings are read from this file path location.
26
+ env_file_encoding: The encoding of the .env file, defaults to 'utf-8'.
27
+
28
+ Examples:
29
+ .. code-block:: python
30
+
31
+ from agent_framework_github_copilot import GithubCopilotSettings
32
+
33
+ # Using environment variables
34
+ # Set GITHUB_COPILOT_MODEL=gpt-5
35
+ settings = GithubCopilotSettings()
36
+
37
+ # Or passing parameters directly
38
+ settings = GithubCopilotSettings(model="claude-sonnet-4", timeout=120)
39
+
40
+ # Or loading from a .env file
41
+ settings = GithubCopilotSettings(env_file_path="path/to/.env")
42
+ """
43
+
44
+ env_prefix: ClassVar[str] = "GITHUB_COPILOT_"
45
+
46
+ cli_path: str | None = None
47
+ model: str | None = None
48
+ timeout: float | None = None
49
+ log_level: str | None = None
@@ -0,0 +1,89 @@
1
+ [project]
2
+ name = "agent-framework-github-copilot"
3
+ description = "GitHub Copilot integration for Microsoft Agent Framework."
4
+ authors = [{ name = "Microsoft", email = "af-support@microsoft.com"}]
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ version = "1.0.0b260127"
8
+ license-files = ["LICENSE"]
9
+ urls.homepage = "https://aka.ms/agent-framework"
10
+ urls.source = "https://github.com/microsoft/agent-framework/tree/main/python"
11
+ urls.release_notes = "https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true"
12
+ urls.issues = "https://github.com/microsoft/agent-framework/issues"
13
+ classifiers = [
14
+ "License :: OSI Approved :: MIT License",
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.10",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: 3.13",
22
+ "Programming Language :: Python :: 3.14",
23
+ "Typing :: Typed",
24
+ ]
25
+ dependencies = [
26
+ "agent-framework-core",
27
+ "github-copilot-sdk>=0.1.0",
28
+ ]
29
+
30
+ [tool.uv]
31
+ prerelease = "if-necessary-or-explicit"
32
+ environments = [
33
+ "sys_platform == 'darwin'",
34
+ "sys_platform == 'linux'",
35
+ "sys_platform == 'win32'"
36
+ ]
37
+
38
+ [tool.uv-dynamic-versioning]
39
+ fallback-version = "0.0.0"
40
+ [tool.pytest.ini_options]
41
+ testpaths = 'tests'
42
+ addopts = "-ra -q -r fEX"
43
+ asyncio_mode = "auto"
44
+ asyncio_default_fixture_loop_scope = "function"
45
+ filterwarnings = [
46
+ "ignore:Support for class-based `config` is deprecated:DeprecationWarning:pydantic.*"
47
+ ]
48
+ timeout = 120
49
+
50
+ [tool.ruff]
51
+ extend = "../../pyproject.toml"
52
+
53
+ [tool.coverage.run]
54
+ omit = [
55
+ "**/__init__.py"
56
+ ]
57
+
58
+ [tool.pyright]
59
+ extends = "../../pyproject.toml"
60
+
61
+
62
+ [tool.mypy]
63
+ plugins = ['pydantic.mypy']
64
+ strict = true
65
+ python_version = "3.10"
66
+ ignore_missing_imports = true
67
+ disallow_untyped_defs = true
68
+ no_implicit_optional = true
69
+ check_untyped_defs = true
70
+ warn_return_any = true
71
+ show_error_codes = true
72
+ warn_unused_ignores = false
73
+ disallow_incomplete_defs = true
74
+ disallow_untyped_decorators = true
75
+
76
+ [tool.bandit]
77
+ targets = ["agent_framework_github_copilot"]
78
+ exclude_dirs = ["tests"]
79
+
80
+ [tool.poe]
81
+ executor.type = "uv"
82
+ include = "../../shared_tasks.toml"
83
+ [tool.poe.tasks]
84
+ mypy = "mypy --config-file $POE_ROOT/pyproject.toml agent_framework_github_copilot"
85
+ test = "pytest --cov=agent_framework_github_copilot --cov-report=term-missing:skip-covered tests"
86
+
87
+ [build-system]
88
+ requires = ["flit-core >= 3.11,<4.0"]
89
+ build-backend = "flit_core.buildapi"