agent-framework-github-copilot 1.0.0rc1__tar.gz → 1.0.0rc3__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.
- agent_framework_github_copilot-1.0.0rc3/PKG-INFO +87 -0
- agent_framework_github_copilot-1.0.0rc3/README.md +61 -0
- {agent_framework_github_copilot-1.0.0rc1 → agent_framework_github_copilot-1.0.0rc3}/agent_framework_github_copilot/_agent.py +294 -54
- {agent_framework_github_copilot-1.0.0rc1 → agent_framework_github_copilot-1.0.0rc3}/pyproject.toml +3 -4
- agent_framework_github_copilot-1.0.0rc1/PKG-INFO +0 -37
- agent_framework_github_copilot-1.0.0rc1/README.md +0 -11
- {agent_framework_github_copilot-1.0.0rc1 → agent_framework_github_copilot-1.0.0rc3}/LICENSE +0 -0
- {agent_framework_github_copilot-1.0.0rc1 → agent_framework_github_copilot-1.0.0rc3}/agent_framework_github_copilot/__init__.py +0 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-framework-github-copilot
|
|
3
|
+
Version: 1.0.0rc3
|
|
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>=1.11.0,<2
|
|
20
|
+
Requires-Dist: github-copilot-sdk==1.0.2; python_version >= '3.11'
|
|
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
|
+
|
|
38
|
+
## Tool approval (`approval_mode="always_require"`)
|
|
39
|
+
|
|
40
|
+
The GitHub Copilot SDK owns the tool-calling loop for this provider, so approval for
|
|
41
|
+
custom function tools is enforced through the SDK's native pre-execution hook rather
|
|
42
|
+
than the standard Agent Framework approval round-trip.
|
|
43
|
+
|
|
44
|
+
When you register a `FunctionTool` declared with `approval_mode="always_require"` and you
|
|
45
|
+
do **not** supply your own `on_pre_tool_use` hook, `GitHubCopilotAgent` installs a default
|
|
46
|
+
`on_pre_tool_use` hook that returns `"ask"` for that tool and defers (`None`) for all other
|
|
47
|
+
tools. The `"ask"` decision routes to your `on_permission_request` handler, where you
|
|
48
|
+
approve or deny the call:
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from agent_framework import tool
|
|
52
|
+
from agent_framework.github import GitHubCopilotAgent, GitHubCopilotOptions
|
|
53
|
+
from copilot.session import PermissionHandler
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@tool(approval_mode="always_require")
|
|
57
|
+
def delete_file(path: str) -> str:
|
|
58
|
+
"""Delete a file."""
|
|
59
|
+
...
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
agent = GitHubCopilotAgent(
|
|
63
|
+
tools=[delete_file],
|
|
64
|
+
# The "ask" decision is routed here; approve or deny the call.
|
|
65
|
+
default_options=GitHubCopilotOptions(on_permission_request=PermissionHandler.approve_all),
|
|
66
|
+
)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
> **⚠️ If you provide your own `on_pre_tool_use` hook**, it takes precedence and the agent
|
|
70
|
+
> does **not** install its default approval hook. In that case **you are fully responsible**
|
|
71
|
+
> for enforcing approval — including for any `approval_mode="always_require"` tool (e.g. by
|
|
72
|
+
> returning a `"deny"` or `"ask"` decision). The agent logs a warning naming any
|
|
73
|
+
> approval-required tool that your hook must handle.
|
|
74
|
+
>
|
|
75
|
+
> Note: with the default (deny-all) permission handler, an `always_require` tool is denied
|
|
76
|
+
> unless you wire an approving `on_permission_request`.
|
|
77
|
+
|
|
78
|
+
### Deprecated: `on_function_approval`
|
|
79
|
+
|
|
80
|
+
The `on_function_approval` callback is **deprecated**. It still works (and is still enforced
|
|
81
|
+
inside the tool handler for backward compatibility), but it emits a `DeprecationWarning` and
|
|
82
|
+
will be removed in a future version. Migrate to the `on_pre_tool_use` + `on_permission_request`
|
|
83
|
+
model described above. When `on_function_approval` is set, it gates `always_require` tools and
|
|
84
|
+
the default ask-hook is not installed. It is **mutually exclusive** with `on_pre_tool_use` —
|
|
85
|
+
setting both (whether at construction or per run) raises `ValueError`.
|
|
86
|
+
|
|
87
|
+
|
|
@@ -0,0 +1,61 @@
|
|
|
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.
|
|
12
|
+
|
|
13
|
+
## Tool approval (`approval_mode="always_require"`)
|
|
14
|
+
|
|
15
|
+
The GitHub Copilot SDK owns the tool-calling loop for this provider, so approval for
|
|
16
|
+
custom function tools is enforced through the SDK's native pre-execution hook rather
|
|
17
|
+
than the standard Agent Framework approval round-trip.
|
|
18
|
+
|
|
19
|
+
When you register a `FunctionTool` declared with `approval_mode="always_require"` and you
|
|
20
|
+
do **not** supply your own `on_pre_tool_use` hook, `GitHubCopilotAgent` installs a default
|
|
21
|
+
`on_pre_tool_use` hook that returns `"ask"` for that tool and defers (`None`) for all other
|
|
22
|
+
tools. The `"ask"` decision routes to your `on_permission_request` handler, where you
|
|
23
|
+
approve or deny the call:
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from agent_framework import tool
|
|
27
|
+
from agent_framework.github import GitHubCopilotAgent, GitHubCopilotOptions
|
|
28
|
+
from copilot.session import PermissionHandler
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@tool(approval_mode="always_require")
|
|
32
|
+
def delete_file(path: str) -> str:
|
|
33
|
+
"""Delete a file."""
|
|
34
|
+
...
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
agent = GitHubCopilotAgent(
|
|
38
|
+
tools=[delete_file],
|
|
39
|
+
# The "ask" decision is routed here; approve or deny the call.
|
|
40
|
+
default_options=GitHubCopilotOptions(on_permission_request=PermissionHandler.approve_all),
|
|
41
|
+
)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
> **⚠️ If you provide your own `on_pre_tool_use` hook**, it takes precedence and the agent
|
|
45
|
+
> does **not** install its default approval hook. In that case **you are fully responsible**
|
|
46
|
+
> for enforcing approval — including for any `approval_mode="always_require"` tool (e.g. by
|
|
47
|
+
> returning a `"deny"` or `"ask"` decision). The agent logs a warning naming any
|
|
48
|
+
> approval-required tool that your hook must handle.
|
|
49
|
+
>
|
|
50
|
+
> Note: with the default (deny-all) permission handler, an `always_require` tool is denied
|
|
51
|
+
> unless you wire an approving `on_permission_request`.
|
|
52
|
+
|
|
53
|
+
### Deprecated: `on_function_approval`
|
|
54
|
+
|
|
55
|
+
The `on_function_approval` callback is **deprecated**. It still works (and is still enforced
|
|
56
|
+
inside the tool handler for backward compatibility), but it emits a `DeprecationWarning` and
|
|
57
|
+
will be removed in a future version. Migrate to the `on_pre_tool_use` + `on_permission_request`
|
|
58
|
+
model described above. When `on_function_approval` is set, it gates `always_require` tools and
|
|
59
|
+
the default ask-hook is not installed. It is **mutually exclusive** with `on_pre_tool_use` —
|
|
60
|
+
setting both (whether at construction or per run) raises `ValueError`.
|
|
61
|
+
|
|
@@ -7,13 +7,9 @@ import contextlib
|
|
|
7
7
|
import inspect
|
|
8
8
|
import logging
|
|
9
9
|
import sys
|
|
10
|
+
import warnings
|
|
10
11
|
from collections.abc import AsyncIterable, Awaitable, Callable, Mapping, MutableMapping, Sequence
|
|
11
|
-
from typing import Any, ClassVar, Generic, Literal, TypedDict, overload
|
|
12
|
-
|
|
13
|
-
if sys.version_info >= (3, 11):
|
|
14
|
-
from typing import Self # pragma: no cover
|
|
15
|
-
else:
|
|
16
|
-
from typing_extensions import Self # pragma: no cover
|
|
12
|
+
from typing import Any, ClassVar, Generic, Literal, TypedDict, cast, overload
|
|
17
13
|
|
|
18
14
|
from agent_framework import (
|
|
19
15
|
AgentMiddlewareLayer,
|
|
@@ -28,6 +24,8 @@ from agent_framework import (
|
|
|
28
24
|
Message,
|
|
29
25
|
ResponseStream,
|
|
30
26
|
SessionContext,
|
|
27
|
+
UsageDetails,
|
|
28
|
+
add_usage_details,
|
|
31
29
|
normalize_messages,
|
|
32
30
|
)
|
|
33
31
|
from agent_framework._settings import load_settings
|
|
@@ -36,11 +34,28 @@ from agent_framework._types import AgentRunInputs, normalize_tools
|
|
|
36
34
|
from agent_framework.exceptions import AgentException
|
|
37
35
|
from agent_framework.observability import AgentTelemetryLayer
|
|
38
36
|
|
|
37
|
+
if sys.version_info >= (3, 11):
|
|
38
|
+
from typing import Self # pragma: no cover
|
|
39
|
+
else:
|
|
40
|
+
from typing_extensions import Self # pragma: no cover
|
|
41
|
+
if sys.version_info >= (3, 13):
|
|
42
|
+
from typing import TypeVar # pragma: no cover
|
|
43
|
+
else:
|
|
44
|
+
from typing_extensions import TypeVar # pragma: no cover
|
|
45
|
+
|
|
39
46
|
try:
|
|
40
47
|
from copilot import CopilotClient, CopilotSession, RuntimeConnection
|
|
41
48
|
from copilot.generated.rpc import PermissionDecisionUserNotAvailable
|
|
42
|
-
from copilot.session import
|
|
43
|
-
|
|
49
|
+
from copilot.session import (
|
|
50
|
+
MCPServerConfig,
|
|
51
|
+
PermissionRequestResult,
|
|
52
|
+
PreToolUseHandler,
|
|
53
|
+
PreToolUseHookOutput,
|
|
54
|
+
ProviderConfig,
|
|
55
|
+
SessionHooks,
|
|
56
|
+
SystemMessageConfig,
|
|
57
|
+
)
|
|
58
|
+
from copilot.session_events import AssistantUsageData, PermissionRequest, SessionEvent, SessionEventType
|
|
44
59
|
from copilot.tools import Tool as CopilotTool
|
|
45
60
|
from copilot.tools import ToolInvocation, ToolResult
|
|
46
61
|
except ImportError as _copilot_import_error:
|
|
@@ -49,12 +64,6 @@ except ImportError as _copilot_import_error:
|
|
|
49
64
|
"Please use Python 3.11 or later."
|
|
50
65
|
) from _copilot_import_error
|
|
51
66
|
|
|
52
|
-
if sys.version_info >= (3, 13):
|
|
53
|
-
from typing import TypeVar
|
|
54
|
-
else:
|
|
55
|
-
from typing_extensions import TypeVar
|
|
56
|
-
|
|
57
|
-
|
|
58
67
|
DEFAULT_TIMEOUT_SECONDS: float = 60.0
|
|
59
68
|
"""Default timeout in seconds for Copilot requests."""
|
|
60
69
|
|
|
@@ -65,23 +74,18 @@ PermissionHandlerType = Callable[
|
|
|
65
74
|
|
|
66
75
|
|
|
67
76
|
FunctionApprovalCallback = Callable[[Content], "bool | Awaitable[bool]"]
|
|
68
|
-
"""
|
|
77
|
+
"""Deprecated approval callback for ``FunctionTool`` instances declared with
|
|
78
|
+
``approval_mode="always_require"``.
|
|
79
|
+
|
|
80
|
+
.. deprecated::
|
|
81
|
+
Use the SDK ``on_pre_tool_use`` hook together with ``on_permission_request``
|
|
82
|
+
instead. The default ``on_pre_tool_use`` hook returns ``"ask"`` for
|
|
83
|
+
``always_require`` tools and routes the decision to ``on_permission_request``.
|
|
69
84
|
|
|
70
85
|
The callback receives a ``FunctionCallContent`` describing the pending call
|
|
71
86
|
(``name``, ``arguments``, and a synthetic ``call_id``) and must return ``True``
|
|
72
87
|
to allow execution or ``False`` to deny it. Both synchronous and ``await``-able
|
|
73
88
|
return values are supported.
|
|
74
|
-
|
|
75
|
-
The Copilot CLI manages its own tool-calling loop, so the framework cannot
|
|
76
|
-
round-trip a ``FunctionApprovalRequestContent`` / ``FunctionApprovalResponseContent``
|
|
77
|
-
pair the way the standard chat-client pipeline does. This callback is the
|
|
78
|
-
agent-level enforcement point for tools declared with
|
|
79
|
-
``approval_mode="always_require"``: when no callback is configured the agent
|
|
80
|
-
denies these calls by default.
|
|
81
|
-
|
|
82
|
-
Note: this is independent of ``on_permission_request``, which gates the
|
|
83
|
-
Copilot SDK's *built-in* shell/file actions; ``on_function_approval`` gates
|
|
84
|
-
agent-framework ``FunctionTool`` calls.
|
|
85
89
|
"""
|
|
86
90
|
|
|
87
91
|
|
|
@@ -90,7 +94,7 @@ async def _resolve_function_approval(
|
|
|
90
94
|
func_tool: FunctionTool,
|
|
91
95
|
arguments: Mapping[str, Any] | None,
|
|
92
96
|
) -> bool:
|
|
93
|
-
"""Run the agent-level approval callback for a pending tool call.
|
|
97
|
+
"""Run the deprecated agent-level approval callback for a pending tool call.
|
|
94
98
|
|
|
95
99
|
Returns ``True`` only when ``callback`` is configured and explicitly returns
|
|
96
100
|
a truthy value. A missing callback or any callback failure is treated as a
|
|
@@ -202,13 +206,51 @@ class GitHubCopilotOptions(TypedDict, total=False):
|
|
|
202
206
|
files beyond the default locations.
|
|
203
207
|
"""
|
|
204
208
|
|
|
209
|
+
skill_directories: list[str]
|
|
210
|
+
"""Directories containing SKILL.md files to load into the Copilot CLI session.
|
|
211
|
+
These are loaded natively by the Copilot CLI process, letting applications point
|
|
212
|
+
the CLI at project-specific or team-shared skills beyond the default locations.
|
|
213
|
+
"""
|
|
214
|
+
|
|
215
|
+
disabled_skills: list[str]
|
|
216
|
+
"""Names of skills to disable for the session.
|
|
217
|
+
Lets applications opt out of specific skills that would otherwise be discovered
|
|
218
|
+
from ``skill_directories`` or the default locations.
|
|
219
|
+
"""
|
|
220
|
+
|
|
221
|
+
base_directory: str
|
|
222
|
+
"""Directory where the CLI stores session state, configuration, and other persistent data."""
|
|
223
|
+
|
|
224
|
+
on_pre_tool_use: PreToolUseHandler
|
|
225
|
+
"""Pre-tool-use hook handler for the Copilot SDK.
|
|
226
|
+
|
|
227
|
+
Called by the Copilot SDK before any tool is executed. The handler receives a
|
|
228
|
+
``PreToolUseHookInput`` and a context dict, and returns a ``PreToolUseHookOutput``
|
|
229
|
+
(or ``None`` to defer). Returning ``{"permissionDecision": "ask"}`` routes the
|
|
230
|
+
decision to ``on_permission_request``; ``"allow"`` / ``"deny"`` gate the call
|
|
231
|
+
directly.
|
|
232
|
+
|
|
233
|
+
If you do **not** supply this hook, the agent installs a default ``on_pre_tool_use``
|
|
234
|
+
hook that returns ``"ask"`` for ``FunctionTool`` instances declared with
|
|
235
|
+
``approval_mode="always_require"`` (deferring all other tools), so those tools are
|
|
236
|
+
gated through ``on_permission_request``. If you **do** supply your own hook, it
|
|
237
|
+
takes precedence and **you** are responsible for enforcing approval for any
|
|
238
|
+
``always_require`` tool; the agent logs a warning naming such tools."""
|
|
239
|
+
|
|
205
240
|
on_function_approval: FunctionApprovalCallback
|
|
206
|
-
"""
|
|
207
|
-
``approval_mode="always_require"``.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
241
|
+
"""Deprecated approval callback for ``FunctionTool`` instances declared with
|
|
242
|
+
``approval_mode="always_require"``.
|
|
243
|
+
|
|
244
|
+
.. deprecated::
|
|
245
|
+
Use ``on_pre_tool_use`` together with ``on_permission_request`` instead.
|
|
246
|
+
When neither this callback nor ``on_pre_tool_use`` is set, the agent
|
|
247
|
+
installs a default ``on_pre_tool_use`` hook that returns ``"ask"`` for
|
|
248
|
+
``always_require`` tools and routes the decision to ``on_permission_request``.
|
|
249
|
+
|
|
250
|
+
When set, this callback is enforced inside the SDK tool-handler before the tool
|
|
251
|
+
runs; a falsy return value denies the call. Setting it emits a
|
|
252
|
+
``DeprecationWarning``. It is **mutually exclusive** with ``on_pre_tool_use`` —
|
|
253
|
+
setting both raises ``ValueError``."""
|
|
212
254
|
|
|
213
255
|
|
|
214
256
|
OptionsT = TypeVar(
|
|
@@ -316,9 +358,29 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
316
358
|
mcp_servers: dict[str, MCPServerConfig] | None = opts.pop("mcp_servers", None)
|
|
317
359
|
provider: ProviderConfig | None = opts.pop("provider", None)
|
|
318
360
|
instruction_directories: list[str] | None = opts.pop("instruction_directories", None)
|
|
361
|
+
skill_directories: list[str] | None = opts.pop("skill_directories", None)
|
|
362
|
+
disabled_skills: list[str] | None = opts.pop("disabled_skills", None)
|
|
363
|
+
on_pre_tool_use: PreToolUseHandler | None = opts.pop("on_pre_tool_use", None)
|
|
319
364
|
on_function_approval: FunctionApprovalCallback | None = opts.pop("on_function_approval", None)
|
|
320
365
|
base_directory = opts.pop("base_directory", None)
|
|
321
366
|
|
|
367
|
+
if on_function_approval is not None and on_pre_tool_use is not None:
|
|
368
|
+
raise ValueError(
|
|
369
|
+
"on_function_approval and on_pre_tool_use cannot both be set. "
|
|
370
|
+
"on_function_approval is deprecated; use on_pre_tool_use together with "
|
|
371
|
+
"on_permission_request instead."
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
if on_function_approval is not None:
|
|
375
|
+
warnings.warn(
|
|
376
|
+
"on_function_approval is deprecated and will be removed in a future version. "
|
|
377
|
+
"Use the SDK 'on_pre_tool_use' hook together with 'on_permission_request' instead: "
|
|
378
|
+
"the default 'on_pre_tool_use' hook returns 'ask' for approval_mode='always_require' "
|
|
379
|
+
"tools and routes the decision to 'on_permission_request'.",
|
|
380
|
+
DeprecationWarning,
|
|
381
|
+
stacklevel=2,
|
|
382
|
+
)
|
|
383
|
+
|
|
322
384
|
self._settings = load_settings(
|
|
323
385
|
GitHubCopilotSettings,
|
|
324
386
|
env_prefix="GITHUB_COPILOT_",
|
|
@@ -333,10 +395,13 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
333
395
|
|
|
334
396
|
self._tools = normalize_tools(tools)
|
|
335
397
|
self._permission_handler = on_permission_request
|
|
398
|
+
self._on_pre_tool_use: PreToolUseHandler | None = on_pre_tool_use
|
|
336
399
|
self._function_approval_handler: FunctionApprovalCallback | None = on_function_approval
|
|
337
400
|
self._mcp_servers = mcp_servers
|
|
338
401
|
self._provider = provider
|
|
339
402
|
self._instruction_directories = instruction_directories
|
|
403
|
+
self._skill_directories = skill_directories
|
|
404
|
+
self._disabled_skills = disabled_skills
|
|
340
405
|
self._default_options = opts
|
|
341
406
|
self._started = False
|
|
342
407
|
|
|
@@ -441,7 +506,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
441
506
|
session: AgentSession | None = None,
|
|
442
507
|
middleware: Sequence[AgentMiddlewareTypes] | None = None,
|
|
443
508
|
options: OptionsT | None = None,
|
|
444
|
-
**kwargs: Any,
|
|
509
|
+
**kwargs: Any,
|
|
445
510
|
) -> Awaitable[AgentResponse] | ResponseStream[AgentResponseUpdate, AgentResponse]:
|
|
446
511
|
"""Get a response from the agent.
|
|
447
512
|
|
|
@@ -498,6 +563,27 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
498
563
|
)
|
|
499
564
|
return self._run_impl(messages=messages, session=session, options=options)
|
|
500
565
|
|
|
566
|
+
@staticmethod
|
|
567
|
+
def _parse_usage_details_from_copilot(data: AssistantUsageData) -> UsageDetails | None:
|
|
568
|
+
total_token_count = (
|
|
569
|
+
data.input_tokens + data.output_tokens
|
|
570
|
+
if data.input_tokens is not None and data.output_tokens is not None
|
|
571
|
+
else None
|
|
572
|
+
)
|
|
573
|
+
usage_details = UsageDetails(**{
|
|
574
|
+
key: value
|
|
575
|
+
for key, value in {
|
|
576
|
+
"input_token_count": data.input_tokens,
|
|
577
|
+
"output_token_count": data.output_tokens,
|
|
578
|
+
"total_token_count": total_token_count,
|
|
579
|
+
"cache_read_input_token_count": data.cache_read_tokens,
|
|
580
|
+
"cache_creation_input_token_count": data.cache_write_tokens,
|
|
581
|
+
"reasoning_output_token_count": data.reasoning_tokens,
|
|
582
|
+
}.items()
|
|
583
|
+
if value is not None
|
|
584
|
+
})
|
|
585
|
+
return usage_details or None
|
|
586
|
+
|
|
501
587
|
async def _run_impl(
|
|
502
588
|
self,
|
|
503
589
|
messages: AgentRunInputs | None = None,
|
|
@@ -519,6 +605,12 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
519
605
|
"via default_options at agent construction time. It cannot be overridden "
|
|
520
606
|
"per run."
|
|
521
607
|
)
|
|
608
|
+
if "on_pre_tool_use" in opts and self._function_approval_handler is not None:
|
|
609
|
+
raise ValueError(
|
|
610
|
+
"on_pre_tool_use cannot be combined with the deprecated on_function_approval "
|
|
611
|
+
"(set via default_options). Remove on_function_approval and use on_pre_tool_use "
|
|
612
|
+
"together with on_permission_request instead."
|
|
613
|
+
)
|
|
522
614
|
timeout = opts.get("timeout") or self._settings.get("timeout") or DEFAULT_TIMEOUT_SECONDS
|
|
523
615
|
|
|
524
616
|
input_messages = normalize_messages(messages)
|
|
@@ -531,6 +623,27 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
531
623
|
opts["tools"] = existing + list(session_context.tools)
|
|
532
624
|
|
|
533
625
|
copilot_session = await self._get_or_create_session(session, streaming=False, runtime_options=opts)
|
|
626
|
+
usage_details: UsageDetails | None = None
|
|
627
|
+
finish_reason: str | None = None
|
|
628
|
+
model: str | None = None
|
|
629
|
+
|
|
630
|
+
def usage_event_handler(event: SessionEvent) -> None:
|
|
631
|
+
nonlocal usage_details, finish_reason, model
|
|
632
|
+
if event.type != SessionEventType.ASSISTANT_USAGE:
|
|
633
|
+
return
|
|
634
|
+
if isinstance(event.data, AssistantUsageData):
|
|
635
|
+
parsed_usage_details = self._parse_usage_details_from_copilot(event.data)
|
|
636
|
+
if parsed_usage_details:
|
|
637
|
+
usage_details = add_usage_details(usage_details, parsed_usage_details)
|
|
638
|
+
if event.data.finish_reason:
|
|
639
|
+
finish_reason = event.data.finish_reason
|
|
640
|
+
if event.data.model:
|
|
641
|
+
model = event.data.model
|
|
642
|
+
else:
|
|
643
|
+
logger.warning(
|
|
644
|
+
"Ignoring GitHub Copilot assistant usage event with unexpected payload type: %s",
|
|
645
|
+
type(event.data).__name__,
|
|
646
|
+
)
|
|
534
647
|
|
|
535
648
|
# Build the prompt from the full set of messages in the session context,
|
|
536
649
|
# so that any context/history provider-injected messages are included.
|
|
@@ -539,10 +652,13 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
539
652
|
if session_context.instructions:
|
|
540
653
|
prompt = "\n".join(session_context.instructions) + "\n" + prompt
|
|
541
654
|
|
|
655
|
+
unsubscribe = copilot_session.on(usage_event_handler)
|
|
542
656
|
try:
|
|
543
657
|
response_event = await copilot_session.send_and_wait(prompt, timeout=timeout)
|
|
544
658
|
except Exception as ex:
|
|
545
659
|
raise AgentException(f"GitHub Copilot request failed: {ex}") from ex
|
|
660
|
+
finally:
|
|
661
|
+
unsubscribe()
|
|
546
662
|
|
|
547
663
|
response_messages: list[Message] = []
|
|
548
664
|
response_id: str | None = None
|
|
@@ -564,7 +680,13 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
564
680
|
)
|
|
565
681
|
response_id = message_id
|
|
566
682
|
|
|
567
|
-
response = AgentResponse(
|
|
683
|
+
response = AgentResponse(
|
|
684
|
+
messages=response_messages,
|
|
685
|
+
response_id=response_id,
|
|
686
|
+
finish_reason=cast(Any, finish_reason),
|
|
687
|
+
usage_details=usage_details,
|
|
688
|
+
additional_properties={"model": model} if model else None,
|
|
689
|
+
)
|
|
568
690
|
session_context._response = response # type: ignore[assignment]
|
|
569
691
|
await self._run_after_providers(session=session, context=session_context)
|
|
570
692
|
return response
|
|
@@ -608,6 +730,12 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
608
730
|
"via default_options at agent construction time. It cannot be overridden "
|
|
609
731
|
"per run."
|
|
610
732
|
)
|
|
733
|
+
if "on_pre_tool_use" in opts and self._function_approval_handler is not None:
|
|
734
|
+
raise ValueError(
|
|
735
|
+
"on_pre_tool_use cannot be combined with the deprecated on_function_approval "
|
|
736
|
+
"(set via default_options). Remove on_function_approval and use on_pre_tool_use "
|
|
737
|
+
"together with on_permission_request instead."
|
|
738
|
+
)
|
|
611
739
|
|
|
612
740
|
input_messages = normalize_messages(messages)
|
|
613
741
|
|
|
@@ -644,6 +772,26 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
644
772
|
raw_representation=event,
|
|
645
773
|
)
|
|
646
774
|
queue.put_nowait(update)
|
|
775
|
+
elif event.type == SessionEventType.ASSISTANT_USAGE:
|
|
776
|
+
if not isinstance(event.data, AssistantUsageData):
|
|
777
|
+
logger.warning(
|
|
778
|
+
"Ignoring GitHub Copilot assistant usage event with unexpected payload type: %s",
|
|
779
|
+
type(event.data).__name__,
|
|
780
|
+
)
|
|
781
|
+
return
|
|
782
|
+
usage_details = self._parse_usage_details_from_copilot(event.data)
|
|
783
|
+
finish_reason = event.data.finish_reason or None
|
|
784
|
+
model = event.data.model or None
|
|
785
|
+
if usage_details or finish_reason or model:
|
|
786
|
+
update = AgentResponseUpdate(
|
|
787
|
+
contents=[Content.from_usage(usage_details, raw_representation=event.data)]
|
|
788
|
+
if usage_details
|
|
789
|
+
else None,
|
|
790
|
+
finish_reason=cast(Any, finish_reason),
|
|
791
|
+
additional_properties={"model": model} if model else None,
|
|
792
|
+
raw_representation=event,
|
|
793
|
+
)
|
|
794
|
+
queue.put_nowait(update)
|
|
647
795
|
elif event.type == SessionEventType.TOOL_EXECUTION_START:
|
|
648
796
|
tool_call_id = getattr(event.data, "tool_call_id", None) or ""
|
|
649
797
|
tool_name = getattr(event.data, "tool_name", None) or ""
|
|
@@ -732,7 +880,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
732
880
|
if isinstance(provider, HistoryProvider) and not provider.load_messages:
|
|
733
881
|
continue
|
|
734
882
|
await provider.before_run(
|
|
735
|
-
agent=self,
|
|
883
|
+
agent=self,
|
|
736
884
|
session=session,
|
|
737
885
|
context=session_context,
|
|
738
886
|
state=session.state.setdefault(provider.source_id, {}),
|
|
@@ -781,7 +929,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
781
929
|
if isinstance(tool, CopilotTool):
|
|
782
930
|
copilot_tools.append(tool)
|
|
783
931
|
elif isinstance(tool, FunctionTool):
|
|
784
|
-
copilot_tools.append(self._tool_to_copilot_tool(tool))
|
|
932
|
+
copilot_tools.append(self._tool_to_copilot_tool(tool))
|
|
785
933
|
elif isinstance(tool, MutableMapping):
|
|
786
934
|
copilot_tools.append(tool) # type: ignore[arg-type]
|
|
787
935
|
# Note: Other tool types (e.g., dict-based hosted tools) are skipped
|
|
@@ -789,31 +937,32 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
789
937
|
return copilot_tools
|
|
790
938
|
|
|
791
939
|
def _tool_to_copilot_tool(self, ai_func: FunctionTool) -> CopilotTool:
|
|
792
|
-
"""Convert an FunctionTool to a Copilot SDK tool.
|
|
940
|
+
"""Convert an FunctionTool to a Copilot SDK tool.
|
|
941
|
+
|
|
942
|
+
Approval for tools declared with ``approval_mode="always_require"`` is normally
|
|
943
|
+
enforced by the Copilot SDK's native ``on_pre_tool_use`` hook (see
|
|
944
|
+
:meth:`_build_session_hooks`). When the deprecated ``on_function_approval``
|
|
945
|
+
callback is configured instead, approval is enforced inside this handler for
|
|
946
|
+
backward compatibility. (``on_function_approval`` and ``on_pre_tool_use`` are
|
|
947
|
+
mutually exclusive, so only one mechanism is ever active.)
|
|
948
|
+
"""
|
|
793
949
|
approval_handler = self._function_approval_handler
|
|
794
|
-
|
|
950
|
+
enforce = approval_handler is not None and ai_func.approval_mode == "always_require"
|
|
795
951
|
|
|
796
952
|
async def handler(invocation: ToolInvocation) -> ToolResult:
|
|
797
953
|
args: dict[str, Any] = invocation.arguments or {}
|
|
798
954
|
try:
|
|
799
|
-
if
|
|
800
|
-
deny_text = (
|
|
801
|
-
f"Tool '{ai_func.name}' requires human approval "
|
|
802
|
-
"(approval_mode='always_require') and the request was denied."
|
|
803
|
-
if approval_handler is not None
|
|
804
|
-
else (
|
|
805
|
-
f"Tool '{ai_func.name}' requires human approval "
|
|
806
|
-
"(approval_mode='always_require') but no on_function_approval "
|
|
807
|
-
"callback is configured on the agent; the request was denied."
|
|
808
|
-
)
|
|
809
|
-
)
|
|
955
|
+
if enforce and not await _resolve_function_approval(approval_handler, ai_func, args):
|
|
810
956
|
logger.info(
|
|
811
|
-
"Denying execution of tool '%s' (approval_mode='always_require',
|
|
957
|
+
"Denying execution of tool '%s' (approval_mode='always_require', "
|
|
958
|
+
"on_function_approval callback denied).",
|
|
812
959
|
ai_func.name,
|
|
813
|
-
"callback denied" if approval_handler is not None else "no callback configured",
|
|
814
960
|
)
|
|
815
961
|
return ToolResult(
|
|
816
|
-
text_result_for_llm=
|
|
962
|
+
text_result_for_llm=(
|
|
963
|
+
f"Tool '{ai_func.name}' requires human approval "
|
|
964
|
+
"(approval_mode='always_require') and the request was denied."
|
|
965
|
+
),
|
|
817
966
|
result_type="failure",
|
|
818
967
|
error="approval_denied",
|
|
819
968
|
)
|
|
@@ -847,6 +996,80 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
847
996
|
parameters=ai_func.parameters(),
|
|
848
997
|
)
|
|
849
998
|
|
|
999
|
+
def _build_session_hooks(
|
|
1000
|
+
self,
|
|
1001
|
+
all_tools: Sequence[ToolTypes | CopilotTool],
|
|
1002
|
+
opts: Mapping[str, Any],
|
|
1003
|
+
) -> SessionHooks | None:
|
|
1004
|
+
"""Build the ``SessionHooks`` to pass to the Copilot SDK for this session.
|
|
1005
|
+
|
|
1006
|
+
Approval enforcement for ``FunctionTool`` instances declared with
|
|
1007
|
+
``approval_mode="always_require"`` is delegated to the Copilot SDK's native
|
|
1008
|
+
``on_pre_tool_use`` hook:
|
|
1009
|
+
|
|
1010
|
+
- If the caller supplies their own ``on_pre_tool_use`` (via per-run ``options``
|
|
1011
|
+
or ``default_options``), it takes precedence and is returned unchanged. A
|
|
1012
|
+
warning is logged naming any approval-required tool that will therefore not
|
|
1013
|
+
be automatically gated, since the caller's hook is responsible for enforcing
|
|
1014
|
+
approval.
|
|
1015
|
+
- Otherwise, when any approval-required tool is present, a default hook is
|
|
1016
|
+
installed that returns ``"ask"`` for those tools (routing the decision to
|
|
1017
|
+
``on_permission_request``) and defers (``None``) for all other tools.
|
|
1018
|
+
- The default hook is **not** installed when the deprecated
|
|
1019
|
+
``on_function_approval`` callback is configured: in that case approval is
|
|
1020
|
+
enforced inside the tool handler (see :meth:`_tool_to_copilot_tool`) to
|
|
1021
|
+
preserve backward-compatible behavior.
|
|
1022
|
+
- When there are no approval-required tools and no caller hook, ``None`` is
|
|
1023
|
+
returned so no hooks are registered.
|
|
1024
|
+
|
|
1025
|
+
Args:
|
|
1026
|
+
all_tools: The full set of tools resolved for the session.
|
|
1027
|
+
opts: Runtime options that take precedence over ``default_options``.
|
|
1028
|
+
|
|
1029
|
+
Returns:
|
|
1030
|
+
The hooks to register for the session, or ``None`` if none are needed.
|
|
1031
|
+
"""
|
|
1032
|
+
user_hook: PreToolUseHandler | None = opts.get("on_pre_tool_use") or self._on_pre_tool_use
|
|
1033
|
+
|
|
1034
|
+
approval_required_names = {
|
|
1035
|
+
tool.name for tool in all_tools if isinstance(tool, FunctionTool) and tool.approval_mode == "always_require"
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
if user_hook is not None:
|
|
1039
|
+
if approval_required_names:
|
|
1040
|
+
logger.warning(
|
|
1041
|
+
"A custom 'on_pre_tool_use' hook is configured, so %d approval-required tool(s) (%s) "
|
|
1042
|
+
"will not be automatically gated by GitHubCopilotAgent. The custom hook is responsible "
|
|
1043
|
+
"for enforcing approval (for example, by returning a 'deny' or 'ask' decision).",
|
|
1044
|
+
len(approval_required_names),
|
|
1045
|
+
", ".join(sorted(approval_required_names)),
|
|
1046
|
+
)
|
|
1047
|
+
return {"on_pre_tool_use": user_hook}
|
|
1048
|
+
|
|
1049
|
+
if not approval_required_names:
|
|
1050
|
+
return None
|
|
1051
|
+
|
|
1052
|
+
# The deprecated on_function_approval callback enforces approval in the tool
|
|
1053
|
+
# handler; don't also install the default ask-hook (which would double-gate).
|
|
1054
|
+
if self._function_approval_handler is not None:
|
|
1055
|
+
return None
|
|
1056
|
+
|
|
1057
|
+
def default_pre_tool_use(
|
|
1058
|
+
hook_input: Mapping[str, Any],
|
|
1059
|
+
_context: Mapping[str, str],
|
|
1060
|
+
) -> PreToolUseHookOutput | None:
|
|
1061
|
+
tool_name = hook_input.get("toolName")
|
|
1062
|
+
if tool_name in approval_required_names:
|
|
1063
|
+
return {
|
|
1064
|
+
"permissionDecision": "ask",
|
|
1065
|
+
"permissionDecisionReason": (
|
|
1066
|
+
f"Tool '{tool_name}' is marked as requiring approval (approval_mode='always_require')."
|
|
1067
|
+
),
|
|
1068
|
+
}
|
|
1069
|
+
return None
|
|
1070
|
+
|
|
1071
|
+
return {"on_pre_tool_use": default_pre_tool_use}
|
|
1072
|
+
|
|
850
1073
|
async def _get_or_create_session(
|
|
851
1074
|
self,
|
|
852
1075
|
agent_session: AgentSession,
|
|
@@ -871,7 +1094,12 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
871
1094
|
|
|
872
1095
|
try:
|
|
873
1096
|
if agent_session.service_session_id:
|
|
874
|
-
|
|
1097
|
+
service_session_id = agent_session.service_session_id
|
|
1098
|
+
if not isinstance(service_session_id, str):
|
|
1099
|
+
raise AgentException(
|
|
1100
|
+
"GitHubCopilotAgent expects a string service_session_id for session resumption."
|
|
1101
|
+
)
|
|
1102
|
+
return await self._resume_session(service_session_id, streaming, runtime_options)
|
|
875
1103
|
|
|
876
1104
|
session = await self._create_session(streaming, runtime_options)
|
|
877
1105
|
agent_session.service_session_id = session.session_id
|
|
@@ -902,8 +1130,11 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
902
1130
|
mcp_servers = opts.get("mcp_servers") or self._mcp_servers or None
|
|
903
1131
|
provider = opts.get("provider") or self._provider or None
|
|
904
1132
|
instruction_directories = opts.get("instruction_directories", self._instruction_directories)
|
|
1133
|
+
skill_directories = opts.get("skill_directories", self._skill_directories)
|
|
1134
|
+
disabled_skills = opts.get("disabled_skills", self._disabled_skills)
|
|
905
1135
|
all_tools = list(self._tools or []) + list(opts.get("tools") or [])
|
|
906
1136
|
tools = self._prepare_tools(all_tools) if all_tools else None
|
|
1137
|
+
hooks = self._build_session_hooks(all_tools, opts)
|
|
907
1138
|
|
|
908
1139
|
return await self._client.create_session(
|
|
909
1140
|
on_permission_request=permission_handler,
|
|
@@ -914,6 +1145,9 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
914
1145
|
mcp_servers=mcp_servers or None,
|
|
915
1146
|
provider=provider or None,
|
|
916
1147
|
instruction_directories=instruction_directories,
|
|
1148
|
+
skill_directories=skill_directories,
|
|
1149
|
+
disabled_skills=disabled_skills,
|
|
1150
|
+
hooks=hooks,
|
|
917
1151
|
)
|
|
918
1152
|
|
|
919
1153
|
async def _resume_session(
|
|
@@ -941,8 +1175,11 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
941
1175
|
mcp_servers = opts.get("mcp_servers") or self._mcp_servers or None
|
|
942
1176
|
provider = opts.get("provider") or self._provider or None
|
|
943
1177
|
instruction_directories = opts.get("instruction_directories", self._instruction_directories)
|
|
1178
|
+
skill_directories = opts.get("skill_directories", self._skill_directories)
|
|
1179
|
+
disabled_skills = opts.get("disabled_skills", self._disabled_skills)
|
|
944
1180
|
all_tools = list(self._tools or []) + list(opts.get("tools") or [])
|
|
945
1181
|
tools = self._prepare_tools(all_tools) if all_tools else None
|
|
1182
|
+
hooks = self._build_session_hooks(all_tools, opts)
|
|
946
1183
|
|
|
947
1184
|
return await self._client.resume_session(
|
|
948
1185
|
session_id,
|
|
@@ -954,6 +1191,9 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
954
1191
|
mcp_servers=mcp_servers or None,
|
|
955
1192
|
provider=provider or None,
|
|
956
1193
|
instruction_directories=instruction_directories,
|
|
1194
|
+
skill_directories=skill_directories,
|
|
1195
|
+
disabled_skills=disabled_skills,
|
|
1196
|
+
hooks=hooks,
|
|
957
1197
|
)
|
|
958
1198
|
|
|
959
1199
|
|
{agent_framework_github_copilot-1.0.0rc1 → agent_framework_github_copilot-1.0.0rc3}/pyproject.toml
RENAMED
|
@@ -4,7 +4,7 @@ description = "GitHub Copilot integration for Microsoft Agent Framework."
|
|
|
4
4
|
authors = [{ name = "Microsoft", email = "af-support@microsoft.com"}]
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.0rc3"
|
|
8
8
|
license-files = ["LICENSE"]
|
|
9
9
|
urls.homepage = "https://aka.ms/agent-framework"
|
|
10
10
|
urls.source = "https://github.com/microsoft/agent-framework/tree/main/python"
|
|
@@ -23,8 +23,8 @@ classifiers = [
|
|
|
23
23
|
"Typing :: Typed",
|
|
24
24
|
]
|
|
25
25
|
dependencies = [
|
|
26
|
-
"agent-framework-core>=1.
|
|
27
|
-
"github-copilot-sdk
|
|
26
|
+
"agent-framework-core>=1.11.0,<2",
|
|
27
|
+
"github-copilot-sdk==1.0.2; python_version >= '3.11'",
|
|
28
28
|
]
|
|
29
29
|
|
|
30
30
|
[tool.uv]
|
|
@@ -102,4 +102,3 @@ interpreter = "posix"
|
|
|
102
102
|
[build-system]
|
|
103
103
|
requires = ["flit-core >= 3.11,<4.0"]
|
|
104
104
|
build-backend = "flit_core.buildapi"
|
|
105
|
-
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: agent-framework-github-copilot
|
|
3
|
-
Version: 1.0.0rc1
|
|
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>=1.8.0,<2
|
|
20
|
-
Requires-Dist: github-copilot-sdk>=1.0.0,<2; python_version >= '3.11'
|
|
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
|
-
|
|
@@ -1,11 +0,0 @@
|
|
|
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.
|
|
File without changes
|